|
|
  |
avr-gcc и IAR, сравнение, но не холивар |
|
|
|
Feb 21 2011, 14:05
|

Знающий
   
Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065

|
Цитата(neiver @ Feb 21 2011, 18:27)  Решение для avr-gcc - не вызывать из обработчиков прерываний функции из других единиц трансляции или использовать inline функции. да. Хороша мысль. Но не сейчас, а для второй фазы, когда нужно будет оптимизировать код и писать рекомендации для пользователей gcc. Цитата Второй пожиратель ресурсов это как уже все догадались функция sprintf. В IAR проекте у вас используется минимальная урезанная версия, в gcc - полная с поддержкой float и чтения параметров из памяти программ. Точно! И об этом я тоже как-то не додумался, не дошел! В IAR-е тип функций printf (и scanf) задается в Опциях проекта (General Options / Library Options) из выпадающих списков, а вот в опций для gnu-линковщика я не удосужился поискать. Былпа такая светлая мысль, поискать, но утонула среди других вопросов. (В IAR-e у меня стоял Printf Formatter = Small) Сейчас попробую нащупать подобную опцию в avr-ld... Отбой! Пока я писал этот пост, уже опередили http://electronix.ru/forum/index.php?showt...st&p=888593Откомпилировал с Да, действительно скидывает 372 байта. Объем кода по avr-size -- 3400 байт (text), в бинарнике под заливку во флешь 0x0DBA байт (= 3514). У IAR-а бинарник под заливку -- 0x0A32 байт (= 2610) Все еще много лишних байт (почти 900) надо чем-то объяснять
--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
|
|
|
|
|
Feb 21 2011, 14:40
|

Знающий
   
Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065

|
в ответ на http://electronix.ru/forum/index.php?showt...st&p=888594Ну вот, посчитал количество команд (считал через $ grep -iw sts *.lst | wc -l и ее модификации для других мнемоник) Код command gcc IAR ------- --- ---- LDS 87 23 STS 86 25 LD 16 24 ST 26 33  и?
--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
|
|
|
|
|
Feb 22 2011, 05:35
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(zhevak @ Feb 21 2011, 18:18)  Как Вы считали? (87-23)+(86-25)=125 слов, имея ввиду только разницу между нормальными командами и этой, придурошной  Цитата(neiver @ Feb 21 2011, 18:30)  Думаю, что не на 250 байт, поменьше. А вообще, IAR более оптимально использует косвенную адресацию со смещением. AVR-GCC приходится явно намекать какую адресацию использовать, например работая с переменной через указатель. Ну, поменьше, это ж на глазок было. Гцц как ни намекай, он иногда в такую бяку сваливается  , жаждешь от него этих "со смещением", а их все нету. Это РТЛ деревья, видать, по мозгам сильно проехались. Не умеет он по-настоящему юзать три указателя. Еще Гцц не любит действия со старшим битом. Еще... да нафиг! Зато "на переднем крае" всегда.
|
|
|
|
|
Feb 22 2011, 11:57
|

Знающий
   
Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065

|
Ну вроде как стало соизмеримо (если не сказать сравнялось в ноль!): gcc: 2787(text) + 30(data) = 2817 байт флеши. IAR: 2596(text) + 221(data) = 2817 байт флеши Но что значит "без использования"? Цитата(klen @ Feb 22 2011, 14:08)  ''чистая культура" без использования библиотечных аля printf Вы вызовы просто закомментировали или сохранили функциональность, заменив их на strcpy() и itoa()? В исходниках для IAR-а вызовы printf() не удалены и не заменены. Т.е. как бы условия состязания нарушены. Вчера ночью попробовал postmessage(), которую вызывают оба прерывания, сделать inline -- ни какой реакции  , как было, так и осталось. А пока резюме такое (извините, оно получилось несколько персонифицированным конкретно ко мне) 1. Функции printf и их модификации в тулчейне для avr имеют большие размеры, чем в IAR. Поэтому, если стоит вопрос компактности кода, их использования следует избегать. 2. Не забывать, что функции printf имеют несколько реализаций, выбор которых через ключи линковщика -Wl, -u, ... Ну что, если других предложений нет, тогда переходим к фазе оптимизации два -- оптимизация кода. Тут я вижу сразу две точки приложения: 1. Заменить вызовы printf() на strcpy(), strcat() и itoa() 2. Сделать по уму, заменить функции работы с оперативой на функции работы с констатами во флеш, т.е. вместо strcat() использовать strcat_P() и т.д. Ну вот пожалуй это все, что я вижу, что можно сделать, чтобы легко выдавить из gcc. Давить наверняка можно еще, но это уже будет сродни национальным танцам народов севера с использованием ударных музыкальных инструментов. По крайней мере для себя я понял, почему в первом приближении на gcc не достигается компактность кода присущая IAR, и что следует делать, что бы хоть как-то уменьшить размер кода. ГОСПОДА, СПАСИБО ЗА КОЛЛАБОРАЦИЮ! Через какое-то время я сообщу, что у меня получилось после реализации фазы два.
--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
|
|
|
|
|
Feb 22 2011, 23:46
|
Группа: Участник
Сообщений: 13
Регистрация: 22-01-11
Пользователь №: 62 402

