STM32 内存/ROM分配-启动-升级

STM32 之 RAM/ROM-启动-升级

一、 文章概述
STM32(包括其它所有单片机、ARM等),我们能看到的只是其中一部分运行代码,包括自行编写(x.c,x.h)、库(x.lib\x.a)、启动文件(startup_xxx.s)等。还有其它一些IDE环境自带的启动代码(如图一,可从MAP文件中查看到)
图一
对于以上所有代码编译后的东西,再经过链接等步骤加工后,形成一种叫二进制可执行文件(x.bin)。bin文件按照对于的ROM地址烧写到芯片中,即可运行。

二、 ROM存储结构
对于STM32来说,BIN文件在ROM中的存储结构,则主要包括几大部分data段、bss段、heap段、stack段、code段、中断向量表段、复位启动入口(包括主堆栈指针初始值)等。
我们从头开始了解一下流程。
首先,便是这“复位启动入口”。这入口指明了两个人的身份-PC和SP。也就是这入口接下来得继续走下去的路。图二便是复位启动入口的代码。
图二
由于STM32是小端的存储模式,所以“08 C3 00 20”便指明了主堆栈指针SP=0x2000C308,“A1 41 00 08”便指明了程序指针PC=0x080041a1。由图一MAP可看出,0x080041a1便是startup_xxx.s的入口。图三是由实际仿真窗口捕捉的代码,确实是startup_xxx.s文件的SystemInit()函数。
图三
此处为何PC=?,SP=?SystemInit()之后,又干了什么?

其次,便是中断向量表。中断向量表,即相应中断产生时,程序指针跳转到此处向量表,由向量表再跳转至相应的中断处理。表面上看,它没啥特殊,但是如果你的程序起始地址存在偏移时(与0x08000000)比如增加Bootloader时,那这向量表的意义就很大很大了。你可以想象一个问题,你的Bootloader(简称bl)有中断吧,你的主程序(简称app)有中断吧,那如何让你的Bl和app跑自己的中断呢?
这个时候,在bl和app做跳转时,有个特别重要的对接会议要开一下,商讨一下app的这个表在哪里,这个东西叫SCB。程序初始化时预设,运行时也可重设。
图四

再次,就是code段了。这个就不用多说了,就是你的app代码。
再再次,就是data段,存放已初始化的全局变量、静态变量(不管初始化还是未初始化)。此处嘛,容易与RAM的data段混在一起。我提个问题,大概就能明白了,你有一个初始化的全局变量A=10,而运行时,A是在RAM里边的,同时RAM又是掉电不保存的,那么这个A=10是如何保证的呢?
原因就在这里,“复位启动入口”的SystemInit()完事之后,有个加载过程叫“加载数据段”(_scatterload_copy),之后才转到_main处运行。这个加载过程,便是将这段ROM的data段数据,拷贝到对应的RAM,从而保证上电后A=10之类的承诺。
这个地方,既重要,也不重要。做升级时,如果你的下载,掉了这一段,不会影响你的代码运行,只是会影响到与这些全局变量和静态变量的判断。

最后,就是bss段了,是存放未初始化的全局变量。这个在我看来,没啥特殊。若有特殊,后面遇到再补上。

三、 RAM分配
直接上图

图五
从内存上看,已经很明了了,先是data段,再是bss段,然后是heap(堆),最后是stack(栈)。
Data段,就是已初始化的全局变量和静态变量(未初始化、初始化),需要从code段加载。Bss就是未初始化的全局变量。这两个都属于静态内存分配,是程序编译时已经决定大小的。
Heap段,就是传说中的堆,大小是固定,但是怎么用,用多少,就是我们决定的了,因为它就是malloc和free的那块内存。
Stack段,就是很熟悉的那个栈,很像个客栈对吧。对,它就是个客栈,包含了同样的属性-临时。这一块内存,是函数跳转、局部变量等用到的。函数跳转时,是怎么回来的呢?回来之后,是怎么保证原来的变量值能继续运行呢?局部变量为什么出了作用域就用不了了呢?所有的这些,都是栈的作用。

说到这里,罗嗦几句。Heap分配太小,那你会经常malloc不到内存。Stack分配太小,那你会经常程序跑飞。

四、 启动
到这里,相信大家已经明白了,把上面的流程组合起来,就是完整的启动流程。
1、上电复位,设置PC,SP
2、跳转到SystemInit(),其中初始化了时钟、SCB(即中断向量表)
3、跳转到_scatterload_copy,完成data\bss段的加载工作
4、跳转到main

五、 升级
升级过程遇到的问题:
1、keil总是停止在某个地方,无法全速运行和单步运行,但是在汇编窗口,却可以单步运行。
可能原因:keil中使用断点的地方太多,把所有断点去掉后再试。
2、BL中中断响应正常,但是APP中断却不响应。特别是某些地方使用了HAL_GetTick();
原因:由于Bl中使用了disable_irq(),造成跳转到APP后无法正常中断(如果没有调用enable_irq())。
3、APP经常复位。
原因:由于BL中开了IWDG,又由于IWDG开启后无法再次关闭,IWDG只有在程序复位后才会失效。
升级过程后面再补上。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值