Перейти к содержанию
    

Вышел WinAVR 20080402...20080411

А я пока до сих пор использую WinAVR20070525, даже до декабрьской версии прошлого года обнавляться побаиваюсь

 

А я как пионер, обновлялся... Думал, а вдруг какую ошибку неприятную исправили? И каждый раз всё хужее и хужее :-) В прошлый переход пара проектов перестала помещаться в кристалл... Хорошо хоть вовремя наткнулся на сообщение Сергея Борща про -ffunction-sections -fdata-sections, с их помощью - впихнул:-)

Короче, я пока тоже пас:-)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А я как пионер, обновлялся... Думал, а вдруг какую ошибку неприятную исправили? И каждый раз всё хужее и хужее :-) В прошлый переход пара проектов перестала помещаться в кристалл... Хорошо хоть вовремя наткнулся на сообщение Сергея Борща про -ffunction-sections -fdata-sections, с их помощью - впихнул:-)

Короче, я пока тоже пас:-)

А здесь сообщения тоже противоречивые, хотя есть и положительные. Наверно стоит подождать. Либо пробывать самому.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А здесь сообщения тоже противоречивые, хотя есть и положительные. Наверно стоит подождать. Либо пробывать самому.

 

Проекты компилируются без ошибок, но часть из них не работает в железе. Есть серьёзная бага с не сохранением R16 (почитайте баглист на http://sourceforge.net/tracker/?atid=52007...mp;func=browse)

 

Размер кода только увеличился в сравнении с WinAVR 20070525.

 

И ещё, я нашёл пару приколов в стабилной версии WinAVR 20070525, которую использую постоянно:

1)

При компиляции с -oS код получается больше (212 байт), чем с -o2 (210 байт).

Пример во вложенном файле.

Там процедура mcu_init присутствует дважды один раз она встраивается компилятором как inline,

но при этом она же остаётся в asm листинге и как обычная процедура с заканчивающаяся ret.

2)

В прерываниях сохраняется в стэке, а потом очищается регистр __zero_reg__ (r1), после чего востанавливается перед reti.

Хотя он вовсе не используется процедурой.

3)

Код при оптимизации -o2 получается просто смешным:

проверка условия происходит дважды!!!

 

if (time_is_up)

loop:

lds r24, 0x0061 // первый раз

and r24, r24

breq loop

 

// тело условия

 

lds r24, 0x0061 // второй раз вместо rjmp loop !!!

and r24, r24

breq loop

 

Я в шоке! (всё это можно увидеть скомпилировав вложенный файл)Test_bug.rar

Изменено пользователем demiurg_spb

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Размер кода только увеличился в сравнении с WinAVR 20070525.
к сожалению по моим пробам после 20060421 код очень часто увеличивается,

правда сО всякими спецключами я не пробовал, но и код который пробовал не требует этих ключей.

При компиляции с -oS код получается больше (212 байт), чем с -o2 (210 байт).
нуу... 2 байта это совсем не показатель, всегда можно написать так что при оптимизации

по скорости код будет более медленным чем при оптимизации по размеру, ну и конечно наоборот..

2)

В прерываниях сохраняется в стэке, а потом очищается регистр __zero_reg__ (r1), после чего востанавливается перед reti.

Хотя он вовсе не используется процедурой.

Ну это не баг а уже довольно давно фича AVR Gcc, если это фсе мне начинает сильно

мешать то объявляю прерывание как:

void TIMER2_COMP_vect(void) __attribute__((signal)) __attribute__((naked));

ну и уже все сохранение/востановление пишу сам.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

к сожалению по моим пробам после 20060421 код очень часто увеличивается,

правда сО всякими спецключами я не пробовал, но и код который пробовал не требует этих ключей.

нуу... 2 байта это совсем не показатель, всегда можно написать так что при оптимизации

по скорости код будет более медленным чем при оптимизации по размеру, ну и конечно наоборот..

Специально я ничего не делал.

На мой взгляд это действительно бага, т.к. сгенерированный компилятором код одной функции присутствует _дважды_ в одой единице трансляции. И именно по этой причине размер программы увеличивается...

Ну это не баг а уже довольно давно фича AVR Gcc, если это фсе мне начинает сильно

мешать то объявляю прерывание как:

void TIMER2_COMP_vect(void) __attribute__((signal)) __attribute__((naked));

ну и уже все сохранение/востановление пишу сам.

Всё делать руками... А для чего тогда вообще на С писать?

Изменено пользователем demiurg_spb

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всё делать руками... А для чего тогда вообще на С писать?
Я не говорю что все делать руками,

только в тех случаях когда нужно сделать очень короткое быстрое прерывание с минимумом

накладных расходов. При этом вся остальная прога может быть на С.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я не говорю что все делать руками,

только в тех случаях когда нужно сделать очень короткое быстрое прерывание с минимумом

накладных расходов. При этом вся остальная прога может быть на С.

Это я чисто риторически спрашивал.... :)

 

Проверил на 20080411:

1)

Проблема с дублированием кода процедуры осталось.

2)

Размер кода при оптимизации o2 и oS одинаков 214 байт.

Ушла проблема с двойной проверкой условий, что не может не радовать!

3)

Ненужное сохранение в стэке __zero_reg__ (r1) осталось.

 

Может кто-нибудь зарегистрирует ошибки 1 и 3 на:

http://sourceforge.net/tracker/?atid=52007...mp;func=browse)

А то у меня с письменным английским не так хорошо, как могло бы быть...

 

Использование данной версии 20080411 невозможно из-за баги с R16.

