цифровая электроника
вычислительная техника
встраиваемые системы

 

Срежьте жирок с AVR-GCC кода

Автор: Mike(admin) от 8-12-2013, 09:15

Хотя использование AVR-ассемблера позволяет легко писать компактные по размеру кода программы, все же использование языка C и AVR Libc дает больше удобств. В этой статье будет показано, как написать код на C, который avr-gcc скомпилирует с минимальным размером. Существует ряд руководств по написанию компактного кода для AVR, но ни одно из них не рассматривает вопрос сокращения оверхеда в start-up библиотеке avr-gcc (gcrt1).


Многие все еще применяют avr-gcc 4.3.3, поскольку он дает более плотный код по сравнению с версиями 4.5.3 и 4.7, но для ниже приведенного примера avr-gcc 4.8.2 дал еще более компактный код, нежели 4.3.3.


Тестовая программа работает со встроенным температурным датчиком ATtiny85 и мигает светодиодом. После компиляции с оптимизацией –Os получаем программу размером 274 байта:


avr-size temperature
text data bss dec hex filename
274 0 0 274 112 temperature.bu


Благодаря avr-gcc 4.8.2 программа стала весить 240 байтов:


avr-size temperature-4.8
text data bss dec hex filename
240 0 0 240 f0 temperature-4.8


Разница прежде всего заключается в startup-файлах, связанных с кодом. Дизассемблирование с помощью avr-objdump –d показывает, что вектор сброса содержит переход на функцию под названием __ctors_end:


0: 0e c0 rjmp .+28 ; 0x1e
0000001e :
1e: 11 24 eor r1, r1
20: 1f be out 0x3f, r1 ; 63
22: cf e5 ldi r28, 0x5F ; 95
24: d2 e0 ldi r29, 0x02 ; 2
26: de bf out 0x3e, r29 ; 62
28: cd bf out 0x3d, r28 ; 61


Функция __ctors_end переходит в __do_copy_data, которая в свою очередь переходит в __do_clear_bss до rcall-вызова main, за которым следует rjmp-переход на _exit. Таким образом, мы получаем 50 байтов кода, предшествующих вызову main. В avr-gcc 4.8.2 перед main имеется только __ctors_end, то есть всего лишь 16 байтов оверхеда.


До того, как убрать __ctors_end, нужно убедиться, что код __ctors_end действительно является оверхедом, который можно безопасно удалить. Первые две строчки очищают SREG. Раздел 8.1 документации на ATtinyX5 гласит: «Во время сброса все регистры ввода/вывода устанавливаются в свои начальные значения, и программа начинает выполнение с вектора сброса». Этот даташит также говорит нам о том, что под начальным значением понимается 0, поэтому первые две строчки можно спокойно убирать. Последние 4 строки устанавливают указатель стека (регистры SPL и SPH) в RAMEND, что, как утверждает раздел 4.6, и является начальным значением. В связи с этим можно смело удалять __ctors_end и переходить с вектора сброса сразу на main, что сэкономит 16 байтов.


Еще 30 байтов данных используется для таблицы векторов прерываний (для ATmega даже более 30 байтов). Раздел 9.1 гласит: «Если программа не задействует источник прерывания, векторы прерывания не используются, и обычный код программы может быть размещен в этой области памяти вместо кода для прерываний». В данном случае программе не нужны никакие прерывания, поэтому можно освободить больше места, избавившись от таблицы прерываний.


Способом сказать компилятору avr-gcc, что не нужно линковать startup-код является директива –nostartfiles. Тогда avr-gcc привяжет первый объектный файл к адресу 0 (вектор сброса). Чтобы быть уверенным, что вектор сброса содержит переход на main, можно написать небольшую программку на ассемблере (crt1.s):


.org 0x0000
__vectors:
rjmp main


Этот необычный startup-код нужно задействовать вместо gcrt1, который включен в библиотеки компиляторов. Далее следует скомпилировать его (avr-gcc -c crt1.s) и слинковать со своим кодом на C. Чтобы получить еще более компактный код, можно применить пару дополнительных флагов:


avr-gcc -mmcu=attiny85 -Os -fno-inline-small-functions -mrelax -nostartfiles crt1.o temperature.c -o temperature


В итоге программа весит 190. Это экономит 84 байта по сравнению с обычным использованием avr-gcc 4.3.3 или 50 байтов при использовании avr-gcc 4.8.2:


avr-size temperature
text data bss dec hex filename
190 0 0 190 be temperature


Перевод © digitrode.ru


<Источник>


Теги: AVR, ассемблер, язык C




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

Комментарии:

Оставить комментарий