Изменить уровень приоритета работающего обработчика прерываний?
Я пытаюсь реализовать следующий псевдокод на контроллере cortex-m3 (в частности, STM32L151)
void SysTick_Handler() {
do_high_priority_periodic_tasks(); // not to be interrupted
lower_interrupt_priority();
do_low_priority_periodic_tasks(); // these may be interrupted
}
Другими словами, запустите первую часть с уровнем приоритета 0, затем каким-то образом понизьте текущий приоритет прерывания до 15, чтобы остальные могли быть прерваны другими аппаратными прерываниями.
Одна идея состоит в том, чтобы двигаться do_low_priority_periodic_tasks();
в отдельный обработчик прерываний, и вызвать этот обработчик через NVIC_SetPendingIRQ()
который устанавливает ожидающий бит в NVIC->ISPR[]
регистр. Таким образом, другое прерывание будет немедленно следовать SysTick
, если нет ничего с приоритетом между 0 и 14 в ожидании.
#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 */
}
}
Я выбрал IRQ 55, потому что он не занят на моем контроллере, это будет обработчик прерываний AES на STM32L162, но я немного волнуюсь там. Должен ли я выбрать другой IRQ вместо, возможно, неиспользуемого прерывания канала DMA? Безопасно ли использовать прерывания 57-67, которые определены в ядре Cortex-M3, но не в серии STM32L? Есть ли лучший способ сделать это?
1 ответ
Безопасно ли использовать прерывания 57-67, которые определены в ядре Cortex-M3, но не в серии STM32L?
Нет. Ваша NVIC может на самом деле не реализовывать их.
Но PendSV точно создан для этой задачи:
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
}
Смотрите также этот ответ о PendSV.