Abo (20.06.2006 18:17, просмотров: 3340)
То ли GCC 4.0 зажигает, то ли я не того вкурил? Обясните, знающие. Работаю на CW 1.6 3 билда.
Пишу функцию обработки прерывания:
<pre>
void UsbIsr(void) __attribute__((interrupt("IRQ")));
void UsbIsr(void){
UsbChip.IsrHandler();
VICVectAddr = 0;
}
</pre>
Если в опциях не указывать оптимизацию то данная функция транслируется вот в это:
<pre>
void UsbIsr(void){
E52DC004 str r12, [sp, #-0x004]!
E1A0C00D mov r12, sp
E92DD80F stmfd sp!, {r0-r3, r11-r12, lr-pc}
E24CB004 sub r11, r12, #0x00000004
UsbChip.IsrHandler();
E59F0020 ldr r0, [pc, #+0x020]
EB00057B bl 0x0000347c <TLpc2148UsbController::IsrHandler()>
VICVectAddr = 0;
E3A03000 mov r3, #0x00000000
E2433EFD sub r3, r3, #0x03f40000
E3A02000 mov r2, #0x00000000
E5832000 str r2, [r3]
}
E24BD01C sub sp, r11, #0x0000001c
E89D680F ldmfd sp, {r0-r3, r11, sp-lr}
E8BD1000 ldmfd sp!, {r12}
E25EF004 subs pc, lr, #0x00000004
</pre>
А если попросить пооптимизировать хотябы Level1 то получается вот что:
<pre>
void UsbIsr(void) __attribute__((interrupt("IRQ")));
void UsbIsr(void){
E24EE004 sub lr, lr, #0x00000004
E92D500F stmfd sp!, {r0-r3, r12, lr}
UsbChip.IsrHandler();
E59F0014 ldr r0, [pc, #+0x014]
EB00028C bl 0x00001ad4
VICVectAddr = 0;
E3A02000 mov r2, #0x00000000
E3E03000 mvn r3, #0x00000000
E5032FCF str r2, [r3, #-0xfcf]
}
E8BD500F ldmfd sp!, {r0-r3, r12, lr}
E25EF004 subs pc, lr, #0x00000004
</pre>
Обратите внимание на самую первую и последнюю команду. Получается что смещение из lr два раза вычитается и возврат из прерывания происходит на команду, которая была выполнена перед вызовом обработчика прерывания. То есть команда выполнится 2 раза.
И опыт это подтверждает. Простенькая программка, которая в фоновой функции мыргает светодиодом во время енумерации (производит обращения к памяти и устройствам) отваливаеься в data_abort, если включить оптимизацию. Если оптимизацию выключить - нормально работает. Если же фоновую программу заменить простым while(1); - работает в обоих случаях. Подскажите, знающие, может я чего не так понимаю. Или действительно GCC ЖЖОТ.