2016-11-22 58 views
5

Próbuję realizować następujące Pseudokod na kontrolerze cortex-m3 (STM32L151 w szczególności)Zmienianie poziomu priorytetu uruchomionej procedury obsługi przerwań?

void SysTick_Handler() { 
    do_high_priority_periodic_tasks(); // not to be interrupted 
    lower_interrupt_priority(); 
    do_low_priority_periodic_tasks(); // these may be interrupted 
} 

Innymi słowy, należy uruchomić pierwszą część z priorytetem poziomie 0, a potem jakoś obniżyć aktualny priorytet przerwań do 15, tak aby reszta mogła zostać wywłaszczona przez inne przerwania sprzętowe.

Jednym z pomysłów jest przeniesienie do_low_priority_periodic_tasks(); do oddzielnego programu obsługi przerwań i wywołanie tego handlera poprzez NVIC_SetPendingIRQ(), który ustawia bit oczekujący w rejestrze NVIC->ISPR[]. W ten sposób drugie przerwanie będzie natychmiast następowało po SysTick, chyba że istnieje coś z priorytetem między 0 a 14 w oczekiwaniu.

#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 */ 
    } 
} 

wybrałem IRQ 55, ponieważ nie jest zajęty na moim kontrolera, byłoby przerwanie obsługi AES na STM32L162, ale tam jestem nieco zaniepokojony. Czy zamiast tego powinienem wybrać inny IRQ, być może nieużywane przerwanie kanału DMA? Czy bezpieczne jest stosowanie przerwań 57-67, które są zdefiniowane w rdzeniu Cortex-M3, ale nie w serii STM32L? Czy istnieje lepszy sposób to zrobić?

Odpowiedz

4

Czy można bezpiecznie używać przerwań 57-67, które są zdefiniowane w rdzeniu Cortex-M3, ale nie w serii STM32L?

Nie. Twój NVIC może ich nie realizować.

Ale PendSV jest dokładnie wykonane dla tego zadania:

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 
} 

Zobacz także ten answer o PendSV.

+0

Dokładnie tego szukam, dziękuję – berendi

+0

Bardzo dobrze można zmienić priorytet. 'PendSV jest zwykle używany w procedurach RTOS, a nie w procedurach obsługi przerwań dla użytkowników, co nie jest możliwe dla wielu procedur obsługi. To zupełnie nie ma związku z używaniem niezatwierdzonych przerwań. – Olaf