打印
[AT32F413]

F413中断重入错误【已解决】

[复制链接]
3482|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 muyichuan2012 于 2020-8-31 09:11 编辑

调试F413定时器遇到问题,程序只开了溢出中断,最开始每次溢出产生两次中断。

后来在中断函数退出前加 __DSB()指令可以恢复正常,或者在清中断标志后插入10条NOP指令也可以。

错误现象虽然消失,但问题的根源不清楚。 是CPU有BUG还是原本就是这样,这个解决办法是否可靠。

代码:
#define APP_TIM        TMR4
#define app_timer_isr  TMR4_GLOBAL_IRQHandler
#define APP_TIM_IRQn   TMR4_GLOBAL_IRQn

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  app timer init
  * @param  None
  * @retval None
  */
  
void app_timer_init(char pos)
{
    RCC_ClockType RCC_Clocks;
   
    RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_TMR4, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1PERIPH_TMR4, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1PERIPH_TMR4, DISABLE);
   
    APP_TIM->CTRL1 = TMR_CTRL1_UVERS;
    APP_TIM->CTRL2 = 0;
    APP_TIM->DIE = TMR_DIE_UEVIE;
    APP_TIM->STS = 0;
   
    /*1ms 中断*/
    RCC_GetClocksFreq(&RCC_Clocks);
    APP_TIM->DIV = RCC_Clocks.APB1CLK_Freq / 1000000-1;
    APP_TIM->AR = 2000-1;
   
    NVIC_SetPriority(APP_TIM_IRQn, 0x01);
    NVIC_ClearPendingIRQ(APP_TIM_IRQn);
    NVIC_EnableIRQ(APP_TIM_IRQn);
   
    APP_TIM->CTRL1 |= TMR_CTRL1_CNTEN;
}

OBJ_INIT_APP_EXPORT(app_timer_init);

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  app timer isr
  * @param  None
  * @retval None
  */
void app_timer_isr(void)
{
    if(APP_TIM->STS & TMR_STS_UEVIF)
    {
        sys_st.u_tick++;
    }
    else
    {
        sys_st.app_timer_err++;
    }
   
    APP_TIM->STS = 0;
   
    __DSB();
}


使用特权

评论回复
沙发
ArterySW| | 2020-8-26 16:55 | 只看该作者
应该是代码的问题,请再检查一下代码;或者可以用 BSP 所提供的库函数来操作,先单独验证一下你说的这个问题。

使用特权

评论回复
板凳
aple0807|  楼主 | 2020-8-26 19:06 | 只看该作者
ArterySW 发表于 2020-8-26 16:55
应该是代码的问题,请再检查一下代码;或者可以用 BSP 所提供的库函数来操作,先单独验证一下你说的这个问 ...

上面贴的代码是完整的,这个问题已经反复验证了,不是偶尔出现,是必然出现。去掉_DSB,可以看到中断里面的两个计数值是相同的。

使用特权

评论回复
地板
ArterySW| | 2020-8-27 10:00 | 只看该作者
aple0807 发表于 2020-8-26 19:06
上面贴的代码是完整的,这个问题已经反复验证了,不是偶尔出现,是必然出现。去掉_DSB,可以看到中断里面 ...

我试了下你的代码,你是不是把TMR的时钟搞错了?TMR的时钟是挂在APB1上面,但是如果APB1有分频的话,那么 TMR_CLK = APB1_CLK * 2
RCC章节时钟树框图有具体描述:


所以,修改下面的代码:
APP_TIM->DIV = RCC_Clocks.APB1CLK_Freq / 1000000-1;

APP_TIM->DIV = (RCC_Clocks.APB1CLK_Freq*2) / 1000000-1;
即可。

使用特权

评论回复
5
muyichuan2012| | 2020-8-27 11:41 | 只看该作者
感谢aple0807的反馈,目前我们已经复现了该问题,不过STM32F103也有该现象。
Anyway,等我们研发彻底理清后会给您一个满意的回复。

