Hallo Dirk,
hier ist der Code (die Formatierung ist leider irgendwie abhanden gekommen ...) Im wesentlichen ist er aus der Doku des 328P übernommen ...
Danke für Deine Unterstützung.
Peter
.equ PAGESIZEB = 128 ;pagesize in bytes
.equ PGERS = 1 ;page erase bit
.equ SELFPRGEN = 0 ;SP enable bit
.equ RWWSRE = 4 ;App section read enable
.equ PGWRT = 2 ;page write bit
.equ RWWSB = 6 ;app section busy bit
.equ SPMCSR = 0x57 ;spm control register
.equ TCNT2 = 0x24 ;TCNT2 addresses (Borrow as a temp storage)..
.def spmcrval = R19 ;spm value for subroutine
.def temp1 = R20 ;temp register
.def temp2 = R21 ;ditto
.def errors = R18
.def looplo = R26 ;loop counter
.def loophi = R27
CLI ; disable all interrupts
;get page from data stack into Z
LDD R30,Y+2
LDD R31,Y+3
;get ram image buffer address from stack
LD R22,Y
LDD R23,Y+1
;save registers for return
ST -Y, R0
ST -Y, R1
ST -Y, R16
ST -Y, R18
ST -Y, R19
ST -Y, R20
ST -Y, R21
ST -Y, R22
ST -Y, R23
ST -Y, R26
ST -Y, R27
ST -Y, R30
ST -Y, R31
IN R0, SREG
ST -Y, R0
MOV R14,R28 ;save Y
MOV R15,R29
;get image data storage location into Y
mov R28, R22
mov R29, R23
Write_page:
; page erase
ldi spmcrval, (1<<PGERS) | (1<<SELFPRGEN)
call Do_spm
; re-enable the Application Section
ldi spmcrval, (1<<RWWSRE) | (1<<SELFPRGEN)
call Do_spm
; transfer data from RAM to Flash page buffer
ldi looplo,low(PAGESIZEB) ;init loop variable
ldi loophi,high(PAGESIZEB) ;not required for PAGESIZEB<=256
Wrloop:
ld r0, Y+ ;get data byte from ram
ld r1, Y+
ldi spmcrval, (1<<SELFPRGEN)
call Do_spm
adiw R31:R30, 2 ; bump z
sbiw loophi:looplo, 2 ; (use with PAGESIZEB>256)
brne Wrloop
; execute page write
subi R30, low(PAGESIZEB) ; restore pointer
sbci R31, high(PAGESIZEB) ; restore upper byte of pointer
ldi spmcrval, (1<<PGWRT) | (1<<SELFPRGEN)
call Do_spm
; re-enable the Application Section
ldi spmcrval, (1<<RWWSRE) | (1<<SELFPRGEN)
call Do_spm
; read back and check, optional
ldi looplo,low(PAGESIZEB) ;init loop variable
ldi loophi,high(PAGESIZEB) ;not required for PAGESIZEB<=256
ldi errors,0 ;load error tester
subi R28, low(PAGESIZEB) ;restore pointer
sbci R29, high(PAGESIZEB)
Rdloop:
lpm r0, Z+
ld r1, Y+
cpse r0, r1
inc errors ;count errors
sbiw loophi:looplo, 2 ;(use for PAGESIZEB>256)
brne Rdloop
; return to Application Section
; verify that Application Section is safe to read
Return:
lds temp1, SPMCSR
sbrs temp1, RWWSB ; If ASB is set, the AS is not ready yet
rjmp goback ; go back to calling function
; re-enable the Applicaiton Section
ldi spmcrval, (1<<RWWSRE) | (1<<SELFPRGEN)
call Do_spm
rjmp Return
Do_spm:
; check for previous SPM activity..
Wait_spm:
lds temp1, SPMCSR
sbrc temp1, SELFPRGEN
rjmp Wait_spm
; input: spmcrval determines SPM action
; check that no EEPROM write access is running
Wait_ee:
sbic EECR, EEWE
rjmp Wait_ee
; SPM timed sequence
sts SPMCSR, spmcrval
spm
nop ; of next instruction
; check for SPM complete on next round..
ret
goback:
out TCNT2,errors ; load error indicator
MOV R28,R14 ; restore Y
MOV R29,R15
LD R0, Y+ ; restore registers
OUT SREG, R0
LD R31, Y+
LD R30, Y+
LD R27, Y+
LD R26, Y+
LD R23, Y+
LD R22, Y+
LD R21, Y+
LD R20, Y+
LD R19, Y+
LD R18, Y+
LD R16, Y+
LD R1, Y+
LD R0, Y+
SEI ; enable Interrupts
#endasm
return (TCNT2); //return error status