Get interrupt execution status on Cortex-M processors
You might come to a situation when you wanna know if current code is executing inside interrupt or not. This might be handy when you do a library and you have one function which you wanna call in interrupt handler for specific event or without interrupt handler, buf wanna execute something specific in function only if you are currently in interrupt. You can create 2 different functions of course, but what if you have one very big function, and for example when you are in interrupt, you wanna just do something small inside function somewhere at the middle?
Then you wanna know if you are executing code within interrupt or not. Cortex-M processors have special section SCB (System Control Block) inside. ICSR (Interrupt Control and State Register) register inside this section can be used to detect, if there is currently active any interrupt handler or not. Below is image of ICSR register for Cortex-M4 processor (Have in mind that all Cortex-M processors uses bottom 9 bits to detect proper interrupt number currently executing).
VECTACTIVE bits of ICSR register told us which interrupt is active, it’s value is as follow:
- 0: Interrupt is not active, we are in thread mode
- > 0: Interrupt is active, not in thread mode
So, the idea is to read this bits from register and if result is more than zero, we are currently executing from interrupt source.
Example
Bottom example runs on STM32F401-Nucleo board and shows principle how to check if current execution is inside interrupt or not. It calls the same function inside interrupt and in main function (thread mode).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
/** * Keil project example for detecting code execution inside interrupt * * Before you start, select your target, on the right of the "Load" button * * @author Tilen Majerle * @email tilen@majerle.eu * @website http://stm32f4-discovery.net * @ide Keil uVision 5 * @conf PLL parameters are set in "Options for Target" -> "C/C++" -> "Defines" * @packs STM32F4xx Keil packs version 2.4.0 or greater required * @stdperiph STM32F4xx Standard peripheral drivers version 1.5.0 or greater required */ /* Include core modules */ #include "stm32f4xx.h" /* Include my libraries here */ #include "defines.h" #include "tm_stm32f4_delay.h" #include "tm_stm32f4_disco.h" #include "tm_stm32f4_usart.h" /* Create function for checking */ void SendString(void) { /* Your function can do work here */ /* Check if we are called from interrupt */ if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) { /* We are called from interrupt */ TM_USART_Puts(USART2, "Called from interrupt\n"); } else { /* Normal call, no interrupt, thread mode */ TM_USART_Puts(USART2, "Normal call, no interrupt called\n"); } /* Your function can do work here */ } int main(void) { /* Initialize system */ SystemInit(); /* Initialize delay and 1ms interrupts */ TM_DELAY_Init(); /* Init USART2 on TX pin: PA2 at 921600 bauds */ TM_USART_Init(USART2, TM_USART_PinsPack_1, 921600); while (1) { /* Call function from thread mode every 500ms */ if (TM_DELAY_Time() >= 500) { /* Reset tune */ TM_DELAY_SetTime(0); /* Call function from thread mode */ SendString(); } } } /* Called when TM DELAY makes interrupts */ void TM_DELAY_1msHandler(void) { static uint32_t x; /* Call function from interrupt every 300ms */ if (++x >= 300) { x = 0; /* Call function from interrupt */ SendString(); } } |
Recent comments