ATTiny13 - avr-gcc Hello World utilizza oltre 100 byte?


9

Sto cercando di scrivere un programma per ATTiny13. Il mio problema è che ha vincoli di dimensioni enormi. Bene, quando ho realizzato il mio primo programma Hello World, ci sono voluti 100 byte di spazio del programma solo per accendere e spegnere la luce! Ci sono opzioni che posso dare ad avr-gcc per ridurre questa dimensione? Inoltre, cosa c'è nel crt0? Non sono troppo appassionato di assemblaggio AVR, quindi non lo capisco molto ..

Non voglio passare all'assemblaggio per questo progetto.


Come piccola nota a margine, alcune persone lo chiamerebbero un programma "Blinky".
Johan

1
@Johan bene non ero sicuro di come si scrive "luci lampeggianti"
Earlz

Risposte:


9

crt0 è la routine di avvio per l'UC. Le routine eseguono la configurazione dei registri e anche l'inizializzazione dei dati.

I 100 byte includono la tabella vettoriale di interrupt? Non sono sicuro di ATtiny13 ma ATtiny25 / 45/85 ha 15 vettori di interrupt. Ciò richiederebbe 30 byte.

gcc ha un'opzione per il collegamento nel tuo crt0. È possibile prendere il file crt0.S di AVR e modificarlo. Non è molto lungo, quindi non dovrebbe essere difficile da fare.


Non riesco a trovare l'origine crt0, ma in crt1 c'è quella che sembra essere una tabella vettoriale di interrupt. Forse è così
Earlz,

Non riesco nemmeno a trovarlo sul mio sistema :( Ho compilato tutti gli strumenti dal sorgente, quindi ho pensato che sarebbe stato lì. Se cerchi Google "crt0.S atmel" un paio di note app Atmel sull'avvio, crt0 e gcc l'ottimizzazione arriva. Forse ci sono alcuni suggerimenti in quei documenti.
jluciani,

@jlu Sto cercando di capire la differenza tra i due, ma non ho ancora ottenuto alcun cosa buona su Stack Overflow: stackoverflow.com/questions/2709998/...
Earlz

2
avr-libc ha un CRT diverso per ogni tipo di chip AVR e le distro standard avr-libc includono solo la versione .o del file. Quello per ATtiny13 si trova in [avr-libc-path] /avr-3/lib/crttn13.o
todbot,

@todbot hmm. Ah, ok sì, ce l'ho/avr-libc-1.6.7/avr/lib/avr2/attiny13/crttn13.S
Earlz,

19

Puoi usare avr-objdump -d .elf per vedere cosa viene generato:

Analizziamolo un po ':

[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>

Tabella vettoriale di interrupt di 20 byte (almeno alcune voci potrebbero essere omesse se si insistesse e si fosse promesso di non abilitare mai gli interrupt corrispondenti).

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>

Cancella SREG (non sono sicuro che sia davvero necessario), scrive 0x9f (RAMEND) su SPL (il puntatore dello stack) e passa alla schermata principale. L'ultimo rjmp è un po 'ridondante. (potresti promettere di non tornare mai dalla rete principale)

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

Procedura di interruzione predefinita per quegli interrupt che non ne hanno uno sovrascritto in C. (stesse regole di __vettori)

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>

Il tuo proc principale. Stretto.

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

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

Questi due non sono molto utili. _exit è probabilmente richiesto dallo standard C ed __stop_program è necessario per farlo funzionare come dovrebbe.


16

Qual è la tua eventuale domanda? Un ATtiny13 ha 1kB di flash e puoi fare molto con quello in C. crt0 è il runtime C di avr-libc. Contiene cose come la gestione dello stack in modo da poter usare le funzioni con argomenti e valori di ritorno.

100 byte per l'installazione C incorporata non sono troppo male e hanno dimensioni costanti. Raddoppiare le linee della logica del programma non lo renderà necessariamente di 200 byte. A quale livello di ottimizzazione stai compilando? Dovresti essere in "-Os". E come lo stai compilando? I Makefile nei progetti demo disponibili dal sito avr-libc sono abbastanza buoni e completi.

Il semplice programma di attivazione / disattivazione LED di seguito prende 62 byte su un ATtiny13 con "-Os" su avr-gcc 4.3.3. da CrossPack-AVR:

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

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

La rimozione delle chiamate _delay_ms () lo rende 46 byte.

Un esempio più ampio su ATtiny13 sono i miei prototipi di Smart LED . Questo codice contiene un software PWM a 3 canali, una conversione di colore da HSV a RGB, una macchina a stati e legge due pulsanti. Non è scritto particolarmente bene e arriva a 864 byte. Sotto avr-gcc 3.x era ancora più piccolo. (per qualche ragione avr-gcc 4 ha fatto crescere di quasi tutti i programmi quasi pochi byte)


avr-gcc -std=c99 -Wall -Os -mmcu=attiny13 -o hello.out helloworld.cè la riga pertinente nel mio makefile (auto-creato). e uso un codice quasi identico, tranne per capovolgere il LED che uso PORTB &= ~(1 << LED);e simili
Earlz

E sì, la dimensione è costante, ma anche 46 byte sembrano un po 'pesanti se tutto ciò che deve fare è impostare uno stackframe
Earlz

2

Se sei a corto di spazio, prova il banco di lavoro integrato di IAR: la loro versione gratuita di "kickstart" ha un limite di dimensioni del codice parola 4K, quindi molto per ATTiny e probabilmente un'ottimizzazione migliore di gcc


1
I confronti di ottimizzazione sono oggetto di contese elevate. Non ci andrei.
Tyblu,

1
@tyblu Sono d'accordo, ma IAR è noto per la produzione di file binari più piccoli di avr-gcc per esempio .. Concordo anche con mikeselectricstuff e penso che sia un consiglio sensato.
Morten Jensen,

1

Dispositivi del genere sono spesso programmati in assemblatore, con conseguente eseguibili più piccoli. Vale la pena fare lo sforzo e imparare a usarlo.


1
Sono d'accordo, ma l'obiettivo di IMHO non è programmare interi dispositivi in ​​assembly (so che questo è fatto spesso e l'ho fatto anch'io) ma essere in grado di decodificare e verificare cosa sta facendo il compilatore C alle tue spalle. Significa anche che sarai spesso in grado di indovinare il compilatore e ottimizzare il codice che scrivi in ​​C per ottenere piccole dimensioni eseguibili.
jpc,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.