简体   繁体   中英

Change priority level level of running interrupt handler?

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?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM