Hello,
I am using an ATmega324PA in a new application and want to provide IAP
capability, i.e. there is a loader that can update the application by
serial communication.
The IAP loader is located at the top of the flash memory (in the RWW
section), and exactly follows the description given in the data sheet
and some application notes to erase and write the flash.
However, the SPM command simply does nothing - neither does ist erase a
flash page, nor does it program any data into the flash. There isn't any
delay when programming, either - SPMEN becomes inactive immediately
again after SPM has been issued.
I have looked at several (supposed to work) code samples, and I think
the accesses and their sequence is exactly identical. What could be wrong?
Here's the code (IAPBase is at word address 0x1E00):
----
; Erase Flash from 0x0000 up to IAP loader:
...
clr ZL
clr ZH ; start at 0
EraseLoop: ldi r16,(1<<PGERS)|(1<<SPMEN)
rcall DoSPM ; Page Erase
rcall EnableRWW ; re-enable RWW section
adiw Z,60
adiw Z,60
adiw Z,8 ; Z+128: next page
cpi ZH,high(IAPBase<<1) ; reached IAP loader?
brlo EraseLoop ; erase flash up to IAP loader
...
; Program a 128 byte flash page. X points to data in RAM, Z to the
; target (byte) address in flash.
FlashProg128: ld r0,X+
ld r1,X+
ldi r16,(1<<SPMEN)
rcall DoSPM ; enable page buffer write
adiw Z,2
mov r16,ZL
andi r16,0x7F ; 128 byte boundary reached?
brne FlashProg128 ; copy 128 bytes into buffer
subi ZL,128
sbci ZH,0 ; back to page start
ldi r16,(1<<PGWRT)|(1<<SPMEN)
rcall DoSPM ; start the page write
rjmp EnableRWW ; re-enable RWW section
; Do the flash accesses (erase, write) via SPM.
; Called with SPMSCR control byte in R16.
EnableRWW: ldi r16,(1<<RWWSRE)|(1<<SPMEN) ; re-enable RWW
DoSPM: in r17,SPMCSR
sbrc r17,SPMEN ; if SPM still in progress:
rjmp DoSPM ; wait for completion
out SPMCSR,r16
spm
ret
----
Thanks for any hints and/or ideas,
Tilmann