Files
aqhomecontrol/avr/modules/flash/flash.asm

181 lines
4.1 KiB
NASM

; ***************************************************************************
; copyright : (C) 2023 by Martin Preuss
; email : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome". *
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
; ***************************************************************************
; code
.cseg
FLASH_BEGIN:
; ---------------------------------------------------------------------------
; start flashing a page
;
; Interrupts must be disabled!
;
; IN:
; - Z: Address to work on (byte address as for LPM!)
; OUT:
; - nothing
; REGS: R16 (R0, R1, R16, R20, R24, R25)
Flash_StartPage:
push zh
push zl
ldi r16, ~((PAGESIZE*2)-1)
and zl, r16
rcall Flash_ReadPageIntoPageBuffer ; (R0, R1, R16, R20, R24, R25, Z)
pop zl
pop zh
ret
; ---------------------------------------------------------------------------
; finish flashing a page
;
; Interrupts must be disabled!
;
; IN:
; - Z: Address to work on (byte address as for LPM!)
; OUT:
; - nothing
; REGS: R16 (R15, R20)
Flash_FinishPage:
ldi r16, ~((PAGESIZE*2)-1)
and zl, r16
rcall Flash_ErasePage ; (R15, R16, R20)
rcall Flash_WritePage ; (R15, R16, R20)
ret
; ---------------------------------------------------------------------------
; Flash_ReadPageIntoPageBuffer
;
; Interrupts must be disabled!
;
; IN:
; - Z: Address to read from (byte address as for LPM!)
; OUT:
; - nothing
; REGS: R0, R1, R16, R20, R24, R25, Z
Flash_ReadPageIntoPageBuffer:
ldi r24, LOW(PAGESIZE*2)
ldi r25, HIGH(PAGESIZE*2)
Flash_ReadPageIntoPageBuffer_loop:
lpm r0, Z+ ; read source data from FLASH (low)
lpm r1, Z ; read source data from FLASH (high)
sbiw ZH:ZL, 1 ; rewind Z address for following SPM
ldi r20, (1<<SPMEN) ; enable next SPM, write into temp page buffer
rcall flashDoSpm ; (R16)
adiw ZH:ZL, 2
sbiw r25:r24, 2 ; use subi for PAGESIZEB<=256
brne Flash_ReadPageIntoPageBuffer_loop
ret
; ---------------------------------------------------------------------------
; Flash_WriteIntoPage
;
; Interrupts must be disabled!
;
; IN:
; - Z: Address to write to (byte address as for LPM!)
; - R1:R0: Word to write into page
; OUT:
; - Z: address for next write
; REGS: R16
Flash_WriteIntoPage:
ldi r20, (1<<SPMEN) ; enable next SPM, write into temp page buffer
rcall flashDoSpm ; (R16)
adiw zh:zl, 2
ret
; ---------------------------------------------------------------------------
; Flash_ErasePage
;
; Interrupts must be disabled!
;
; IN:
; - Z: Address of the page to erase.
; OUT:
; - nothing
; REGS: R20 (R16)
Flash_ErasePage:
ldi r20, (1<<PGERS) + (1<<SPMEN) ; enable next SPM, erase page (R1/R0 ignored)
rcall flashDoSpm ; (R16)
ret
; ---------------------------------------------------------------------------
; Flash_WritePage
;
; Interrupts must be disabled!
;
; IN:
; - Z: Address of the page to erase.
; OUT:
; - nothing
; REGS: R15, R20 (R16)
Flash_WritePage:
ldi r20, (1<<PGWRT) + (1<<SPMEN) ; enable next SPM, write page (R1/R0 ignored)
rcall flashDoSpm ; (R16)
ret
; ---------------------------------------------------------------------------
; flashDoSpm
;
; wait until possible previous SPM finished and then issue another SPM.
;
; IN:
; - R20: value for register SPMCR
; - R0: low value for SPM
; - R1: high value for SPM
; - Z : address for SPM (byte address!)
; OUT:
; - nothing
; REGS: R16
flashDoSpm:
flashDoSpm_wait: ; wait for possibly previous SPM to complete
in r16, SPMCSR
sbrc r16, SPMEN
rjmp flashDoSpm_wait
; SPM timed sequence
out SPMCSR, r20
spm
ret
FLASH_END:
.equ MODULE_SIZE_FLASH = FLASH_END-FLASH_BEGIN