/* flash_rw.c in handgemachtem Assembler
* Benötigt GPIOR0 Bit 6, wie auch das C-Programm
* Flash-Adresse < 64 KByte, SPM_PAGESIZE <= 128 Byte
*/
#define __SFR_OFFSET 0
#include <avr/io.h>
.global flash_read, flash_write, flash_flush, eeprom_update
.section .noinit
buffer: .space SPM_PAGESIZE
FlashPtr: .space 2
.text
.extern memcpy_P
flash_flush:
sbis GPIOR0,6
ret
lds ZH,FlashPtr+1
lds ZL,FlashPtr
ldi XH,hi8(buffer)
ldi XL,lo8(buffer)
cbi GPIOR0,6
// PE: Z = Flash-Adresse; untere Bits müssen 0 sein!
// X = RAM-Adresse
// VR: R24, R25, X, Z
program_page:
sbic EECR,1 ; warten bis EEPROM fertig
rjmp program_page
ldi r24,3
rcall spm_op ; löschen
ldi r24,1
ldi r25,SPM_PAGESIZE/2
1: ld r0,X+
ld r1,X+
rcall spm_op ; füllen
adiw ZL,2
dec r25
brne 1b
clr r1 ; Null hinterlassen
sbiw ZL,2
andi ZL,~(SPM_PAGESIZE-1)
ldi r24,5 ; programmieren
spm_op: cli
out SPMCSR,r24
spm
reti
// R24x = Ziel, R22x = Quelle, R20x = Länge
flash_read:
sbis GPIOR0,6
rjmp memcpy_P
movw XL,r24
movw ZL,r22
// Jetzt: X = Ziel, Z = Quelle, R20x = Länge
rjmp 3f
1: movw r24,ZL
lds r0,FlashPtr
sub r24,r0
lds r0,FlashPtr+1
sbc r25,r0
lpm r0,Z+ // immer LPM, später korrigieren
cpi r24,SPM_PAGESIZE
cpc r25,r1
brcc 2f
movw r22,ZL // retten
ldi ZH,hi8(buffer)
ldi ZL,lo8(buffer)
add ZL,r24
adc ZH,r25
ld r0,Z
movw ZL,r22 // zurück
2: st X+,r0
3: subi r20,1
sbci r21,0
brcc 1b
ret
// R24~ = Ziel, R22~ = Quelle, R20~ = Länge
flash_write:
push YL
push YH // retten
movw YL,r22
movw ZL,r24
// Jetzt: Z = Ziel, Y = Quelle, R20~ = Länge
rjmp 5f
1: movw r22,ZL
andi r23,~(SPM_PAGESIZE-1) // untere Bits = 0
sbis GPIOR0,6
rjmp 2f
lds r0,FlashPtr
cp r22,r0
lds r0,FlashPtr+1
cpc r23,r0
breq 3f
2: lpm
ld XL,Y
cp XL,r0
breq 4f
push ZL
push ZH
push r20
push r21
rcall flash_flush // verändert R22x nicht
sts FlashPtr+1,r23
sts FlashPtr,r22
sbi GPIOR0,6
ldi r25,hi8(buffer)
ldi r24,lo8(buffer)
ldi r21,hi8(SPM_PAGESIZE)
ldi r20,lo8(SPM_PAGESIZE)
rcall memcpy_P
pop r21
pop r20
pop ZH
pop ZL
3: ldi XH,hi8(buffer) // buffer[Ziel&maske]
ldi XL,lo8(buffer)
mov r22,ZL
andi r22,SPM_PAGESIZE-1 // 0..63
add XL,r22
adc XH,r1
ld r0,Y
st X,r0
4: adiw YL,1
adiw ZL,1
5: subi r20,1
sbci r21,0
brcc 1b
pop YH
pop YL
ret
// R24~ = Ziel, R22~ = Quelle, R20~ = Länge
eeprom_update:
sbic EECR,1
rjmp 4f
movw ZL,r22
rjmp 3f
// Jetzt: R24~ = Ziel, Z = Quelle, R20~ = Länge
1: out EEARH,r25
out EEARL,r24
sbi EECR,0
ld r0,Z
in r1,EEDR
sub r1,r0
brne 2f
adiw ZL,1
adiw r24,1
3: subi r20,1
sbci r21,1
brcc 1b
4: clr r24
clr r25
ret
2: out EEDR,r0
clr r1
cli
sbi EECR,2
sbi EECR,1
sei
movw r24,ZL
ret
.end
Detected encoding: ANSI (CP1252) | 4
|
|