你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

经验分享 | STM32G474 勘误手册中 SRAM Write Error 详解

[复制链接]
STMCU小助手 发布时间:2025-8-11 14:29

勘误手册中的 “SRAM Write Error” 在 STM32G474 的勘误手册 ES0430 的第 2.2.7 章节中提到 SRAM Write Error 问题,具体内容如下: image.png

图1. 勘误手册 ES0430 中对 SRAM Write Error 问题的说明

对于大于 32kbytes 的 SRAM,它的每 32kbytes 空间对应一个 SRAM 状态机,对于SRAM 独立空间但没有超过 32kbytes 的空间,比如 SRAM2,CCM SRAM,都对应各自的一个 SRAM 状态机。正是由于这个原因,在 workaround 中需要对每个空间进行一次状态机的恢复操作。以确保每个 SRAM 状态机都能正常工作。

芯片复位系统起来后,即使存在“SRAM Write Error”,对 SRAM 的第一次读操作是没有问题的(对 SRAM 的读操作只能恢复对应这个地址段的 SRAM 的状态机,不影响其他地址段的 SRAM 状态机),并且这次读操作可以恢复属于这个地址段的有问题的 SRAM 状态机到正常状态;如果复位后的 SRAM 的第一次操作是写操作,则发生“SRAM Write Error”时对SRAM 的第一次写操作会出错。但之后对 SRAM 的操作由于状态机的恢复都不会存在读写问题。

  1. 怎样复现此问题 由于编译器生成的代码(startup code)会对全局变量进行初始化,因此要复现这个问题需要在编译器对全局变量进行初始化之前进行问题的复现。

发生“SRAM Write Error”问题的 SRAM 空间地址段即为对这个 SRAM 进行写入同时又异常复位的 SRAM 空间。

在软件工程文件中会有一个 Startup code ,比如 STM32G474 的 IAR 工程会有startup_stm32g474xx.s 文件,处理器从复位起来后首先执行的是这部分代码:

image.png

图2. 初始化代码

复现问题需要在 Reset_Handler 的开始就去对 SRAM 进行循环写入的动作,可以使用汇编代码或者是 C 代码,C 代码可以放置在 SystemInit 函数中,但要注意不要进行函数的调用(函数调用会压栈,即对栈所在的 32kbytes 区域进行了写入,这部分空间对应的 SRAM 状态机会恢复到正常状态(存在问题的情况下),SRAM 问题就不能复现了)。

在对 SRAM 进行写入的同时对 MCU 进行 NRST 的复位操作就可以复现问题,复现概率大概是千分之一左右,取决于代码运行主频、异常复位信号产生的频率等因素(这个 NRST 信号来自于另外一块开发板或是信号发生器)。

对写入数据的判断要放置在数据写入之后。

2.1. STM32G474 的 workaround 代码 在 ES0430 2.2.7 章节中提到 workaround,下面的代码就是处理器复位后需要首先执行 的代码,放置 Reset_Handler 开始的地方:

image.png

图3. UVISION 工程使用的 workaround 代码

image.png

图4. STM32CUBEIDE 工程使用的 workaround 代码

image.png

图5. IAR 工程使用的 workaround 代码

  1. 问题概率分析 正常情况下出现“SRAM Write Error”问题的概率是非常低的,因此很多客户只有出现问题后对问题进行分析时考虑。“SRAM Write Error”属于非常低的概率事件的具体原因如下:

(1)正在运行的处理器发生异常复位的概率比较低。然后发生复位时 SRAM 正处于写入阶段的概率会更低一些,再者发生复位时 SRAM 正在写入并恰巧引发“SRAM Write Error”的概率又进一步降低。

(2)对于一般的编译器,都有自动生成的 Startup code,在这部分代码中会对不带初值的全局变量(SRAM 地址空间)进行初始化(写 0),使得有问题的 SRAM 状态机转为正常(“SRAM Write Error”恰巧出现在这部分地址段)。

(3)在普通应用中,代码执行到 main()函数之前要运行 startup code,第一次压栈的数据直到代码运行到用户自己的 main 函数中时也永远不会有弹出的情况。因此即使第一次对栈空间进行写入发生 SRAM write error 造成写入错误,也不会对这部分 SRAM 地址段造成影响。

