0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

实战经验 | 一个 Flash 编程错误标志的探析

STM32单片机 来源:未知 2023-11-10 17:45 次阅读


关键词:Flash, 编程错误


目录预览

1、问题现象与分析

2、小结

3、后记


01

问题现象与分析


客户项目中使用的 MCU 型号是 STM32G0B1, 他们反馈在代码中尝试擦除并编程 FLASH时, 发现 FLASH 的状态寄存器显示编程错误(如图 1 所示). 问题是当前代码还没有开始擦除和编程, 怎么就有了编程错误标志了呢 ? 如果不将此错误标志清除, 后续的编程操作无法继续.客户对于每次想要操作 FLASH 之前这个清除动作既感觉多余也感觉别扭, 且还不得不做, 且做了也不知对整个产品的稳定性会有什么样的影响 ?


图1.Flash 编程错误标志


访问客户时, 客户也曾私下里反馈, 经常在网络论坛上获取类似这种问题, 客户怀疑是不是STM32 本身就存在某些未曾公开的问题 ? 其实, STM32 的所有问题都已公开在勘误手册中, 如果客户的问题在勘误手册中没找到, 那么极有可能是自己代码哪里出了问题。


问题分析及测试


查看客户的工程, 由于客户的工程相当庞大, 各个模块和任务相互交叉, 一时半刻是很难从如此庞大的工程中找出问题, 更麻烦地是, 客户的电脑是有加密系统的, 导致在工程内查找任何字符和函数都相当痛苦. 好在是, 问题能够稳定地复现。


于是尽量精简客户的代码, 将所有不相关的任务,模块统统移除掉, 并且保持问题能够重现. 并使其能够在 ST 官方的 NUCLEO 板上重现. 这样一来, 就完全可以脱离客户原来的硬件环境进行测试. 由于客户的环境非常不利于查找问题, 效率事倍功半. 于是, 将客户的最小化工程提取出来(与软件泄密无关), 并拿到办公室进行测试. 很快就找到了问题所在。


原来客户的工程中有用到两个串口, 串口 2 和串口 3, 都是使用的 DMA 模式。客户不同的软件人员负责不同的模块, 最终在整合代码时, 串口 2 并没有使用, 所以串口 2 对应的初始化代码是删除掉的, 但由于串口 2 和串口 3 的 DMA 中断是共用一条中断线, 是相同的中断入口, 在中断处理时,串口 2 的 DMA 处理函数和串口 3 的处理函数都会一起处理. 问题就出在串口 2 的 DMA 中断处理并没有移除 。如 stm32g0xx_it.c 文件 :



如上图,DMA 的通道 4~7 以及 DAM2 的通道 1~5 都是共用一个中断入口的。在这个中断处理函数内, 串口 2 并没有使用到, 但其对应处理代码由于疏忽仍然保留了下来。句柄hdma_usart2_rx, 和 hdma_usart2_tx 内的数据成员很多都是不定内容或为 0. 当代码运行到函数内部, 如下图所示出问题的代码行:



如上面代码所示, 代码运行到上图 866 行代码 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU));时, 实际上是给错误地址 0x0800 4109 赋值了, 此地址是内部 FLASH 地址, 这样相当于直接写 FLASH, 肯定会出错, 这也是为什么FLASH->SR.PGSERR 置位的原因. 我们都知道, 写内部 FLASH, 必须先擦除, 才可以写入, 而且写也是调用对应的 HAL API 函数, 且还需要先写 key 解锁 FLASH 等操作, 有一套写操作流程. 并不是直接用赋值语句, 这样操作出现问题一点也不奇怪。


当在中断中将串口 2 的 DMA 对应处理函数移除掉后功能就恢复正常, 这也佐证了结论的准确性。


另外, 客户反映, 这个最小化工程, 相同的代码, 使用 IAR 时测试会出错, 但使用 KEIL 时并没有出错. 这个很奇怪. 这就引出的另外一个问题. 相同代码, 不同编译器运行结果不一致的问题。于是继续找原因, 对比 IAR 和 KEIL 的调试情况, 发现当代码运行到图 2 中 857 行代码 if 语句时其判断结果不相同. IAR 调试环境会进入到 if 语句内容, 从而导致错误的给内部 FLASH 地址赋值, 进行导致问题. 而 KEIL 调试环境并没有进入到 if 语句内部, 因此并没有触发问题. 那么为什么if 语句的判断结果不一样呢?


为了方便并避免不同编译器对长语句的执行顺序的差异, 将这个 if 长语句拆开:



