Разбираюсь с прерываниями в PIC24F под MPLAB C30 v3.30
Для изменения уровней прерываний в С30 рекомендуются безопасные макросы
SET_CPU_IPL(ipl)
SET_AND_SAVE_CPU_IPL(save_to, ipl)
RESTORE_CPU_IPL(saved_to)
которые определяются как
Код
#define SET_CPU_IPL(ipl) { \
int DISI_save; \
\
DISI_save = DISICNT; \
asm volatile ("disi #0x3FFF"); \
SRbits.IPL = ipl; \
DISICNT = DISI_save; } (void) 0;
#define SET_AND_SAVE_CPU_IPL(save_to, ipl) { \
save_to = SRbits.IPL; \
SET_CPU_IPL(ipl); } (void) 0;
#define RESTORE_CPU_IPL(saved_to) SET_CPU_IPL(saved_to)
Допустим я собираюсь изменить текущий уровень прерываний на 5-й,
выполнить какой-то код и вернуть прежний уровень прерываний.
Транслируется это в понятный код, приведенный ниже.
Но размеры его просто поражают воображение:
Код
45: unsigned int ipl_stat;
46: SET_AND_SAVE_CPU_IPL(ipl_stat,5);
07E4 200422 mov.w #0x42,w2 ; (0x42 - address SR)
07E6 784112 mov.b [w2],w2
07E8 FB8102 ze w2,w2
07EA DE1145 lsr w2,#5,w2
07EC 800293 mov.w DISICNT,w3
07EE FC3FFF disi #16383
07F0 BFC042 mov.b SR,w0
07F2 60407F and.b w0,#0x1f,w0
07F4 B3CA01 mov.b #0xa0,w1
07F6 704001 ior.b w0,w1,w0
07F8 B7E042 mov.b w0,SR
07FA 880293 mov.w w3,DISICNT
47: Nop();
07FC 000000 nop
48: RESTORE_CPU_IPL(ipl_stat);
07FE 800291 mov.w DISICNT,w1
0800 FC3FFF disi #16383
0802 DD1145 sl w2,#5,w2
0804 BFC042 mov.b SR,w0
0806 60407F and.b w0,#0x1f,w0
0808 704002 ior.b w0,w2,w0
080A B7E042 mov.b w0,SR
080C 880291 mov.w w1,DISICNT
Возникают два вопроса:
1. Зачем запрещать прерывания на время модификации битов уровня прерывания регистра статуса?
Ведь если произойдет прерывание, оно все равно обязано восстановить весь регистр статуса.
2. Зачем вообще сохранять остальные биты регистра статуса, на которые расходуется больше половины вышеприведенного кода?
Разве компилятор будет отложенно применять какие-нибудь биты статуса после того, как в программе в явном виде производится модификация регистра статуса?