(4)在 167945 (bugzilla) 里,提到如下的问题复现概率: /the problem arises when the product is reset (NRST signal) during a phase of writing into SRAM. I had a nucleo board constantly writing into SRAM while other nucleo was toggling its NRST pin. The first board was logging the cases when the reset was causing the problem. The test rig counted 188571 resets of STM32G4 to get 100 errors./

(5)下面 3.1 章节的一种情况会产生“SRAM Write Error”可能影响系统运行。

在有些特殊情况下,比如在客户处发现的一个 Keil 工程,第一次对 SRAM 的写入动作出现在 startup code 代码中的一处压栈操作中,并且这个压栈的数据在跳转到 main.c 之前存在出栈操作,这样的压栈数据是有用的,“SRAM Write Error”问题的存在会对程序运行造成风险(客户代码和跟踪情况无法在此处展示)。

3.1. 实验一(IAR 工程):为了验证上面的第 2 点、第 3 点和第 5 点,做了如下的实验 使用 STM32G474 开发板:Nucleo_G474RE

PC 端编译调试软件: IAR 9.40.1

使用的软件工程为:…\STM32Cube_FW_G4_V1.5.0\Projects\NUCLEO-G474RE\Examples\GPIO\GPIO_IOToggle

需要修改 main.c 代码如下: image.png

对于 SRAM 空间:0x20010000, 属于不带初值的全局变量,startup code 会进行写“0”操作。

对于 CCM SRAM 空间:0x10000500,属于带初值的全局变量。产生“SRAM Write Error”时,可能会有错误的初值。反汇编代码跟踪如下:

Trace information: 由于存在断点,系统运行起来后会停在: “Reset_Handler”,此时栈指针指向 0x20000428 ,然后先执行 SystemInit: image.png

image.png

单步跟踪代码,发现第一次对 SRAM 的操作为压栈。见下图第一次压栈: image.png

单步运行一步后, 栈指针为 0x20000420,R0 和 R1 中的数据入栈。请留意这是对 SRAM 的写操作,之后程序运行到 main()函数后一直不会返回,这个值一直会在栈中,因此这个 SRAM 地址段即使发生了“SRAM Write Error”也不会对程序造成不好的影响,并且能使有问题的 SRAM 状态机恢复到正常状态 : image.png

之后继续跟踪代码(代码在 Startup code 中),寻找每个 SRAM 状态机地址段的第一次读出或是写入的位置。

执行的代码流程大概如下:

如果对应的 MCU 有 FPU,iar_program_start 首先会调用iar_init_vfp 对 FPU 进行初始化:然后iar_program_start 会调用cmain: image.png

cmain 首先会调用low_level_init:

cmain 然后会调用iar_data_init3 进行全局和静态变量的初始化: image.png

iar_data_init3 首先会调用iar_zero_init3 进行初始值为 0 的全局和静态变量的初始化:

然后iar_data_init3 会调用iar_copy_init3 进行初始值为非 0 的全局和静态变量的初始化:

最后__call_main 会调用 main 函数跳转到 main 函数:

至此 MCU 从复位向量开始,运行启动代码之后就跳转到 main 函数,然后开始运行用户的代码:

跟踪代码对 SRAM 的操作,下面图片是对没有初始值的全局变量的初始化(写入 0), 此位置对应的 SRAM 状态机也能转为正常(如果存在 SRAM Write Error):

pragma location=0x20010000

char Data1[16]; image.png

对 0x20010000 初始化完成后的情况(都清零): image.png

然后全速运行到对 0x10000500 的初始化(此案例中是运行到断点处),由于是带初值的,因此第一次对这个地址段的 SRAM 的操作为写入操作。

pragma location=0x10000500

char Data4[4]= {0x11, 0x22, 0x33, 0x44}; image.png

单步运行: image.png

单步运行: image.png

单步运行: image.png

image.png

单步运行: image.png

单步运行: image.png

单步运行: image.png

单步运行: image.png

单步运行: image.png

单步运行: image.png

由于之前的 0x44332211 已经写入,并且程序复位起来后仍然存在,在再次写入时会影响代码的跟踪和判断,因此我们先给它写入其它区别于 0x44332211 的值。

直接在 memory 窗口中的 0x10000500 地址中写入 0xaaaaaaaa: image.png

