Source file: /~heha/basteln/PC/FunkUsb/FunkUsb.zip/FunkUsb/ve/flash_rw.S

/* 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
Wrong umlauts? - Assume file is ANSI (CP1252) encoded