Anatomia di unistruzione in Arduino Pt.2

Preview:

Citation preview

Arduino:Anatomia di un’istruzione - 2

Enrico Colombini (Erix)

µhackademy 4 Novembre 2016

Setta il bit 5 di PORTB

Riassunto della puntata precedente

digitalWrite(LED_BUILTIN, HIGH);

*out |= bitmask;

esegue:

1 cifra hex = 4 cifre bin

Corso lampo di esadecimale

0 1 2 3 4 5 6 7 8 9 A B C D E F

8 + 2 = A (hex)

= A5 (hex)

Da qui all’hardware?

Questi sono solo dei caratteri

*out |= bitmask;

Vediamo l'eseguibile...

Compilazione

Codice sorgente (testo)

Compilazione + link

--> Codice eseguibile (binario)

Istruzioni per la MCU

Eseguite dall’hardware

61 e0 80 91 00 01 0c 9493 01 cf 93 df 93 c0 e0d1 e0 61 e0 88 81 0e 94cf 01 68 ee 73 e0 80 e090 e0 0e 94 09 01 60 e088 81 0e 94 cf 01 68 ee73 e0 80 e0 90 e0 df 91cf 91 0c 94 09 01

Alcune istruzioni di ‘Blink’

Tutto chiaro, no?

Non portatile

Linguaggio assembly (asm)

Umanamente leggibile

Corrisponde 1:1 alle istruzioni MCU

Si può usare per scrivere codice

...o per leggere l'eseguibile

(o embedded nel C)

Come si usa(va)

Sorgente Assembly

Assembler

Linker

Eseguibile

Sorgente C

Compilatore

Come si ricava?

Usi dell'assembly

Il C ottimizzato è un asm (quasi) portatile

Si usa l'asm in casi o punti particolari

Saperlo leggere per migliorare il C

Due modi

Dal C all'assembly

Sorgente C

Compilatore

Linker

Eseguibile

Assemblycon sorgente C

Disassemblato(meno informazioni)

(no sorgente C)

Disassemblare con Arduino

Dal file .elf

avr-objdump -d /tmp/build4048337971841970682.tmp/Blink.cpp.elf >blink.lst

(copiare, incollare e modificaredal'IDE di Arduino)

‘Blink’ eseguibile + assembly

0000039e <digitalWrite>: 39e: 1f 93 push r17 3a0: cf 93 push r28 3a2: df 93 push r29 3a4: 28 2f mov r18, r24 3a6: 30 e0 ldi r19, 0x00 ; 0 3a8: f9 01 movw r30, r18 3aa: e8 59 subi r30, 0x98 ; 152 3ac: ff 4f sbci r31, 0xFF ; 255 3ae: 84 91 lpm r24, Z 3b0: f9 01 movw r30, r18 3b2: e4 58 subi r30, 0x84 ; 132 3b4: ff 4f sbci r31, 0xFF ; 255 3b6: d4 91 lpm r29, Z 3b8: f9 01 movw r30, r18 3ba: e0 57 subi r30, 0x70 ; 112 3bc: ff 4f sbci r31, 0xFF ; 255 3be: c4 91 lpm r28, Z 3c0: cc 23 and r28, r28 3c2: c9 f0 breq .+50 ; 0x3f6 <digitalWrite+0x58> 3c4: 16 2f mov r17, r22

(etc.)

Mette a 1 un bit

3ee: ec 91 ld r30, X 3f0: ed 2b or r30, r29 3f2: ec 93 st X, r30

Che vuol dire?

Da digitalWrite:

Gli asm non sono tutti uguali

I concetti sì

Architettura e numero di bit

Organizzazione della memoria

Set di istruzioni

Modi di indirizzamento

Registri dei microcontrollori AVR

Alcuni sono dedicati

r0

r1

r2

r29

r30

r31

...

32 registri a 8 bit: le‘variabili’ della MCU

Pseudo-registria 16 bit:

r26 + r27 = X

Mettere a 1 un bit

ld r30, Xor r30, r29st X, r30

X=out, r29=bitmask, r30=temp.

Viene compilato in:

Il sorgente C:

*out |= bitmask;

Soluzioni ibride

C: scrivere senza librerie?

Massima efficienza

Pieno controllo (es. set più bit)

Costa in portatilità e lavoro

Blink ‘ibrido’ senza digitalWrite

#define LED_PORT PORTB#define LED_DDR DDRB#define LED_PIN PB5

void setup() { LED_DDR |= _BV(LED_PIN);}

void loop() { LED_PORT |= _BV(LED_PIN); delay(1000); LED_PORT &= ~_BV(LED_PIN); delay(1000);}

Macro: sostituzioni nel sorgente C

#define PB5 5

#define LED_PIN PB5

LED_PIN diventa 5

Preprocessore

Macro da sostituire

#define LED_PORT PORTB#define LED_PIN PB5

void loop() { LED_PORT |= _BV(LED_PIN);

// ... etc.

}

Mette un bit a 1

Sostituzione macro (1)

#define LED_PORT PORTB#define LED_PIN PB5

LED_PORT |= _BV(LED_PIN);

PORTB |= _BV(PB5);

Usare costanti

Sostituzione macro (2)

#define PB5 5

PORTB |= _BV(PB5);

PORTB |= _BV(5);

Definita in .h

Sostituzione macro (3)

#define _BV(bit) (1 << (bit))

PORTB |= _BV(5);

PORTB |= (1 << 5);

Crea una bitmask

Left shift

Bitmask

0x01

0x20

1

1 << 5

Sostituzione macro (3a)

#define _BV(bit) (1 << (bit))

PORTB |= _BV(5);

PORTB |= (1 << 5);

PORTB |= 0x20; //0010 0000

In sintesi: mette a 1 il PB5

Cos’è PORTB?

LED_PORT |= _BV(LED_PIN);

PORTB |= 0x20;

Sostituzione macro (4)

Cast a puntatore

PORTB |= 0x20;

(*(volatile uint8_t *)(0x05)) |= 0x20;

In sintesi

C puro

LED_PORT |= _BV(LED_PIN);

(*(volatile uint8_t *)(0x05)) |= 0x20;

Parliamo di efficienza

Quanto si guadagna?

Libreria di Arduino

vs.

Accesso diretto

digitalWrite

ld r30, Xor r30, r29st X, r30

3 istruzioni asm

È compilato in:

Il sorgente C:

*out |= bitmask;

Accesso diretto

sbi 0x05, 5

Più veloce, atomica

È compilato in:

Il sorgente C:

PORTB |= 0x20;

Perché la differenza?

PORTB

Leggere l'asm

Il compilatore non sa a quale casella punta

*out

Il compilatore sache è un registro di I/O

Sfruttare l'ottimizzatore

Arduino: solo -Os

Si può scrivere in C...

...con l'efficienza dell'assembly

Il debugging è più complicato

Contando l'intera funzione

Quasi 30:1

Accesso direttodigitalWrite

3.45 µs

0.125 µs

t

Accesso diretto

That's all folks!

Capire le librerie

Modificare le librerie

Programmare senza limiti

Divertirsi!

Recommended