ATTiny13 - avr-gcc Hello World ใช้มากกว่า 100 ไบต์?


9

ฉันพยายามเขียนโปรแกรมสำหรับ ATTiny13 ปัญหาของฉันคือมันมีข้อ จำกัด ขนาดใหญ่ เมื่อสร้างโปรแกรม Hello World ครั้งแรกของฉันมันใช้พื้นที่ของโปรแกรม 100 ไบต์เพื่อเปิดและปิดไฟ! มีตัวเลือกใดบ้างที่ฉันสามารถมอบให้ avr-gcc เพื่อย่อขนาดให้เล็กลงได้หรือไม่? นอกจากนี้อะไรใน crt0 ฉันไม่ค่อยกระตือรือร้นกับชุด AVR ดังนั้นฉันไม่เข้าใจมันมาก ..

ฉันไม่ต้องการที่จะวางลงในการชุมนุมสำหรับโครงการนี้ ..


ในฐานะที่เป็นบันทึกด้านข้างเล็กน้อยบางคนจะเรียกว่าโปรแกรม "Blinky" -
Johan

1
@ โจฮันดีฉันไม่แน่ใจว่าจะสะกด "
blinkenlights

คำตอบ:


9

crt0 เป็นรูทีนเริ่มต้นสำหรับ uC รูทีนดำเนินการตั้งค่าของรีจิสเตอร์และการกำหนดค่าเริ่มต้นของข้อมูล

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 distros มาตรฐานจะมีเฉพาะไฟล์. o เวอร์ชันเท่านั้น หนึ่งสำหรับ ATtiny13 ตั้งอยู่ที่ [avr-libc-path] /avr-3/lib/crttn13.o
todbot

@todbot hmm อ่าใช่แล้วฉันมีมันใน/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 (กฎเดียวกับ __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 หลักของคุณ แน่น

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

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

ทั้งสองนี้ไม่มีประโยชน์มาก _exit อาจเป็นที่ต้องการโดยมาตรฐาน C และ __stop_program จำเป็นสำหรับการทำงานตามที่ควร


16

ใบสมัครของคุณในที่สุดคืออะไร? ATtiny13 มีแฟลชขนาด 1kB และคุณสามารถทำได้มากใน C crt0 เป็น avr-libc C runtime มันมีสิ่งต่าง ๆ เช่นการจัดการสแต็คเพื่อให้คุณสามารถใช้ฟังก์ชั่นที่มีข้อโต้แย้งและค่าตอบแทน

100 ไบต์สำหรับการตั้งค่า C แบบฝังไม่เลวเกินไปและมีขนาดคงที่ การเพิ่มจำนวนบรรทัดของโปรแกรมตรรกะไม่จำเป็นต้องเท่ากับ 200 ไบต์ คุณกำลังรวบรวมระดับการปรับให้เหมาะสมระดับใด คุณควรอยู่ที่ "-Os" และคุณรวบรวมสิ่งนี้อย่างไร Makefiles ในโครงการตัวอย่างพร้อมใช้งานจากเว็บไซต์ avr-libc นั้นค่อนข้างดีและครอบคลุม

โปรแกรมเปิด / ปิด LED อย่างง่ายด้านล่างใช้เวลา 62 ไบต์บน ATtiny13 พร้อมด้วย "-Os" บน avr-gcc 4.3.3 จาก CrossPack-AVR:

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

int main (เป็นโมฆะ)
{
    DDRB | = _BV (PB3);
    ในขณะที่ (1) { 
        PORTB | = _BV (PB3);
        _delay_ms (200);
        PORTB & = ~ _BV (PB3);
        _delay_ms (200);
    }
}

การลบการเรียก _delay_ms () ทำให้มีขนาด 46 ไบต์

ตัวอย่างขนาดใหญ่บน ATtiny13 เป็นของฉันต้นแบบ Smart LED รหัสนี้ประกอบด้วยซอฟต์แวร์ PWM 3 ช่องสัญญาณ, การแปลงสี HSV-to-RGB, เครื่องสถานะและอ่านสองปุ่ม มันเขียนไม่ค่อยดีและมีขนาด 864 ไบต์ ภายใต้ avr-gcc 3.x มันมีขนาดเล็กลง (ด้วยเหตุผลบางอย่าง avr-gcc 4 ทำให้โปรแกรมเกือบทั้งหมดเติบโตขึ้นด้วยไม่กี่ไบต์


avr-gcc -std=c99 -Wall -Os -mmcu=attiny13 -o hello.out helloworld.cคือบรรทัดที่เกี่ยวข้องใน makefile ของฉัน (สร้างขึ้นเอง) และฉันใช้รหัสที่เกือบเหมือนกันยกเว้นเพื่อพลิก LED ที่ฉันใช้PORTB &= ~(1 << LED);และเช่นนั้น
Earlz

และใช่ขนาดคงที่ แต่แม้กระทั่ง 46 ไบต์ดูเหมือนจะหนักถ้าทั้งหมดที่ต้องทำคือการติดตั้งส
แต็กเฟรม

2

หากคุณว่างในพื้นที่ลอง Workbench ที่ฝังตัวของ IAR - รุ่น 'kickstart' ฟรีของพวกเขามีขีด จำกัด ขนาดของรหัสคำ 4K เพื่อประโยชน์มากมายสำหรับ ATTiny และอาจเป็นการเพิ่มประสิทธิภาพที่ดีกว่า gcc


1
การเปรียบเทียบการเพิ่มประสิทธิภาพเป็นเรื่องที่มีความขัดแย้งสูง ฉันจะไม่ไปที่นั่น
tyblu

1
@tyblu ฉันเห็นด้วย แต่ IAR นั้นเป็นที่รู้จักกันดีในการผลิตไบนารีขนาดเล็กกว่า avr-gcc เช่นกัน .. ฉันก็เห็นด้วยกับ mikeselectricstuff แม้ว่าและฉันคิดว่ามันเป็นคำแนะนำที่มีเหตุผล
มอร์เทนเซ่น

1

อุปกรณ์เช่นนั้นมักถูกตั้งโปรแกรมไว้ในแอสเซมเบลอร์ มันคุ้มค่าที่จะใช้ความพยายามและเรียนรู้ที่จะใช้มัน


1
ฉันจะเห็นด้วย แต่ IMHO เป้าหมายไม่ใช่การตั้งโปรแกรมอุปกรณ์ทั้งหมดในชุดประกอบ (ฉันรู้ว่ามันทำบ่อยและฉันก็ทำเช่นนี้ด้วย) แต่สามารถถอดรหัสและตรวจสอบสิ่งที่คอมไพเลอร์ C กำลังทำอยู่ด้านหลังของคุณ นอกจากนี้ยังหมายความว่าคุณจะสามารถคาดเดาคอมไพเลอร์เป็นครั้งที่สองและเพิ่มประสิทธิภาพโค้ดที่คุณเขียนใน C เพื่อให้ได้ขนาดไฟล์เล็ก
jpc
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.