关于Gpt时基无缘无故被清0的问题
-
Gpt包含两个通道:
1 - 通道0:硬件IP为TMR-0;作为自由计数器使用;
2 - 通道1:硬件IP为TMR-1;作为50ms周期定时器使用;初始化:
// Gpt定时器配置,定时器时钟=50M)
Gpt_Init(&Gpt_Config);
Gpt_StartTimer(0, 0xffffffff); // 通道0:通用计数,不产生中断
Gpt_StartTimer(1, 50*50000U); // 通道1:定时周期=50ms(定时器时钟=50M)
Gpt_EnableNotification(1); // 使能定时器中断Gpt1中断回调:
void Gpt_Tmr0Ch1Notification(void)
{
}Gpt0用于计数:
uint32 precise_us_time(uint8 mode, uint32* stime)
{
uint32 temp=0;
switch(mode){
case 0: // 开始
*stime = Gpt_GetTimeElapsed(0);
break;
case 1: // 停止
temp = Gpt_GetTimeElapsed(0);
if(temp >= *stime) temp = temp-*stime;
else temp = 0xffffffff-(*stime-temp);
temp = temp/50; // 1us(clk=50M)
break;
default:break;
}
return(temp);
}其它Gpt操作代码:通道1重启50ms定时
Gpt_StopTimer(1); // 停止计数
// 。。。
Gpt_StartTimer(1, 50*50000U); Gpt_EnableNotification(1);Gpt通道0计时:
uint32_t debug_time[5];
precise_us_time(0, &debug_time[0]);
。。。。
debug_time[1]=precise_us_time(1,&debug_time[0]);
if(debug_time[1]>debug_time[2]) debug_time[2]=debug_time[1];怪异现象:
Gpt0计时部分的代码理论时间不会超过10000us,但连续测试时,会偶发的出现一个极大数,跟踪发现:此现象均出现在结束点计数器值<起始点计数器值:如
这里的[1]为计算得到的代码时间开销,单位us。很明显出现85s是不对的。
[3]: 起始点时基滴答值,单位1/50us
[4]:结束点时基滴答值,单位1/50usIDE调试器肉眼观察看,[3]在未走到0xffffffff时,就自动从0重新计数了。
这种现象属于偶发现象;测试1小时可能会出现一两次,绝大部分时间都正常。
如果的确属于芯片问题或驱动问题,那就是及其严重的问题了。Gpt0还好毕竟只是内测使用;但如果Gpt1也存在这种问题,后果就非常严重了。
-
zyq case 1: // 停止
temp = Gpt_GetTimeElapsed(0);
if(temp >= *stime) temp = temp-*stime;
else temp = 0xffffffff-(*stime-temp);
temp = temp/50; // 1us(clk=50M)// 测试//////////////////////////// Gpt_StopTimer(1); // 停止计数 Gpt_StartTimer(1, 50*50000U); Gpt_EnableNotification(1); if(temp>20000){ debug_time[3] = *stime; debug_time[4] = Gpt_GetTimeElapsed(0); } /////////////////////////////////////
-
zyq 感谢回复. 梳理一下完整测试过程:
1 - gpt(0)为TMR0_1, 配置为自由计数器;
2 - gpt(1)为TMR0_2,配置为50ms中断定时器;
3 - 其它模块包括uart,can,fls,pwm,也包括几个os(threadx)线程;
4 - 测试环境: 以上位机作为软件模拟器, 模拟现场工况发送can,uart报文给32B1H;
5 - Gpt操作api见一楼, 为工程检索Gpt_关键词得到的所有代码;
6 - 以Gpt(0)对一段代码进行时间开销计算, 基本50ms会计算一次, 最大时间开销应<20ms
7 - 计时错误频率大致为一小时会捕捉到两三次;最初没留意; IDE观察到后尝试修改代码,无果;目前的测试:
1 - gpt(0)改为pTMR0_1;
2 - gpt(1)改为pTMR0_2;
3 - 代码不做任何改动;
4 - 连续测试2个小时, 之前的问题不再出现.结论: 怀疑是TMR有问题.
-
由于TMR模块的4个通道共用一个中断向量,当进入TMR0-2的中断时,如果TMR0-1的中断标志被置起,可能会导致代码误判。建议尝试将TMR的中断服务函数修改为以下代码,观察问题是否得到改善。
GPT_FUNC void Gpt_Lld_Tmr_ChannelIrqProcess(uint8 Instance) { SchM_Enter_Gpt_GPT_EXCLUSIVE_AREA_19(); /* Check which channel triggered the interrupt */ uint32 IntFlag; uint32 Channel = TMR_CHANNEL_COUNT; TMR_Type const volatile * Base = Tmr_Lld_Base[Instance]; for(uint32 ChannelId = 0; ChannelId < TMR_CHANNEL_COUNT; ++ChannelId) { IntFlag = TMR_REG_ADDR32_READ(TMR_BASE_ADDR32[Instance] + TMR_CH_INT_OFFSET32(ChannelId)); if ((1U == IntFlag) && (1U == (((Base->CH[ChannelId].CTRL) & TMR_CH_CTRL_CHIE_MASK) >> TMR_CH_CTRL_CHIE_SHIFT))) { Channel = ChannelId; break; } } if(Channel != TMR_CHANNEL_COUNT) { /* when one-shot mode, stop timer and transter channel state to expired */ if (TMR_CH_MODE_ONESHOT == Tmr_ChannelInfo[Instance][Channel].CountMode) { /* stop timer */ TMR_REG_ADDR32_CLEAR_BITS(TMR_BASE_ADDR32[Instance] + TMR_CH_CTRL_OFFSET32(Channel), TMR_CH_CTRL_CHEN_MASK); Tmr_ChannelInfo[Instance][Channel].State = TMR_CHANNEL_STATE_EXPIRED; } /* when continuous mode, update Stop time stamp and CMP register value */ else { Gpt_Lld_Tmr_IrqCmpUpdate(Instance, Channel); } /* Clear flag */ TMR_REG_ADDR32_SET_BITS(TMR_BASE_ADDR32[Instance] + TMR_CH_INT_OFFSET32(Channel), TMR_CH_INT_CHIF_MASK); SchM_Exit_Gpt_GPT_EXCLUSIVE_AREA_19(); /* Call Notifacation function */ if (TRUE == Tmr_ChannelInfo[Instance][Channel].IsNotificationEnabled) { if (NULL_PTR != Tmr_ChannelInfo[Instance][Channel].NotificationPtr) { Tmr_ChannelInfo[Instance][Channel].NotificationPtr(); } } } else { SchM_Exit_Gpt_GPT_EXCLUSIVE_AREA_19(); } }
如果问题仍未解决,需要进一步排查。建议先排查TMR计数是否正常,确认是TMR计数受到了干扰,还是计算逻辑中存在未考虑到的情况。
也可以将工程文件发出来我测试看看。 -
E Enwei 将这个主题转为问答主题,在
-
E Enwei 将这个主题标记为已解决,在
发帖前请查看
帮助没办法联网的电脑使用YCT
帮助改进和优化YT CONFIG TOOL,有机会抽取YTM32B1ME0 EVB哦...