STM32出现FLASH擦除失败异常现象分析及解决方法

目录

前言:

先说结论:

一、问题分析

二、异常排查

三、发现原因!

四、如果这篇文章能帮助到你,请点个赞鼓励一下吧ξ( ✿>◡❛)~


前言:

长颈鹿最近在使用STM32G070单片机进行项目开发,过程中遇到了一个很棘手的Bug,设备在调试中突然死机,仿真得知,原来是写FLASH操作失败,导致设备进入FLASH错误处理流程,陷入无限循环。好奇怪的现象,FLASH读写属于底层驱动,一般是不会有改动的,笔者也并没有动FLASH的相关代码,但莫名其妙出现这样的情况。决定刨根问底,探究一下深层次的原因。

先说结论:

出现该异常是因为FLASH擦除失败,从而导致FLASH写入操作失败,而FLASH擦除失败的原因在于类的构造函数位置问题,出于项目需要,长颈鹿把一个类定义在了文件作用域内,在这个类中一个类成员对象的构造函数中调用了HAL_TIM_PWM_Start() 函数,虽加上了static前缀,但其仍相当于一个全局变量,而系统中定义的全局变量会在main函数调用之前先被创建,对于类而言,被创建时会自动调用其构造函数,而我又在这个构造函数中调用了HAL_TIM_PWM_Start()函数,在所有外设初始化之前就操作了RCC寄存器(HAL_TIM_PWM_Start()会修改RCC寄存器,如RCC->APB1ENR使能TIM时钟),导致RCC寄存器的状态出现了异常,而FLASH操作要求系统时钟处于稳定且已知的状态,由此就产生了冲突,导致FLASH擦除失败,进而系统卡死。

所以如果你也遇到了类似的问题而又无从下手,可以检查一下代码中类的构造函数或者类中包含的成员类的构造函数,类定义的作用域有没有问题,构造函数中是不是有在外设初始化之前操作RCC寄存器的嫌疑!

这里的HAL_FLASH_Program()函数写入失败
导致程序进入Error_Handler()错误处理函数,陷入无限循环

一、问题分析

仿真发现,写FLASH失败是因为上一步擦除FLASH扇区出现了异常

擦除FLASH的操作调用了HAL库的HAL_FLASHEx_Erase(),在FLASH擦除函数中,调用了 FLASH_WaitForLastOperation() 函数来检测FLASH当前是否空闲,是否可对FLASH进行擦除和写入等操作,但是FLASH_WaitForLastOperation()函数在检测时,这个FLASH->SR中的FLASH_SR_CFGBSY位始终为1,导致函数超时退出。

FLASH->SR表示FLASH中的SR状态寄存器,FLASH_SR_CFGBSY 标志位是 SR 的状态位之一,该位表示FLASH当前是空闲,为 0 表示可执行擦除或写入操作。

FLASH->SR寄存器位

通过Watch窗口查看FLASH-SR的值,以及HAL库中定义的FLASH_SR_CFGBSY的值,两者都为0x00040000,对应上了,表示当前FLASH正处于忙状态。

二、异常排查

那么问题来了,这步的FLASH读写操作是程序对FLASH进行的首次操作,FLASH的状态怎么会是BUSY呢?况且STM32G070只有一个内核,程序只能顺序执行,对FLASH的操作一般都会等待FLASH状态回归正常才会结束,这个现象真的是非常奇怪。

是什么导致的呢?

长颈鹿一步一步的在项目中寻找,终于发现了端倪,造成FLASH擦除出错的原因竟然是一个通过定时器实现的呼吸灯!这个呼吸灯函数放在代码的开始部分,检查有无设备是否处于充电状态,如果处于充电状态,就开启呼吸灯。如果没有,设备正常开机。笔者将呼吸灯的源文件注释掉,代码编译后可以正常运行,将呼吸灯的源文件添加进项目中编译,即使不调用该函数,设备在进行FLASH擦除操作时也会卡死在这个地方。

但是定时器和FLASH,两个八竿子打不着的外设,为什么会互相影响?

而且只要参与编译,即使没有在程序中调用该函数,也会对FLASH造成影响。因此推测,影响很可能在编译阶段就已经发生,需要重点关注编译阶段的有关代码,宏定义,全局变量,以及全局变量类的构造函数!

果不其然,在呼吸灯的构造函数中发现了异常点。

CBreathingLight::CBreathingLight() { bDirction = DOWN; u32CCRVal = LEDS_CCR_VAL; u8ChargeState = CHARGE_OFF; /* 充电状态 */ vON(); /* 启动PWM输出 */ }

