Очередной шедевр.
В обновлении софта по I2C в контроллере дата передается блоками по 64 байта. Не мог понять, почему первый байт даты всегда флэшуется какой то левый.
Искал места где портится буфер даты - нет таких мест.
- Code: Select all
volatile U8 dbuf[256]; // Data buffer
...
void program_page(U16 page, volatile U8 *buf)
{
U16 w;
...
U16 i;
for (i = 0; i < SPM_PAGESIZE; i += 2)
{
w = *buf++;
w += (*buf++) << 8;
boot_page_fill(page + i, w);
}
...
}
...
int main (void)
{
...
sei();
while(1)
{
while (!event)
{
wdt_reset();
sleep_cpu();
}
switch(event)
{
...
/* Page flash request */
case EVENT_FLPG:
wdt_disable();
program_page(ufpage, dbuf);
wdt_enable(WDT_TIME);
break;
...
}
}
}
Вышеозначенный dbuf используется на ISR для приема даты по I2C.
Мало того, что компилер не раздупляет, что одни и те же глобальные переменные юзаются на иср и в мейне, хуй бы с ним. Обозначен же: волатайл!
В сумме этот мегаоптимайзер генерит такую хуйню: dbuf[0] (самый первый байт буфера) читается один раз сразу после sei() и потом передается в готовом виде в program_page(). Охуенная оптимизация!
- Code: Select all
18b4: 78 94 sei
18b6: c0 91 6f 00 lds r28, 0x006F ;dbuf[0]
В компилированном коде полный бардак, но замечу, что этот lds r28, 0x006F находится ОЧЕНЬ далеко от вылета по ивенту (когда дата загружена), мало того - инструкция SPM встречается несколько раз (!) - "первый" и "все остальные".
Обошел это костылем:
- Code: Select all
static U16 w;
После костыля все стало более менее на место, бинарь уменьшился на 6 байт
Как это исправить по-нормальному, не знаю.
avr-c++ (AVR_8_bit_GNU_Toolchain_3.4.3_1072) 4.8.1