[an error occurred while processing this directive] [an error occurred while processing this directive]
PICC-18: Будьте осторожны - крутой баг.
(«Телесистемы»: Конференция «Микроконтроллеры и их применение»)
[an error occurred while processing this directive] [an error occurred while processing this directive] [an error occurred while processing this directive]

Отправлено DP 20 августа 2001 г. 17:42

Что-то вдруг не так повела себя программа, написанная на PICC-18 (компилятор той самой "freeware" версии 8.00).
Стал разбираться, что же он там нагенерировал. Нашел следующее:

На текст:
extern void adcIntHandler(void);
/***************************************************************
Interrupt switch
****************************************************************/
#ifdef HI_TECH_C
static void interrupt isr(void)
#else
void isr(void)
#endif
{
if(ADIF && ADIE)
{
ADIF = 0;
adcIntHandler();
}

if(SSPIF && SSPIE)
{
SSPIF = 0;
}

if(TMR0IF && TMR0IE)
{
TMR0IF = 0;
}
}

Было сгенерировано следующее:
Вход в прерывание -
246 psect intcode,class=CODE,space=0,reloc=2
247 psect intcode
248 0008 CFD8 F02E movff status,saved_regsh+30
249 000C CFFA F02D movff pclath,saved_regsh+29
250 0010 EF84 F001 goto f4094
251 psect text
252 0308 f4094:
253 0308 CFE0 F00F movff bsr,saved_bsrh
254 030C 6AE0 clrf bsr
255 030E CFE8 F02C movff wreg,saved_regsh+28
... тут ещё куча сохранений вырезана, в них всё правильно
275 035E C001 F018 movff btemp+1,saved_regsh+8
276 0362 C000 F017 movff btemp,saved_regsh+7
277 0366 CFF7 F016 movff tblptrh,saved_regsh+6
278 036A CFF6 F015 movff tblptrl,saved_regsh+5
279 036E CFF4 F014 movff prodh,saved_regsh+4
280 0372 CFF3 F013 movff prodl,saved_regsh+3
281 0376 EF0A F001 goto _isr

И возврат из прерывания -
209 psect text
210 0282 C010 FFF3 movff saved_regsh+0,prodl
211 0286 C011 FFF4 movff saved_regsh+1,prodh
212 028A C012 FFF6 movff saved_regsh+2,tblptrl
213 028E C013 FFF7 movff saved_regsh+3,tblptrh
214 0292 C014 F00C movff saved_regsh+4,btemp+12
215 0296 C015 F00D movff saved_regsh+5,btemp+13
216 029A C016 F00E movff saved_regsh+6,btemp+14
217 029E C017 F000 movff saved_regsh+7,btemp
218 02A2 C018 F001 movff saved_regsh+8,btemp+1
... тут вырезаны те же пересылки, что и выше
238 02F2 C02C FFE8 movff saved_regsh+28,wreg
239 02F6 C02D FFFA movff saved_regsh+29,pclath
240 02FA C02E FFD8 movff saved_regsh+30,status
241 02FE C00F FFE0 movff saved_bsrh,bsr
242 0302 0010 retfie

Обратите внимание на то куда он засовывает prodl, prodh, tblptrl, tblptrh и откуда потом вытаскивает.
Это действительно так! Я по шагам этот кусок в машинных кодах проходил.

Происходит это только если функция, вызываемая обработчиком, находится в другом модуле.
Этот случай в документации описан. Если компилятор "видит" вызываемую функцию, сохраняются только, используемые ею, регистры. И делается это правильно!
В случае, если компилятор функцию не "видит", предполагается наихудщий случай и сохраняется всё что можно, как в вышеприведённом примере. Но эту ветку разработчики протестировать, похоже, забыли.
Ради интереса скачал демо-версию с HI-TECHа. То же самое.

Если требуется вызов "невидимых" функций в обработчике прерываний, то обход этого бага пока таков:
1. Выделить обработчик прерывания в отдельный модуль.
2. Скомпилировать его в ассемблер.
3. Расставить номера регистров так как надо.
4. Включить этот ассемблерный файл в проект.
Проверено.

Составить ответ  |||  Конференция  |||  Архив

Ответы



Перейти к списку ответов  |||  Конференция  |||  Архив  |||  Главная страница  |||  Содержание  |||  Без кадра

E-mail: info@telesys.ru