我有一个工程,功能很简单,定义了两个中断:
一个40us的定时器中断,目前没有重定义rtiNotification函数,库中自带week函数;
另一个是500us的het pwm中断,重定义pwmNotification函数,在此函数中调用一个算法函数ArthmetricTask();
还定义了两个结构体,fcrParamDef fcrCtrlParamStu,fcrCtrlParamStu结构体作为参数传递进函数使用,没有想到,程序执行完计算后,这个结构体的内容被篡改了。
更诡异的是,这个结构体的第一个元素的值变成了ExcUIPIDCtrlStu这个结构体的地址,
有MAP文件为证:
void pwmNotification(hetBASE_t * hetREG,uint32 pwm, uint32 notification)
{
/* enter user code between the USER CODE BEGIN and USER CODE END. */
/* USER CODE BEGIN (35) */
if((pwm == 1U) && (notification == pwmEND_OF_PERIOD))
{
ArthmetricTask();
}
fcrCtrlParamStu2.f32IfKB = 1.0;
/********************/
/* USER CODE END */
}
void ArthmetricTask(void)
{
float32_t f32DataU=0.0F,f32DataI=0.0F;
float32_t f32DataU2=0.0F,f32DataI2=0.0F;
uint8_t u8norDataCnt=0U;
float32_t f32three_vec_sum=0.0f;
ExcAdjustPID(0,0,0,0,&ExcUIPIDCtrlStu,&fcrCtrlParamStu);
}
void ExcAdjustPID(uint32_t u32Exc_on_cmd,float32_t f32Ug_rel,float32_t f32If_rel,fcrCtrlDef *fcrCtrl,ExcPIDCtrlDef *ExcUIPIDCtrl,fcrParamDef *fcrCtrlParam)
{
float32_t f32Result=0.0F,f32DataTemp=0.0F;
float32_t f32IfLb1=0.0F,f32IfLb2=0.0F,f32IfLb=0.0F;
float32_t f32avr_uc=0.0F,f32AvrUcTmp=0.0F;
float32_t f32Va2=0.0F;
f32Result = DealteU_DeltaT_Reset(f32Ug_rel,f32If_rel,fcrCtrlParam->f32If_up_limit,&IIR1_Deltau_tStu,&IIR1_Deltau_tParamStu);
}
ToffDef ToffDeltau_tStu={
.u32TmrNum=6000U,
.u32Delay=0U,
.u32Out=0U
};
ExcPIDCtrlDef ExcUIPIDCtrlStu={
.f32avr_setp = 1.0F,
.f32If_ExiSetp_en = 0U,
.u32navr_avr_uc_sel=0U,
};
float32_t DealteU_DeltaT_Reset(float32_t f32Ug_rel,float32_t f32If_rel,float32_t f32up_limt,IIRFormIIDef *iirInfor,IIR1ParamDef *iir1Param)
{
uint32_t u32CtrlBit=0U;
float32_t f32uplim=0.0F;
float32_t f32Res=0.0F;
Filter_IIR1_FormII(f32Ug_rel,iirInfor,iir1Param);
if(iirInfor->f32Result < -0.5F)
{
u32CtrlBit = bTrue;
}
Toff(u32CtrlBit,&ToffDeltau_tStu);
if(ToffDeltau_tStu.u32Out == bTrue)
{
f32uplim = 0.5F*f32up_limt;
}
else
{
f32uplim = 1.5F*f32up_limt;
}
f32Res = f32If_rel;
if(f32Res > f32uplim)
{
f32Res = f32uplim;
}
if(f32Res < -1000.0F)
{
f32Res = -1000.0F;
}
return f32Res;
}
void Toff(uint32_t u32In,ToffDef *ToffInfor)
{
uint32_t u32Temp=0U;
if(u32In == 0U)
{
ToffInfor->u32Delay++;
}
else
{
ToffInfor->u32Delay = 0U;
}
if(ToffInfor->u32Delay >= 65530U)
{
ToffInfor->u32Delay = 65530U;
}
if(ToffInfor->u32Delay > ToffInfor->u32TmrNum)
{
u32Temp = bTrue;
}
ToffInfor->u32Out = ~u32Temp;
}
主函数
uint32_t u32system_start_flg=0U;
/* USER CODE END */
int main(void)
{
/* USER CODE BEGIN (3) */
hetInit();
rtiInit(); /*compare1 40us*/
rtiEnableNotification(rtiNOTIFICATION_COMPARE1);
rtiStartCounter(rtiCOUNTER_BLOCK1);
_enable_interrupt_();
u32system_start_flg = bTrue;
while(1)
{
}
/* USER CODE END */
return 0;
}
/¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥/
最奇怪的是,如果我注释掉main函数中的定时器的初始化,或者将rti的中断改为compare0,程序功能就会恢复正常
(1)第一种恢复正常的修改
(2)第二种恢复正常的修改
求大神指点,我一度怀疑是不是这个CPU的compare1有bug
这是完整工程的压缩包
您好,
已经收到了您的案例,调查需要些时间,感谢您的耐心等待。
请问测试结果如何了?
从现象看,很像是定时器中断嵌套了pwm中断,现场保护有问题,出栈的时候把08001500的地址弹出到了变量fcrCtrlParamStu的第一个元素,我尝试在程序中增加或删减变量,使得变量ExcUIPIDCtrlStu的地址发生改变,发现函数执行后,fcrCtrlParamStu的第一个元素的地址仍然是ExcUIPIDCtrlStu改变后的地址。
首先、我对拖延的反应表示歉意。 今天我做了代码调试。
更诡异的是,这个结构体的第一个元素的值变成了ExcUIPIDCtrlStu这个结构体的地址,
关于此问题、我保留了一个硬件观察点来确定写入 u32block_flg 的位置:
After keeping this hardware watchpoint i found where exactly we are writing into this variable:
造成问题的代码中的上述突出显示行实际上在此函数的首次调用中没有发生这种情况。
iirInfor 结构包含前几个调用的其他地址、但在多次调用后会将其地址分配为"fcrCtrlParamStu"。 我不知道具体发生的时间、因为我对您的代码没有完全的了解。
正如您在上面的案例中看到的、f32inPut 的十六进制值为0x08001500。
那么、这是在执行突出显示的行后移至 u32block_flg 变量的值。
这应该是我怀疑的代码问题。 请仔细验证代码、我们确切地说是在此处将 fcrCtrlParamStu 地址传递给 irInfor。