如上红色代码, 用它替换原来的 if 判断语句. 结果发现 tmp1 在 IAR 和 KEIL 两个编译器环境中的值是一样的, 但是 tmp2 的值却不一样, 正是由于 tmp2 值的不一样, 导致 if 语句的最终判断结果不同。进一步发现, tmp2 的值主要是由于 flag_it 的值在两种编译器环境不一样所致。



如上 IAR 编译器环境, flag_it 的值为 0x2000 10f8。



如上 KEIL 编译器环境, flag_it 的值却是 0x2000 14F0。


那么 flag_it 的值又是如何来的呢? 从如下代码:



如上所示, flag_it 的值来自 hdma->DmaBaseAddress->ISR, 原来是 DMA 相关 ISR 寄存器的值, 但实际调试如下:



如上 IAR 调试环境下, 出错时, hdma->DmaBaseAddress 实际指向的是地址 0, 其成员 ISR为其第一个成员, 实际也就是地址 0 上的数据. 我们都知道, 在默认情况下, MCU 的地址 0 默认是映射到内部 FLASH 的首地址 0x0800 0000 上的, 而此地址一般保存的是栈顶.。也就是说, IAR 编译环境下, 地址 0 指向栈顶地址 0x2000 10f8。


对应地, 在 KEIL 调试环境下:



如上 KEIL 调试环境, hdma->DmaBaseAddress 同样地实际指向的是地址 0, 而地址 0 的上对应的数据为栈顶地址: 0x2000 14F0。


也就是说, 在不同的 编译器 IAR 和 KEIL 环境下, 地址 0 指向栈顶地址是未必相同的, 进而导致两种编译环境下运行相同的代码结果不一样。


我们知道, 通常栈地址是由编译器来指定的, 在默认情况下, IAR 和 KEIL 都会将栈放在内存的所有静态变量之后来分配. 其具体的分配地址这两个编译器都会默认按自动填充地方式来. 实际分配的地址具有不确定性, 当然, 我们也可以通过链接配置文件(IAR 的.icf 文件, KEIL 的.sct 文件)来将栈地址指定某一固定地址, 但我们通常不会这么做, 且完全没有必要.


02

小结


至此,将问题稍作小结。给变量 flag_it 实际赋值栈顶地址, 不同的编译器环境下, 此栈顶地址的不一致导致变量 flag_it 的值不一致, 进而导致 if 语句的判断结果不同, 最终导致 IAR 和 KEIL 这两个编译器环境下运行相同代码而结果不一样的情形。


03

后记


有时会听到某某客户反馈说, 在网络上看到 STM32 某款 MCU 存在某某问题, 然后问是不是 ST 故意隐瞒 ?


不存在故意隐瞒的说法,芯片终究是要经过终端验证的。


正常来讲, 任何芯片存在应用局限是正常的。对于 ST,一方面会正式地将所有已知 bug或应用局限放入到勘误手册中公示, 大家需要注意使用最新版勘误手册;另一方面,对于 ST 量产芯片,因本身缺陷导致的问题的概率非常低。事实上,绝大多数问题都来自我们自身的应用,遇到问题若简单的基于芯片品质来回猜疑非常不利于开发者静下心来查找问题原因。其实,面对问题时,我们很多人欠缺的并不是多么高深的水平,而是一颗冷静、自信并富有条理的心。



完整内容请点击“阅读原文”下载原文档。




原文标题:实战经验 | 一个 Flash 编程错误标志的探析

文章出处:【微信公众号:STM32单片机】欢迎添加关注!文章转载请注明出处。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6046

    文章

    44674

    浏览量

    640773
  • STM32
    +关注

    关注

    2275

    文章

    10939

    浏览量

    358871

原文标题:实战经验 | 一个 Flash 编程错误标志的探析

