Так что я озадачен этим ...
Я работаю с микроконтроллером ARMv7-M и компилятором GCC, отлаживаю некоторый код, где пытаюсь включить прерывание. Я пытаюсь сделать следующее: включить прерывание, чтобы при изменении значения для контакта PA31, контакт PA9 был установлен на низкий уровень, используя контроллер PIO MCU. Обработчик прерываний просто называется PIOA_Handler, он объявлен в одном из файлов устройства как:
void PIOA_Handler (void) атрибут ((прерывание));
И внутренности функции находятся в main.cpp:
void PIOA_Handler(void)
{
if ((*((Pio*)PIOA)).PIO_PDSR < PIO_PDSR_P31_Msk) {
((*((Pio*)PIOA)).PIO_CODR |= PIO_CODR_P9_Msk); // clear output on pin 9 if pin PA31 is logic low
}
Я начну с разрешения глобальных прерываний и установки выхода PA9, включения прерывания изменения для контакта PA31 на периферийной стороне, а также включения вектора прерываний NVIC, чтобы процессор принимал и обрабатывал прерывание:
gpio_set_pin_direction(PIN_PA9, GPIO_DIRECTION_OUT); // set PA9 to out and PA31 to in
sys->setPin(PIN_PA9, true); // enable PA9
((Pio *)PIOA)->PIO_IER |= PIO_IER_P31_Msk;
NVIC_EnableIRQ(PIOA_IRQn);
Реальная проблема, с которой я сталкиваюсь, заключается в следующем: по какой-то причине, когда я отлаживаю без установки точки останова, вместо вызова PIOA_Handler, когда происходит смена пина, он просто вызывается непрерывно, снова и снова для всю длину сеанса отладки.
Если, однако, я установил точку останова на строке кода, где я включаю прерывание изменения уровня PIO:
((Pio *)PIOA)->PIO_IER |= PIO_IER_P31_Msk;
этого как-то не происходит, и PIOA_Handler вызывается, как и должно быть, когда действительно происходит изменение уровня на PA31. После того, как он вызывается правильно, он снова вызывается непрерывно, аналогично тому, как он вызывается без точки останова.
Еще одна вещь, которую я заметил, заключается в том, что если я установлю точку останова на следующей строке NVIC_EnableIRQ(PIOA_IRQn);
и посмотрю на регистр отложенного набора прерываний NVIC (ISPR) в одном из окон наблюдения отладчика, то будет ожидающее прерывание для PIOA_IRQn. Но если я установлю точку останова на ((Pio *)PIOA)->PIO_IER |= PIO_IER_P31_Msk;
и перейду к строке NVIC_EnableIRQ, прерывания не будет.
Я пытался вставить NVIC_ClearPendingIRQ между двумя строками, но он не очищает ожидающий IRQ. По какой-то причине точка останова очищает ее, но использование действующей функции Clear Pending не помогает. Почему это так и как мне написать код, которому не требуется точка останова для правильного вызова обработчика прерываний?
Заранее спасибо!