记录一下这个bug,让后人避免这个bug。
这个bug复现很简单
首先需要一个开了o1优化的keil
然后需要一个绝对对不齐的结构体,并使用pack(1)
如果对齐了就无法触发了
然后你需要一个直接读取到fpu中的指令
你就需要一个形如这样的代码
float *fVoltage_line = &(sAdSample_GetL2BusVolt()->stAdcData.fRealValue);
float voltage= *fVoltage_line;
然后这段代码就会生成一段
0x080168C4 ED900A00 VLDR s0,[r0,#0x00]
就类似于这样
到这里,恭喜你,发现了一个稳定触发fpu的hardfault的方式
当然需要注意以下几点:
如果你么欸有代码优化或者先读到了r1里,那么就不会触发这个bug
或者你手动对齐了位置,比如添加了一个uint8_t 类似于这样:
那么就不会触发这个bug
添加最简短的稳定触发代码··············································
#include "gd32f30x.h" // Device header
#pragma pack(1)
typedef struct
{
uint8_t u8LostZero; // ?????
// uint8_t u8LostZerogroup[1]; // ?????
uint32_t Cnt; // ???
uint16_t u16RealVal; // ?????
float fRms; // ???
float fFreq; // ????????
float fRealValue; // ?????
float fSquareSum; // ???
} ADCCALC_AC;
#pragma pack()
ADCCALC_AC tRtADC[4];
float *p;
float ftest;
int main(void){
p=&(tRtADC[1].fRealValue);
float voltage =*p;
ftest=voltage*12;
while(1);
// return 0;
}
至于解决方案,,还是得等厂商修复。