打印

关于STM32中断多进的问题总结

[复制链接]
8976|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
luckytoad|  楼主 | 2010-7-16 12:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1、问题提出:如果你操作不当STM32的中断每次会进2次。
2、验证方法:如下面的1ms中断程序:
void TIM6_IRQHandler(void)                  //1ms
{
  ms_100_cntdbu++;
  if ((TIM6->SR & 0x0001) != 0)    // check interrupt source
  {                 
                ms_100_cnt++;
                   TIM6->SR &= ~(1<<0);                          // clear UIF flag        
   }
               
}
     你会看到  ms_100_cntdbu =2*  ms_100_cn
如果增加硬件管脚指示,从示波器上很容易看到1ms内中断近了2次,但1ms中断技术没问题,也就是说SR标志清掉了,SR中也没有其他标志置位,进中断是保存下来看。
     其他所有的中断都是这个问题。我验证了,不是仿真,是真运行。
3、解决方法:清中断标志,只要不是中断函数的最后一条语句就没问题了。
4、指令流水线问题。其他的片子有的也会有这问题。
5、结论:如果你对程序要求不严,可以不用管它,不会影响到你应用的。否则参照3.
如果你的习惯是先清中断后干活,你不会碰到这个问题。如果你使用的是库函数差标志,也不会碰到这个问题。
沙发
hgjinwei| | 2010-7-16 19:38 | 只看该作者
能否给个详细分析?

如果真有这事,那串口通信应该不能正常进行了,每次进两次,那岂不接收数据全乱了?

使用特权

评论回复
板凳
luckytoad|  楼主 | 2010-7-16 20:22 | 只看该作者
2# hgjinwei
你理解错了,进2次,但不影响应用的。第二次你查不到中断标志

使用特权

评论回复
地板
kevin_ares| | 2010-7-17 11:16 | 只看该作者
这问题我遇到过,

因为只开一种中断,就把检查标志代码省了,

结果搞出N多莫名其妙的错误,

使用特权

评论回复
5
香水城| | 2010-7-17 11:31 | 只看该作者
目前分析的初步结论是因为APB桥的延迟造成这个现象,还需进一步确认,我会不断更新。

使用特权

评论回复
6
lut1lut| | 2010-7-20 10:26 | 只看该作者
哇哇哇。。。

CPU从AHB的角度来看,数据已经写入(清零SR标志),实际上APB上的写操作需要由AHB2APB桥来管理,需要一定时间才能真正完成写操作(SR才能被清零)。那么当CPU退出中断ISR,此时SR还没有真正被清零,此时对应的pending bit仍旧置位,于是又一次触发了中断。

如何避免这个情况涅?
1)进入中断后,判断了相应标志位,就clear之,在作后续的处理。
2)如果你硬是要把清标志放在ISR最后,那么为了避免以上情况的发生,写完SR后,再读出来

哇哇哇。

使用特权

评论回复
7
shizaigaole| | 2010-7-20 10:38 | 只看该作者
顶 LS。
没想到AHB2APB桥延迟时间这么大。

这多少是一个小的缺陷。
知道了很容易绕过去,
不知道有可能会在一个大跟头

使用特权

评论回复
8
香水城| | 2010-7-21 10:02 | 只看该作者
查了一下公司的系统服务器,这个问题早在2008年已经以FAQ的形式解释过,并给出了分析和解决方法,我以前也没有注意到这个问题,这次有网友提出才去关注。

在ARM的系统架构下,这是一个普遍的问题,而不是STM32所特有的问题。

这个FAQ的内容如下:

Q: When I cleared the interrupt as the last instruction in the ISR,
the ISR code is called immediately upon exit half the time. Is there a
possibility of race condition ?

Answer:
The core (Cortex-M3) generates bufferable write transfer. This mean
that the CPU consider that the data is written from an AHB point of
view while the APB write transfer is managed by the AHB2APB bridge and
could be written later. In this case the CPU left the interrupt
routine while the interrupt is not yet cleared the CPU will re-enter  
again on the interrupt handler. To avoid this race condition :

1) ISR routine has to clear the interrupt  peripheral flag when just
entering in the routine to avoid interrupt missing.

2)ISR routine has to Implement a write to the APB  peripheral register
( to clear the peripheral flag) then followed by a read  access to the
same register/flag. This operation will force the write buffer to
complete the effective write and will stall the CPU until the
effective write of the bit in the register. Therefore  it is
independent from the AHB/APB ratio prescaler.
Here an example :

