|
|
Interrupts are hardware signals that can be handled by the software. They can be generated by different events, such as exceptions, timer counter overflows, incoming messages on a bus, GPIO level change etc... These events generate Interrupt REQuests (IRQ), which are managed in the software by defining a corresponding IRQHandler() function.
|
|
|
|
|
|
This page gives some quick information on how to use Interrupts with MIOSIX in STM32 boards.
|
|
|
|
|
|
### Step 1: Enable IRQ Generation
|
|
|
|
|
|
Some Interrupts, called **unmaskable** interrupts, are enabled by default and are handled by the OS. Other interrupts have to be explicitly enabled by the software. In STM32 boards this typically means that you have to set a register of the peripheral you are using to tell it to generate an interrupt. For example, for TIMER peripherals in STM32 you ave to set the `DIER` register. You can find this kind of information is the microcontroller's datasheet.
|
|
|
|
|
|
### Step 2: Enable IRQ Handling
|
|
|
|
|
|
Before handling your interrupt, you also have to enable it the NVIC (Nested Vector Interrupt Controller), giving it a priority. More information on NVIC can be found on the datasheet.
|
|
|
|
|
|
```cpp
|
|
|
// Enable the interrupt called EXTI15_10
|
|
|
NVIC_EnableIRQ(EXTI15_10_IRQn);
|
|
|
// Set its priority to 15
|
|
|
NVIC_SetPriority(EXTI15_10_IRQn, 15);
|
|
|
```
|
|
|
|
|
|
### Step 3: Writing a IRQHandler
|
|
|
|
|
|
In the `core/stage_1_boot.cpp` file of your board (located in `miosix-kernel/miosix/arch/<ARCH>/<BOARD>/`) all the possible IRQHandlers are defined. They are all defined with `__attribute__((weak))`: this means that if you provide your own implementation of the same function in a .cpp file and compile it, the default one will be overridden by yours.
|
|
|
|
|
|
To do this you will have to write the following code, which contains some magic related to [GCC name mangling](https://en.wikipedia.org/wiki/Name_mangling), in a .cpp file.
|
|
|
|
|
|
```cpp
|
|
|
// You need to define the IRQHandler you want to override as naked
|
|
|
// and write the mangled name of the function that the handler will call
|
|
|
// in the form: _Z<NUM_OF_FOLLOWING_CHARS><NAME_OF_FUNCTION><ARGUMENTS or 'v'>
|
|
|
void __attribute__((naked)) CAN2_RX1_IRQHandler()
|
|
|
{
|
|
|
saveContext();
|
|
|
asm volatile("bl _Z17CAN_IRQHandlerImplv");
|
|
|
restoreContext();
|
|
|
}
|
|
|
|
|
|
// This is the function executed. You will need to declare it as 'used'
|
|
|
void __attribute__((used)) CAN_IRQHandlerImpl()
|
|
|
{
|
|
|
// Write me!
|
|
|
}
|
|
|
``` |