1050|3

2384

帖子

0

资源

纯净的硅(高级)

关于HAL库外部中断进两次中断服务的问题 [复制链接]

最近一个应用里用到了STM32F4的两个外部中断,但是最终结果一直不对,发现仿真是正确的,单独运行就不正确,多次调试后发现问题出现在中断上,中断服务函数进了两次,但是这个应用只允许进一次中断
在网上搜索到问题的原因

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.


知道了问题出现的原因是AHB2APB桥延迟,其中看到几条建议:
1)进入中断后,判断了相应标志位,就clear之,在作后续的处理
3、解决方法:清中断标志,只要不是中断函数的最后一条语句就没问题了。
当前这个情况下把程序下载到板子上运行的时候,按下按键,LED的状态会翻转两次,后来尝试改了一下软件生成的代码,将清中断标志位那条语句放到调用中断回调函数之后就可以了



程序原本的代码:


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{  
        if(GPIO_Pin == GPIO_PIN_8)
        {
                xxxxxxxxxxxxxxxxxxxxxxxxx;

        }
        else if(GPIO_Pin == GPIO_PIN_9)
        {
                xxxxxxxxxxxxxxxxxxxxxxxxx;
        }
}


原本的清标志是自动生成的


void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  /* EXTI line interrupt detected */
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
  {
        __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
       HAL_GPIO_EXTI_Callback(GPIO_Pin);
  }
}



按照建议,改成如下依旧无效果


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{  
       __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); 
        if(GPIO_Pin == GPIO_PIN_8)
        {
                xxxxxxxxxxxxxxxxxxxxxxxxx;

        }
        else if(GPIO_Pin == GPIO_PIN_9)
        {
                xxxxxxxxxxxxxxxxxxxxxxxxx;
        }
}

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  /* EXTI line interrupt detected */
      if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
      {
               __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
              HAL_GPIO_EXTI_Callback(GPIO_Pin);
             __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
     }
}
 

此帖出自stm32/stm8论坛

回复

3619

帖子

1

资源

版主

本帖最后由 damiaa 于 2020-6-18 15:57 编辑

按下按键

 这个一般不用EXIT中断。 因为按下一次其实会有下降沿 上升沿 还有中间的毛刺。产生几次正常。

 要解决好这个问题最好用定时中断(10毫米)。定时中断里面检测下降沿 上升沿 多测几次滤除毛刺。

定时中断里:

  {  
      static uint8_t  Key_IO_stats=0;
      static uint8_t  Key_IO_Oldstats=0;
      Key_IO_stats <<=1;
      if(Key_IO)
         Key_IO_stats +=1;
   }

 

你只需要在程序的某个地方检测Key_IO_stats 

这里还要记住上次的状态

如果是变为0xFF 那就是变高了

if((Key_IO_stats==0xff)&&(Key_IO_Oldstats==0))

{

   Key_IO_Oldstats=0xff;

}

如果是变为0 那就是变低了

if((Key_IO_stats==0)&&(Key_IO_Oldstats==0xff))

{

   Key_IO_Oldstats=0;

}

其他时候就是正在检测中(8次检测过滤 8次连续为1才为高,8次连续第才为低,其他的都不算。检测次数可以调整 )

 

 

点评

关键点在于,不能用这种方法,外部信号一来,必须让单片机触发操作  详情 回复 发表于 2020-6-19 09:01

回复

2384

帖子

0

资源

纯净的硅(高级)

damiaa 发表于 2020-6-18 15:34 按下按键  这个一般不用EXIT中断。 因为按下一次其实会有下降沿 上升沿 还有中间的毛刺。产生几次 ...

关键点在于,不能用这种方法,外部信号一来,必须让单片机触发操作


回复

3619

帖子

1

资源

版主

本帖最后由 damiaa 于 2020-6-19 10:42 编辑

嗯,如果不是按键的情况 有些是要用到中断。嗯 回调函数延迟时间可能长了点。清除中断函数最好改到中断函数里面最前面部分。HAL_GPIO_EXTI_Callback(GPIO_Pin);的前面。自动产生的软件是有问题。


回复
您需要登录后才可以回帖 登录 | 注册

最新文章 更多>>
    关闭
    站长推荐上一条 1/9 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2021 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表