avr: added flash4p (flashing basically works now).
This commit is contained in:
358
avr/modules/flash/flash4p.asm
Normal file
358
avr/modules/flash/flash4p.asm
Normal file
@@ -0,0 +1,358 @@
|
||||
; ***************************************************************************
|
||||
; copyright : (C) 2025 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. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
.equ FLASH_PAGESIZE = (PAGESIZE*2*4)
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data
|
||||
|
||||
.dseg
|
||||
|
||||
flashPageNum: .byte 2
|
||||
flashPageBuffer: .byte FLASH_PAGESIZE
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine Flash_Init
|
||||
;
|
||||
; @clobbers R16
|
||||
|
||||
Flash_Init:
|
||||
ldi r16, 0xff
|
||||
sts flashPageNum, r16
|
||||
sts flashPageNum+1, r16
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine Flash_Fini
|
||||
;
|
||||
; @clobbers (R0, R1, R16, R18, R19, R20, R21, R24, R25, X)
|
||||
|
||||
Flash_Fini:
|
||||
push r15
|
||||
in r15, SREG
|
||||
cli
|
||||
rcall flash4pEndPage ; (R0, R1, R16, R18, R19, R20, R24, R25, X)
|
||||
out SREG, r15
|
||||
pop r15
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine Flash_WriteData
|
||||
;
|
||||
; @param Z destination address in FLASH memory (byte address as for LPM!)
|
||||
; @param Y source address
|
||||
; @param r17 number of bytes to write
|
||||
; @clobbers (R0, R1, R16, R18, R19, R20, R24, R25, X)
|
||||
|
||||
Flash_WriteData:
|
||||
push r15
|
||||
in r15, SREG
|
||||
cli
|
||||
Flash_WriteData_loop:
|
||||
tst r17
|
||||
breq Flash_WriteData_done
|
||||
rcall flashWriteData ; (R0, R1, R16, R18, R19, R20, R24, R25, X)
|
||||
rjmp Flash_WriteData_loop
|
||||
Flash_WriteData_done:
|
||||
out SREG, r15
|
||||
pop r15
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine flashWriteData
|
||||
;
|
||||
; Interrupts must be disabled!
|
||||
;
|
||||
; @return Z next position
|
||||
; @return R17 remainder of bytes to flash
|
||||
; @param Z position to flash data to
|
||||
; @param Y source pointer
|
||||
; @param R17 number of bytes to flash
|
||||
; @clobbers R16, R18, R24, R25, X (R0, R1, R19, R20)
|
||||
|
||||
flashWriteData:
|
||||
rcall flashWriteCheckPage ; (r18, r19)
|
||||
brcs flashWriteData_calcPosAndLength
|
||||
rcall flash4pEndPage ; (R0, R1, R16, R18, R19, R20, R24, R25, X)
|
||||
rcall flash4pBeginPage ; (r16, r24, r25, X, Z)
|
||||
flashWriteData_calcPosAndLength:
|
||||
rcall flashCalcPosAndLength ; (r24, r25)
|
||||
; X=abs pos in buffer, r18=bytes to read, r17=bytes initially requested
|
||||
; prepare data for return
|
||||
sub r17, r18 ; r17 holds remainder
|
||||
add zl, r18 ; Z points to next data
|
||||
adc zh, r18 ; only add carry flag
|
||||
sub zh, r18
|
||||
flashWriteData_copyLoop:
|
||||
ld r16, Y+
|
||||
st X+, r16
|
||||
dec r18
|
||||
brne flashWriteData_copyLoop
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine flashCalcPosAndLength
|
||||
;
|
||||
; @return X absolute write position inside buffer
|
||||
; @return R18 bytes to write
|
||||
; @param Z destination pos
|
||||
; @param R17 number of bytes to write
|
||||
; @clobbers r24, r25
|
||||
|
||||
flashCalcPosAndLength:
|
||||
; calc offset into buffer
|
||||
mov r24, zl
|
||||
andi r24, (FLASH_PAGESIZE-1) ; r24=rel pos inside buffer
|
||||
ldi r25, FLASH_PAGESIZE
|
||||
sub r25, r24 ; r25=bytes left inside page
|
||||
mov r18, r17
|
||||
cp r25, r17
|
||||
brcc flashCalcPosAndLength_l1
|
||||
mov r18, r25
|
||||
flashCalcPosAndLength_l1:
|
||||
ldi xl, LOW(flashPageBuffer)
|
||||
ldi xh, HIGH(flashPageBuffer)
|
||||
add xl, r24
|
||||
adc xh, r24
|
||||
sub xh, r24
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine flashWriteCheckPage
|
||||
;
|
||||
; check whether the given address is inside the current page in buffer
|
||||
;
|
||||
; @return CFLAG set if same page, cleared otherwise
|
||||
; @clobbers r18, r19
|
||||
|
||||
flashWriteCheckPage:
|
||||
; check low byte of page
|
||||
mov r18, zl
|
||||
andi r18, LOW(~(FLASH_PAGESIZE-1))
|
||||
lds r19, flashPageNum
|
||||
cp r18, r19
|
||||
brne flashWriteCheckPage_ClcRet
|
||||
; check high byte of page
|
||||
mov r18, zh
|
||||
andi r18, HIGH(~(FLASH_PAGESIZE-1))
|
||||
lds r19, flashPageNum+1
|
||||
cp r18, r19
|
||||
brne flashWriteCheckPage_ClcRet
|
||||
sec
|
||||
ret
|
||||
flashWriteCheckPage_ClcRet:
|
||||
clc
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine flashCheckCurrentValid
|
||||
;
|
||||
; check whether the page buffer contains a valid page (e.g. flashPageNum is not 0xffff)
|
||||
;
|
||||
; @return CFLAG set if current page is valid, cleared otherwise
|
||||
; @clobbers r18, r19
|
||||
|
||||
flashCheckCurrentValid:
|
||||
lds r18, flashPageNum
|
||||
lds r19, flashPageNum+1
|
||||
and r18, r19
|
||||
inc r18
|
||||
breq flashCheckCurrentValid_ClcRet
|
||||
sec
|
||||
ret
|
||||
flashCheckCurrentValid_ClcRet:
|
||||
clc
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine flash4pBeginPage
|
||||
;
|
||||
; Interrupts must be disabled!
|
||||
;
|
||||
; @param Z Address to read from (byte address as for LPM!)
|
||||
; @clobbers (r16, r24, r25, X)
|
||||
|
||||
flash4pBeginPage:
|
||||
push zl
|
||||
push zh
|
||||
andi zl, LOW(~(FLASH_PAGESIZE-1))
|
||||
andi zh, HIGH(~(FLASH_PAGESIZE-1))
|
||||
sts flashPageNum, zl
|
||||
sts flashPageNum+1, zh
|
||||
rcall flash4pReadPagesIntoSram ; r16, r24, r25, X, Z
|
||||
pop zh
|
||||
pop zl
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine flash4pEndPage
|
||||
;
|
||||
; Interrupts must be disabled!
|
||||
;
|
||||
; @clobbers (R0, R1, R16, R18, R19, R20, R24, R25, X)
|
||||
|
||||
flash4pEndPage:
|
||||
rcall flashCheckCurrentValid ; (r18, r19)
|
||||
brcs flash4pEndPage_write
|
||||
ret
|
||||
flash4pEndPage_write:
|
||||
push zl
|
||||
push zh
|
||||
rcall flash4pErasePages ; (R16, R20, Z)
|
||||
rcall flash4pWritePages ; (r0, r1, r20, r24, r25, X, Z)
|
||||
pop zh
|
||||
pop zl
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine flash4pReadPagesIntoSram
|
||||
;
|
||||
; Interrupts must be disabled!
|
||||
;
|
||||
; @param Z Address to read from (byte address as for LPM!)
|
||||
; @clobbers r16, r24, X, Z
|
||||
|
||||
flash4pReadPagesIntoSram:
|
||||
ldi xl, LOW(flashPageBuffer)
|
||||
ldi xh, HIGH(flashPageBuffer)
|
||||
ldi r24, LOW(FLASH_PAGESIZE)
|
||||
flash4pReadPagesIntoSram_loop:
|
||||
lpm r16, Z+
|
||||
st X+, r16
|
||||
adiw ZH:ZL, 1
|
||||
dec r24
|
||||
brne flash4pReadPagesIntoSram_loop
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine flash4pErasePages
|
||||
;
|
||||
; Interrupts must be disabled!
|
||||
;
|
||||
; @clobbers R16, R20, Z
|
||||
|
||||
flash4pErasePages:
|
||||
lds zl, flashPageNum
|
||||
lds zh, flashPageNum+1
|
||||
ldi r20, (1<<PGERS) + (1<<SPMEN) ; enable next SPM, erase page (R1/R0 ignored)
|
||||
rcall flash4pDoSpm ; (R16)
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; flash4pWritePages
|
||||
;
|
||||
; Interrupts must be disabled!
|
||||
;
|
||||
; @clobbers r0, r1, r20, r24, r25, X, Z
|
||||
|
||||
flash4pWritePages:
|
||||
; copy from SDRAM into MCUs temporary page buffer
|
||||
lds zl, flashPageNum
|
||||
lds zh, flashPageNum+1
|
||||
ldi xl, LOW(flashPageBuffer)
|
||||
ldi xh, HIGH(flashPageBuffer)
|
||||
ldi r25, 4 ; handle 4 pages at a time
|
||||
flash4pWritePages_loop1:
|
||||
ldi r24, LOW(PAGESIZE)
|
||||
flash4pWritePages_loop2:
|
||||
ld r0, X+ ; read source data from buffer (low)
|
||||
ld r1, X+ ; read source data from buffer (high)
|
||||
ldi r20, (1<<SPMEN) ; enable next SPM, write R1:R0 into temp page buffer
|
||||
rcall flash4pDoSpm ; (R16)
|
||||
adiw zh:zl, 2
|
||||
dec r24
|
||||
brne flash4pWritePages_loop2
|
||||
|
||||
sbiw zh:zl, (PAGESIZE*2) ; point back to begin of page
|
||||
; transfer data from temporary page buffer into FLASH memory
|
||||
ldi r20, (1<<PGWRT) + (1<<SPMEN) ; enable next SPM, write page (R1/R0 ignored)
|
||||
rcall flash4pDoSpm ; (R16)
|
||||
adiw zh:zl, (PAGESIZE*2) ; point forward to next page
|
||||
dec r25
|
||||
brne flash4pWritePages_loop1
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; flas4phDoSpm
|
||||
;
|
||||
; 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
|
||||
|
||||
flash4pDoSpm:
|
||||
flash4pDoSpm_wait: ; wait for possibly previous SPM to complete
|
||||
in r16, SPMCSR
|
||||
sbrc r16, SPMEN
|
||||
rjmp flash4pDoSpm_wait
|
||||
; SPM timed sequence
|
||||
out SPMCSR, r20
|
||||
spm
|
||||
ret
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user