Zaten bazı mükemmel cevaplarınız var. Bunu sadece bir gün yaptığım bazı istatistikleri paylaşmak için gönderiyorum. Kendime aynı soruları sordum: Minimal bir taslakta bu kadar yer kaplayan nedir? Aynı işlevselliği elde etmek için gereken minimum miktar nedir?
Aşağıda, her saniye pin 13'teki LED'i değiştiren minimal bir blinky programının üç versiyonu bulunmaktadır. Her üç sürüm de avr-gcc 4.8.2, avr-libc 1.8.0 ve arduino-core 1.0.5 (Arduino IDE kullanmıyorum) kullanılarak bir Uno (USB dahil değil) için derlenmiştir.
İlk olarak, standart Arduino yolu:
const uint8_t ledPin = 13;
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
delay(1000);
}
Bu 1018 bayta derlenir. Her ikisini de avr-nm
ve sökmeyi kullanarak , bu boyutu bireysel işlevlere ayırdım. Büyükten küçüğe:
148 A ISR(TIMER0_OVF_vect)
118 A init
114 A pinMode
108 A digitalWrite
104 C vector table
82 A turnOffPWM
76 A delay
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 (call main, jmp exit)
4 C __bad_interrupt
4 C _exit
-----------------------------------
1018 TOTAL
Yukarıdaki listede, ilk sütun bayt cinsinden boyuttur ve ikinci sütun kodun Arduino çekirdek kütüphanesinden (toplam A, 822 bayt), C çalışma zamanından (C, 148 bayt) veya kullanıcıdan (U , 48 bayt).
Bu listede görülebileceği gibi, en büyük fonksiyon zamanlayıcı 0 taşma kesintisine hizmet eden rutindir. Bu rutin süresini izleme sorumludur ve ihtiyaç duyduğu millis()
, micros()
ve delay()
. İkinci en büyük işlev, init()
PWM için donanım zamanlayıcılarını ayarlayan TIMER0_OVF kesmesini etkinleştiren ve USART (önyükleyici tarafından kullanılan) bağlantısını kesen işlevdir. Hem bu hem de önceki işlev
<Arduino directory>/hardware/arduino/cores/arduino/wiring.c
.
Sonraki C + avr-libc sürümüdür:
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRB |= _BV(PB5); /* set pin PB5 as output */
for (;;) {
PINB = _BV(PB5); /* toggle PB5 */
_delay_ms(1000);
}
}
Bireysel boyutların dökümü:
104 C vector table
26 U main
12 C __init
8 C .init9 (call main, jmp exit)
4 C __bad_interrupt
4 C _exit
----------------------------------
158 TOTAL
Bu, C çalışma zamanı için 132 bayt ve inline işlevi dahil 26 baytlık kullanıcı kodudur _delay_ms()
.
Bu program kesintileri kullanmadığından, kesme vektör tablosuna gerek olmadığı ve yerine normal kullanıcı kodunun konabileceği belirtilebilir. Aşağıdaki derleme sürümü tam olarak bunu yapar:
#include <avr/io.h>
#define io(reg) _SFR_IO_ADDR(reg)
sbi io(DDRB), 5 ; set PB5 as output
loop:
sbi io(PINB), 5 ; toggle PB5
ldi r26, 49 ; delay for 49 * 2^16 * 5 cycles
delay:
sbiw r24, 1
sbci r26, 0
brne delay
rjmp loop
Bu avr-gcc -nostdlib
sadece 14 bayta monte edilir (ile birlikte ), çoğu yanıp sönmeyi görünür hale getirmek için geçişleri geciktirmek için kullanılır. Bu gecikme döngüsünü kaldırırsanız, görülemeyecek kadar hızlı yanıp sönen 6 baytlık bir programla sonuçlanırsınız (2 MHz'de):
sbi io(DDRB), 5 ; set PB5 as output
loop:
sbi io(PINB), 5 ; toggle PB5
rjmp loop