使用特权

评论回复
6
aple0807|  楼主 | 2020-8-27 13:05 | 只看该作者
ArterySW 发表于 2020-8-27 10:00
我试了下你的代码,你是不是把TMR的时钟搞错了?TMR的时钟是挂在APB1上面,但是如果APB1有分频的话,那么 ...

我的重载值是2000, 上面就不需要乘2了

使用特权

评论回复
7
七颗咖啡豆| | 2020-8-27 14:22 | 只看该作者
我可能知道答案。应该就是芯片BUG。
产生原因也清楚,也有解决方案,

使用特权

评论回复
8
七颗咖啡豆| | 2020-8-27 14:31 | 只看该作者
AT32没玩过。
APP_TIM->STS = 0;
这句是清除中断标志吧。
这句话并不能保证中断真正清除了,内核速度高于外设,不稍微延时一下,外设可能没反应过来,内核又检测到中断了。就出现了重复中断的现象
进入中断就立刻清标志位可以缓解。

使用特权

评论回复
9
七颗咖啡豆| | 2020-8-27 14:31 | 只看该作者
muyichuan2012 发表于 2020-8-27 11:41
感谢aple0807的反馈,目前我们已经复现了该问题,不过STM32F103也有该现象。
Anyway,等我们研发彻底理清后 ...

不用等了,我猜对了记得发红包

使用特权

评论回复
10
muyichuan2012| | 2020-8-27 15:34 | 只看该作者
七颗咖啡豆 发表于 2020-8-27 14:31
不用等了,我猜对了记得发红包

厉害,请问您是在什么芯片上发现的该问题?

使用特权

评论回复
11
aple0807|  楼主 | 2020-8-27 16:55 | 只看该作者
七颗咖啡豆 发表于 2020-8-27 14:31
AT32没玩过。
APP_TIM->STS = 0;
这句是清除中断标志吧。

我这个中断里原本只有两行,就是TST=0;u_ticks++;是先清的的中断,因为出了问题才加了这么多程序来判定问题的。不过你说的有道理,我也怀疑是流水线的问题,才试了试_DSB();

使用特权

评论回复
12
七颗咖啡豆| | 2020-8-27 17:11 | 只看该作者
muyichuan2012 发表于 2020-8-27 15:34
厉害,请问您是在什么芯片上发现的该问题?

STM32咯,

使用特权

评论回复
13
ArterySW| | 2020-8-27 17:58 | 只看该作者
这个问题实际上是由于外设与内核之间指令传递和执行所导致的,具体的原因可以参考下面keil所提供的资料,以及提供的三种解决方法:
https://www.keil.com/support/docs/3928.htm

使用特权

评论回复
14
muyichuan2012| | 2020-8-28 09:12 | 只看该作者
本帖最后由 muyichuan2012 于 2020-8-28 09:17 编辑

正如楼上所讲,ARM Keil也是确认到M3、 M4内核有该问题(如下图)。我们也实测了STM32F1xx,STM32F4xx的确存在该问题,看来的确是ARM内核的问题,芯片是没有问题的。
再次感谢aple0807提出该问题,以及七颗咖啡豆的精彩回答。


使用特权

评论回复
15
aple0807|  楼主 | 2020-8-29 09:50 | 只看该作者
多谢各位答疑解惑,找到原因就放心了

使用特权

评论回复
16
borrow1988| | 2020-9-2 10:55 | 只看该作者
ArterySW 发表于 2020-8-27 17:58
这个问题实际上是由于外设与内核之间指令传递和执行所导致的,具体的原因可以参考下面keil所提供的资料,以 ...

确实这样

使用特权

评论回复
17
自己的灌饼| | 2020-9-2 18:13 | 只看该作者
这篇**学习到了很多知识,谢谢楼主的推荐

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

77

主题

328

帖子

2

粉丝