Часть программ не работает в железе по этой причине.

Изменено пользователем demiurg_spb

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проверил на 20080411:

1)

Проблема с дублированием кода процедуры осталось.

 

Не надо свое незнание языка С выдавать за баг компилятора уже третий пост подрят.

 

В дали компилятору команду оптимизировать код? Он вставил инлай версию функции 'mcu_init' в 'main', при этом ускорив код на команды вызова/возврата?

 

Вы обьявили функцию 'mcu_init' как глобальную, компилятор должен обрабатывть ситуацию что эта функция может быть вызвана из другого модуля? И для этого случая оставить код полной версии 'mcu_init'?

 

Где ошибся компилятор?

 

Объявите 'mcu_init' как static.

 

Анатолий.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не надо свое незнание языка С выдавать за баг компилятора уже третий пост подрят.

 

К слову, могли бы и не ждать три поста подряд а поправить ранее:)

 

В дали компилятору команду оптимизировать код? Он вставил инлай версию функции 'mcu_init' в 'main', при этом ускорив код на команды вызова/возврата?

 

Вы обьявили функцию 'mcu_init' как глобальную, компилятор должен обрабатывть ситуацию что эта функция может быть вызвана из другого модуля? И для этого случая оставить код полной версии 'mcu_init'?

 

Где ошибся компилятор?

 

Объявите 'mcu_init' как static.

 

Анатолий.

 

Спасибо за поучение.

Static совершенно упустил из виду.

С кодом функции всё в порядке.

Вопрос был задан для того чтобы понять суть проблемы.

Одна проблема была в недопонимании и она решилась благодаря Вам.

Я думаю, что это было интересно не только мне...

Антон.

Изменено пользователем demiurg_spb

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ненужное сохранение в стэке __zero_reg__ (r1) осталось.

 

Веду проект на Си, все прерывания только на асме, в которых стараюсь SREG не портить. в этом сильно помогает условие равенства r1=0. d в какой-то момент прога начала глючить.

оказалось:

при операциях умножения результат в r1:r0. при этих операциях компилятор не обрамляет участок кода рапретом/разрешением прерываний.

поэтому __zero_reg__ не всегда равен 0. и поэтому при прерываниях гцц генерирует пуш/поп r0

/*******/

off

хотелось бы чтоб r0,r1 стали общими регистрами,а r2==0 и р3==1 ВСЕГДА

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

хотелось бы чтоб r0,r1 стали общими регистрами,а r2==0 и р3==1 ВСЕГДА
Кстати, да. Давно такое желание возникло - иметь фактически словный временный регистр __temp_hi__/__temp_lo__, возможно, c синонимом __temp_reg__ для младшего, а __zero_reg__ перекинуть на R2. Единичный регистр как-то вроде и не очень нужен.

Да, это исключает пару R3/R2 из возможных словных пар, но добавляет R1/R0.

На распределение регистров для передачи аргументов, сохраняемых вызываемым и вызывающим это вроде бы не влияет.

 

Понадобится перетряхивание ассемблерной части libc - почти уверен, что не везде хватит просто переименования __zero_reg__ да и исключить ненужные теперь его обнуления после использования R1 надо будет. Что-то ещё (те же подпрограммы блочной работы с eeprom) тоже могут упроститься.

 

Готов принять участие в этом куске работы (асм-часть libc, ассемберные вставки типа util/crc16.h, ...).

Что это потянет за собой в кодогенераторе - просто плохо себе представляю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Веду проект на Си, все прерывания только на асме, в которых стараюсь SREG не портить. в этом сильно помогает условие равенства r1=0. d в какой-то момент прога начала глючить.

оказалось:

при операциях умножения результат в r1:r0. при этих операциях компилятор не обрамляет участок кода рапретом/разрешением прерываний.

поэтому __zero_reg__ не всегда равен 0. и поэтому при прерываниях гцц генерирует пуш/поп r0

Во всём есть скрытый смысл!

off

хотелось бы чтоб r0,r1 стали общими регистрами,а r2==0 и р3==1 ВСЕГДА

Пять баллов!

Изменено пользователем demiurg_spb

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На официальном сайте сейчас другая версия:

WinAVR-20080411 от 2008-04-12 12:24

Снова спрятали, теперь 20080430. Релноты старые. Ну и как теперь искать, что они изменили?

 

Ага, судя по Bug 1945375 поправили багу с сохранением R16. Выходит, можно переползать и менять топик на "уже вполне созрел" :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Выходит, можно переползать и менять топик на "уже вполне созрел" :)

 

Багу превнесённую исправили - это хорошо. А в чём преимущества новой версии?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Снова спрятали, теперь 20080430. Релноты старые. Ну и как теперь искать, что они изменили?

 

Ага, судя по Bug 1945375 поправили багу с сохранением R16. Выходит, можно переползать и менять топик на "уже вполне созрел" :)

 

Все сборки avr-gcc основанные на GCC 4.3 имеют еще один критический баг. Если из обработчика прерывания вызывается функция то может возникнуть ситуация когда будут сохранены не все регистры которые изменяются в обработчике. Должны сохраняться все call-used регистры, а сохраняются только те регистры которые используются а обработчике. Если вызываемая функция использует какие нибудь из call-used регистров которые не используются в вызвавшем ее обработчике прерывания, то они будет искажены.

 

Если обработчики прерываний написаны правильно, то есть максимально короткими, то в них обычно не бывает вызовов функций и такая программа, с большой вероятностью, не подвержена этому багу компилятора.

 

Анатолий.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...