1、 2、芯片STM32F103C8T6。 3、程序意图:(1)用TIM4产生1ms定时,在其TIM4_IRQHandler()中计数并设置70ms、500ms等定时器标记。(2)在main()的死循环子函数中,每70ms,读取编码器数值并显示在LCD上;每500ms,读取ADC数值并显示在LCD上,同时为了方便观察,闪烁LED灯。 4、故障现象:刚开始运行,正常,LED灯闪正常;一阵子后,LED灯不闪,“死机”了。 5、用debug方式运行,复现“死机”后,按Stop,cpu模式为Handler,异常中断号为46(TIM4),程序在0000 125A到0000 12A6之间循环, 访问内存地址2000 0032到2000 0035。 查map文件,并正常运行时,单步跟踪,2000 0032到2000 0035 对应 g_10msOK到g_500msOK; 正常运行时,单步跟踪,0800 125A到0800 12A6,是while(1){}中判断g_10msOK到g_500msOK的地方。 猜测,Thread模式时,地址是0800 125A,切换到Handler模式后,地址是0000 125A。 说明,“死机”后,while(1){}中判断是否70ms、500ms的代码还一直在跑,只是70ms、500ms的标记一直为0,所以没有执行点灯。 死机后,在TIM4_IRQHandler()加断点,并不触发。为什么? |
使用STM32F103控制两步进电机同时进行不同的运动(软件指令驱动),与控制一个电机的不同之处在于哪里?
stm32f030定时器输入捕获异常
与HAL_ADC_Start_DMA相关的一个十分怪异的问题
L9663驱动开发
PWM+DMA分多次发送缺点明显,会造成脉冲不连续,有解决的办法吗。
flash的app区域有上一次的残留代码,会造成死机
STM32H723使用DMA方式实现定时器输入捕获只能执行一次?
求助佬们,STM32U083 进行外部计数只能计数8000多一点
STM32F103RCT6 马来西亚丝印,程序无法与PLC通信,请问是怎么回事,求解答
用stm32cubeide上传串口通信代码之后,st-link红灯一直亮,再想下载的时候显示Target no device found
[md]SV,PendSV,SysTick系统自动设置其使能且优先级为0s0。 我自己的代码,优先级组2,USART1为3s3,TIM4为0s3,EXTI9_5_IRQn为1s1,EXTI15_10_IRQn为1s1。 TIM4中断程序中,更新70ms变量标记;EXTI中断程序中,更新编码器数值;main中,读取70ms变量标记值和编码器数值。都只是变量读写,没有看出死锁。 死马当活马医,尝试把上面几个中断的优先级统一设为0s0,居然不死机了! 再试,优先级统一设为1s0,还是死机。 再试,我虽然USART1、EXTI设置有使能中断,但没插串口、没插编码器,不会有中断吧?打断点,确实没有USART1、EXTI的中断,只有TIM4中断在跑。 中断的优先级统一设为0s0不死机,设为1s0会死机,这是为什么呢?
另外,TIM4这边只是看中断出门了没。我还查看NVIC这边,看中断进门了没。如上,中断使能ISER0、中断活动IABR0都是对的,说明NVIC对TIM4中断,是允许进门的,并且正在响应处理(活动)中。
查看过,TIM4相关的寄存器,PSC, ARR控制频率的,没变化,CNT也在循环计数中。CR1使能计数器的,都正常中。DIER.UIE=1,允许更新中断的,而且状态SR.UIF=1,说明有计数到溢出产生更新,硬件把这个标志位置1了。以上说明,TIM4是正常计数,并产生了中断标记的。
sw.rar是我的代码工程压缩包,有7M多,怎么上传不了吗?
你可以借助断点看看是否落在那个Hardfault中断里了。
重点检查哪些地方涉及数组访问的,看看有无可能发生越界的情形,当然这也是常发生问题的地方。
再就是有无可能堆栈溢出了,尤其中断嵌套较多时。
再者,我也查看了中断向量表,TIM4是46号异常,对应向量表地址0000 00B8存放的入口地址是0800 3EAD,也就是TIM4_IRQHandler()的地址。说明向量表没有破坏。
根据《权威指南》说的,中断的活动状态寄存器IABR是硬件自动维护的,执行了ISR的第一条指令,活动状态置1,到ISR返回时,活动状态清0。我这里观察到活动状态为1,说明ISR没返回?但是单步跟踪,执行的是main()里面的while(1){}循环。这就怪了?
但是这里也有一个线索:死机后,stop,单步执行,执行代码地址是0000 125A;正常时,单步执行,执行代码地址是0800 125A。实际对应就是main()里面while(1){}判断70ms、500ms标志的代码。这部分代码应该是thread模式执行的,怎么到了handler模式?
1、供电和时钟目前看不是主因。因为我对软件做些改动的话,就不会出现死机。 2、在HardFault、MemManageFault、BusFault、UsageFault都加了断点,出现死机时,没有进入这些Fault,而且这些Fault的相关寄存器,也看起来是正常的。 3、我只用了TIM4和USART1这2个中断,而且TIM4优先级高。不应有嵌套的情况。
void TIM4_IRQHandler(void)
{
i70msCnt++;
if (i70msCnt == 70)
{
i70msCnt = 0;
g_70msOK = 1;
}
i500msCnt++;
if (i500msCnt == 500)
{
i500msCnt = 0;
g_500msOK = 1;
}
}
main()
{
while(1)
{
if (g_70msOK == 1)
{
g_70msOK = 0;
Timer_70ms_Proc();
}
if (g_500msOK == 1)
{
g_500msOK = 0;
Timer_500ms_Proc();
}
}
}
卧槽,这论坛,贴代码格式都很难,发压缩包又上不去。是程序猿论坛吗?
问题目前的小结: 1、死机时,TIM4相关寄存器正常,并置位了中断标记。NVIC允许TIM4中断进门,且表示TIM4正在处理中(活动状态置1)。 2、但是stop后单步跟踪,实际代码执行的是main() while(1){}的。这部分代码正常执行时是thread模式的,但现在是handler模式。 3、查看向量表,TIM4异常向量位置所放的地址就是TIM4_IRQHandler()地址,向量表没有被破坏。 4、所以,本应是执行TIM4_IRQHandler()的,怎么实际执行main() while(1){}?
[md]核心就是:死机后,stop并单步执行,看到是handler模式,且表示正在处理TIM4中断,中断向量表也没有被破坏,按理应执行TIM4_IRQHandler(),但执行代码实际对应的是main() while(1){},这是怎么回事啊?
[md]不用着急。
看看你到底开启了哪些中断,看看是否有在中断里需被使用的变量,因为中断优先级方面的原因导致变量信息的获取出现死锁。
比方,在中断A里调用B延时服务函数,B服务函数又需用到另一定时中断,可该定时中断优先级又低于A的,这时就会出现死锁。
还有,对于那些在中断和主程序里都使用的变量,记得加上volatile。