STM32 固件升级之SRAM(运行内存)、FLASH(闪存)分配及栈顶地址合法性检查详解

运行内存、FLASH(闪存)分配在远程升级开发过程中尤为重要,内存分配不严谨可能会导致代码出现各种异常(跑飞、无法运行、运行不受控的代码段)

什么是SRAM(运行内存)、FLASH(闪存)?

          (1)FLASH(闪存):Flash 存储器是一种非易失性存储器,用于存储程序代码和常量数据。在 STM32 微控制器中,Flash 存储器通常用于存储程序代码,它是在编译并烧录程序后被写入的。Flash 存储器的内容在断电后通常会保持不变,因此适用于存储固化的程序。

          (2)SRAM(运行内存):运行内存通常指的是随机存储器(RAM),这种存储器用于临时存储程序执行过程中产生的数据、堆栈信息以及其他临时变量。在 STM32 微控制器中,RAM 存储器用于存储程序执行时需要修改或访问的数据,它的内容在断电后会丢失。

简单来说 FLASH(闪存)用来存代码的,掉电不会丢失。 SRAM(运行内存)是用来存放代码运行时所需的变量、中间结果和临时数据,掉电就丢失。

STM32的运行内存和我们电脑的运行内存功能大多是一致的,但还是有差别。在个人电脑(PC)中,代码通常是从硬盘(或其他非易失性存储设备,如SSD)加载到RAM(随机存取存储器)中执行的。这是因为RAM提供了比硬盘更快的数据访问速度,从而提高了程序运行的效率。STM32选择直接从Flash中读取代码执行,而将RAM用于存储运行时的变量和中间数据。

以STM32F407VET6为例内存参数如下:

  • FLASH(闪存):512 KB。
  • SRAM(运行内存):192 KB+4KB.

1、FLASH(闪存)

地址范围:0x08000000-0x0807FFFF

STM32F407VET6的FLASH(闪存)共分为8个扇区,每个扇区起始地址及空间大小分配情况如下,写操作前要先对flash进行擦除,擦除的最小单位为扇区。所以存储BOOT和APP的代码的FLASH空间要按扇区地址来分配。APP代码空间的起始地址要为扇区起始地址,flash的空间利用率最高且在boot更新APP代码时不容易出错。

我的BOOT代码大小为35K,且只用了一个APP,未做备份,FLASH闪存空间分配如下

                扇区0-3作为BOOT代码空间 起始地址0x08000000  大小0x10000  即:64k 

                扇区4作为IAP标志存储空间 起始地址 0x08010000大小0x10000  即:64

                扇区5-7作为APP代码空间  起始地址 0x08020000   大小0x60000  即:384k

(注:IAP标志一般存外部eeprom, 我此处是把内部FALSH当EEPROM使。根据自己实际情况配置!)

BOOT FLASH空间分配配置:

                                
APP FLASH空间分配配置:
                        ​​​​​​​        ​​​​​​​

2、SRAM(运行内存)

  • 系统SRAM:从地址 0x20000000 到 0x20030000,总共 192 KB(112KB+16KB+64KB)。
  • 备份SRAM: 起始地址 0x40024000-0x40025000,总共4KB

2.1 STM32F4XX中文手册关于SRAM的描述如下:

通过上图  关于STM32F407VET6 SRAM得出以下总结:

        (1)112 KB + 16 KB的SRAM
                这部分SRAM映射在地址0x2000 0000-0x2002 0000,总共128KB,可供所有的AHB(Advanced High-performance Bus)主控总线访问。AHB主总线支持多个主控设备(如CPU、DMA控制器等)的并发访问,因此这部分SRAM可以用于存储需要被多个设备共享或同时访问的数据。128K分成两段的,一段是112K,一段是16K,这样做的好处是两块RAM有各自的地址总线,可以同时被访问。举个例子,你用网口往16K段里面写数据,而同时CPU可以正常访问112K段,不受影响。

        (2)64 KB的CCM(Core Coupled Memory)
                这部分SRAM映射在地址0x1000 0000-0x1001 0000只能供CPU通过数据总线访问。CCM是直接挂在D-bus(数据总线)上的,因此CPU能以最大的系统时钟和最小的等待时间从CCM中读取数据或代码。CCM通常用于存储那些需要快速访问的数据,如中断处理程序、堆栈和局部变量等。

        (3)STM32F407VET6 SRAM由128K常规SRAM+64K的CCM组成。

2.2、四种类型的数据占用内存情况


如下图:
(来源:STM32深入系列01——内存简述(Flash和SRAM)_stm32内存-CSDN博客

通过以上几点可知

通过查看map文件 得知我的BOOT和APP编译后各类型大小如下:

BOOT:


    Total RO  Size (Code + RO Data)                36124 (  35.28kB)
    Total RW  Size (RW Data + ZI Data)             25320 (  24.73kB)
    Total ROM Size (Code + RO Data + RW Data)      36488 (  35.63kB)

APP:

    Total RO  Size (Code + RO Data)               250740 ( 244.86kB)
    Total RW  Size (RW Data + ZI Data)             95688 (  93.45kB)
    Total ROM Size (Code + RO Data + RW Data)     251204 ( 245.32kB)

其中RW  Size (RW Data + ZI Data)即为占用的SRAM空间(在不使用动态内存的情况下)

已知BOOT 占用SRAM 25KB ,APP占用SRAM 94KB   可用SRAM128KB,
分配28K SRAM 给BOOT, 分配100K SRAM给APP。

BOOT FLASH空间及SRAM分配配置:

APP FLASH空间及SRAM分配配置:

3、64K的CCM也是SRAM,为什么不参与运行内存分配?

        64K的CCM是不支持DMA的,只能供CPU通过数据总线访问。如果APP中使用了DMA,接收DMA的缓存地址又是编译器编译时决定的,编译器不会主动规避这个风险,若使用了DMA又使用了CCM的话,编译器有可能将DMA接收地址编译给CCM就会造成异常,若是要使用DMA又要使用CCM得将DMA接收缓存的地址指定到常规的128K的SRAM里面去。
总结起来就是:
 IRAM2 :0x10000000  0x10000  CCM只能由CPU访问,除非你知道你在干嘛,否则不要使能它。(多方查找资料得到的结论,没空去验证,欢迎各方道友验证后留言评论给予指正)。

4、栈顶地址合法性校验

在固件更新完成校验通过后需要BOOT跳转到APP,在跳转前就需要进行栈顶地址合法性校验.确保栈地址在STM32的sram范围内。首先要知道的是栈顶地址以小端模式存放在固件的前4个字节,如下图是我APP的BIN文件打开后,即栈顶地址为0x2001B9E8。在地址 0x20000000 到 0x20030000之间,则说明该栈顶地址合法。

代码中最直接的检查栈顶地址是否合法方法是

if ((*(vu32*)APPLICATION_ADDRESS)  <= 0x20030000&&(*(vu32*)APPLICATION_ADDRESS)>=0x20000000 )

高端一点把人看迷糊的方法:

if (((*(vu32*)APPLICATION_ADDRESS) & 0x2FFC0000) == 0x20000000)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌乱的小老弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值