ATTiny13 - avr-gcc Hello World використовує понад 100 байт?


9

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

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


Як невелику сторону зауважте, деякі люди називали б це "мерехтінням" -програмою.
Йохан

1
@Johan добре, я не був упевнений, як написати "блималки"
Earlz

Відповіді:


9

crt0 - це програма запуску uC. Підпрограми виконують налаштування регістрів, а також ініціалізацію даних.

Чи містить 100 байт таблицю векторів переривань? Я не впевнений у ATtiny13, але ATtiny25 / 45/85 має 15 перериваючих векторів. Це займе 30 байт.

gcc має можливість посилання у crt0. Ви можете взяти файл AVR crt0.S і змінити його. Це не дуже довго, тому це не повинно бути складно.


Я не можу знайти джерело crt0, але в crt1 є те, що, схоже, є векторною таблицею переривань. Можливо, це все
граф

Я також не можу його знайти у своїй системі :( Я скомпілював усі інструменти з джерела, тому я подумав, що це буде. Якщо ви google для "crt0.S atmel", кілька приміток програми Atmel щодо запуску, crt0 та gcc оптимізація підійде. Можливо, є якісь підказки в цих документах
jluciani

@jlu Я намагаюся з'ясувати різницю між ними , але не отримав жодної річ хорошого на Stack Overflow ще: 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
мене

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.

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 байт для вбудованої установки C не надто погано, і це постійний розмір. Подвоєння рядків програмної логіки не обов'язково становитиме 200 байт. На якому рівні оптимізації ви збираєтесь? Ви повинні бути на "-Os". І як ти це складеш? Makefiles в демонстраційних проектах, доступних на сайті avr-libc, досить хороші та всебічні.

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

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

int main (пустота)
{
    DDRB | = _BV (PB3);
    while (1) { 
        PORTB | = _BV (PB3);
        _delay_ms (200);
        ПОРТБ & = ~ _BV (PB3);
        _delay_ms (200);
    }
}

Якщо видалити виклики _delay_ms (), це 46 байт.

Більш великий приклад ATtiny13 - мої прототипи Smart LED . Цей код містить 3-канальне програмне забезпечення PWM, перетворення кольорів HSV в RGB, стан машини і зчитує дві кнопки. Він не написаний особливо добре і надходить у 864 байт. Під avr-gcc 3.x вона була ще меншою. (чомусь avr-gcc 4 зробив майже всі програми зростають на кілька байтів)


avr-gcc -std=c99 -Wall -Os -mmcu=attiny13 -o hello.out helloworld.cє відповідним рядком у моєму makefile (створено самостійно). і я використовую майже однаковий код, за винятком перегортання використовуваного світлодіода PORTB &= ~(1 << LED);і такого
Earlz

І так, розмір постійний, але навіть 46 байт здається важким, якщо все, що він повинен зробити, - це встановити
стекфрейм

2

Якщо вам не вистачає місця, спробуйте вбудований робочий стіл IAR - їхня безкоштовна версія 'kickstart' має 4K обмеження розміру коду слова, так що багато для ATTiny, і, можливо, краща оптимізація, ніж gcc


1
Порівняння оптимізації є предметом великих суперечок. Я б не поїхав туди.
tyblu

1
@tyblu Я згоден, але IAR відомий тим, що виробляє менші бінарні файли, ніж, наприклад, avr-gcc. Я б також погодився з mikeselectricstuff, хоча і я думаю, що це розумна порада.
Мортен Йенсен

1

Такі пристрої часто запрограмовані в асемблері, що призводить до менших виконуваних файлів. Варто докласти зусиль і навчитися ним користуватися.


1
Я погодився б, але мета IMHO - не програмувати цілі пристрої в зборі (я знаю, що це часто робиться, і я це робив також), а мати можливість розшифрувати та перевірити, що компілятор C робить за вашою спиною. Це також означає, що ви часто зможете вдруге здогадуватися про компілятор і оптимізувати код, який ви пишете на C, щоб отримати невеликий розмір виконуваного файлу.
jpc
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.