ATTiny13 - avr-gcc Hello World использует более 100 байтов?


9

Я пытаюсь написать программу для ATTiny13. Моя проблема в том, что он имеет огромные ограничения по размеру. Что ж, при создании моей первой программы Hello World потребовалось 100 байт программного пространства, чтобы включить и выключить свет! Есть ли варианты, которые я могу дать avr-gcc, чтобы уменьшить этот размер? Кроме того, что находится в crt0? Я не слишком увлечен сборкой AVR, поэтому не очень разбираюсь в ней ..

Я не хочу бросать сборку для этого проекта ..


В качестве небольшого примечания, некоторые люди называют это «Blinky» -программой.
Йохан

1
@Джохан: Ну, я не был уверен, как пишется "
blinkenlights

Ответы:


9

crt0 - процедура запуска для ОК. Подпрограммы выполняют настройку регистров, а также инициализацию данных.

Включает ли 100 байтов таблицу векторов прерываний? Я не уверен насчет ATtiny13, но ATtiny25 / 45/85 имеет 15 векторов прерываний. Это займет 30 байтов.

У gcc есть опция для ссылки в вашем crt0. Вы можете взять файл AVR crt0.S и изменить его. Это не очень долго, поэтому это не должно быть трудно сделать.


Я не могу найти источник crt0, но в crt1 есть то, что кажется векторной таблицей прерываний. Возможно это
Earlz

