ATTiny13 - avr-gcc Hello World menggunakan lebih dari 100 byte?

9

Saya mencoba menulis program untuk ATTiny13. Masalah saya adalah ia memiliki batasan ukuran yang sangat besar. Nah, ketika membuat program Hello World pertama saya, butuh ruang program 100 byte hanya untuk menghidupkan dan mematikan lampu! Apakah ada opsi yang bisa saya berikan untuk avr-gcc untuk memperkecil ukuran ini? Juga, apa yang ada di crt0? Saya tidak terlalu tertarik pada perakitan AVR jadi saya tidak terlalu mengerti ..

Saya tidak mau harus turun ke perakitan untuk proyek ini ..

Earlz
sumber
Sebagai catatan tambahan, beberapa orang akan menyebutnya program "Blinky".
Johan
1
@ Yah, aku tidak yakin bagaimana mengeja "blinkenlights"
Earlz

Jawaban:

9

crt0 adalah rutinitas startup untuk UC. Rutinitas melakukan pengaturan register dan juga inisialisasi data.

Apakah 100 byte menyertakan tabel vektor interupsi? Saya tidak yakin tentang ATtiny13 tetapi ATtiny25 / 45/85 memiliki 15 vektor interupsi. Ini akan memakan waktu 30 byte.

gcc memiliki opsi untuk menautkan di crt0 Anda. Anda bisa mengambil file AVR crt0.S dan memodifikasinya. Ini tidak terlalu lama sehingga seharusnya tidak sulit untuk dilakukan.

jluciani
sumber
Saya tidak bisa menemukan sumber crt0, tetapi di crt1 ada apa yang tampaknya menjadi tabel vektor interupsi. Mungkin itu saja
Earlz
Saya juga tidak dapat menemukannya di sistem saya :( Saya mengkompilasi semua alat dari sumber, jadi saya pikir itu akan ada di sana. Jika Anda mencari "crt0.S atmel", beberapa aplikasi-catatan Atmel tentang startup, crt0 dan gcc optimasi muncul Mungkin ada beberapa petunjuk dalam dokumen tersebut
jluciani
@ jlu Saya mencoba untuk mencari tahu perbedaan antara keduanya tetapi belum mendapatkan hal yang baik di Stack Overflow: stackoverflow.com/questions/2709998/…
Earlz
2
avr-libc memiliki CRT yang berbeda untuk setiap jenis chip AVR, dan distro avr-libc standar hanya menyertakan versi file .o. Yang untuk ATtiny13 terletak di [avr-libc-path] /avr-3/lib/crttn13.o
todbot
@todbot hmm. Ah, ok ya saya memilikinya di/avr-libc-1.6.7/avr/lib/avr2/attiny13/crttn13.S
Earlz
19

Anda dapat menggunakan avr-objdump -d .elf untuk melihat apa yang dihasilkan:

Mari kita analisa sedikit:

[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 byte tabel vektor interupsi (setidaknya beberapa entri dapat dihilangkan jika Anda bersikeras dan berjanji Anda tidak akan pernah mengaktifkan interupsi yang sesuai).

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>

Menghapus SREG (saya tidak yakin ini benar-benar diperlukan), menulis 0x9f (RAMEND) ke SPL (penumpukan tumpukan) dan melompat ke main. Rjmp terakhir adalah jenis yang berlebihan. (Anda bisa berjanji untuk tidak pernah kembali dari utama)

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

Prosedur interupsi default untuk interupsi-interupsi tersebut daripada yang tidak memiliki satu ditimpa dalam C. (aturan yang sama seperti untuk vektor _)

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>

Proc utama Anda. Ketat.

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

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

Keduanya tidak terlalu berguna. _exit mungkin diperlukan oleh standar C dan __stop_program diperlukan agar bisa berfungsi sebagaimana mestinya.

jpc
sumber
16

Apa aplikasi akhirnya Anda? ATtiny13 memiliki 1kB flash dan Anda dapat melakukan banyak hal dengan itu di C. Crt0 adalah runtime avr-libc C. Ini berisi hal-hal seperti penanganan tumpukan sehingga Anda dapat menggunakan fungsi dengan argumen dan mengembalikan nilai.

100 byte untuk pengaturan C tertanam tidak terlalu buruk, dan ukurannya konstan. Menggandakan garis-garis logika program tidak akan membuatnya 200 byte. Di tingkat optimisasi apa Anda menyusun? Anda harus berada di "-Os". Dan bagaimana Anda menyusun ini? Makefiles dalam proyek demo yang tersedia dari situs avr-libc cukup bagus dan komprehensif.

Program on / off LED sederhana di bawah ini membutuhkan 62 byte pada ATtiny13 dengan "-Os" pada avr-gcc 4.3.3. dari CrossPack-AVR:

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

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

Menghapus panggilan _delay_ms () membuatnya menjadi 46 byte.

Contoh yang lebih besar pada ATtiny13 adalah prototipe Smart LED saya . Kode ini berisi PWM perangkat lunak 3-channel, konversi warna HSV-ke-RGB, mesin status, dan membaca dua tombol. Ini tidak ditulis dengan baik dan masuk pada 864 byte. Di bawah avr-gcc 3.x itu bahkan lebih kecil. (untuk beberapa alasan avr-gcc 4 telah membuat hampir semua program tumbuh beberapa byte)

todbot
sumber
avr-gcc -std=c99 -Wall -Os -mmcu=attiny13 -o hello.out helloworld.cadalah baris yang relevan di makefile saya (dibuat sendiri). dan saya menggunakan kode yang hampir sama kecuali untuk membalikkan LED yang saya gunakan PORTB &= ~(1 << LED);dan semacamnya
Earlz
Dan ya, ukurannya konstan, tetapi bahkan 46 byte tampaknya agak berat jika yang harus dilakukan hanyalah mengatur stackframe
Earlz
2

Jika Anda kekurangan ruang, coba meja kerja Embedded IAR - versi 'kickstart' gratis mereka memiliki batas ukuran kode kata 4K, begitu banyak untuk ATTiny, dan mungkin optimalisasi yang lebih baik daripada gcc

mikeselectricstuff
sumber
1
Perbandingan optimasi adalah subjek pertentangan yang tinggi. Saya tidak akan pergi ke sana.
tyblu
1
@tyblu Saya setuju, tetapi IAR dikenal untuk memproduksi binari yang lebih kecil daripada avr-gcc misalnya .. Saya juga akan setuju dengan mikeselectricstuff dan saya pikir itu adalah nasihat yang masuk akal.
Morten Jensen
1

Perangkat seperti itu sering diprogram dalam assembler, menghasilkan executable yang lebih kecil. Perlu upaya dan pembelajaran untuk menggunakannya.

Leon Heller
sumber
1
Saya setuju tetapi IMHO tujuannya bukan untuk memprogram seluruh perangkat dalam perakitan (saya tahu ini sering dilakukan dan saya melakukan ini juga) tetapi untuk dapat memecahkan kode dan memverifikasi apa yang dilakukan kompiler C di belakang Anda. Ini juga berarti Anda akan sering dapat menebak kompiler dan mengoptimalkan kode yang Anda tulis dalam C untuk mendapatkan ukuran kecil yang dapat dieksekusi.
jpc