Interrupts is the must-known concept in embedded programming. So I wanna explain the interrupt management in ARM Cortex-M.
ARM architecture distinguishes between the two types: interrupt and system exception. Interrupts are primarily sourced by external hardware like UART that warns about arrival of data. System exceptions are more software-related and caused by ARM Cortex internal.
Interrupts and system exceptions are exchangeably used. But even if both of these do same thing (especially in programming), the differences are important for us, engineers!
I'll use "interrupt" word for both terms further, if otherwise declared.
Before diving into interrupts, you need to understand the general execution workflow of ARM Cortex. There are two types of execution modes: thread and interrupt. After resetting the microcontroller, execution flow starts in thread mode so that if you want to use interrupts, you need to enter the interrupt mode. But how?
When you flash your firmware into microcontroller (base address of 0x08000000, in case), ARM Cortex starts to execute the firmware's machine instructions in thread mode. If you want to use any interrupt, you have to explicitly say it to ARM Cortex by using Interrupt Service Routines (ISRs). ISRs are actually standard C functions, but have the special signatures. I'm gonna explain it later.
The most important question about interrupts is that why do we need interrupts?
The answer: Interrupts are the source of multiprogramming!
Interrupts give us second execution flow besides the main flow (executed in thread mode by default). It also gives the context switch mechanism for RTOS. I will explain it lastly.
ARM Cortex has a special hardware called Nested Vectored Interrupt Controller (NVIC). It handles and manages the all interrupt usage. Below is the its simple schematic:
Another important dedicated hardware is the EXTI Controller. The peripheral interrupts in the microcontroller directly are connected to NVIC. But If you want to use interrupts over microcontroller pins (like detecting rising or falling edge of a button), you have to use EXTI lines. Microcontroller pins are grouped and tied to specific EXTI lines. Please look at the reference manual to find it.
We have many different types of interrupts. For now, let's look at these:
ARM Cortex has defined 15 fixed system exceptions (coming from internal of Cortex). But microcontroller vendors specify also variable-length interrupts (coming from external of Cortex). For example, STM32 series microcontrollers allow up to 256 interrupts.
But where are located these interrupts? The answer is the at vector table.
The vector table is an array of word data inside the system
memory, each representing the starting address of one exception type [1].
If you've flashed any firmware into microcontroller over OpenOCD + GDB, you've seen probably the this vector table. If you've not, let's see it exactly.
I have STM32F446RE microcontroller and ST-LINK connection. I've compiled a firmware (firmware.elf) to flash it. Open a terminal and type:
$ openocd -f interface/stlink.cfg -f target/stm32f4x.cfg
And open the second terminal and type:
$ arm-none-eabi-gdb firmware.elf
Lastly, type these into GDB session:
(gdb) target remote localhost:3333
(gdb) monitor reset halt
(gdb) load
After flashed the firmware into microcontroller, you will see:
Loading section .isr_vector, size 0x1c4 lma 0x8000000
Loading section .text, size 0x1080 lma 0x80001d0
Loading section .rodata, size 0x10 lma 0x8001250
Loading section .init_array, size 0x4 lma 0x8001260
Loading section .fini_array, size 0x4 lma 0x8001264
Loading section .data, size 0x10 lma 0x8001268
Start address 0x80011d0, load size 4716
Transfer rate: 9 KB/sec, 786 bytes/write.
Yeah! You see the interrupt vector table (.isr_vector) section was flashed at the base address of flash memory and other sections after the vector table. If you use any type of interrupt, the ARM Cortex gets the corresponding ISR handler from there so that ARM Cortex exactly knows the ISR handler addresses. You just need to select the required ISR handler function!
As I said before, ISR handlers are special type of C functions. But why? Because the handlers have predefined function prototypes. You have to use these function prototypes. Otherwise, ARM Cortex cannot find it and treated as normal C functions, not the ISR handlers.
These predefined handler prototypes are stored in the startup code. For STM32F446RE, it is startup_stm32f446xx.S file. Below is a part of this startup code:
(...)
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
(...)
.word CAN1_TX_IRQHandler /* CAN1 TX */
.word CAN1_RX0_IRQHandler /* CAN1 RX0 */
.word CAN1_RX1_IRQHandler /* CAN1 RX1 */
.word CAN1_SCE_IRQHandler /* CAN1 SCE */
.word EXTI9_5_IRQHandler /* External Line[9:5]s */
.word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */
.word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */
.word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */
.word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
.word TIM2_IRQHandler /* TIM2 */
.word TIM3_IRQHandler /* TIM3 */
.word TIM4_IRQHandler /* TIM4 */
.word I2C1_EV_IRQHandler /* I2C1 Event */
.word I2C1_ER_IRQHandler /* I2C1 Error */
.word I2C2_EV_IRQHandler /* I2C2 Event */
.word I2C2_ER_IRQHandler /* I2C2 Error */
(...)
At the beginning, I've stated that interrupts are the source of multiprogramming. This is core logic behind the RTOS!
RTOSes use the interrupts to create many tasks. In classic firmware written with RTOS, there are many tasks that the RTOS kernel have to handle and manage. You can think that task in the firmware corresponds to process in the computers.
The RTOS kernel needs to execute these tasks in order and with same time-slice so that the kernel cuts the one task execution and passes to the next task execution using context switch_es. This is done by using interrupts. For example, FreeRTOS kernel uses _SVC and PendSV interrupts specificly to make the contex switch. Apart from that, the RTOS kernel uses also the SysTick interrupt to give the equal execution time to each task.
Got it. I've explain the interrupt management in ARM Cortex-M in general. I put the some references below. You can look at the interrupts and similar topics in there.
References:
[1]. Yiu J., The Definitive Guide to The ARM Cortex-M3, Second Edition, Newnes, page 36.
Noviello C., Mastering STM32, 0.26 Release, Leanpub
Top comments (0)