OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8056|回复: 6

STM32F10x 启动过程 +内存分布+中断偏移量+IAP解析

[复制链接]

8

主题

39

帖子

0

精华

初级会员

Rank: 2

积分
118
金钱
118
注册时间
2015-9-7
在线时间
8 小时
发表于 2015-9-9 09:38:04 | 显示全部楼层 |阅读模式

    接触STM32已经有数天了。现在把对STM32的一些认识分享出来。希望给像我一样的新手一些启发。同时希望高手给看看有无理解不到位或错误的地方,还望指正~~~

STM32内存布局:

程序代码可以烧录在内存的SRAMmain Flash中。其中System memory区存放ST固化的bootloader程序,实现ICP下载,用户不能修改或删除。


程序代码在内存中的布局:

程序代码被编译连接后,其在内存中的组织结构如下图(假设将代码烧录在0x0800 0000处)。在IDE中可以配置程序代码的下载位置(必须位于flashSRAM中)。

图中给出“程序代码的各个区域”在内存中相对位置的一种示意(实际情况可能并非如此,对于stm32来说中断向量表肯定在程序代码的最开头处存放)。程序代码中各个区域的划分以及在内存中的相对位置由编译器(有专门的内存映射[机制]文件,此文件可能开源也可能非开源)决定。一般情况开发人员应该可以人为的干预。

程序代码使用RAM布局:

当一个程序代码通过编译连接后,其全局、静态变量、堆栈的位置已经赋予了具体的内存地址了。因此其RAM布局就是定死了的。

程序代码的启动过程解析:

根据BOOT引脚的配置,芯片上电后由硬件完成栈顶SPPC的定位(注1)。PC定位在复位中断函数Reset_Handler(void)的入口地址去执行此中断函数。此函数会调用SystemInit()__main()两个函数。而__main()会调用开发人员编写的main()函数而main()函数调用子函数实现项目需求。

/*****************

1:通过配置BOOT[0,1]引脚,来选择程序的启动位置(即根据BOOT引脚的设置,硬件自动将PC指向固定的位置处)。

当选择从main Flash memorysystem memory启动时,硬件使SP默认从0x0000 0000处取栈顶地址,PC默认从0x0000 0004处取复位中断函数的入口地址。

当选择从SRAM启动时,SP默认从0x8000 0000处取栈顶地址,硬件使PC默认从0x8000 0004处取复位中断函数的入口地址

2Reset_Handler(void)的函数体在启动文件startup_stm32f10x_xx.s中。

3SystemInit()system_stm32f10x.h中。SystemInit()中含有对中断向量表重定位的语句:

/****************

#ifdef VECT_TAB_SRAM

SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Relocation in Internal SRAM. */

#else

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Relocation in Internal FLASH. */

******************/

4__main()是非开源函数,其总要功能是完成SRAM中变量的初始化工作并调用main()

*******************/

在调试或软件仿真的时候,可以通过IDE来设置启动的位置(见下图),因此可以随意将程序烧录在main FlashSRAM的任意位置(由IDE给出PC的定位)。但是将程序“单独”(不与IDE相连)在芯片上运行时,却只能将代码烧录在0x0800 00000x2000 0000处,因为PC的定位由硬件根据BOOT引脚确定。


中断向量表偏移量的分析:

由于Cortex-M3芯片固定中断向量表的位置(0x0000 0004),而不固定程序的位置。也就是说程序代码可以烧录在不同的内存中,但芯片发生中断时认为总断向量表默认固定在了0x0000 0004的地方,因此发生中断响应时将从0x0000 0004处取寻找对应中断函数的入口地址。

但程序代码中的中断向量表可不一定位于0x0000 0004处,因此需要重映射中断向量表。重映射是将默认的中断向量表的地址从新映射到偏移量所对应的地址处(并非是“将偏移量处的程度代码的中断向量表内容映射到0x0000 0004处的默认中断向量表中”。当然两种理解方法都讲得通,不过实际情况是第一种。可通过IDE进行验证)。一般在SystemInit()main()中设置中断向量表的偏移量。

当配置为“从main Flash memorysystem memory启动”时,存在一种映射机制,将main Flash memorysystem memory区整体映射到boot memroy区。这样一来,在0x0000 0000处正好存储的就是程序代码的中断向量表,因此无需重映射中断向量表(默认偏移量为0)。而“从SRAM启动”时不存在上述的映射机制,因此中断向量表就需要重映射。

通过“注1”可以知道,必须将程序代码烧录在0x0800 00000x2000 0000处才能保证由硬件完成的“PC定位”能准确的找到程序代码的中断向量表的复位中断函数Reset_Handler(void)的入口地址。

从芯片上电开始,截止到配置偏移量之前,是不会发生中断请求的(包括系统异常和IQR)。在SystemInit()中含有禁止所有中断的设置。由于中断请求时,硬件自动到0x0000 0004处的默认中断向量表取相应中断函数的入口地址,因此在main()中使能某个中断之前,必须配置好偏移量,这样才能保证0x0000 0004处的默认中断向量表的内容与程序代码中的中断向量表一致。

