|
SAM7SE застревает прерывание |
|
|
|
May 27 2013, 16:51
|
Группа: Новичок
Сообщений: 7
Регистрация: 19-09-09
Пользователь №: 52 458

|
AT91SAM7SE512. На SYS_IRQ (ID=2) висит обработчик. Всё работает долго и успешно, но в какой-то момент обработчик перестаёт вызываться. При этом, AIC_IPR=2 , AIC_IMR=2 , AIC_DCR.GMSK=0 , CPSR.I=0 , CPSR.MODE без изменений. А обработчик не вызывается. Вот как такое может быть?! Подскажите, люди добрые!
|
|
|
|
|
 |
Ответов
(1 - 13)
|
May 27 2013, 17:18
|
Группа: Новичок
Сообщений: 7
Регистрация: 19-09-09
Пользователь №: 52 458

|
В AIC_SVR[1] адрес моего обработчика. Дык в периферии уже вроде поздняк запрещать, если он уже в AIC_IPR попал...
|
|
|
|
|
May 27 2013, 17:29
|
Группа: Новичок
Сообщений: 7
Регистрация: 19-09-09
Пользователь №: 52 458

|
Нет, FIQ не используется.
|
|
|
|
|
May 27 2013, 20:43
|
Группа: Новичок
Сообщений: 7
Регистрация: 19-09-09
Пользователь №: 52 458

