Du har redan några helt bra svar. Jag lägger upp det här bara för att dela statistik som jag gjorde en dag och jag frågade mig samma slags frågor: Vad tar så mycket utrymme på en minimal skiss? Vad behövs minst för att uppnå samma funktionalitet?
Nedan följer tre versioner av ett minimalt blinkande program som växlar mellan LED på stift 13 varje sekund. Alla tre versionerna har sammanställts för anUno (ingen USB inblandad) med avr-gcc 4.8.2, avr-libc 1.8.0 andarduino-core 1.0.5 (jag använder inte Arduino IDE).
Först, det vanliga Arduino-sättet:
const uint8_t ledPin = 13; void setup () {pinMode (ledPin, OUTPUT);} void loop () {digitalWrite (ledPin, HIGH); fördröjning (1000); digitalWrite (ledPin, LOW); delay (1000);}
Detta sammanställs till 1018 byte. Med både avr-nm
och demontering delade jag upp den storleken i enskilda funktioner. Från största till minsta:
148 A ISR (TIMER0_OVF_vect) 118 A init 114 A pinMode 108 A digitalWrite 104 C vektortabell 82 A turnOffPWM 76 A fördröjning 70 A micros 40 U loop 26 A main 20 A digital_pin_to_timer_PGM 20 A digital_pin_to_port_PGM 20 A digital_pin_to_bit_mask_PGM 16 C __do_clear_bss 12 C __init 10 A port_to_output_PGM 10 A port_to_mode_PGM 8 U setup 8 C .init9) ------------------------ 1018 TOTALT
I listan ovan är den första kolumnen storleken i byte , och den andra kolumnen berättar om koden kommer från Arduino-kärnbiblioteket (A, totalt 822 byte), C-körningstiden (C, 148 byte) eller användaren (U, 48byte).
Som kan vara sett i den här listan är den största funktionen rutinservicering av timern 0 överflödsavbrott. Denna rutin ansvarar för spårningstiden och behövs av millis ()
, micros ()
och delay ()
. Den näst största funktionen är init ()
, som ställer in hårdvarutimrarna
för PWM, möjliggör avbrott i TIMER0_OVF och kopplar bort USART (som användes av startladdaren). Både denna och den tidigare funktionen definieras i <Arduino-katalog> / hardware / arduino / cores / arduino / wiring.c
.
Nästa är C + avr-libc-versionen:
#include <avr / io.h> # include <util / delay.h>int main (void) {DDRB | = _BV (PB5); / * ställa in stift PB5 som utgång * / för (;;) {PINB = _BV (PB5); / * växla PB5 * / _fördröjning_ms (1000); }}
Fördelningen av de enskilda storlekarna:
104 C vektortabell 26 U main 12 C __init 8 C .init9 (call main, jmp exit) 4 C __bad_interrupt 4 C _exit ---------------------------------- 158 TOTALT
Detta är 132 byte för C-körning och 26 byte användarkod, inklusive den inline-funktionen _fördröjning_ms().
Det kan noteras att eftersom detta programmet använder inte avbrott, avbrottsvektortabellen behövs inte och vanlig användarkod kan placeras på sin plats. Följande monteringsversion gör exakt det:
#include <avr / io.h> # define io (reg) _SFR_IO_ADDR (reg) sbi io (DDRB), 5; ställa in PB5 som utgångsslinga: sbi io (PINB), 5; växla PB5 ldi r26, 49; fördröjning för 49 * 2 ^ 16 * 5 cyklerfördröjning: sbiw r24, 1 sbci r26, 0 brne fördröjning rjmp-slinga
Detta är monterat (med avr-gcc -nostdlib kod >) i endast 14 byte, varav de flesta används för att fördröja växlarna så att blinkningen är synlig. Om du tar bort fördröjningsslingan slutar du med ett 6-byte-program som blinkar för snabbt för att ses (vid 2 MHz):
sbi io (DDRB), 5; ställa in PB5 som utgångsslinga: sbi io (PINB), 5; växla PB5 rjmp-slinga