头像-365595

384fae8e9da47178

个人成就

获得 0 次赞

帮助过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);  }}