|
Цитата(DmitryM @ May 27 2013, 21:37)  Приведите обработчик прерывания. Что висит на SYS_IRQ? Учитываете, что SYS_IRQ несколько источников? CODE __nested __irq __arm void IRQ_Handler(void){ static char ADC_Av=0; static int ADC_Acc=0; unsigned int SavI=__get_CPSR(); __set_CPSR((SavI&(~I_BIT)));
//*********** DBGU BEGIN ***************** __no_init static unsigned char RX_D_Buf[RX_D_BUF_LEN]; // Áóôåð ïðèåìà èç RS232 static unsigned short int RX_D_Buf_Head; // Óêàçàòåëè â áóôåðå ïðèåìà èç RS232 unsigned int Status; static unsigned char Ready=0,PrevByte=0; unsigned char Tmp; Status=*AT91C_DBGU_CSR; // Ñ÷èòûâàåì èñòî÷íèê ïðåðûâàíèÿ
if ( Status & AT91C_US_RXRDY ){ // Åñëè áûë ïðèíÿò áàéò Tmp=*AT91C_DBGU_RHR; if(Ready) RX_D_Buf[RX_D_Buf_Head++]=Tmp; // Åñëè áûëà ïîéìàíà ñèíõðà, ïåðåïèñûâàåì áàéò â áóôåð if(RX_D_Buf_Head>=RX_D_BUF_LEN){ // Åñëè áóôåð íàïîëíèëñÿ, ïåðåâàëèâàåì åãî â ñòðóêòóðó Bat_Data=*((struct Bat_Struct*)RX_D_Buf); Ready=0; BuiltInBattary_Connected=1; } if(PrevByte==0xFA && Tmp==0xF0){ RX_D_Buf_Head=0; Ready=1; } //Èùåì ñèíõðó PrevByte=Tmp; *AT91C_DBGU_CR = AT91C_US_RSTSTA; // Î÷èùàåì ôëàãè îøèáîê }
//*********** DBGU END *****************
//*********** PIT BEGIN ***************** if(((*AT91C_PITC_PISR)&(AT91C_PITC_PITS))){ if((*AT91C_ADC_SR&(1<<4))){ //Åñëè ÀÖÏ ñîçðåëî if(ADC_Av++<10) ADC_Acc+=*AT91C_ADC_LCDR; else //Êîïèì { Batt_Volt=(ADC_Acc*275)/10240; // (25/10)/10240*N*11 //Íàêîïèëîñü - âû÷èñëÿåì íàïðÿæåíèå ADC_Acc=0; ADC_Av=0; if(!CritSect){ if(!BuiltInBattary_Connected && Batt_Volt<=Batt_Threshold_Off){ LowBat(); TurnOff(); } /* if(BuiltInBattary_Connected && ( Bat_Data.UBat[0]<Batt_Threshold_Off_Li || Bat_Data.UBat[1]<Batt_Threshold_Off_Li || Bat_Data.UBat[2]<Batt_Threshold_Off_Li) ){ LowBat(); TurnOff(); } */ } } *AT91C_ADC_CR=AT91C_ADC_START; }
unsigned char *KeyPressU,KeyNum; static unsigned char KPR,KeyPress[KEY_ROW*KEY_COL],BeepCount=1; unsigned short int BinRow,Key_St;
if(BeepCount){ BeepCount--; if(!BeepCount) NoSound(); }
// Åñëè íè ïðè ïîñëåäíåì ïðîõîäå íè ñåé÷àñ íè îäíà êíîïêà íå íàæàòà - íå÷åãî ñêàíèðîâàòü if(KPR==0 && (KEY_DATA_PIN&(KEY_MSK_COL<<KEY_D0))==(KEY_MSK_COL<<KEY_D0)){ KeyDown=0; goto SYS_EOI; } else KeyDown=1;
KeyPressU=KeyPress; KPR=0; BinRow=1; KeyNum=0; KEY_DATA_INP=KEY_MSK_ROW<<(KEY_D0+KEY_COL); // Êîãäà ñêàíèðóåì, òîëüêî òåêóùàÿ íîãà íà âûõîä, KEY_DATA_OUT=BinRow<<(KEY_D0+KEY_COL); // îñòàëüíûå íà âõîä è ïðèòÿíóòû ïîäòÿæêîé for(char nop=0;nop<KEY_NOPS;nop++) asm("nop");// Çàäåðæêà, ÷òîáû ïðîøëî ÷åðåñ RC (RC, ÷òîáû íå ãàäèëî â ýôèð)
for(char x=0;x<KEY_ROW;x++){ for(char nop=0;nop<KEY_NOPS;nop++) asm("nop");// Çàäåðæêà, ÷òîáû ïðîøëî ÷åðåñ RC Key_St=KEY_DATA_PIN>>KEY_D0; // Ñ÷èûâàåì ñòðî÷êó BinRow KEY_DATA_INP=BinRow<<(KEY_D0+KEY_ROW); // Âêëþ÷àåì BinRow<<=1; // ñëåäóþùóþ KEY_DATA_OUT=BinRow<<(KEY_D0+KEY_ROW); // íîãó for(char y=0;y<KEY_COL;y++,Key_St>>=1,KeyNum++) // Èùåì, â êàêîì ñòîëáöå íàæàòà êíîïêà if((Key_St&1)) *(KeyPressU++)=0; else // Êíîïêà íå íàæàòà { char k=++*(KeyPressU); KPR=1; // Êíîïêà íàæàòà - ñ÷èòàåì ñêîëüêî âðåìåíè if((k==2 || k==2+KEY_WAIT_REP) && KeyBufLen!=(KEY_LEN-1)){ KeyBuf[++KeyBufLen]=KeyNum; // Åñëè ïðîøëî ñîîòâ. âðåìÿ - çàïèñûâàåì êíîïêó â áóôåð Sound(3000); BeepCount=5; } if( k==1+KEY_WAIT_REP+KEY_REP ) *KeyPressU=1+KEY_WAIT_REP-1; KeyPressU++; // Ïåðåõîäèì ê ñëåäóþùåé êíîïêå } } // Ñòîëáöû íà âûõîä, ÷òîáû ðàçîì ìîæíî áûëî ïîñìîòðåòü, íå íàæàòî ëè ÷òî-íèáóäü KEY_DATA_OUT=KEY_MSK_ROW<<(KEY_D0+KEY_COL);
SYS_EOI:
if(TimeMenuTimer) TimeMenuTimer--; else { TimeMenuTimer=KEY_SEC; TimeMenu=0; }
WarmUpTimer++; *AT91C_PITC_PIVR; }// else while(1);
__set_CPSR(SavI);
*AT91C_AIC_ICCR=1<<AT91C_ID_SYS; *AT91C_AIC_EOICR=1; // Îòïðàâëÿåì ñèãíàë îêîí÷àíèÿ îáðàáîòêè ïðåðûâàíèÿ EOI } Извиняюсь за кракозябры вместо комментов, но почему то вот так скопировалось
Сообщение отредактировал IgorKossak - May 28 2013, 06:59
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
May 27 2013, 20:58
|
Группа: Новичок
Сообщений: 7
Регистрация: 19-09-09
Пользователь №: 52 458

|
Цитата(aaarrr @ May 27 2013, 23:26)  Проверьте, нет ли вероятности выхода из какого-либо прерывания без записи AIC_EOICR. Вероятность всегда есть  Только вот где бы это могло случиться, я не вижу. Во всех обработчиках, return один и последним оператором. А предпоследним EOICR. Ну допустим, что где-то, что-то сглючивается, и вылетает она из какого-нибудь обработчика посередине. А увидеть, что AIC_EOICR не записали в каком-нибудь регистре можно? Цитата(aaarrr @ May 28 2013, 00:53)  Код *AT91C_AIC_ICCR=1<<AT91C_ID_SYS; Если прерывание сконфигурировано для работы по уровню, то эта строчка не имеет смысла; если по фронту - это готовый источник проблем. А, да, это атавизм. Спасибо, уберу.
|
|
|
|
|
May 27 2013, 21:27
|
Группа: Новичок
Сообщений: 7
Регистрация: 19-09-09
Пользователь №: 52 458

|
Цитата(aaarrr @ May 28 2013, 01:14)  Увы, нет. Печалько... Но видимо, больше ничего быть не может. Буду пока копать в этом направлении. Спасибо за подсказку.
|
|
|
|
|
May 27 2013, 21:36
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(KITA @ May 28 2013, 01:27)  Печалько... Но видимо, больше ничего быть не может. Буду пока копать в этом направлении. Спасибо за подсказку. Похоже: сброс внутри прерывания по записи ICCR тоже привел бы к неработающим прерываниям, но в этом случае не было бы единички в IPR. UPD: или оно все же сконфигурировано по уровню? Если нет, то настоятельно рекомендую. Попробуйте записать EOICR, когда поймаете "зависание" - если логика была нарушена, то после этой записи должно запустится прерывание. Еще неплохо бы проверить листинг на предмет корректности кода для вложенных прерываний.
|
|
|
|
|
May 27 2013, 22:55
|
Группа: Новичок
Сообщений: 7
Регистрация: 19-09-09
Пользователь №: 52 458

|
Цитата(aaarrr @ May 28 2013, 01:36)  Похоже: сброс внутри прерывания по записи ICCR тоже привел бы к неработающим прерываниям, но в этом случае не было бы единички в IPR. UPD: или оно все же сконфигурировано по уровню? Если нет, то настоятельно рекомендую. По уровню. Цитата(aaarrr @ May 28 2013, 01:36)  Попробуйте записать EOICR, когда поймаете "зависание" - если логика была нарушена, то после этой записи должно запустится прерывание. Да, до этого я уже додумался, но теперь надо подождать денёк, пока эта тварь снова повиснет  Цитата(aaarrr @ May 28 2013, 01:36)  Еще неплохо бы проверить листинг на предмет корректности кода для вложенных прерываний. А вложенных нету, без _nested что-то не так с вызовом процедур из обработчика было (давно было, не помню, что-то они там в один регистр с обработчиком адрес возврата запоминали что-ли...). Сейчас уже, правда, вызовов нет, ну а _nested остался, по-моему так надёжнее
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|