Почему DSPIC33F перезапускается при обращении к флагу прерывания таймера?

У меня своеобразная проблема с таймером на DSPIC33F. Мне нужно создать функцию задержки, и я решил использовать Таймер 2 для подсчета количества циклов команд. Функция включает таймер, а затем ждет в цикле while, ожидая установки флага прерывания. См. код ниже:

T2CONbits.TON = 0;                  // disable Timer 2  
IFS0bits.T2IF = 0;                  // reset Timer 2 interrupt flag
TMR2 = 0;                           // reset timer accumulator
T2CONbits.TON = 1;                  // enable Timer 2

while(!IFS0bits.T2IF);              // Wait until until the timer 2 timeout
IFS0bits.T2IF = 0;                  // reset Timer 2 interrupt flag

T2CONbits.TON = 0;                  // disable Timer 2

Функция отлично работает, если прерывания TMR2 отключены. Однако, если прерывания TMR2 разрешены, микропрограмма перезапускается при установке флага прерывания. Этот перезапуск происходит только тогда, когда я запускаю код, но не во время пошагового выполнения (я использую ICD3 с MPLab 8.something). Я не настраивал ISR для TMR2. Все остальные прерывания отключены.

Несмотря на то, что я достиг своей цели по созданию функции задержки, я все еще задаюсь вопросом о возможных причинах перезапуска прошивки. Это потому, что по какой-то причине я могу адресовать флаг прерывания только внутри ISR? Или есть какие-то другие причины?

Если вы разрешите прерывание и не укажете ISR, произойдут плохие вещи. Процессор перейдет к вектору независимо от того, добавили ли вы какой-либо код ISR в свою прошивку...
Ну, я думаю, это объясняет, почему он отлично работает во время пошагового выполнения. Спасибо.
В режиме отладки все может отличаться от режима приложения, особенно с ISR (мой опыт работы с Microchip).

Ответы (1)

На странице 2 справочника по семейству прерываний PIC33f показано, как работает процесс прерывания для dsPIC33f:

http://ww1.microchip.com/downloads/en/DeviceDoc/70300C.pdf

Когда вы разрешаете прерывание (например, T2IE) и прерывание срабатывает, оно переходит к ячейке адреса, найденной в периферийном векторе прерывания. если вы не определили юридический адрес для периферийного устройства, вектор прерывания периферийного устройства будет иметь неизвестный адрес (возможно, 0), и когда прерывание сработает, оно отправится по этому адресу, и могут произойти непредсказуемые вещи.

в вашем случае, предполагая, что бит ALTIVT (INTCON2<15>) очищен, когда срабатывает прерывание TMR2, оно переходит к адресу, найденному в 0x000022.

когда вы пишете:

void __attribute__((__interrupt__, auto_psv)) _T2Interrupt (void)
{

}

вы фактически сообщаете своему компилятору, что хотели бы разместить адрес начала этого кода по адресу 0x000022 (адрес TMR2 IVT)

и когда вы пишете:

void __attribute__((__interrupt__, auto_psv)) _AltT2Interrupt (void)
{

}

вы говорите своему компилятору разместить адрес начала этого кода по адресу 0x000122 (адрес TMR2 AIVT)