Я также не могу найти его в своей системе :( Я скомпилировал все инструменты из исходного кода, поэтому я подумал, что он будет там. Если вы заглянете в Google для "crt0.S atmel", пара замечаний по поводу приложений Atmel о запуске, crt0 и gcc оптимизация подходит. Может быть, есть какие-то подсказки в этих документах
jluciani

@jlu Я пытаюсь выяснить разницу между этими двумя понятиями, но пока что не получил ничего хорошего о переполнении стека: stackoverflow.com/questions/2709998/…
Earlz

2
avr-libc имеет разные CRT для каждого типа микросхемы AVR, а стандартные дистрибутивы avr-libc включают только .o версию файла. Один для ATtiny13 находится по адресу [avr-libc-path] /avr-3/lib/crttn13.o
todbot

@todbot хм. Ах, да, у меня это есть/avr-libc-1.6.7/avr/lib/avr2/attiny13/crttn13.S
Earlz

19

Вы можете использовать avr-objdump -d .elf, чтобы увидеть, что генерируется:

Давайте немного разберемся:

[jpc@jpc ~] avr-objdump -d avr.elf | sed -e 's/^/    /' | pbcopy

avr.elf:     file format elf32-avr

Disassembly of section .text:

00000000 <__vectors>:
   0:   09 c0           rjmp    .+18        ; 0x14 <__ctors_end>
   2:   0e c0           rjmp    .+28        ; 0x20 <__bad_interrupt>
   4:   0d c0           rjmp    .+26        ; 0x20 <__bad_interrupt>
   6:   0c c0           rjmp    .+24        ; 0x20 <__bad_interrupt>
   8:   0b c0           rjmp    .+22        ; 0x20 <__bad_interrupt>
   a:   0a c0           rjmp    .+20        ; 0x20 <__bad_interrupt>
   c:   09 c0           rjmp    .+18        ; 0x20 <__bad_interrupt>
   e:   08 c0           rjmp    .+16        ; 0x20 <__bad_interrupt>
  10:   07 c0           rjmp    .+14        ; 0x20 <__bad_interrupt>
  12:   06 c0           rjmp    .+12        ; 0x20 <__bad_interrupt>

20-байтовая таблица векторов прерываний (по крайней мере, некоторые записи можно было бы опустить, если бы вы настаивали и обещали, что никогда не включите соответствующие прерывания).

00000014 <__ctors_end>:
  14:   11 24           eor r1, r1
  16:   1f be           out 0x3f, r1    ; 63
  18:   cf e9           ldi r28, 0x9F   ; 159
  1a:   cd bf           out 0x3d, r28   ; 61
  1c:   02 d0           rcall   .+4         ; 0x22 <main>
  1e:   05 c0           rjmp    .+10        ; 0x2a <_exit>

Очищает SREG (я не уверен, что это действительно необходимо), записывает 0x9f (RAMEND) в SPL (указатель стека) и переходит к основному. Последний rjmp является излишним. (вы могли бы обещать никогда не возвращаться с основного)

00000020 <__bad_interrupt>:
  20:   ef cf           rjmp    .-34        ; 0x0 <__vectors>

Процедура прерывания по умолчанию для тех прерываний, которые не были перезаписаны в C. (те же правила, что и для __vectors)

00000022 <main>:
  22:   bb 9a           sbi 0x17, 3 ; 23
  24:   c3 9a           sbi 0x18, 3 ; 24
  26:   c3 98           cbi 0x18, 3 ; 24
  28:   fd cf           rjmp    .-6         ; 0x24 <main+0x2>

Ваш основной процесс. Плотно.

0000002a <_exit>:
  2a:   f8 94           cli

0000002c <__stop_program>:
  2c:   ff cf           rjmp    .-2         ; 0x2c <__stop_program>

Эти два не очень полезны. _exit, вероятно, требуется стандартом C, и __stop_program необходим для того, чтобы он работал как надо.


16

Какова ваша возможная заявка? ATtiny13 имеет 1 КБ флэш-памяти, и вы можете многое сделать с этим в C. crt0 - это среда выполнения avr-libc C. Он содержит такие вещи, как обработка стека, поэтому вы можете использовать функции с аргументами и возвращаемыми значениями.

100 байтов для установки встроенного Си не так уж и плохи, и это постоянный размер. Удвоение строк программной логики не обязательно составит 200 байт. На каком уровне оптимизации вы компилируете? Вы должны быть в "-Os". И как вы это компилируете? Makefiles в демонстрационных проектах, доступных на сайте avr-libc, довольно хороши и полны.

Простая программа включения / выключения светодиода ниже занимает 62 байта на ATtiny13 с «-Os» на avr-gcc 4.3.3. от CrossPack-AVR:

#include <avr / io.h>
#include <avr / delay.h>

int main (void)
{
    DDRB | = _BV (PB3);
    while (1) { 
        PORTB | = _BV (PB3);
        _delay_ms (200);
        PORTB & = ~ _BV (PB3);
        _delay_ms (200);
    }
}

Удаление вызовов _delay_ms () делает его 46 байтов.

Большим примером на ATtiny13 являются мои прототипы Smart LED . Этот код содержит 3-канальный программный ШИМ, преобразование цветов HSV в RGB, конечный автомат и считывает две кнопки. Он не очень хорошо написан и занимает 864 байта. Под avr-gcc 3.x он был еще меньше. (по какой-то причине avr-gcc 4 увеличил почти все программы на несколько байтов)


avr-gcc -std=c99 -Wall -Os -mmcu=attiny13 -o hello.out helloworld.cявляется соответствующей строкой в ​​моем make-файле (самостоятельно создан). и я использую почти идентичный код, за исключением того, чтобы перевернуть светодиод, который я использую, PORTB &= ~(1 << LED);и тому подобное
Earlz

И да, размер постоянен, но даже 46 байтов кажутся довольно тяжелыми, если все, что нужно сделать, это установить стековый фрейм
Earlz

2

Если у вас мало места, попробуйте встроенный верстак IAR - их бесплатная версия «кикстарта» имеет ограничение размера кода в 4K, что достаточно для ATTiny и, возможно, лучше для оптимизации, чем для gcc.


1
Оптимизационные сравнения являются предметом большого спора. Я бы не пошел туда.
Тыбл

1
@tyblu Я согласен, но IAR известен тем, что он производит меньшие двоичные файлы, чем, например, avr-gcc .. Я также согласен с mikeselectricstuff, хотя и думаю, что это вменяемый совет.
Мортен Дженсен

1

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


1
Я бы согласился, но ИМХО цель не в том, чтобы запрограммировать целые устройства в сборке (я знаю, что это часто делается, и я тоже), а в том, чтобы иметь возможность декодировать и проверять, что делает компилятор C за вашей спиной. Это также означает, что вы часто сможете догадываться о компиляторе и оптимизировать код, написанный на C, для получения небольшого размера исполняемого файла.
JPC
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.