I am trying to implement the following pseudocode on a cortex-m3 controller, (STM32L151 in particular)
void SysTick_Handler() {
do_high_priority_periodic_tasks(); // not to be interrupted
lower_interrupt_priority();
do_low_priority_periodic_tasks(); // these may be interrupted
}
In other words, run the first part with priority level 0, then somehow lower the current interrupt priority to 15, so that the rest could be preempted by other hardware interrupts.
One idea is to move do_low_priority_periodic_tasks();
into a separate interrupt handler, and invoke this handler through NVIC_SetPendingIRQ()
which sets a pending bit in the NVIC->ISPR[]
register. This way, the other interrupt would immediately follow SysTick
, unless there is anything with priority between 0 and 14 pending.
#define LOWPRIO_IRQn 55
void IRQ55_Handler() {
do_low_priority_periodic_tasks(); // these may be interrupted
}
void SysTick_Handler() {
do_high_priority_periodic_tasks(); // not to be interrupted
NVIC_SetPendingIRQ(LOWPRIO_IRQ);
}
void main() {
HAL_Init();
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
HAL_NVIC_SetPriority(LOWPRIO_IRQn, 15, 0);
HAL_NVIC_EnableIRQ(LOWPRIO_IRQn);
while(1) {
/* main loop */
}
}
I've picked IRQ 55 because it's not occupied on my controller, it would be the AES interrupt handler on a STM32L162, but I'm a bit worried there. Should I pick a different IRQ instead, perhaps an unused DMA channel interrupt? Is it safe to use interrupts 57-67, which are defined in the Cortex-M3 core, but not on the STM32L series? Is there any better way to do it?
All the (non exception) interrupt priorities can be configured directly by writing to the NVIC (Nested Vectored Interrupt Controller) registers, which are part of the Cortex-M3 core.
In several operating systems—Linux, Unix, macOS, Microsoft Windows, z/OS, DESQview and some other operating systems used in the past—interrupt handlers are divided into two parts: the First-Level Interrupt Handler (FLIH) and the Second-Level Interrupt Handlers (SLIH).
Assigning different priorities to interrupt requests can be useful in trying to balance system throughput versus interrupt latency: some kinds of interrupts need to be responded to more quickly than others, but the amount of processing might not be large, so it makes sense to assign a higher priority to that kind of ...
The timer interrupt, critical to the functioning of the system, has the highest priority, while the printer driver (parallel port driver) has one of the lowest. There are certain exceptions to this rule, such as a serial port with limited on-board FIFOs that has an IPL of 7.
Is it safe to use interrupts 57-67, which are defined in the Cortex-M3 core, but not on the STM32L series?
No. Your NVIC may not actually implement them.
But the PendSV is exactly made for this task:
void SysTick_Handler() {
do_high_priority_periodic_tasks(); // not to be interrupted
// Set the PENDSVSET to trigger a PendSV exception
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
}
void PendSV_Handler() {
do_low_priority_periodic_tasks(); // these may be interrupted
}
See also this answer about PendSV.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With