芯片运行过程中发生的复位中断请求(同其他中断请求)通过查找0x0000 0004处的中断向量表中Reset_Handler(void)的入口地址来执行此函数。但芯片从没供电到供电时,不会引起复位中断请求,而是由硬件锁定PC执行位置直接执行Reset_Handler(void),因为此情况下,0x0000 0004处的默认中断向量表的内容是空的。

IAP分析:

IAPbootlader代码必须放在0x0800 00000x2000 0000处。而APP代码可以放在main FlashSRAM的任意位置,原因就是通过bootloder代码来定位APP的复位中断函数的入口地址(仿照“硬件根据BOOT引脚定位PC”的过程)。当然在APP中也可以定位bootloader的复位中断函数的入口地址,实现bootloaderAPP的相互跳转。

芯片上电执行bootloader代码:

当需要更新APP时,与PC通信将APP新代码先安置在SRAM中。接受完后,判断是APPinFlash还是APPinARAM,如果是APPinFlash就进行Flash操作将APP新代码放在Flash指定位置,最后跳转到APPinFlash执行;如果是APPinARAM,直接跳转到APPinARAM执行。

当不需要更新APP时,直接跳转到APP代码或显示没有可执行的APP代码。

设计方案:假设使用的芯片是STM32f103ZE。其具有512kB Flash(0x0800 0000~0x0808 0000)64kB SRAM(0x2000 0000~0x2001 0000)。

Bootloader

放在0x0800 0000处,并限制其最大代码量为64KB。使用的RAM不能超过4KB

ROM:  0x0800 0000~0x0801 0000 64KB

RAM:  0x2000 0000~0x2000 1000 4KB

APPinFlash

Bootloader接受APPinFlash代码时首先将其放在SRAM0x2000 1000处,其最大代码量为0x2000 1000~0x2001 0000(60KB);然后通过Flas操作将其转移到0x0800 1000之后的Flash区域。最后跳转到APPinFlashreset_handle(),~~~~~

APPinFlash可以使用的RAM区域为整个SRAM区域。

APPinSRAM

Bootloader接受APPinSRAM代码时将其放在SRAM0x2000 1000处,其最大代码量为0x2000 1000~0x2001 0000(60KB);然后跳转到APPinSRAMreset_handle(),~~~~~

APPinSRAM可以使用的RAM区域为除去APPinSRAM占领的其他SRAM区域

比如APPinSRAM占领0x2000 1000~0x2000 5000(20KB),那APPinSRAM可以使用的RAM区域为0x2000 0000~0x2000 0FFF(4KB)0x2000 5000~0x2001 0000(40KB)

程序代码的ROMRAM区域可以通过IDE进行设置,不过最多可以将其拆分为2块。


这里需要指出的是,为什么APPinFlashAPPinSRAMRAM区域可以占用bootloaderRAM区域呢?

执行bootloader代码过程是:reset_handle()------systemini()------__main()------main().__main()中就会对其通过IDE设定的RAM中初始化全局变量和静态变量,堆栈指针的地址也是早就定死了的。当跳转到APP程序的时候,还是按着如上的流程进行。

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

8

主题

39

帖子

0

精华

初级会员

Rank: 2

积分
118
金钱
118
注册时间
2015-9-7
在线时间
8 小时
 楼主| 发表于 2015-9-9 09:40:14 | 显示全部楼层
帖子所示的DIY资料的word附件。内容一样。

STM32 内存布局+启动过程+中断向量表偏移解析+IAP.doc

160.59 KB, 下载次数: 211

回复 支持 反对

使用道具 举报

109

主题

1606

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2222
金钱
2222
注册时间
2011-12-15
在线时间
37 小时
发表于 2015-9-9 09:58:52 | 显示全部楼层
写的挺详细,不错,谢谢分享
专业制作STM32 物联网通信模块板,模块交流群:369840039。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
发表于 2015-9-9 10:10:16 | 显示全部楼层
分析的很清晰,谢谢分享,nice
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

4

主题

38

帖子

0

精华

初级会员

Rank: 2

积分
160
金钱
160
注册时间
2014-11-28
在线时间
27 小时
发表于 2018-1-14 14:29:31 来自手机 | 显示全部楼层
最近在学习IAP编程,用原子哥的bootloaderv1.0,加载不带系统的程序可以正常跳转,但是加上FreeRTos之后 中断向量检查一直不过,不知道为什么。有大神遇到过没有?
回复 支持 反对

使用道具 举报

2

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
110
金钱
110
注册时间
2018-5-26
在线时间
7 小时
发表于 2018-6-22 14:22:05 | 显示全部楼层
挺不错了 谢谢分享
ABB定位器www.chinaabb-positio.com
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
3
金钱
3
注册时间
2019-10-26
在线时间
0 小时
发表于 2020-3-14 19:48:08 | 显示全部楼层
我擦,我学了一年半刚刚才有这些觉悟
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-22 10:36

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表