• 已解决 73482 个问题
  • 已帮助 5993 位优秀工程师

关于HAL库外部中断进两次中断服务的问题

384fae8e9da47178 2020-06-18 浏览量:692
最近一个应用里用到了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);
  }
}


显示全部
0 0 收起

我来回答

上传资料:
选择文件 文件大小不超过15M(格式支持:doc、ppt、xls、pdf、zip、rar、txt)
最佳答案
  • 自动清什么的,一般不太靠谱,在实际项目中使用的,一般都会手动再清一次,来保证清除成功
    • 发布于 2020-07-08
    • 举报
    • 评论 0
    • 0
    • 0

其他答案 数量:0

相关问题

问题达人换一批

关于HAL库外部中断进两次中断服务的问题