Я использую еще версию 3.20, но самую последнию версию компилера 3.20D
Тут неожиданно всплыла бага оптимизатора.
Самый короткий способ получить
Код
#include <iom128.h>
__no_init __regvar volatile unsigned char test@14;
void test_failed(void)
{
test = 0x0f;
while(1) {
PORTA = 0;
PORTA = 0x0f;
}
}
В листинге получаем
Код
4 void test_failed(void)
\ test_failed:
5 {
\ 00000000 REQUIRE ?Register_R14_is_global_regvar
6 test = 0x0f;
\ 00000000 E00F LDI R16,15
\ 00000002 2EE0 MOV R14,R16
7 while(1) {
8 PORTA = 0;
\ ??test_failed_0:
\ 00000004 E000 LDI R16,0
\ 00000006 BB0B OUT 0x1B,R16
9 PORTA = 0x0f;
\ 00000008 BAEB OUT 0x1B,R14
\ 0000000A CFFC RJMP ??test_failed_0
10 }
11 }
А т.к. test используется в прерываниях...
У меня в проекте в одном месте есть похожее присваивание, а дальше регистр только в прерываниях используется...
У себя обошел примерно так:
Код
void test_ok(void)
{
volatile unsigned char dummy;
dummy = 0x0f;
test = dummy;
while(1) {
PORTA = 0;
PORTA = 0x0f;
}
}
13 void test_ok(void)
\ test_ok:
14 {
\ 00000000 REQUIRE ?Register_R14_is_global_regvar
\ 00000000 95CA DEC R28
15 volatile unsigned char dummy;
16 dummy = 0x0f;
\ 00000002 E00F LDI R16,15
\ 00000004 8308 ST Y,R16
17 test = dummy;
\ 00000006 8108 LD R16,Y
\ 00000008 2EE0 MOV R14,R16
18 while(1) {
19 PORTA = 0;
\ ??test_ok_0:
\ 0000000A E000 LDI R16,0
\ 0000000C BB0B OUT 0x1B,R16
20 PORTA = 0x0f;
\ 0000000E E00F LDI R16,15
\ 00000010 BB0B OUT 0x1B,R16
\ 00000012 CFFB RJMP ??test_ok_0
21 }
22 }
Как видно из второго листинга, с обычным volatile работает нормально сохраняет константу, потом загружает обратно, потом в регистр запихивает.
У меня тут валялся еще 4.11A тот же эффект.
Пропадает еще если вызывается хотя бы одна функция между присваиваниями.
Сообщение отредактировал KRS - Jan 18 2008, 17:03