
Nelle applicazioni embedded è spesso necessario spostare interi blocchi di memoria dalla FLASH alla SRAM o all’interno della SRAM stessa. Ecco una serie di routine assembler (o assembly) per microcontrollori AVR di Atmel ottimizzate per lo spostamento di blocchi di dimensioni fino a 256 bytes. La routine flash2ram consente la copia di un blocco di memoria dalla FLASH alla SRAM. Per la copia di un blocco di dati all’interno della SRAM, verrà illustrata la routine ram2ram.
LA COPIA DA MEMORIA FLASH A SRAM
I parametri richiesti dalla routine flash2ram sono tre: flashsize, Z-pointer e Y-pointer. Il primo specifica la dimensione del blocco di memoria che verrà copiato, Z-pointer è l’indirizzo della FLASH a partire dal quale ha inizio il blocco interessato nella copia e Y-pointer è l’indirizzo di destinazione in RAM a partire dal quale verrà collocato il blocco dati. La routine fa uso dell’istruzione LPM che opera il trasferimento di un dato dalla FLASH ad un registro. Tale istruzione viene utilizzata per prelevare dalla FLASH la word puntata dai 15 byte più significativi di Z-pointer. Il byte prelevato viene memorizzato in R0. Il puntatore viene incrementato automaticamente. L’istruzione “ST Y+,Rs” consente di scrivere il dato all’indirizzo di destinazione e poiché l’istruzione LPM non supporta l’incremento automatico del puntatore, questo viene fatto utilizzando l’istruzione ADIW. In figura 1 il diagramma di flusso della routine flash2ram e nel listato 1 il relativo codice assembler.
La tabella 1 riassume i registri utilizzati e le caratteristiche della routine in termini di risorse utilizzate.
Il codice assembler (o assembly) riportato nel listato 1 può essere compilato utilizzando AVR studio, l’ambiente di sviluppo dedicato ai microcontrollori Atmel.
.include “8515def.inc” rjmp RESET ;reset handle .def flashsize=r16 ;size of block to be copied flash2ram: lpm ;get constant st Y+,r0 ;store in SRAM and increment Y-pointer adiw ZL,1 ;increment Z-pointer dec flashsize brne flash2ram ;if not end of table, loop more ret
Listato 1 |
COPIA DA SRAM A SRAM
I parametri richiesti dall ram2ram sono: ramsize, Z-pointer e Y-pointer. I due puntatori costituiscono rispettivamente l’indirizzo sorgente e destinatario in SRAM, mentre ramsize è la dimensione del blocco dati da copiare. Per spostare un byte ed incrementare i due puntatori sono necessarie solo due istruzioni, mentre altre due istruzioni aggiuntive sono necessarie per il decremento di ramsize che viene utilizzato come contatore all’interno della routine. Durante il trasferimento i dati vengono temporaneamente memorizzati nella variabile ramtemp. Il diagramma di flusso è riportato in figura 2, mentre il listato 2 contiene il codice assembler e la tabella 2 le risorse utilizzate.
.include “8515def.inc” rjmp RESET ;reset handle .def ramtemp =r1 ; .def ramsize =r16 ; ram2ram: ld ramtemp,Z+ ; st Y+,ramtemp ; dec ramsize ; brne ram2ram ; ret
Listato 2 |
Il listato 3, infine, riporta un piccolo programma di esempio di uso delle routines. Il programma provvede a copiare 20 bytes di dati dalla memoria programma alla SRAM a partire dalla locazione puntata da BLOCK1, quindi esegue una seconda copia a partire dalla locazione BLOCK2. Anche per il listato 2 e il listato 3 può essere utilizzato AVR studio per la compilazione ed il debugger.
;* Test Program .equ BLOCK1 =$60 ;start address of SRAM array #1 .equ BLOCK2 =$80 ;start address of SRAM array #2 .def temp =r16 ;temporary storage variable RESET: ldi temp,low(RAMEND) out SPL,temp ;init Stack Pointer ldi temp,high(RAMEND) out SPH,temp ;***** Copy 20 bytes ROM -> RAM ldi ZH,high(F_TABLE*2) ldi ZL,low(F_TABLE*2) ;init Z-pointer ldi YH,high(BLOCK1) ldi YL,low(BLOCK1) ;init Y-pointer ldi flashsize,20 rcall flash2ram ;copy 20 bytes ;***** Copy 20 bytes RAM -> RAM ldi ZH,high(BLOCK1) ldi ZL,low(BLOCK1) ;init Z-pointer ldi YH,high(BLOCK2) ;(not necessary in this specific case) ldi YL,low(BLOCK2) ;init Y-pointer ldi ramsize,20 rcall ram2ram ;copy 20 bytes forever:rjmp forever ;eternal loop F_TABLE: .db 0,1 ;start of table (20 bytes) .db 2,3 .db 4,5 .db 6,7 .db 8,9 .db 10,11 .db 12,13 .db 14,15 .db 16,17 .db 18,19
Listato 3 |

Per come è strutturato non dovrebbe essere difficile “tradurre” il codice in C (per chi programma in C). Da valutare un po’ gli aspetti computazionali che entrano in gioco in questi casi, evitando overflow vari.