Im trying a bit of asm/bootloader/spm stuff for the first time, but it just doesnt work ( even though i think everything is correct ). Im writing my code in AS7 for an atmega328p and im only using the simulator to test it.
I try to do a page erase but it doesnt do what it should do. I put my spm code in the bootloader section and setup some test data in different regions of the flash to see how the page erase behaves. The datasheet says that the address of the page is put into the Z pointer and that bits 13:6 (datasheet page 349/334) are used for that and all others are ignored. Since the atmega328 has 256 pages, every page can be addressed by those 8 bits. So if i put the value "0x40" in the lower Z byte, then it should address flash page 1(well it is flash page 2 in that case, depents how you count) and erase only the part with "hello2". But it doesnt behave like that. When i return from "pageErase", page 0 is erased (hello1 is gone) and then i spend 4129 cycles in "isFlashRdy" and when that is done, also page 1 (hello2) is erased. Im very confused...
.ORG 0x0000 ;page 0 t1: .db "hello1" .ORG 0x0040 ;byte addr 128:0x80 | page1 t2: .db "hello2" .ORG 0x0080 ;byte addr 256:0x0100 | page2 t3: .db "hello3" .ORG 0x00c0 ;byte addr 384:0x0180 | page3 t4: .db "hello4" jmp LARGEBOOTSTART .ORG LARGEBOOTSTART loop: cli ldi zh, 0x00 ldi zl, 0x40 ;page 1 ? rcall pageErase rcall enableRWW rjmp loop isFlashRdy: in r16, SPMCSR sbrc r16, SPMEN rjmp isFlashRdy ret enableRWW: rcall isFlashRdy ldi r16, (1<<RWWSRE) | (1<<SPMEN) out SPMCSR, r16 SPM ret pageErase: rcall isFlashRdy ldi r16, (1<<PGERS) | (1<<SPMEN) out SPMCSR, r16 ;set erase and spm enable bit spm ret