STR R1, [R0, #0] ; Store R1 register  peripheral   register  ( or
using bit-banding peripheral address)

LDR R2, [R0, #0] ; Load the peipheral register; This will  hold the
CPU until the effective write of R1.

Use Cortex-M3 Bit-banding feature for interrupt clearing since it is
an atomic operation and NVIC pending interrupts will be ignored during
this operation, however Read-Modify-Write is not.


ST网站的FAQ页面入口是:http://www.st.com/stonline/faq/user_faqbrowser.php
这几天这个页面出了点问题,正在检查维护,很快会恢复。

使用特权

评论回复
9
lwj006| | 2011-8-10 15:06 | 只看该作者
本帖最后由 lwj006 于 2011-8-10 15:22 编辑

这是一篇不错的帖子,今天我也遇到这个问题了。我遇到的显现这样子的:我用串口调试助手给m3发数据,此时m3是全速运行,然后m3接收到数据后,让它返回一个值,比如,0x55,结果在串口调试助手上接收到了两个0x55,奇怪啊;后来我单步调试,结果是正确的,只进入中断1次,也不明白为什么,看了此贴后我就把清除中断标志位从最后挪到了最前,结果还是进两次中断,后来我就把清中断放到了中间,可以啦!:lol,只进入一次中断。我后来按照6楼的方法改一下,也是可行的,多谢打家哦。

使用特权

评论回复
10
Chaos_zc| | 2011-8-10 16:03 | 只看该作者
该多一些这样的好贴!

使用特权

评论回复
11
phidia| | 2011-8-10 17:44 | 只看该作者
谢谢,学习了

使用特权

评论回复
12
styeven| | 2011-8-10 19:05 | 只看该作者
最好是把中断标志位清零放在每次执行玩中断服务函数的最后面。这样就可以保证一次中断,即使由于延迟产生的多次中断,服务函数也还是只调用一次。

使用特权

评论回复
13
dingwave_2000| | 2013-4-27 12:08 | 只看该作者
能不能给段例程出来,我怎么试都不行,还是进两次。
我的中断程序如下:
void USART1_IRQHandler(void)
{   
        uint16_t Counter0 = 0;
    uint16_t next = 0;
    uint8_t *buf;
        uint8_t RxBuffer[1200];

        OS_CPU_SR  cpu_sr;

    OS_ENTER_CRITICAL();                         /* Tell uC/OS-II that we are starting an ISR          */
    OSIntNesting++;
    OS_EXIT_CRITICAL();

        if(Counter1 == 0)
    {
            do
            {         
                        if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
                        {
                                       
                                        USART_ClearITPendingBit(USART1,USART_IT_RXNE);
                                        /* Read one byte from the receive data register */
                                    RxBuffer[Counter0] = USART_ReceiveData(USART1);                       
                                       
                                        if(Counter0<BufferSize1)
                                        {       
                                                Counter0++;
                                            next = 0;
                                        }
                        }
                        else
                        {
                            next++;
                        }       
            }while(next<85);
       
                if(Counter0>1)
            {
                        OS_ENTER_CRITICAL();

                        buf = Buffer1;
               
                        for(next = 0; next<Counter0; next++)
                        {
                            *(buf+next) = RxBuffer[next];
                        }
                        Counter1 = Counter0;
               
                        OS_EXIT_CRITICAL();
                               
                        OSSemPost(P_COM1_Event); //发送一次信号量  
                }
        }

    if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)==SET)//溢出
        {
                USART_ClearFlag(USART1,USART_FLAG_ORE);//读SR
                USART_ReceiveData(USART1); //读DR
        }

        OSIntExit();
}

使用特权

评论回复
14
dingwave_2000| | 2013-4-27 12:14 | 只看该作者
这个问题已经折磨我一个星期了,什么办法都试了,没用,望高手指点。。。。急急。。。。。。

使用特权

评论回复
15
tarzanfun| | 2015-8-31 20:12 | 只看该作者
N年前的帖子解决了我的问题,我在EXTI0中闪烁小灯一直没反映,串口输出才发现是两次中断,闪烁抵消了MD。果然清中断弄到第一句就OK了。

使用特权

评论回复
16
tarzanfun| | 2015-8-31 20:14 | 只看该作者
我去13楼在中断里操作OS。还大循环,本身就是个问题。

使用特权

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

本版积分规则

0

主题

72

帖子

2

粉丝