Stm32F030的Bootloader制作与其他ST芯片一致;但是Stm32F030的APP程序就有特殊变动:因为M0是不能设置重量向量表偏移量;本篇就讲M0的APP程序的中断向量表重映射,和还有一些会用到的冷知识,如编译工具链等。
一、M0的中断向量表重映射
在STM32F103等cortex-m3/m4内核的单片机上可以通过设置中断向量表的偏移量,完成重映射中断向量表。
1 | SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; |
Stm32f0系列MCU中断矢量表的定位跟STM32其它系列相比有点差异,即M0系列没有像其它M3/M4/M0+系列所具备的中断矢量表重定位寄存器,其中断矢量表不能借助矢量重定位寄存器简单修改实现。所以Stm32f0x IAP的过程会跟其它系列的STM32芯片的IAP动作有所不同。
M0的中断向量表如下:
1 | __Vectors DCD __initial_sp ; Top of Stack |
M0的中断向量表重映射方法如下:
- 将APP的中断向量表拷贝到SRAM里面去。M0的中断向量表由48个有序字(32bit)组成,把它们从flash区0x08004000开始的中断向量表拷贝到0x2000 0000的SRAM区。
- 做存储地址的映射,即把SRAM映射到代码执行区的地址0X00处。
1 |
|
经过上述操作步骤后,当APP里发生中断时,内核就从地址0x00处的向量表取相应中断的入口地址,即相当于从0x2000 0000处的向量表取中断入口地址,当然也相当于从0x08003000处的向量表取中断入口地址,然后去执行相应中断程序。
二、编译工具链
STM32中ARM系列编译工具链的编译宏选择(__CC_ARM、__ICCARM__、__GNUC__、__TASKING__)。这里简单介绍一下。
在 core_cm3.h 文件中,有如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
这几个宏都是什么含义呢?分别对应什么平台呢?
- __CC_ARM对应的平台是:
ARM RealView
- RealView,是一套包含编译、调试和模拟的开发工具,需结合开发环境如uvision、eclipse或者CodeWarrior,形成集成开发环境来使用。
- __ICCARM__对应的平台是:
IAR EWARM
- Embedded Workbench for ARM 是IARSystems 公司为ARM 微处理器开发的一个集成开发环境(下面简称IAR EWARM)。比较其他的ARM 开发环境,IAR EWARM 具有入门容易、使用方便和代码紧凑等特点
- __GNUC__对应的平台是:
GNU Compiler Collection
- GCC的初衷是为GNU操作系统专门编写的一款编译器。GNU系统是彻底的自由软件。
- __TASKING__对应的平台是:
Altinum Designer
- Altium Designer 是原Protel软件开发商Altium公司推出的一体化的电子产品开发系统,主要运行在Windows操作系统。这套软件通过把原理图设计、电路仿真、PCB绘制编辑、拓扑逻辑自动布线、信号完整性分析和设计输出等技术的完美融合,为设计者提供了全新的设计解决方案,使设计者可以轻松进行设计,熟练使用这一软件使电路设计的质量和效率大大提高。
三、__attribute__ ((at())
绝对定位
__attribute__
,这个是用来指定变量或结构位域的特殊属性,该关键字后的双括弧中的内容是属性说明。at
,该关键字可以用来设置变量的绝对地址,也就是你可以通过这个关键字,指定某个变量处于内存里面的某个给定的地址.
__attribute__( at(绝对地址) )
的用法分两种,一个是绝对定位到Flash,另一种是绝对定位到RAM。
定位到flash中,一般用于固化的信息,如出厂设置的参数,上位机配置的参数,ID卡的ID号,flash标记等等。
1
2const u16 gFlashDefValue[512] __attribute__((at(0x0800F000))) = {0x1111,0x1111,0x1111,0x0111,0x0111,0x0111};//定位在flash中,其他flash补充为00
const u16 gflashdata__attribute__((at(0x0800F000))) = 0xFFFF;定位到RAM中,一般用于数据量比较大的缓存,如串口的接收缓存,再就是某个位置的特定变量
1
u8 USART2_RX_BUF[USART2_REC_LEN] __attribute__ ((at(0X20001000)));//接收缓冲,最大USART_REC_LEN个字节,起始地址为0X20001000.
- 绝对定位不能在函数中定义;局部变量是定义在栈区的,栈区由MDK自动分配、释放,不能定义为绝对地址,只能放在函数外定义。
- 定义的长度不能超过栈或Flash的大小,否则,造成栈、Flash溢出。
四、重映射 & 系统启动
4.1 重映射
1 | SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM); |
例如F072的参考文档张SYSCFG寄存器的介绍,如下图:
MEM_MODE的介绍如下:
从以上内容我们可以得到以下信息:
- MEM_MODE的值在上电后由BOOT0,BOOT1的状态值决定。
- MEM_MODE的值决定了哪个内存映射到地址0x0000 0000 ,也就是说:
- 当MEM_MODE =00/10时, Main Flash映射到地址0x0000 0000,即地址0x0800 0000映射到0x0000 0000。
- 当MEM_MODE =01时, System Flash映射到地址0x0000 0000,也就是芯片自带的Bootloader代码部分会映射到地址0x0000 0000;例如,0x1FFF C800映射到地址0x0000 0000。
- 当MEM_MODE =11时, Embeded SRAM映射到地址0x0000 0000,也就是内存地址0x2000 0000映射到地址0x0000 0000。
- 经过映射后,系统访问地址0x0000 0000地址,就相当于直接访问映射的地址,如0x0800 0000。
- 由BOOT0,BOOT1的状态决定MEM_MODE的值,进而决定哪个地址映射到地址0x0000 0000,这一过程我们称之为映射。默认映射是系统自动完成的,并由BOOT0,BOOT1的状态决定。
- MEM_MODE位是RW的,也就是说可以修改的,如果修改其中,也就会相应的修改映射到0x0000 0000的地址,这一修改的过程,我们就叫其为重映射。重映射是通过用户代码通过修改MEM_MODE的值来完成的。
4.2 系统启动
从STM32F072的参考手册的2.5章,我们可以看到如下内容:
从以上内容我们可以得到以下有用信息:
- 在复位启动后,系统在系统时钟的第4个上升沿根据BOOT0,BOOT1的配置获取其值,也就是存储到寄存器SYSCFG_CFGR1的MEM_MODE位上,根据前面3.1的信息可知,这里进一步确定了0x0000 0000的映射地址。这一过程是系统自动完成的。
- 在系统启动后,CPU从地址0x0000 0000获取栈顶地址,然后从0x0000 0004开始执行代码。换句话说,由于0x0000 0000被映射了其他地址,获取栈顶与执行实际上都是从映射的地址上实施的。也就是从映射的地址开始执行代码,比如从地址0x08000 0004开始执行代码(如Mian Flash映射),比如0x1FFF C804(如System Flash映射,即BootLoader启动)。
于是,我们简单整理下系统的整个启动流程:
- -> 系统复位
- -> CPU在系统时钟的第4个上升沿根据BOOT0,BOOT1的配置确定寄存器SYSCFG_CFGR1的MEM_MODE的值
- -> MEM_MODE进一步决定哪个地址(Main Flash,System Flash,SRAM)映射到地址0x0000 0000.
- -> CPU从地址0x0000 0000获取栈顶,从0x0000 0004开始执行代码,也就是从映射地址获取栈顶,从映射地址+4的地方开始执行代码。
映射地址+4对于着复位中断例程(如0x08000 0004),也就是系统一开始就执行Reset_Handler,进而运行SystemInit然后进入到main函数,就这样,整个代码启动完成。
接下来就是中断产生于中断响应了。
在Coretext-M3与Coretext-M4核中,在 System Control Block
中存在一个向量表偏移量寄存器 VTOR(0xE000ED08),系统产生中断后,内核通过这个寄存器的值来找到中断向量表的地址,进而执行中断例程代码,当然,此寄存器的值是可以修改的,它的默认值为0。
由于STM32F0XX采用的是M0核,它是没有这个VTOR寄存器的;将M0理解成M3/M4的特殊情况,M0假设也存在VTOR这么一个虚拟寄存器,只不过它的值不能修改,固定为0罢了,而M3/M4的这个VTOR寄存器一开始时它的值也是为默认值0,只不过在程序运行到SystemInit()函数后,在代码中明确对其进行了修改。
重新整理下,STM32F0XX中断的调用过程:
- -> 产生中断
- -> CPU固定到地址0x0000 0000上找中断入口函数;由于映射关系,实际上是在从映射地址上寻找。
- -> 找到并执行中断例程
五、Stm32F030的App工程配置
关于Stm32F0的APP,只需要更改工程配置的 IROM 和 IRAM 就行了。
IRAM存放着重映射中断向量表。1个地址存储1个byte(Falsh 和 Ram 都一样),中断向量都是uint32_t;所以 48 * (32/8) = 0xC0 。
六、友情连接
关于Stm32F0的IAP,ST官方有套参考代码;ST官方的IAP + Ymodem代码;提取码为:aan9
本篇文章部分内容来自于这位博主:flydream0,有些更细致的内容可以了解他写的链接文章。