237 lines
5.2 KiB
NASM
237 lines
5.2 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:
|
|
wait: ; wait for possibly previous SPM to complete
|
|
in r16, SPMCSR
|
|
sbrc r16, SPMEN
|
|
rjmp wait
|
|
; SPM timed sequence
|
|
out SPMCSR, r20
|
|
spm
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; flashReadEepromIncr
|
|
;
|
|
; Read a byte from EEPROM (see example in ATtiny24/44/84 manual p.19).
|
|
;
|
|
; IN:
|
|
; - X: EEPROM Address to read from
|
|
; OUT:
|
|
; - R16: byte read
|
|
; - X: EEPROM Address incremented
|
|
; REGS: R16
|
|
|
|
flashReadEepromIncr:
|
|
sbic EECR, EEPE ; wait for previous write to complete (if any)
|
|
rjmp flashReadEepromIncr
|
|
out EEARH, xh ; set EEPROM address
|
|
out EEARL, xl
|
|
sbi EECR, EERE ; start EEPROM read by writing EERE
|
|
in r16, EEDR ; read data from data register
|
|
adiw xh:xl, 1
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; flashReadUid
|
|
;
|
|
; Read UID from EEPROM.
|
|
;
|
|
; IN:
|
|
; OUT:
|
|
; - R18:R19:R20:R21: UID
|
|
; REGS: R16, X
|
|
|
|
flashReadUid:
|
|
push r15
|
|
in r15, SREG
|
|
cli
|
|
ldi xl, LOW(EEPROM_OFFS_UUID)
|
|
ldi xh, HIGH(EEPROM_OFFS_UUID)
|
|
rcall flashReadEepromIncr ; (R16)
|
|
mov r18, r16
|
|
rcall flashReadEepromIncr ; (R16)
|
|
mov r19, r16
|
|
rcall flashReadEepromIncr ; (R16)
|
|
mov r20, r16
|
|
rcall flashReadEepromIncr ; (R16)
|
|
mov r21, r16
|
|
out SREG, r15
|
|
pop r15
|
|
ret
|
|
|
|
|
|
|
|
|
|
|
|
FLASH_END:
|
|
.equ MODULE_SIZE_FLASH = FLASH_END-FLASH_BEGIN
|
|
|
|
|
|
|