构造函数中的vON();函数会启动PWM输出,有操作定时器和调用系统时钟的行为,这个函数放在构造函数中,单独看没有问题,但是CBreathingLight类的对象定义在系统运行类CSystem中,而CSystem类的对象定义在文件作用域内!

#include "CSystem.h" static CSystem m_App; #if defined(__cplusplus) extern "C" { #endif void vInit(void) { m_App.bInit(); } void vRun(void* parameter) { m_App.vRun(0); } #if defined(__cplusplus) } #endif

三、发现原因!

CSystem类是一个全局变量,编译器会在编译时创建全局变量的对象,而针对类的全局变量,会自动调用其构造函数初始化类内成员,也就是说,CSystem类的构造函数会在main函数之前调用,而CBreathingLight类作为CSystem类的类内成员,其构造函数会在CSystem类的构造函数之前调用。

最终,在还没有进入main函数进行外设(GPIO、TIM等)初始化操作时,系统就通过构造函数执行了CBreathingLight类内的vON();函数,启动PWM输出,操作了定时器和系统时钟,虽然语法上没有问题,但这种行为是非法的,推测对后续的系统时钟造成了影响,继而导致FLASH擦除出现错误。

果然,去掉构造函数内调用的vON函数之后,系统恢复正常。

STM32的所有外设(包括TIM和FLASH)都依赖系统时钟配置(RCC寄存器),HAL_TIM_PWM_Start()会修改RCC寄存器(如RCC->APB1ENR使能TIM3时钟),FLASH操作要求系统时钟处于稳定且已知的状态,(如FLASH->CR中的LOCK位需清空),vON()修改了TIM3时钟配置(RCC),导致FLASH控制器误判为"正在配置中"所以出现了FLASH擦除失败的现象

四、如果这篇文章能帮助到你,请点个赞鼓励一下吧ξ( ✿>◡❛)~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1125675.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用keychron Launcher改 K3Max 的功能键

解决问题的关键是发现并描述清楚问题 买了一个 K3Max 有一个痛点,每次按 F12 打开浏览器控制台,需要 fnF12。用起来非常累 看别人描述“而在我的日常工作中,常用的是F1~F12,期望F1~F12功能键和多媒体功能键的位置互换…

RAG(检索增强生成)架构与原理:告别LLM“幻觉”的秘密武器

写在前面的话 RAG是什么?如果你还不清楚或是一知半解,不要紧,如果看完这篇文章,你还不会,算我输! 在人工智能飞速发展的今天,大型语言模型(LLM)以其强大的文本生成能力&a…

IEC-60958

IEC 60958 IEC 60958是一种传递数字音频的接口规范,相比I2S,IEC60958通过一根线同时传递时钟信号和数据信号。 IEC 60958在传输数据时使用双相符号编码(Biphase Mark Code),简称BMC,属于一种相位调制(phase modulation)的编码方法…

RAG分块完全指南:7种核心策略详解,让你的大模型效果翻倍

本文详解RAG系统中分块(Chunking)策略这一关键环节,解析了7种主流分块方法:固定大小、语义、递归、文档、智能体、句子和段落分块。文章指出不存在"万能"策略,建议从512 tokens搭配10-15%重叠率开始,通过调试参数优化&a…

(加交叉验证)基于GPR的数据多变量回归预测 (多输入单输出)

目录 1、代码简介 2、代码运行结果展示 3、代码获取 1、代码简介 基于高斯过程回归GPR的数据多变量回归预测 (多输入单输出)交叉验证 程序已经调试好,无需更改代码替换数据集即可运行!!!数据格式为excel! 本程序…

大模型在自动驾驶中的应用:从VLA到端到端技术全解析

文章介绍了大模型在自动驾驶领域的应用,重点解析了VLA(视觉-语言-动作)技术与端到端的关系,并阐述了两种VLA实现方案:两阶段(大模型Diffusion)和单阶段(纯大模型)。同时提…

专科生必看!8个降AI率工具,高效避坑指南

专科生必看!8个降AI率工具,高效避坑指南 AI降重工具:高效避坑的必备利器 随着人工智能技术的快速发展,越来越多的专科生在撰写论文时开始使用AI工具进行辅助。然而,AI生成的内容往往存在明显的“AI痕迹”,不…

JavaWeb相关环境安装

这篇博客我们讲一下JavaWeb相关得环境安装,用来后续完成前后端的项目部署。 1,JDK 1,下载安装包 下载安装包大家可以去官网进行下载,为了方便起见大家可以直接通过我提供的链接进行下载:JDK安装包,将下载后…

