... | ... | @@ -6,37 +6,59 @@ This page gives some quick information on how to use Interrupts with MIOSIX in S |
|
|
|
|
|
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.
|
|
|
|
|
|
To generate an interrupt on a GPIO rising/falling edge you will have configure the EXTI and SYSCFG->EXTICR registers as follows:
|
|
|
|
|
|
```cpp
|
|
|
// Clear the mask on the wanted line
|
|
|
EXTI->IMR |= EXTI_IMR_MR4;
|
|
|
|
|
|
// Trigger the interrupt on a falling edge
|
|
|
EXTI->FTSR |= EXTI_FTSR_TR4;
|
|
|
|
|
|
// Trigger the interrupt on a rising edge
|
|
|
// EXTI->RTSR |= EXTI_RTSR_TR0;
|
|
|
|
|
|
EXTI->PR |= EXTI_PR_PR4; // Reset pending register
|
|
|
|
|
|
// Assign the interrupt to a GPIO (in this case PC4)
|
|
|
SYSCFG->EXTICR[2] = 0x2;
|
|
|
```
|
|
|
|
|
|
Note that each interrupt line can be associated only to a pin ending with the same number: for example, `EXTI4` can be associated either to PA4 or PB4 or PC4 ecc... More details can be found in the SYSCFG section of the STM32 reference manual.
|
|
|
|
|
|
### 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.
|
|
|
After eneable the interrupt generation, you also have to enable the interrupt **handling** in 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);
|
|
|
// Enable the interrupt called EXTI4
|
|
|
NVIC_EnableIRQ(EXTI4_IRQn);
|
|
|
// Set its priority to 15
|
|
|
NVIC_SetPriority(EXTI15_10_IRQn, 15);
|
|
|
NVIC_SetPriority(EXTI4_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.
|
|
|
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 your separate .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()
|
|
|
// You need to define the IRQHandler you want to override as "naked".
|
|
|
// It must have the same name of the IRQHandler in the stage_1_boot file.
|
|
|
void __attribute__((naked)) EXTI4_IRQHandler()
|
|
|
{
|
|
|
saveContext();
|
|
|
asm volatile("bl _Z17CAN_IRQHandlerImplv");
|
|
|
// write the mangled name of the function that you want to call
|
|
|
// in the form: _Z<LENGTH_OF_FUNCTION_NAME><FUNCTION_NAME><ARGUMENTS('v'=void)>
|
|
|
asm volatile("bl _Z20EXTI4_IRQHandlerImplv");
|
|
|
restoreContext();
|
|
|
}
|
|
|
|
|
|
// This is the function executed. You will need to declare it as 'used'
|
|
|
void __attribute__((used)) CAN_IRQHandlerImpl()
|
|
|
// This is the function executed. It has to be declared as "used".
|
|
|
void __attribute__((used)) EXTI4_IRQHandlerImpl()
|
|
|
{
|
|
|
EXTI->PR |= EXTI_PR_PR4; // Always reset pending register!!!
|
|
|
// Write me!
|
|
|
}
|
|
|
``` |