Anatomia di unistruzione in Arduino Pt.1

34
Arduino: Anatomia di un’istruzione - 1 Enrico Colombini (Erix) µhackademy 21 Ottobre 2016

Transcript of Anatomia di unistruzione in Arduino Pt.1

Arduino:Anatomia di un’istruzione - 1

Enrico Colombini (Erix)

µhackademy 21 Ottobre 2016

Abbastanza semplice: 8 bit, poca RAM

Abbastanza complesso: c'è tanto da imparare!

Meno distrazioni per capire i meccanismi

Perché Arduino Uno?

void setup() { pinMode(LED_BUILTIN, OUTPUT);}

void loop() { digitalWrite(LED_BUILTIN, HIGH); delay(1000); digitalWrite(LED_BUILTIN, LOW); delay(1000); }

Un LED lampeggia

digitalWrite(LED_BUILTIN, HIGH);

Ma cosa c’è sotto?

Semplice, no?

digitalWrite(13, 1);

#define LED_BUILTIN 13

#define HIGH 0x1

(per Arduino Uno)

Sostituzione costanti

Il numero 13 è arbitrario

Pin di I/O

digitalWrite(13, 1);

Non è una funzione standard C(++)

Da dove sbuca?

/hardware/arduino/avr/cores/arduino/wiring_digital.c

Aggiunta dal linker

Libreria

Comodità, semplicitàPortabilità (parziale)Isolamento dall'hardware

Inefficienza, scarso controlloDipendenzaIsolamento dall'hardware

GOOD

BAD

Dipende da cosa si deve fare

Librerie: pro e contro

void digitalWrite(uint8_t pin, uint8_t val){

uint8_t timer = digitalPinToTimer(pin);uint8_t bit = digitalPinToBitMask(pin);uint8_t port = digitalPinToPort(pin);volatile uint8_t *out;

if (port == NOT_A_PIN) return;

if (timer != NOT_ON_TIMER) turnOffPWM(timer);

out = portOutputRegister(port);

uint8_t oldSREG = SREG;cli();

if (val == LOW) {*out &= ~bit;

} else {*out |= bit;

}

SREG = oldSREG;}

digitalWrite()

void digitalWrite(uint8_t pin, uint8_t val){

uint8_t timer = digitalPinToTimer(pin);uint8_t bit = digitalPinToBitMask(pin);uint8_t port = digitalPinToPort(pin);volatile uint8_t *out;

if (port == NOT_A_PIN) return;

if (timer != NOT_ON_TIMER) turnOffPWM(timer);

out = portOutputRegister(port);

uint8_t oldSREG = SREG;cli();

if (val == LOW) {*out &= ~bit;

} else {*out |= bit;

}

SREG = oldSREG;}

Controllo che il pin non sia in uso

void digitalWrite(uint8_t pin, uint8_t val){

uint8_t bit = digitalPinToBitMask(pin);uint8_t port = digitalPinToPort(pin);volatile uint8_t *out;

if (port == NOT_A_PIN) return;

out = portOutputRegister(port);

uint8_t oldSREG = SREG;cli();

if (val == LOW) {*out &= ~bit;

} else {*out |= bit;

}

SREG = oldSREG;}

Blocco temporaneo degli interrupt

void digitalWrite(uint8_t pin, uint8_t val){

uint8_t bit = digitalPinToBitMask(pin);uint8_t port = digitalPinToPort(pin);volatile uint8_t *out;

if (port == NOT_A_PIN) return;

out = portOutputRegister(port);

if (val == LOW) {*out &= ~bit;

} else {*out |= bit;

}}

Parametri a 8 bit

digitalWrite(13, 1);

Argomenti

Valori passati alla funzione

void digitalWrite(uint8_t pin, uint8_t val){

uint8_t bit = digitalPinToBitMask(pin);uint8_t port = digitalPinToPort(pin);volatile uint8_t *out;

if (port == NOT_A_PIN) return;

out = portOutputRegister(port);

if (val == LOW) {*out &= ~bit;

} else {*out |= bit;

}}

bit mask, port address

Memory-mapped I/O (ATmega328P)

Registro PORTB

8 uscite o ingressi binari

Collegamento elettrico

(scelta arbitraria)

Bit di I/O

Nel nostro caso è un’uscita: 0 V / 5 V

Isolare un bit

Mettere un bit a 1

Senza toccare gli altri

Data

Mask

Result

(bit 5)

*out = *out | bitmask;

Non confondere | con l'OR logico ||

OR bitwise in C

out

*out

l'indirizzo del registro (PORTB)

il dato contenuto nel registro

Dereferencing

Indirizzo e dato

viamazzini23

*viamazzini23

l'indirizzo della casa

chi ci abita

*out = *out | bitmask;

(in questo caso è lo stesso)

OR bitwise in C, abbreviato

*out |= bitmask;

void digitalWrite(uint8_t pin, uint8_t val){

uint8_t bit = digitalPinToBitMask(pin);uint8_t port = digitalPinToPort(pin);volatile uint8_t *out;

if (port == NOT_A_PIN) return;

out = portOutputRegister(port);

if (val == LOW) {*out &= ~bit;

} else {*out |= bit;

}}

Tornando a digitalWrite

if (val == LOW) {*out &= ~bit;

} else {*out |= bit;

}

Tornando a digitalWrite

Mette un bit della porta a 1

out indirizzo di PORTBbit bitmask

Mettere un bit a 0

Senza toccare gli altri

Data

Mask

Result

(bit 5)

Invertire la maschera

Complemento a 1

ORmask

ANDmask

if (val == LOW) {*out &= ~bit;

} else {*out |= bit;

}

Tornando a digitalWrite

Mette un bit della porta a 0

& AND bitwise in C~ NOT bitwise in C

Dal software all'hardware

Uscita digitale (in teoria...)

Uscita digitale (un po’ più realistica)

Impostare la direzione del pin

Vale per gli AVR

void setup() { pinMode(LED_BUILTIN, OUTPUT);}

● DDR: data direction register

● DDRB bit 5 = ingresso / uscita

● DDR si usa come PORT

Next time...

Stay tuned!

Comandare il LED direttamente

Macro dietro le quinte

Ma davvero conviene l'assembly?

Ottimizzazioni