04|交付经理真正的 KPI 只有一个:可被接受的结果

在很多公司里,交付经理的 KPI 看起来非常“丰富”。 项目按期率里程碑完成率客户满意度验收通过率投诉数量 但如果你真的在一线做过交付,就会慢慢意识到一件事:这些 KPI,大多数只是“结果的影子”, 而不是交付真正被评…

小白也能学会!2024-2025年RAG系统高精度实现指南,企业级应用必备收藏

本文系统分析了企业级RAG系统面临的五大挑战,包括历史数据过时、文档分块破坏上下文、向量检索局限、图表理解瓶颈和流程缺乏灵活性。针对这些问题,文章提出了多种解决方案:选择合适的LLM和嵌入模型、建立评估体系、采用混合检索与重排序技术…

‌为什么供应商报价有13%和3%两种增值税?‌

为什么供应商报价有13%和3%两种增值税?‌ 13%税率‌:适用于‌一般纳税人‌销售‌货物、加工修理修配劳务、有形动产租赁‌等业务。例如:销售手机、电脑、机械设备、汽车配件、工业原材料等。 3%征收率‌:适用于‌小规模纳税人‌的…

参数高效微调三剑客:LoRA、MoLoRA与MoR1E的深度比较与应用指南

大模型微调的技术演进 在大型语言模型(LLM)时代,全参数微调(Full Fine-tuning)面临三大挑战: 计算资源消耗:微调百亿参数模型需昂贵GPU集群存储开销:每个下游任务需保存完整模型副本灾难性遗忘:微调可能损害模型原有…

of 的发音?弱读最常见/əv/

of 的发音取决于语境,常见有两种读法。 1️⃣ 最常见(弱读,口语 / 学术汇报里几乎都用这个) of → /əv/ 接近中文:“呃v / əv”(很轻) 例子: one of them → /wʌn əv em/ a l…

基于1D-CNN的数据多变量回归预测 (多输入单输出)

目录 1、代码简介 2、代码运行结果展示 3、代码获取 1、代码简介 基于一维卷积神经网络(1D-CNN)的数据多变量回归预测 (多输入单输出) 程序已经调试好,无需更改代码替换数据集即可运行!!!数据格式为excel! 本程序…

PyQt5 解决弹窗后快捷键失效问题

import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QMenuBar, QMenu, QAction, QMessageBox from PyQt5.QtCore import Qt, QEvent, QTimerclass MainWindow(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("菜单快捷键焦点保…

【必收藏】突破传统RAG瓶颈:Deep Thinking RAG架构详解与实战指南

Deep Thinking RAG是一种将RAG与Agent技术融合的新型架构,突破了传统RAG的局限性。它通过四个智能模块(规划代理、检索监督者、多阶段检索漏斗、策略代理)实现从线性链到循环图的跃迁,支持多跳推理、动态知识边界和自适应检索策略…

基于(SVM-RFE-BP)支持向量机递归特征消除特征选择算法结合BP神经网络多变量回归预测(多输入单输出)

目录 1、代码简介 2、代码运行结果展示 3、代码获取 1、代码简介 基于(SVM-RFE-BP)支持向量机递归特征消除特征选择算法结合BP神经网络多变量回归预测(多输入单输出) 采用SVM-RFE支持向量机递归特征消除特征选择对原始特征进行特征选择!随后在结合BP进行回归预…

若依工作流模型管理模块 - 需求分析+设计文档+接口文档

若依工作流模型管理模块 - 需求分析设计文档接口文档 一、需求分析 1. 核心业务背景 该模块是若依(RuoYi-Vue-Plus)框架集成Activiti工作流引擎的核心模块,聚焦流程模型全生命周期管理,解决从模型创建、编辑、部署到导出、转换…

[独家原创]CPO-VMD-KPCA-CPO-LSTM单变量时序预测 (单输入单输出) matlab代码

目录 1、代码简介 2、代码运行结果展示 3、代码获取 1、代码简介 [独家原创]CPO-VMD-KPCA-CPO-LSTM单变量时序预测 (单输入单输出) 基于冠豪猪算法优化变分模态分解-核主成分分析-冠豪猪算法-长短期记忆网络单变量时序预测 matlab代码 由于之前的图像分析太少,…

AI应用架构实战:上下文工程的数据预处理

AI应用架构实战:上下文工程的数据预处理——让模型“听懂”你的每一句话 关键词 上下文工程 | 数据预处理 | AI应用架构 | 对话系统 | 向量数据库 | 上下文窗口 | 语义分割 摘要 在AI应用(如对话系统、知识库问答、个性化推荐)中&#xf…