以下内容大部分是根据零死角玩转STM32这篇文档,写的非常好。这个总结只是写了基础的部分,包括STM32的简介及STM32的IO口操作、中断配置,总结在此处方便以后的回顾。
一、Cortex简介ARM Cortex 系列是新一代的,一个为广泛的技术需求提供标准架构的处理器。与其他的ARM 处理器不同,Cortex 系列是一个完整的处理器核心,一个标准的CPU 和系统架构。 Cortex-M3的4Gbyte地址空间被分成明确定义的区域:代码区,SRAM区,外设区和系统外设区。与ARM7不同的是,Cortex-M3是一个哈佛结构的处理器,所以有多条总线,允许执行并行操作,提高其整体性能。与早期的ARM架构不同,Cortex 系列允许未对齐的数据访问。这将确保最有效地利用内部SRAM。Cortex 系列还有一个称为位带的方法,支持在两个1Mbyte 的内存区域里进行位设置和清除。这样可以有效地访问位于SRAM存储器的外设寄存器和标志,而不需要一个完整的布尔处理器。 Cortex CPU 是一个有加载和存储体系结构的RISC处理器。为了执行数据处理指令,操作数必须被加载到一个中央寄存器,数据操作必须在这些寄存器上执行,并且把结果回存到内存上。
二、STM32简介STM32的核心是Cortex-M3 处理器。Cortex M3 处理器是一个标准化的微控制器,包括32 位CPU,总线结构,嵌套的中断单元,调试系统和标准内存布局。
M3处理器支持两种处理器的工作模式,还支持两级特权操作。
两种工作模式: 处理模式 handler mode 线程模式 thread mode。
引入两个模式的本意,在于区别普通应用程序代码和异常服务程序,包括中断服务程序代码
M3的特权分级: 特权级 用户级,可以提供一种存储器访问的保护机制,使得普通的用户程序代码不能意外地,甚至是恶意地执行涉及到要害的操作。这也是一个基本的安全模型。当处理器运行主应用程序时(线程模式),既可以使用特权级,也可以使用用户级,但是异常服务程序必须在特权模式下执行。复位后,处理器默认进入线程模式,特权级访问。在特权级下,程序可以访问所有的存储器空间(除非被MPU设置禁用),并且可以执行所有指令。(特权级进入用户级后就只能处理在用户级的状态下能做的功能,想要回到特权级只有触发异常)在非特权模式下某些指令将被禁用(如允许访问xPSR 和它的别名的MRS 和MSR指令。 三、开发工具
MDK 是一个集代码编辑,编译,链接和下载于一体的集成开发环境(KDE)。
Translate 就是翻译当下修改过的文件,说明白点就是检查下有没有语法错误,并不会去链接库文件,也不会生成可执行文件。
Build 就是编译当下修改过的文件,它包含了语法检查,链接动态库文件,生成可执行文件。
Rebuild 重新编译整个工程,跟Build 这个按钮实现的功能是一样的,但有所不同的是它编译的是整个工程的所有文件,耗时巨大。
四、STM32库在 51 单片机的程序开发中,我们直接配置 51 单片机的寄存器,控制芯片的工作方式,如中断,定时器等。配置的时候,我们常常要查阅寄存器表,看用到哪些配置位,为了配置某功能,该置1 还是置 0。这些都是很琐碎的、 机械的工作,因为 51 单片机的软件相对来说较简单,而且资源很有限,所以可以直接配置寄存器的方式来开发。 STM32 库是由 ST 公司针对 STM32 提供的函数接口,即 API(Application Program Interface),开发者可调用这些函数接口来配置 STM32 的寄存器,使开发人员得以脱离最底层的寄存器操作,有开发快速,易于阅读,维护成本低等优点。 库是架设在寄存器与用户驱动层之间的代码,向下处理与寄存器直接相关的配置,向上为用户提供配置寄存器的接口。
所谓库函数,就是 STM32的库文件中为我们编写好的函数接口,我们只要调用这些库函数,就可以对 STM32 进行配置,达到控制目的。我们可以不知道库函数是如何实现的,但我们调用函数必须要知道函数的功能、 可传入的参数及其意义、和函数的返回值。
五、为什么采用库来开发?对于 STM32,因为外设资源丰富,带来的必然是寄存器的数量和复杂度的增加,这时直接配置寄存器方式的缺陷就突显出来了:
1) 开发速度慢
2) 程序可读性差
这两个缺陷直接影响了开发效率,程序维护成本,交流成本。库开发方式则正好弥补了这两个缺陷。而坚持采用直接配置寄存器的方式开发的程序员,会列举以下原因:
1) 更直观
2) 程序运行占用资源少
初学 STM32 的读者,普遍因为第一个原因而选择以直接配置寄存器的方法来学习。认为这种方法直观,能够了解到是配置了哪些寄存器,怎样配置寄存器。事实上,库函数的底层实现恰恰是直接配置寄存器方式的最佳例子,想深入了解芯片是如何工作的话,只要追踪到库的最底层实现就能理解,相信你会为它严谨、优美的实现方式而陶醉。相对于库开发的方式,直接配置寄存器方式生成的代码量的确会少一点,但因为 STM32 有充足的资源,权衡库的优势与不足,绝大部分时候,我们愿意牺牲一点资源,选择库开发。一般只有在对代码运行时间要求极苛刻的地方,才用直接配置寄存器的方式代替,如频繁调用的中断服务函数。
六、Cortex 微控制器软件接口标准
因为基于 Cortex的某系列芯片采用的内核都是相同的,区别主要为核外的片上外设(如芯片内部的模数转换外设ADC、串口UART、定时器TIM等)的差异,这些差异却导致软件在同内核,不同外设的芯片上移植困难。为了解决不同的芯片厂商生产的 Cortex微控制器软件的兼容性问题,ARM 与芯片厂商建立了 CMSIS 标准(Cortex MicroController SoftwareInterface Standard)。
CMSIS 标准中最主要的为 CMSIS 核心层,它包括了:
内核函数层:其中包含用于访问内核寄存器的名称、地址定义,主要由 ARM 公司提供。
设备外设访问层:提供了片上的核外外设的地址和中断定义,主要由芯片生产商提供。
CMSIS 为所有的Cortex 微控制器提供业界标准的驱动程序级别的接口。CMSIS 的目标只是使软件驱动程序和组件与硬件的交互变得尽量简单。这使得节省了开发时间,可以集中精力建设最好的应用程序代码。
七、位带
早期的ARM7和ARM9的CPU只能在SRAM和外设存储器位置上通过使用AND和OR指令执行位操作。这需要一个读-修改-写操作,在设置和清除位需要的周期数量和对每一个位操作所需的整体代码空间方面来说,这是很昂贵的。
为了克服这个限制,将有可能引入一个专用的位设置和清除指令,或者一个完整的布尔处理器,但是这将会增加Cortex CPU 的大小和复杂性。取而代之的是,一个叫位带的技术允许直接位操作外设区和SRAM区内存空间,而不需要其他任何特别指令的介入。Cortex存储器映射中的位寻址区域是由位带区(容量高达1M byte的实际存储器或外设寄存器)和占用内存映射32Mbyte 的位带别名区组成的。位带技术把位带区域中的一个位映射到别名区中的一个字地址。因此,通过设置和清除别名区字地址,我们可以设置和清除真正内存中的位。(不同于51单片机,这些位带对应的都是一位的地址,没有字节地址,所以不需要类似51中的sbit来区分是字节还是位地址) 计算别名地址的公式如下: 位带别名区的地址 = 位带别名区的基地址+位带字偏移 位带字偏移 = 位带基地址偏移*32+位号*4 这比一开始看起来要容易得多。对于一个实际的例子,GPIO 输出数据寄存器被设计为可以设置和清除单个IO线。端口B 输出寄存器的物理地址是0x40010C0C。在这个例子中,我们可以使用上面的公式来设置和清除这个字的第8位。 字地址 =0x40010C0C 外设位带基地址 =0x40000000 外设位带别名基地址 = 0x42000000 位带基地址偏移 =0x40010C0C-0x40000000=10C0C 位带字偏移 = (0x10C0C*32)+(8*4)=0x2181A0 位别名地址 =0x42000000+0x2181A0=0x422181A0 现在,我们可以用下面的C代码来创建一个指针指向这个地址: #define PortBbit8 (*((volatile unsigned long *)0x422181A0 ))然后,可以使用这个指针来设置和清除IO端口位: PortBbit8 = 1; //led on |