ATTiny13 - avr-gcc Hello World sử dụng hơn 100 byte?


9

Tôi đang cố gắng viết một chương trình cho ATTiny13. Vấn đề của tôi là nó có những hạn chế kích thước rất lớn. Chà, khi thực hiện chương trình Hello World đầu tiên của tôi, phải mất 100 byte không gian chương trình chỉ để bật và tắt đèn! Có bất kỳ tùy chọn nào tôi có thể cung cấp cho avr-gcc để thu nhỏ kích thước này xuống không? Ngoài ra, những gì trong crt0? Tôi không quá quan tâm đến lắp ráp AVR vì vậy tôi không hiểu nó nhiều ..

Tôi không muốn phải thả để lắp ráp cho dự án này ..


Một lưu ý nhỏ, một số người sẽ gọi đó là chương trình "Blinky".
Johan

1
@Johan Tôi không chắc cách đánh vần "nháy mắt"
Earlz

Câu trả lời:


9

crt0 là thói quen khởi động cho uC. Các thường trình thực hiện việc thiết lập các thanh ghi và cũng là khởi tạo dữ liệu.

100 byte có bao gồm bảng vectơ ngắt không? Tôi không chắc chắn về ATtiny13 nhưng ATtiny25 / 45/85 có 15 vectơ ngắt. Điều này sẽ mất 30 byte.

gcc có một tùy chọn để liên kết trong crt0 của bạn. Bạn có thể lấy tệp AVR crt0.S và sửa đổi nó. Nó không dài lắm nên không khó thực hiện.


Tôi dường như không thể tìm thấy nguồn crt0, nhưng trong crt1 có một bảng vectơ ngắt. Có lẽ vậy thôi
Earlz

