Arduino & Assembler

Utilizzare l'assembler con Arduino

Ci sono casi in cui può essere utile ricorrere all'utilizzo del linguaggio assembler con i microcontrollori Arduino.

Sotto vi mostro un semplice esempio.
Ho creato una funzione fastDigitalRead() per leggere una GPIO alla massima velocità possibile.
Per fare questo utilizzo 21 dei 32 registri ad 8 bit del processore AVR.
I valori letti sono memorizzati in un array di byte "arr" definito come variabile globale in modo da essere facilmente accessibile.

#define NUM_DI_CICLI "40"
byte arr[999] ; // array per memorizzare i registri i dati 21 * 40 + 22 byte per i registri + eccesso

void fastDigitalRead(void) {

cli() ; asm( "ldi r26, lo8(arr) n" // il puntatore X (r26,r27) viene caricato con "ldi r27, hi8(arr) n" // l'indirizzo del buffer arr // Prima cosa salviamo i registri r0-r21 "st X+, r0 n st X+, r1 n st X+, r2 n st X+, r3 n" "st X+, r4 n st X+, r5 n st X+, r6 n st X+, r7 n" "st X+, r8 n st X+, r9 n st X+, r10 n st X+, r11 n" "st X+, r12 n st X+, r13 n st X+, r14 n st X+, r15 n" "st X+, r16 n st X+, r17 n st X+, r18 n st X+, r19 n" "st X+, r20 n st X+, r21 n" // Inizializziaamo il ciclo "ldi r21, " NUM_DI_CICLI " n" "gloop: n" // Azzeriamo i Registri r0-r20 "clr r0 n clr r6 n clr r11 n clr r16 n" "clr r1 n clr r7 n clr r12 n clr r17 n" "clr r2 n clr r8 n clr r13 n clr r18 n" "clr r3 n clr r9 n clr r14 n clr r19 n" "clr r4 n clr r10 n clr r15 n clr r20 n" "clr r5 n" // Impostiamo ad uno il bit T usato da bld "bset 6 n" "sbic 3,4 n bld r0,7 n sbic 3,4 n bld r0,6 n sbic 3,4 n bld r0,5 n sbic 3,4 n bld r0,4 n" "sbic 3,4 n bld r0,3 n sbic 3,4 n bld r0,2 n sbic 3,4 n bld r0,1 n sbic 3,4 n bld r0,0 n" "sbic 3,4 n bld r1,7 n sbic 3,4 n bld r1,6 n sbic 3,4 n bld r1,5 n sbic 3,4 n bld r1,4 n" "sbic 3,4 n bld r1,3 n sbic 3,4 n bld r1,2 n sbic 3,4 n bld r1,1 n sbic 3,4 n bld r1,0 n" "sbic 3,4 n bld r2,7 n sbic 3,4 n bld r2,6 n sbic 3,4 n bld r2,5 n sbic 3,4 n bld r2,4 n" "sbic 3,4 n bld r2,3 n sbic 3,4 n bld r2,2 n sbic 3,4 n bld r2,1 n sbic 3,4 n bld r2,0 n" "sbic 3,4 n bld r3,7 n sbic 3,4 n bld r3,6 n sbic 3,4 n bld r3,5 n sbic 3,4 n bld r3,4 n" "sbic 3,4 n bld r3,3 n sbic 3,4 n bld r3,2 n sbic 3,4 n bld r3,1 n sbic 3,4 n bld r3,0 n" "sbic 3,4 n bld r4,7 n sbic 3,4 n bld r4,6 n sbic 3,4 n bld r4,5 n sbic 3,4 n bld r4,4 n" "sbic 3,4 n bld r4,3 n sbic 3,4 n bld r4,2 n sbic 3,4 n bld r4,1 n sbic 3,4 n bld r4,0 n" "sbic 3,4 n bld r5,7 n sbic 3,4 n bld r5,6 n sbic 3,4 n bld r5,5 n sbic 3,4 n bld r5,4 n" "sbic 3,4 n bld r5,3 n sbic 3,4 n bld r5,2 n sbic 3,4 n bld r5,1 n sbic 3,4 n bld r5,0 n" "sbic 3,4 n bld r6,7 n sbic 3,4 n bld r6,6 n sbic 3,4 n bld r6,5 n sbic 3,4 n bld r6,4 n" "sbic 3,4 n bld r6,3 n sbic 3,4 n bld r6,2 n sbic 3,4 n bld r6,1 n sbic 3,4 n bld r6,0 n" "sbic 3,4 n bld r7,7 n sbic 3,4 n bld r7,6 n sbic 3,4 n bld r7,5 n sbic 3,4 n bld r7,4 n" "sbic 3,4 n bld r7,3 n sbic 3,4 n bld r7,2 n sbic 3,4 n bld r7,1 n sbic 3,4 n bld r7,0 n" "sbic 3,4 n bld r8,7 n sbic 3,4 n bld r8,6 n sbic 3,4 n bld r8,5 n sbic 3,4 n bld r8,4 n" "sbic 3,4 n bld r8,3 n sbic 3,4 n bld r8,2 n sbic 3,4 n bld r8,1 n sbic 3,4 n bld r8,0 n" "sbic 3,4 n bld r9,7 n sbic 3,4 n bld r9,6 n sbic 3,4 n bld r9,5 n sbic 3,4 n bld r9,4 n" "sbic 3,4 n bld r9,3 n sbic 3,4 n bld r9,2 n sbic 3,4 n bld r9,1 n sbic 3,4 n bld r9,0 n" "sbic 3,4 n bld r10,7 n sbic 3,4 n bld r10,6 n sbic 3,4 n bld r10,5 n sbic 3,4 n bld r10,4 n" "sbic 3,4 n bld r10,3 n sbic 3,4 n bld r10,2 n sbic 3,4 n bld r10,1 n sbic 3,4 n bld r10,0 n" "sbic 3,4 n bld r11,7 n sbic 3,4 n bld r11,6 n sbic 3,4 n bld r11,5 n sbic 3,4 n bld r11,4 n" "sbic 3,4 n bld r11,3 n sbic 3,4 n bld r11,2 n sbic 3,4 n bld r11,1 n sbic 3,4 n bld r11,0 n" "sbic 3,4 n bld r12,7 n sbic 3,4 n bld r12,6 n sbic 3,4 n bld r12,5 n sbic 3,4 n bld r12,4 n" "sbic 3,4 n bld r12,3 n sbic 3,4 n bld r12,2 n sbic 3,4 n bld r12,1 n sbic 3,4 n bld r12,0 n" "sbic 3,4 n bld r13,7 n sbic 3,4 n bld r13,6 n sbic 3,4 n bld r13,5 n sbic 3,4 n bld r13,4 n" "sbic 3,4 n bld r13,3 n sbic 3,4 n bld r13,2 n sbic 3,4 n bld r13,1 n sbic 3,4 n bld r13,0 n" "sbic 3,4 n bld r14,7 n sbic 3,4 n bld r14,6 n sbic 3,4 n bld r14,5 n sbic 3,4 n bld r14,4 n" "sbic 3,4 n bld r14,3 n sbic 3,4 n bld r14,2 n sbic 3,4 n bld r14,1 n sbic 3,4 n bld r14,0 n" "sbic 3,4 n bld r15,7 n sbic 3,4 n bld r15,6 n sbic 3,4 n bld r15,5 n sbic 3,4 n bld r15,4 n" "sbic 3,4 n bld r15,3 n sbic 3,4 n bld r15,2 n sbic 3,4 n bld r15,1 n sbic 3,4 n bld r15,0 n" "sbic 3,4 n bld r16,7 n sbic 3,4 n bld r16,6 n sbic 3,4 n bld r16,5 n sbic 3,4 n bld r16,4 n" "sbic 3,4 n bld r16,3 n sbic 3,4 n bld r16,2 n sbic 3,4 n bld r16,1 n sbic 3,4 n bld r16,0 n" "sbic 3,4 n bld r17,7 n sbic 3,4 n bld r17,6 n sbic 3,4 n bld r17,5 n sbic 3,4 n bld r17,4 n" "sbic 3,4 n bld r17,3 n sbic 3,4 n bld r17,2 n sbic 3,4 n bld r17,1 n sbic 3,4 n bld r17,0 n" "sbic 3,4 n bld r18,7 n sbic 3,4 n bld r18,6 n sbic 3,4 n bld r18,5 n sbic 3,4 n bld r18,4 n" "sbic 3,4 n bld r18,3 n sbic 3,4 n bld r18,2 n sbic 3,4 n bld r18,1 n sbic 3,4 n bld r18,0 n" "sbic 3,4 n bld r19,7 n sbic 3,4 n bld r19,6 n sbic 3,4 n bld r19,5 n sbic 3,4 n bld r19,4 n" "sbic 3,4 n bld r19,3 n sbic 3,4 n bld r19,2 n sbic 3,4 n bld r19,1 n sbic 3,4 n bld r19,0 n" "sbic 3,4 n bld r20,7 n sbic 3,4 n bld r20,6 n sbic 3,4 n bld r20,5 n sbic 3,4 n bld r20,4 n" "sbic 3,4 n bld r20,3 n sbic 3,4 n bld r20,2 n sbic 3,4 n bld r20,1 n sbic 3,4 n bld r20,0 n" "st X+, r0 n st X+, r1 n st X+, r2 n st X+, r3 n" "st X+, r4 n st X+, r5 n st X+, r6 n st X+, r7 n" "st X+, r8 n st X+, r9 n st X+, r10 n st X+, r11 n" "st X+, r12 n st X+, r13 n st X+, r14 n st X+, r15 n" "st X+, r16 n st X+, r17 n st X+, r18 n st X+, r19 n" "st X+, r20 n" "dec r21 n" // "brne gloop n" // non si puo' fare il branch perche' il codice e' troppo lungo "breq out n" "jmp gloop n" "out: n" // Effettua il Restore dei registri r0-r21 // così alla fine gli unici registri sporcati saranno X (r26,r27) "ldi r26, lo8(arr) n" // il puntatore X (r26,r27) viene caricato con "ldi r27, hi8(arr) n" // l'indirizzo del buffer arr "ld r0, X+ n ld r1, X+ n ld r2, X+ n ld r3, X+ n" "ld r4, X+ n ld r5, X+ n ld r6, X+ n ld r7, X+ n" "ld r8, X+ n ld r9, X+ n ld r10, X+ n ld r11, X+ n" "ld r12, X+ n ld r13, X+ n ld r14, X+ n ld r15, X+ n" "ld r16, X+ n ld r17, X+ n ld r18, X+ n ld r19, X+ n" "ld r20, X+ n ld r21, X+ n" ); sei() ;
// scrivo il risultato sulla seriale // usando un base64 "sporco" chr(32)-chr(95) int a,b,b0,b1,b2 ; byte * pt = arr+22 ; for( a=0; a<4; a++ ) { for( b=0; b<7; b++ ) { // 21 byte 7*3 b0 = *pt++ ; b1 = *pt++ ; b2 = *pt++ ; Serial.write( 32+(b0>>2)); Serial.write( 32+((b0<<4)&63)+(b1>>4)); Serial.write( 32+((b1<<2)&63)+(b2>>6)); Serial.write( 32+(b2&63)); } Serial.println(""); } }