然后再激活反汇编窗口(使用鼠标在反汇编窗口中单击一下),并单步运行,就可以看到0x44332211 被写入到地址为 0x10000500 的 CCM SRAM 中。

在这个工程中,对于 CCM SRAM 空间来说,属于第一次写入操作,如果存在“SRAM Write Error”问题,那么程序继续运行下去可能会运行不正常,因为一个全局变量拥有了异常的初始值。

如果之后程序跑飞并且客户开启了硬件看门狗,那么看门狗复位后程序才能正常运行(已经有了第一次写入动作,SRAM 状态机已经正常了)。 image.png

然后程序继续运行,一直运行到 Main();: image.png

我们可以看到,进入 main 函数后,之前压栈的数据是不会弹出的,在这个工程中 main 函数永远不会返回,因此对于处于此处栈空间的 32kbytes 地址段,即使存在“SRAM Write Error”问题,系统也能正常运行。

3.2. 实验二(Keil 工程):使用 Keil 工程进行实验 使用 STM32G474 开发板:Nucleo_G474RE

PC 端编译调试软件: Keil V5.40

使用的软件工程为:…\STM32Cube_FW_G4_V1.5.0\Projects\NUCLEO-G474RE\Examples\GPIO\GPIO_IOToggle

Keil startup code 运行情况,Keil 工程比 IAR 工程存在“SRAM Write Error”的风险要高一些,因为 Keil start up code 会先对带初值的全局变量赋初值,之后才是全局变量的清零操作。如果栈空间和这个带初值的全局变量的空间不在同一个 SRAM 区间(32kbytes 大小的空间),就会存在问题。

https://developer.arm.com/documentation/100748/0618/Embedded-Software-Development/Application-startup image.png

需要修改 main.c 代码如下: image.png

Keil 软件工程的跟踪:

*.map 文件部分内容:

Global Symbols image.png

在汇编窗口中跟踪代码运行,下图中程序从 reset 起来,刚开始运行: image.png

Keil 第一次对 SRAM 进行写入的动作发生在压栈的时候。压栈之前: image.png

压栈完成的状态: image.png!

之后继续跟踪代码: image.png

继续跟踪代码的运行: image.png

下来是进行 test 全局变量的加载: 如果这部分全局变量空间和栈空间不属于同一个 32Kbytes SRAM 空间,则在 SRAM 第一次写入如果出错,会造成代码运行问题。 image.png

image.png

继续跟踪代码,接下来是是包含对 test0 等的清零操作: image.png

很大的一块区域被清零: image.png

之后跳转到 main.c 中,之前压栈数据一直没有使用。在栈所处的 32Kbytes SRAM 空间,即使第一次 SRAM 写入出错,也不会有问题。

  1. 应用代码建议 对于有些客户,代码已经稳定并不再修改,也通过了测试;在产品应用上也能接受看门狗复位(硬件看门狗),可以不添加 workaround 部分提到的代码。

对于不想添加这部分代码的客户,又担心存在“SRAM Write Error”问题对系统造成影响;可以结合*.map 文件中全局变量在 SRAM 中的具体地址进行分析,并跟踪 starup code 代码的运行,看“SRAM Write Error”是否会对程序运行造成问题,如果没有问题,可以不添加 workaround 部分的代码。

对于安全性要求较高的应用,建议采用 ES0430 2.2.7 章节的 workaround 代码来提升系统的安全性。

对于使能了 Parity check 的 SRAM,不管有没有可能出现“SRAM Write Error”都建议在代码开头用软件初始化整个 SRAM 内存,以避免读取未初始化的位置时出现奇偶校验错误。 image.png

图6. 使能了 Parity check 的 SRAM 区,建议在程序运行开始处对整个 SRAM 区进行初始化

  1. 小结 根据客户的实际使用情况,可以选择是否使用 “SRAM Write Error” 的 workaround 代码。但对于安全性要求较高的应用,还是建议使用 SRAM 状态机恢复代码(ES0430 2.2.7 章节提到的workaround,或此文章的 2.1 章节),并对开启了 Parity check 的 SRAM 区在程序开始运行时进行初始化。 ————————————————

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/2501_92678806/article/details/149740096

image.png
image.png
收藏 评论0 发布时间:2025-8-11 14:29

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版