文章出处:【微信号:STM32_STM8_MCU,微信公众号:STM32单片机】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    相关推荐

    提升开关电源效率的理论分析与实战经验

    在这里有电源技术干货、电源行业发展趋势分析、最新电源产品介绍、众多电源达人与您分享电源技术经验,关注我们,与中国电源行业共成长! 提升开关电源效率的理论分析与实战经验 引言 开关电源设计中,为获得
    的头像 发表于 01-09 10:04 436次阅读
    提升开关电源效率的理论分析与<b class='flag-5'>实战经验</b>

    使用MCUXpresso for VS Code插件开发Zephyr的hello world

    本期来到Zephyr实战经验演练,小编带着大家起使用MCUXpresso for VS Code插件来开发属于Zephyr的hello world。
    的头像 发表于 01-03 09:21 717次阅读
    使用MCUXpresso for VS Code插件开发Zephyr的hello world

    EEPROM编程常见错误及解决方案

    EEPROM(电可擦可编程只读存储器)在编程过程中可能会遇到多种错误。以下是些常见的EEPROM编程
    的头像 发表于 12-16 17:08 2155次阅读

    C++新手容易犯的十编程错误

    简单的总结下 C++ 新手容易犯的编程错误,给新人们提供参考。 1 有些关键字在 cp
    的头像 发表于 11-15 12:42 583次阅读

    socket编程中的错误处理技巧

    Socket编程是网络编程的基础,它允许程序之间通过TCP/IP协议进行通信。然而,网络通信是不稳定的,可能会遇到各种问题,如网络延迟、连接中断、数据丢失等。 错误处理的重要性 提高程序的健壮性
    的头像 发表于 11-01 17:47 1055次阅读

    Keil uVision5 stm32跑马灯实验错误

    新人刚接触stm32,距离点亮LED灯编程只有步之遥了! 还得请教各位老师问题在哪, 对着《STM32库开发实战指南》示例已经修改了几次错误,还是存在
    发表于 10-18 18:17

    【全新课程资料】正点原子《基于GD32 ARM32单片机项目实战入门》培训课程资料上线!

    ,提高编程能力和实战经验 四、适合人群 (1)单片机编程初学者 (2)电子工程师 (3)对ARM32单片机有兴趣的技术爱好者 五、课程详细介绍 1、培训课程包含: (1)全套培训课程视频(已全部录制
    发表于 09-24 18:06

    文读懂CAN通讯错误

    CAN总线通信技术广泛应用于多个行业,是每个总线设计工程师必学的通讯网络。然而,对于CAN通信中的错误帧,许多人仅停留在表面了解,缺乏深入理解,这导致许多工程师在面对总线通信故障时感到无从下手
    的头像 发表于 06-12 08:24 2957次阅读
    <b class='flag-5'>一</b>文读懂CAN通讯<b class='flag-5'>错误</b>帧

    文读懂CAN控制器错误处理的原理

    “被动错误标志”。站检测到无论是位错误、填充错误、形式错误,还是应答错误,这个站会在下
    的头像 发表于 04-26 08:25 1761次阅读
    <b class='flag-5'>一</b>文读懂CAN控制器<b class='flag-5'>错误</b>处理的原理

    STM32L475VE内部Flash编程出现ECCD错误的原因?

    使用的芯片型号 STM32L475VE,使用 HAL 库 `HAL_FLASH_Program` API 对 内部 Flash 进行编程,出现 ECCD 错误。 返回
    发表于 04-26 07:21

    STM32L476先用仿真器擦除FLASH后在程序中写不成功怎么解决?

    STM32L476写FLASH必须是64位(8字节)写,也就是double WORD,而且要先把要写的字节部分擦除掉。 问题来了,先把整片用仿真器擦除掉,程序中先定义64位的静态变量常数
    发表于 03-28 08:44

    stm32g473 flash擦除失败的原因?

    flash在擦除的时候有需要注意的点没有注意到。 单步调试有时进入HAL_FLASHEx_Erase( EraseInitStruct,PAGEError),就会引起SR寄存器报下面的错误
    发表于 03-26 08:11

    STM32关于FLASH编程对齐错误标志位(PGAERR)的疑问求解

    大神们,我现在正在做一个应用,需要熟悉STM32F4的FLASH的任何错误标识,以用于特殊情况下的错误标识判断做相应处理,但是针对FLASH
    发表于 03-22 07:59

    STM32H5 DA证书链实战经验

    之前我们已经讲过了如何通过 DA 认证来回退芯片产品状态,或者重新打开调试口,这样开发人员在芯片为 Closed 状态下时仍可以调试芯片。
    的头像 发表于 03-12 14:08 1248次阅读
    STM32H5 DA证书链<b class='flag-5'>实战经验</b>

    介绍IC设计错误案例:可读debug寄存器错误跨时钟

    本文将介绍跨时钟错误的案例如图所示,phy_status作为多bit的phy_clk时钟域的信号,需要输入csr模块作为
    的头像 发表于 03-11 15:56 635次阅读
    介绍<b class='flag-5'>一</b><b class='flag-5'>个</b>IC设计<b class='flag-5'>错误</b>案例:可读debug寄存器<b class='flag-5'>错误</b>跨时钟