|
Попробуйте заменить стандартный gcc'ый printf на xprintf от elm-chan'a http://elm-chan.org/fsw/strf/xprintf.htmlЭмм... В общем он теперь тоже сишный и большой, раньше был на асме и маленький, аж удивился  . Но даже сейчас он меньше. Заменил sprintf на xsprintf без потери функциональности Из 4 тулчейнов: WinAVR -> ( тут еще включен -mint8 и --param inline-call-cost=0 ) Program: 3268 bytes (39.9% Full) Data: 161 bytes (15.7% Full) kgp_avr -> Program: 3402 bytes (41.5% Full) Data: 161 bytes (15.7% Full) AVR_Toolchain -> ( тут еще включен -mint8 ) Program: 3366 bytes (41.1% Full) Data: 161 bytes (15.7% Full) mhvavrtools -> Program: 3386 bytes (41.3% Full) Data: 161 bytes (15.7% Full) Для стандартной printf у меня получилось: WinAVR -> ( тут еще включен -mint8 и --param inline-call-cost=0 ) Program: 3514 bytes (42.9% Full) Data: 157 bytes (15.3% Full) kgp_avr -> Program: 3578 bytes (43.7% Full) Data: 157 bytes (15.3% Full) AVR_Toolchain -> ( тут еще включен -mint8 ) Program: 3554 bytes (43.4% Full) Data: 157 bytes (15.3% Full) mhvavrtools -> Program: 3566 bytes (43.5% Full) Data: 157 bytes (15.3% Full) WinAVR -> avr-gcc.exe (WinAVR 20100110) 4.3.3 kgp_avr -> avr-gcc.exe (Klen's GCC package (KGP) for AVR/elf platform) 4.6.0 20100725 (experimental) AVR_Toolchain -> avr-gcc.exe (AVR_Toolchain_3.0_149) 4.4.3 mhvavrtools -> avr-gcc.exe (GCC) 4.5.1 
|
|
|
|
|
Feb 23 2011, 11:44
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Наткнулся на интересную бяку. Для начала, убрал все "ньюансовые" флаги. Размер существенно не менялся. Компилер, тсз conventional 2010-0110  Придрался к стремно-длинным прологам/эпилогам в прерываниях. По опыту - это гавновопрос, сделал так (почти на автопилоте) Код static void postmessage_prim(msg_t msg); void postmessage(msg_t msg) { postmessage_prim(msg); } Соответственно, в прерываниях, поменял вызовы на статик-примитив. Логика железная - статик как на ладони, шохошь то и делай. Так он, собако, абсолютно это игнорирует и прологи те же.  Вот жеж нанизм блин! И самое загадостное, что у мну это много раз так разруливалось. Он что, фамилию спрашиват? UPD причину нашел, надо было указать __attribute__((pure)) С дефолтовым минимальным принтфом 3788 байт.
|
|
|
|
|
Feb 26 2011, 17:02
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(_Pasha @ Feb 23 2011, 14:44)  С дефолтовым минимальным принтфом 3788 байт. аналогично, но у меня поменьше вышло 3424 вообще без правки исходников, лишь переписал Makefile. CODE avr-gcc (AVR_Toolchain_3.0_149) 4.4.3 Copyright © 2010 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Building project: bin/monitor-gcctest/monitor-gcc.elf
avr-gcc -mmcu=atmega8 -MMD -MP -MF ./bin/monitor-gcctest/monitor-gcc.dep -gdwarf-2 -DF_CPU=4608000UL -Os -pedantic -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -fno-split-wide-types --combine -fwhole-program -ffunction-sections -fdata-sections -Wl,--relax -ftree-loop-ivcanon -mcall-prologues -fno-tree-scev-cprop -finline-small-functions -fearly-inlining --param inline-call-cost=2 -finline-limit=65535 -mshort-calls -fno-unit-at-a-time -Wsign-compare -Wa,-adhlns=./bin/monitor-gcctest/monitor-gcc.lst -std=c99 -I. hal.c app.c lcd4.c main.c --output bin/monitor-gcctest/monitor-gcc.elf -Wl,-Map=./bin/monitor-gcctest/monitor-gcc.map,--cref -Wl,--gc-section -Wl,-u,vfprintf -lprintf_min
Creating load file for Flash: bin/monitor-gcctest/monitor-gcc.hex avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature bin/monitor-gcctest/monitor-gcc.elf bin/monitor-gcctest/monitor-gcc.hex
Creating load file for EEPROM: bin/monitor-gcctest/monitor-gcc.eep avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ --change-section-lma .eeprom=0 --no-change-warnings -O ihex bin/monitor-gcctest/monitor-gcc.elf bin/monitor-gcctest/monitor-gcc.eep || exit 0
Creating Extended Listing: bin/monitor-gcctest/monitor-gcc.lss avr-objdump -h -S bin/monitor-gcctest/monitor-gcc.elf > bin/monitor-gcctest/monitor-gcc.lss
Creating Symbol Table: bin/monitor-gcctest/monitor-gcc.sym avr-nm -n bin/monitor-gcctest/monitor-gcc.elf > bin/monitor-gcctest/monitor-gcc.sym
Size after: AVR Memory Usage ---------------- Device: atmega8
Program: 3424 bytes (41.8% Full) (.text + .data + .bootloader)
Data: 157 bytes (15.3% Full) (.data + .bss + .noinit) Последний WinAVR выдал ещё на 4 байта меньше 3420. avr-gcc (Klen's GCC package (KGP) for AVR/elf platform) 4.6.0 20100725 (experimental) выдал на 30 байт больше 3454
Сообщение отредактировал IgorKossak - Feb 27 2011, 09:45
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Feb 26 2011, 21:14
|

Знающий
   
Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065

|
Цитата(demiurg_spb @ Feb 26 2011, 22:02)  ... выдал на 30 байт больше 3454 30 байт это 1%. Мне кажется это не существенно. (что-то все еще никак не могу засесть за свою задачу и заменить printf на более "легкие" функции.)
--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
|
|
|
|
|
Mar 1 2011, 02:14
|

Знающий
   
Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065

|
Похоже что всё, приехали. Дальнейшая борьба за ужатие кода не приносит ощутимых результатов. Я заменил вызовы sprintf() на strcpy_P(). Где -то это оказалось вообще безболезненно (изменения только в файле app.c): Код case MODE_STOP: // strcpy(buf0, " Spectron"); // strcpy(buf1, " Click for start"); strcpy_P(buf0, (PGM_P)pgm_read_word(&(str0))); strcpy_P(buf1, (PGM_P)pgm_read_word(&(str1))); break; , а где-то сполшной туман (как потом, через полгода буду сам продираться через это код -- типа что этим кодом хотел сделать и почему нужно было так извращаться, почему нельзя было написать сразу ясно-понятно-чисто): Код case MODE_0: // sprintf(buf0, "Channel 1:%6lu", uvchannel0); strcpy_P(buf0, (PGM_P)pgm_read_word(&(str4))); buf0[8] = '1'; ltoa(uvchannel0, buf3, 10); len = strlen(buf3); strcpy((buf0 + (16 - len)), buf3);
buf1[0] = 0x00; break; Вот, при такой замене размер секции text даже увеличился с 3400 до 3456 байт, а размер секции data уменьшился со 114 до 86 байт. Потом я вынес повторяющиеся участки в отдельную функцию: Код void preplcd(char *buf, char ach, long uv) { char buf3[12]; uint8_t len;
strcpy_P(buf, (PGM_P)pgm_read_word(&(str4))); buf[8] = ach; ltoa(uv, buf3, 10); len = strlen(buf3); strcpy((buf + (16 - len)), buf3); } оставив на месте только ее вызов: Код // sprintf(buf0, "Channel 1:%6lu", uvchannel0); preplcd(buf0, '1', uvchannel0);
buf1[0] = 0x00; break; То размер секции text удалось еще ужать до 3420 байт. Таким образом, размер бинарного кода для загрузки во флеш сейчас составляет 3506 байт. Резюме всего исследования будет такое: IAR по сравнению с gcc создает заметно более компактный код при минимальных усилиях со стороны программиста.Увы и ах! Я так понимаю, дальнейшие изыскания не приводят к желаемому результату. К сожалению, вынужден признать, что в этот раз gcc "продул" IAR-у. Это вывод №1. Вывод №2. Замена sprintf на серию функций не дала существенной экономии. На деле даже получился небольшой проигрыш. Но это скорее всего из-за того, что были так же взяты не чистые функции (strcpy), а функции работы с флеш-памятью (strcpy_P). Но так или иначе получается, что раз улучшения нет, то функции printf в libc не такие уж и "раздутые", как казалось ранее. Просто что-то еще улучшить в gcc или libc у их создателей уже не получается. Использовать же printf на практике вполне можно и даже нужно, ибо ясность исходного кода куда более важна, чем экономия 20 байт флеша. Если у вас есть что добавить или опровергнуть, пожалуйста скажите, я же дальнейшие "исследования" в этом направлении прекращаю. Здесь ловить не чего.
--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|