STM32F429新芯片首次烧录程序后跑飞问题排查咨询
问题现象
新的STM32F429芯片首次烧录程序后出现死机跑飞现象,屏蔽部分无关代码后重新烧录恢复正常;还原原代码再次烧录也能正常运行。代码中使用了malloc且已正确释放,疑似栈空间问题但无法对应,仅首次烧录新芯片时出现该问题,后续多次烧录无异常。
已知信息:xMbHoldReg为Modbus全局变量,EEPROM底层驱动已验证可用。
相关代码
#include "bsp_all_define.h" #include "bsp_cms_i2c.h" #include "app_init.h" #define EEPROM_STATE_ADR 0X0000 #define EEPROM_DATA_START_ADR 0X0001 uint8_t EEPROM_used_val=0x01; typedef union { struct { uint16_t wData_L:8; uint16_t wData_H:8; }bBit; uint16_t nData; }UN_U16Data; typedef struct { UN_U16Data wAI_Filter; UN_U16Data wTemptureFilter_1; UN_U16Data wTemptureFilter_2; UN_U16Data wVoltageFilter; UN_U16Data wOCV_Filter; UN_U16Data wRCV_Filter; UN_U16Data wCurrentFilter; }S_eeprom_data; S_eeprom_data eeprom_data; S_eeprom_data eeprom_data_new; uint8_t EEPROM_state; /******************************************************************************* * Function Name : structToU8Array * Description : * Input : None * Output : None * Return : None ********************************************************************************/ void structToU8Array(void *data, uint8_t *array, int size) { uint8_t *ptr = (uint8_t *)data; for (int i = 0; i < size; i++) { array[i] = *(ptr + i); } } /******************************************************************************* * Function Name : U8ArrayTostruct * Description : * Input : None * Output : None * Return : None ********************************************************************************/ void U8ArrayTostruct(void *data, uint8_t *array, int size) { uint8_t *ptr = (uint8_t *)data; for (int i = 0; i < size; i++) { *(ptr + i)=array[i]; } } /******************************************************************************* * Function Name : Modbus_data_to_eeprom * Description : * Input : * Output : None * Return : None ********************************************************************************/ void Modbus_data_to_eeprom(void) { eeprom_data_new.wAI_Filter=xMbHoldReg.wAI_Filter; eeprom_data_new.wTemptureFilter_1=xMbHoldReg.wTemptureFilter_1; eeprom_data_new.wTemptureFilter_2=xMbHoldReg.wTemptureFilter_2; eeprom_data_new.wVoltageFilter=xMbHoldReg.wVoltageFilter; eeprom_data_new.wOCV_Filter=xMbHoldReg.wOCV_Filter; eeprom_data_new.wRCV_Filter=xMbHoldReg.wRCV_Filter; eeprom_data_new.wCurrentFilter=xMbHoldReg.wCurrentFilter; } /******************************************************************************* * Function Name : EEPROM_data_to_modbus * Description : * Input : * Output : None * Return : None ********************************************************************************/ void EEPROM_data_to_modbus(void) { xMbHoldReg.wAI_Filter=eeprom_data_new.wAI_Filter; xMbHoldReg.wTemptureFilter_1=eeprom_data_new.wTemptureFilter_1; xMbHoldReg.wTemptureFilter_2=eeprom_data_new.wTemptureFilter_2; xMbHoldReg.wVoltageFilter=eeprom_data_new.wVoltageFilter; xMbHoldReg.wOCV_Filter=eeprom_data_new.wOCV_Filter; xMbHoldReg.wRCV_Filter=eeprom_data_new.wRCV_Filter; xMbHoldReg.wCurrentFilter=eeprom_data_new.wCurrentFilter; } /******************************************************************************* * Function Name : EEPROM_data_init * Description : * Input : * Output : None * Return : None ********************************************************************************/ void EEPROM_data_init(void) { int size=sizeof(S_eeprom_data); EEPROM_Read(EEPROM_STATE_ADR,&EEPROM_state,1); if(EEPROM_state==0xFF||EEPROM_state!=EEPROM_used_val)//EEPROM未使用,设置默认参数 { eeprom_data_new.wAI_Filter.nData =50; eeprom_data_new.wTemptureFilter_1.nData=50; eeprom_data_new.wTemptureFilter_2.nData=50; eeprom_data_new.wVoltageFilter.nData=50; eeprom_data_new.wOCV_Filter.nData=50; eeprom_data_new.wRCV_Filter.nData=50; eeprom_data_new.wCurrentFilter.nData=50; EEPROM_write_buff(EEPROM_STATE_ADR,&EEPROM_used_val,0x01); EEPROM_data_to_modbus(); } else { uint8_t* data=malloc(size); EEPROM_Read(EEPROM_DATA_START_ADR,data,size); U8ArrayTostruct(&eeprom_data,data,size); U8ArrayTostruct(&eeprom_data_new ,data,size); EEPROM_data_to_modbus(); free(data); } } /******************************************************************************* * Function Name : Data_changed_save * Description : * Input : None * Output : None * Return : None ********************************************************************************/ void Data_changed_save(void) { Modbus_data_to_eeprom(); if(memcmp(&eeprom_data, &eeprom_data_new, sizeof(S_eeprom_data)) != 0) { int size=sizeof(S_eeprom_data); uint8_t* data=malloc(size); structToU8Array(&eeprom_data_new,data,size); EEPROM_write_buff(EEPROM_DATA_START_ADR,data,size); free(data); eeprom_data=eeprom_data_new; } } // void Task_dataThread(void* pArg); /******************************************************************************* * Function Name : Task_dataInit * Description : * Input : None * Output : None * Return : None ********************************************************************************/ void Task_dataInit(void) { g_xSysVar.dataThread.id = setThreadStart(Task_dataThread, 1024); } /******************************************************************************* * Function Name : Task_dataThread * Description : 数据更新线程 * Input : None * Output : None * Return : None ********************************************************************************/ void Task_dataThread(void* pArg) { EEPROM_data_init(); while(1) { Data_changed_save(); g_xSysVar.dataThread.nsignal++; osThreadYield(); osDelay(100); } }
排查建议
- 全局变量未初始化问题:全局变量
eeprom_data未显式初始化,若首次上电时进入EEPROM_data_init的else分支(比如EEPROM初始值意外匹配EEPROM_used_val),memcmp会对比未初始化的随机内存值,触发不可预期的操作。建议给eeprom_data和eeprom_data_new添加显式初始化,比如定义时赋值= {0}。 - 堆初始化时机问题:首次上电时,堆内存可能未完成初始化就调用
malloc,导致分配失败返回NULL,后续对NULL指针的读写直接引发硬件错误。可在系统初始化阶段先执行堆初始化,或者替换malloc为静态数组(如uint8_t data[sizeof(S_eeprom_data)]),避免动态内存分配的不确定性。 - 栈空间溢出风险:当前线程栈设置为1024字节,首次上电时可能因系统初始化叠加线程操作导致栈空间不足。尝试增大
Task_dataThread的栈空间(如调整为2048字节),同时开启编译器的栈溢出检测选项,捕捉潜在的越界问题。 - EEPROM首次读写时序问题:新芯片的EEPROM首次上电可能存在时序不稳定,虽然驱动验证可用,但首次烧录时系统初始化速度与后续不同,可能导致读写异常破坏内存数据。建议在
EEPROM_data_init开头添加短暂延时,或在系统初始化完成后再启动数据线程,确保外设稳定就绪。 - 结构体对齐与编译器优化问题:
UN_U16Data的位域定义可能导致结构体对齐异常,读写EEPROM时出现字节错位;同时编译器激进优化可能触发未定义行为。建议给S_eeprom_data添加__attribute__((packed))强制无对齐,或降低编译器优化等级(改用-O1或-O0),观察问题是否复现。
内容的提问来源于stack exchange,提问作者zhicheng SONG
相关产品推荐
相关产品推荐

