I have an STM32 system that works correctly most of the time but occasionally fails to service interrupts. I wonder if there is something I am missing in my understanding of the NVIC:
The system is built around FreeRTOS and uses, among other things, three USART’s and a real time clock. The RTC produces a one second tick on GPIO input E1 which is configured to generate the EXTI1 interrupt. I have proved that the system sometimes misses this interrupt, and I suspect that it sometimes also misses USART interrupts:
The EXTI1 interrupt service routine simply gives an RTOS semaphore:
One of the FreeRTOS tasks waits for this semaphore, but times out if it is not received within 1.02 seconds:
This should obviously never fail, but occasionally it does.
If I run the system through a debugger (OpenOCD) and pause it at random times I often see that the EXTIPR and the NVIC ISPR registers both indicate that the EXTI1 interrupt is pending. I would expect any pending interrupt to be handled immediately and cleared by the ISR. The only reason I can imagine why this is not happening is if the interrupt is disabled.
As far as I can see the only mechanism for disabling interrupts is to set BASEPRI to a value numerically lower than the priority of the interrupt. SCB AIRCR PRIGROUP is set to 3 (i.e. 16 group priority levels, no sub-priorities) and the NVIC IPR for EXTI is set to 0x50. In FreeRTOSconfig.h the value for configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 0x30.
According to my understanding FreeRTOS sets BASEPRI to configMAX_SYSCALL_INTERRUPT_PRIORITY when it is executing a task that can’t be interrupted and 0 at all other times. I don’t believe that I can monitor BASEPRI directly. However, I think FreeRTOS copies it to pxCurrentTCB->uxBasePriority, and whenever I pause the debugger this reads 0.
Can anyone give any suggestions why the interrupts are failing?