Tôi cũng không thể tìm thấy nó trên hệ thống của mình :( Tôi đã biên dịch tất cả các công cụ từ nguồn nên tôi nghĩ nó sẽ ở đó. Nếu bạn google cho "crt0.S atmel" một vài ghi chú ứng dụng Atmel về khởi động, crt0 và gcc tối ưu hóa đi lên. Có thể có một số gợi ý trong các tài liệu đó.
jluciani

@jlu Tôi đang cố gắng tìm ra sự khác biệt giữa hai người nhưng vẫn chưa nhận được điều gì tốt trên Stack Overflow: stackoverflow.com/questions/2709998/
Lỗi

2
avr-libc có CRT khác nhau cho từng loại chip AVR và các bản phân phối avr-libc tiêu chuẩn chỉ bao gồm phiên bản .o của tệp. Cái dành cho ATtiny13 được đặt tại [avr-libc-path] /avr-3/lib/crttn13.o
todbot

@todbot hmm. À, được rồi, tôi có nó rồi/avr-libc-1.6.7/avr/lib/avr2/attiny13/crttn13.S
Earlz

19

Bạn có thể sử dụng avr-objdump -d .elf để xem những gì đang được tạo:

Hãy phân tích một chút:

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

Bảng vectơ ngắt 20 byte (ít nhất một số mục có thể bị bỏ qua nếu bạn khăng khăng và hứa rằng bạn sẽ không bao giờ kích hoạt các ngắt tương ứng).

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>

Xóa SREG (Tôi không chắc điều này thực sự cần thiết), ghi 0x9f (RAMEND) vào SPL (con trỏ ngăn xếp) và nhảy vào chính. Rjmp cuối cùng là loại dư thừa. (bạn có thể hứa sẽ không bao giờ quay lại từ chính)

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

Quy trình ngắt mặc định cho các ngắt đó hơn là không có ghi đè trong C. (quy tắc tương tự như đối với __vector)

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 chính của bạn. Chặt.

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

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

Hai cái này không hữu dụng lắm. _exit có thể được yêu cầu bởi tiêu chuẩn C và __stop_program là cần thiết để nó hoạt động như bình thường.


16

Ứng dụng cuối cùng của bạn là gì? Một ATtiny13 có 1kB flash và bạn có thể làm được rất nhiều với điều đó trong C. Crt0 là thời gian chạy C avr-libc C. Nó chứa những thứ như xử lý ngăn xếp để bạn có thể sử dụng các hàm với các đối số và trả về giá trị.

100 byte cho thiết lập C nhúng không quá tệ và kích thước không đổi. Nhân đôi các dòng logic chương trình sẽ không nhất thiết phải làm cho nó 200 byte. Mức độ tối ưu hóa nào bạn đang biên dịch? Bạn nên ở "-Os". Và làm thế nào bạn biên dịch này? Makefiles trong các dự án demo có sẵn từ trang avr-libc là khá tốt và toàn diện.

Chương trình bật / tắt đèn LED đơn giản dưới đây chiếm 62 byte trên ATtiny13 với "-Os" trên avr-gcc 4.3.3. từ CrossPack-AVR:

#inc loại <avr / io.h>
#inc loại <avr / delay.h>

int chính (void)
{
    DDRB | = _BV (PB3);
    trong khi (1) { 
        PORTB | = _BV (PB3);
        _delay_ms (200);
        PORTB & = ~ _BV (PB3);
        _delay_ms (200);
    }
}

Xóa các lệnh gọi _delay_ms () làm cho nó 46 byte.

Một ví dụ lớn hơn trên ATtiny13 là các nguyên mẫu LED thông minh của tôi . Mã này chứa một phần mềm 3 kênh PWM, chuyển đổi màu HSV-RGB, máy trạng thái và đọc hai nút. Nó không được viết đặc biệt tốt và có đến 864 byte. Theo avr-gcc 3.x, nó thậm chí còn nhỏ hơn. (vì một số lý do avr-gcc 4 đã làm cho hầu hết các chương trình tăng thêm vài byte)


avr-gcc -std=c99 -Wall -Os -mmcu=attiny13 -o hello.out helloworld.clà dòng có liên quan trong tệp tạo tệp của tôi (tự tạo). và tôi sử dụng mã gần như giống hệt nhau ngoại trừ để lật đèn LED tôi sử dụng PORTB &= ~(1 << LED);và tương tự
Earlz

Và yea, kích thước là không đổi, nhưng ngay cả 46 byte dường như kinda nặng nếu tất cả nó phải làm là thiết lập một StackFrame
Earlz

2

Nếu bạn thiếu không gian, hãy thử bàn làm việc nhúng của IAR - phiên bản 'khởi động' miễn phí của họ có giới hạn kích thước mã từ 4K, rất nhiều cho ATTiny, và có thể tối ưu hóa tốt hơn gcc


1
So sánh tối ưu hóa là một chủ đề của sự tranh chấp cao. Tôi sẽ không đến đó.
tyblu

1
@tyblu Tôi đồng ý, nhưng IAR được biết đến với việc sản xuất các nhị phân nhỏ hơn avr-gcc chẳng hạn .. Tôi cũng đồng ý với các sản phẩm điện tử và tôi nghĩ đó là lời khuyên lành mạnh.
Morten Jensen

1

Các thiết bị như thế thường được lập trình trong trình biên dịch chương trình, dẫn đến các tệp thực thi nhỏ hơn. Thật đáng để nỗ lực và học cách sử dụng nó.


1
Tôi đồng ý nhưng IMHO mục tiêu không phải là lập trình toàn bộ thiết bị lắp ráp (tôi biết việc này thường xuyên được thực hiện và tôi cũng đã làm điều này) nhưng để có thể giải mã và xác minh trình biên dịch C đang làm gì sau lưng bạn. Điều đó cũng có nghĩa là bạn sẽ thường xuyên có thể đoán trình biên dịch thứ hai và tối ưu hóa mã bạn viết bằng C để có kích thước thực thi nhỏ.
jpc
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.