Ein paar einfache Assembler Routinen für die AVRs, die man immermalwieder gebrauchen kann. Geht
sicherlich auch noch ein Stück kürzer, den einen oder anderen Takt könnte man auch
noch sparen, aber es tut was es soll. Die aufgeführten Register sollten vor dem Anspringen der
Routinen mit den Ausgangsdaten gefüttert werden, dann einfach mit CALL/ICALL/RCALL (jenachdem,
was der verwendete AVR kann und grade sinnvoll erscheint)aufrufen.
Speicherbereich überschreiben (mit was steht im rgtmpbyte):
FFMem:
; Speicherbereich FF'en, 8 bit Zaehler
; rgi haelt den Zaehler, also wieviele bytes loeschen
; rgtmpbyte haelt das FF (oder was auch immer)
; X haelt die Startadresse im RAM
LDI rgtmpbyte, 0xFF ; tmpbyte = 0xff
slffmem:
ST X+, rgtmpbyte ; tmpbyte in Speicher kopiern
SUBI rgi, 1 ; rgi--
BRNE slffmem ; solange rgi>0 weiter in der Schleife
RET
Einen Bereich vom RAM an eine andere Stelle des RAM kopieren:
CPMem2Mem:
; kopiert Speicherbereich in einen anderen, 8 bit Zaehler
; rgi haelt Zaehler, alse wiviele bytes kopieren
; rgtmpbyte byte zum Zwischenspeichern
; X haelt Adresse des 1. byte im RAM (Ziel)
; Y haelt Adresse des 1. byte im RAM (Quelle), Y->X
sl028:
LD rgtmpbyte, Y+ ; 1 byte ausm Speicher lesen
ST X+, rgtmpbyte ; -> in den Speicehr schreiben
SUBI rgi, 1 ; rgi--
BRNE sl028; ; solange rgi>0 weiter in der Schleife
RET
Einen Bereich aus dem Flash ins RAM kopieren:
CPFlash2Mem:
; kopiert Bereich ausm Flash ins RAM, 8 bit Zaehler
; rgi haelt Zaehler, alse wiviele bytes kopieren
; R0 byte zum Zwischenspeichern (LPM liest nur ins R0)
; X haelt Adresse des 1. byte im RAM (Ziel)
; Z haelt Adresse des 1. byte im Flash (Quelle), Z->X
slcpflash2mem:
LPM ; byte aus Progammspeicher lesen, landet im R0
ST X+, R0 ; byte aus flash ins RAM schreiben
ADIW ZH:ZL, 1 ; Addresspointer fuer Programmspeicher ++
SUBI rgi, 1 ; rgi--
BRNE slcpflash2mem ; solange rgi>0 weiter in der Schleife
RET
Einen Bereich aus dem internen EEProm ins RAM kopieren:
CPEe2Mem:
; kopiert Bereich ausm EEProm ins RAM, 8 bit Zaehler
; rgi haelt Zaehler, alse wiviele bytes kopieren
; X haelt Adresse des 1. byte im RAM (Ziel)
; Z haelt Adresse des 1. byte im EEProm (Quelle), Z->X
; eeprom startadresse setzen
OUT EEARH,ZH ; high byte adresse eeprom schreiben
OUT EEARL,ZL ; low byte adresse eeprom schreiben
slcpee2mem:
SBI EECR, EERE ; Lesevorgang triggern
IN rgtmpbyte, EEDR ; byte aus eeprom ins tmpbyte schieben
ST X+, rgtmpbyte ; byte aus tmpbyte ins RAM schreiben
ADIW ZH:ZL, 1 ; Addresspointer fuer EEProm++
OUT EEARH,ZH ; -> high byte neue adresse eeprom schreiben
OUT EEARL,ZL ; -> low byte neue adresse eeprom schreiben
SUBI rgi, 1 ; rgi--
BRNE slcpee2mem ; solange rgi>0 weiter in der Schleife
RET
Einen Bereich aus dem RAM ins interne EProm kopieren:
CPMem2Ee:
; kopiert Bereich ausm RAM ins EEProm, 8 bit Zaehler
; rgi haelt Zaehler, alse wiviele bytes kopieren
; Y haelt Adresse des 1. byte im RAM (Quelle)
; Z haelt Adresse des 1. byte im EEProm (Ziel), Y->Z
; eeprom startadresse setzen
OUT EEARH,ZH ; high byte adresse eeprom schreiben
OUT EEARL,ZL ; low byte adresse eeprom schreiben
slcpmem2ee:
LD rgtmpbyte,Y+ ; byte ausm Speicehr ins rgtmpbyte lesen
sleeready: ; eeprom fertig zum Schreiben?
SBIC EECR,1 ; if bit1 clear -> den jump ueberspringen
RJMP sleeready ; -> zuruck
OUT EEDR,rgtmpbyte ; zu schreibendes byte ins datenregister tun
SBI EECR,EEMWE ; Schaltet EEPROM Master Write Enable ein
SBI EECR,EEWE ; Löst Schreibvorgang im EEPROM aus
sleeready2: ; auf eeprom mit schreiben fertig warten
SBIC EECR,1 ; if bit1 clear -> den jump ueberspringen
RJMP sleeready2 ; -> zuruck
ADIW ZH:ZL, 1 ; Addresspointer fuer EEProm++
OUT EEARH,ZH ; -> high byte adresse eeprom schreiben
OUT EEARL,ZL ; -> low byte adresse eeprom schreiben
SUBI rgi, 1 ; schleife, i--rgi--
BRNE slcpmem2ee ; solange rgi>0 weiter in der Schleife
RET