avr/module/flash: unified flash code for 1p/4p devices.
AtTiny 841 erases 4 pages at once, others only erase one. Fixed a bug: only send ONE flash response to FLASH_START!!!
This commit is contained in:
@@ -12,7 +12,7 @@
|
|||||||
.equ FLASH_ERROR_NONE = 0
|
.equ FLASH_ERROR_NONE = 0
|
||||||
.equ FLASH_ERROR_MSGERROR = 1
|
.equ FLASH_ERROR_MSGERROR = 1
|
||||||
|
|
||||||
.equ FLASH_RECVBUFFER_MAXLEN = 128
|
.equ FLASH_RECVBUFFER_MAXLEN = 32
|
||||||
.equ FLASH_CMD_FLASH_RSP = 74
|
.equ FLASH_CMD_FLASH_RSP = 74
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
.dseg
|
.dseg
|
||||||
|
|
||||||
flashPageNum: .byte 2
|
flashPageStart: .byte 2
|
||||||
flashPageBuffer: .byte FLASH_PAGESIZE
|
flashPageBuffer: .byte FLASH_PAGESIZE
|
||||||
|
|
||||||
|
|
||||||
@@ -28,253 +28,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
|
||||||
; @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 flash1pEndPage ; (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 flashCheckCurrentValid ; (r18, r19)
|
|
||||||
brcc flashWriteData_beginPage
|
|
||||||
|
|
||||||
rcall flashWriteCheckPage ; (r18, r19)
|
|
||||||
brcs flashWriteData_calcPosAndLength ; still inside current page, jump
|
|
||||||
rcall flash1pEndPage ; (R0, R1, R16, R18, R19, R20, R24, R25, X)
|
|
||||||
flashWriteData_beginPage:
|
|
||||||
rcall flash1pBeginPage ; (r16, r24, r25, X)
|
|
||||||
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 ; bytes to read > bytes left in page?
|
|
||||||
brcc flashCalcPosAndLength_l1 ; no: jump
|
|
||||||
mov r18, r25 ; yes: cut r18 to number of bytes left in page
|
|
||||||
flashCalcPosAndLength_l1:
|
|
||||||
ldi xl, LOW(flashPageBuffer) ; set X to pos within page buffer
|
|
||||||
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
|
|
||||||
; @param Z address to write to
|
|
||||||
; @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 flash1pBeginPage
|
|
||||||
;
|
|
||||||
; Interrupts must be disabled!
|
|
||||||
;
|
|
||||||
; @param Z Address to read from (byte address as for LPM!)
|
|
||||||
; @clobbers (r16, r24, r25, X)
|
|
||||||
|
|
||||||
flash1pBeginPage:
|
|
||||||
push zl
|
|
||||||
push zh
|
|
||||||
andi zl, LOW(~(FLASH_PAGESIZE-1))
|
|
||||||
andi zh, HIGH(~(FLASH_PAGESIZE-1))
|
|
||||||
sts flashPageNum, zl
|
|
||||||
sts flashPageNum+1, zh
|
|
||||||
rcall flash1pReadPageIntoSram ; r16, r24, r25, X, Z
|
|
||||||
pop zh
|
|
||||||
pop zl
|
|
||||||
ret
|
|
||||||
; @end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
|
||||||
; @routine flash1pEndPage
|
|
||||||
;
|
|
||||||
; Interrupts must be disabled!
|
|
||||||
;
|
|
||||||
; @clobbers (R0, R1, R16, R18, R19, R20, R24, R25, X)
|
|
||||||
|
|
||||||
flash1pEndPage:
|
|
||||||
rcall flashCheckCurrentValid ; (r18, r19)
|
|
||||||
brcs flash1pEndPage_write
|
|
||||||
ret
|
|
||||||
flash1pEndPage_write:
|
|
||||||
push zl
|
|
||||||
push zh
|
|
||||||
rcall flash1pWritePage ; (r0, r1, r20, r24, r25, X, Z)
|
|
||||||
pop zh
|
|
||||||
pop zl
|
|
||||||
ret
|
|
||||||
; @end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
|
||||||
; @routine flash1pReadPageIntoSram
|
|
||||||
;
|
|
||||||
; Interrupts must be disabled!
|
|
||||||
;
|
|
||||||
; @param Z Address to read from (byte address as for LPM!)
|
|
||||||
; @clobbers r16, r24, X, Z
|
|
||||||
|
|
||||||
flash1pReadPageIntoSram:
|
|
||||||
ldi xl, LOW(flashPageBuffer)
|
|
||||||
ldi xh, HIGH(flashPageBuffer)
|
|
||||||
ldi r24, LOW(FLASH_PAGESIZE)
|
|
||||||
flash1pReadPageIntoSram_loop:
|
|
||||||
lpm r16, Z+
|
|
||||||
st X+, r16
|
|
||||||
adiw ZH:ZL, 1
|
|
||||||
dec r24
|
|
||||||
brne flash1pReadPageIntoSram_loop
|
|
||||||
ret
|
|
||||||
; @end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
; ---------------------------------------------------------------------------
|
||||||
; flash1pWritePage
|
; flash1pWritePage
|
||||||
;
|
;
|
||||||
@@ -283,58 +36,30 @@ flash1pReadPageIntoSram_loop:
|
|||||||
; @clobbers r0, r1, r20, r24, r25, X, Z
|
; @clobbers r0, r1, r20, r24, r25, X, Z
|
||||||
|
|
||||||
flash1pWritePage:
|
flash1pWritePage:
|
||||||
lds zl, flashPageNum
|
lds zl, flashPageStart
|
||||||
lds zh, flashPageNum+1
|
lds zh, flashPageStart+1
|
||||||
; erase page
|
|
||||||
ldi r20, (1<<PGERS) + (1<<SPMEN) ; enable next SPM, erase page (R1/R0 ignored)
|
|
||||||
rcall flash1pDoSpm ; (R16)
|
|
||||||
; copy from SDRAM into MCUs temporary page buffer
|
; copy from SDRAM into MCUs temporary page buffer
|
||||||
ldi xl, LOW(flashPageBuffer)
|
ldi xl, LOW(flashPageBuffer)
|
||||||
ldi xh, HIGH(flashPageBuffer)
|
ldi xh, HIGH(flashPageBuffer)
|
||||||
ldi r24, LOW(PAGESIZE)
|
ldi r24, LOW(PAGESIZE)
|
||||||
push zl
|
|
||||||
push zh
|
|
||||||
flash1pWritePages_loop:
|
flash1pWritePages_loop:
|
||||||
ld r0, X+ ; read source data from buffer (low)
|
ld r0, X+ ; read source data from buffer (low)
|
||||||
ld r1, X+ ; read source data from buffer (high)
|
ld r1, X+ ; read source data from buffer (high)
|
||||||
ldi r20, (1<<SPMEN) ; enable next SPM, write R1:R0 into temp page buffer
|
ldi r20, (1<<SPMEN) ; enable next SPM, write R1:R0 into temp page buffer
|
||||||
rcall flash1pDoSpm ; (R16)
|
rcall flashDoSpm ; (R16)
|
||||||
adiw zh:zl, 2
|
adiw zh:zl, 2
|
||||||
dec r24
|
dec r24
|
||||||
brne flash1pWritePages_loop
|
brne flash1pWritePages_loop
|
||||||
pop zh
|
|
||||||
pop zl
|
subi zl, LOW(PAGESIZE*2) ; point back to begin of page
|
||||||
|
sbci zh, HIGH(PAGESIZE*2)
|
||||||
; transfer data from temporary page buffer into FLASH memory
|
; transfer data from temporary page buffer into FLASH memory
|
||||||
ldi r20, (1<<PGWRT) + (1<<SPMEN) ; enable next SPM, write page (R1/R0 ignored)
|
ldi r20, (1<<PGWRT) + (1<<SPMEN) ; enable next SPM, write page (R1/R0 ignored)
|
||||||
rcall flash1pDoSpm ; (R16)
|
rcall flashDoSpm ; (R16)
|
||||||
ret
|
ret
|
||||||
; @end
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
.equ flashWritePage = flash1pWritePage
|
||||||
; ---------------------------------------------------------------------------
|
|
||||||
; flash1pDoSpm
|
|
||||||
;
|
|
||||||
; 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
|
|
||||||
|
|
||||||
flash1pDoSpm:
|
|
||||||
flash1pDoSpm_wait: ; wait for possibly previous SPM to complete
|
|
||||||
in r16, SPMCSR
|
|
||||||
sbrc r16, SPMEN
|
|
||||||
rjmp flash1pDoSpm_wait
|
|
||||||
; SPM timed sequence
|
|
||||||
out SPMCSR, r20
|
|
||||||
spm
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
.dseg
|
.dseg
|
||||||
|
|
||||||
flashPageNum: .byte 2
|
flashPageStart: .byte 2
|
||||||
flashPageBuffer: .byte FLASH_PAGESIZE
|
flashPageBuffer: .byte FLASH_PAGESIZE
|
||||||
|
|
||||||
|
|
||||||
@@ -29,330 +29,47 @@
|
|||||||
|
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
; ---------------------------------------------------------------------------
|
||||||
; @routine Flash_Init
|
; flash4pWritePage
|
||||||
;
|
|
||||||
; @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!
|
; Interrupts must be disabled!
|
||||||
;
|
;
|
||||||
; @clobbers r0, r1, r20, r24, r25, X, Z
|
; @clobbers r0, r1, r20, r24, r25, X, Z
|
||||||
|
|
||||||
flash4pWritePages:
|
flash4pWritePage:
|
||||||
; copy from SDRAM into MCUs temporary page buffer
|
; copy from SDRAM into MCUs temporary page buffer
|
||||||
lds zl, flashPageNum
|
lds zl, flashPageStart
|
||||||
lds zh, flashPageNum+1
|
lds zh, flashPageStart+1
|
||||||
ldi xl, LOW(flashPageBuffer)
|
ldi xl, LOW(flashPageBuffer)
|
||||||
ldi xh, HIGH(flashPageBuffer)
|
ldi xh, HIGH(flashPageBuffer)
|
||||||
ldi r25, 4 ; handle 4 pages at a time
|
ldi r25, 4 ; handle 4 pages at a time
|
||||||
flash4pWritePages_loop1:
|
flash4pWritePage_loop1:
|
||||||
ldi r24, LOW(PAGESIZE)
|
ldi r24, LOW(PAGESIZE)
|
||||||
flash4pWritePages_loop2:
|
flash4pWritePage_loop2:
|
||||||
ld r0, X+ ; read source data from buffer (low)
|
ld r0, X+ ; read source data from buffer (low)
|
||||||
ld r1, X+ ; read source data from buffer (high)
|
ld r1, X+ ; read source data from buffer (high)
|
||||||
ldi r20, (1<<SPMEN) ; enable next SPM, write R1:R0 into temp page buffer
|
ldi r20, (1<<SPMEN) ; enable next SPM, write R1:R0 into temp page buffer
|
||||||
rcall flash4pDoSpm ; (R16)
|
rcall flashDoSpm ; (R16)
|
||||||
adiw zh:zl, 2
|
adiw zh:zl, 2
|
||||||
dec r24
|
dec r24
|
||||||
brne flash4pWritePages_loop2
|
brne flash4pWritePage_loop2
|
||||||
|
|
||||||
sbiw zh:zl, (PAGESIZE*2) ; point back to begin of page
|
push zl
|
||||||
; transfer data from temporary page buffer into FLASH memory
|
push zh
|
||||||
ldi r20, (1<<PGWRT) + (1<<SPMEN) ; enable next SPM, write page (R1/R0 ignored)
|
subi zl, LOW(PAGESIZE*2) ; point back to begin of page
|
||||||
rcall flash4pDoSpm ; (R16)
|
sbci zh, HIGH(PAGESIZE*2)
|
||||||
adiw zh:zl, (PAGESIZE*2) ; point forward to next 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 flashDoSpm ; (R16)
|
||||||
|
pop zh
|
||||||
|
pop zl
|
||||||
dec r25
|
dec r25
|
||||||
brne flash4pWritePages_loop1
|
brne flash4pWritePage_loop1
|
||||||
ret
|
ret
|
||||||
; @end
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.equ flashWritePage = flash4pWritePage
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
|
||||||
; 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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -47,11 +47,11 @@ checkFlash:
|
|||||||
rcall flashProcessWriteFlashReady ; (R16, R17, R18, R19, R20, Y, Z)
|
rcall flashProcessWriteFlashReady ; (R16, R17, R18, R19, R20, Y, Z)
|
||||||
rcall ioRawSendMsg ; (r16, r17, X)
|
rcall ioRawSendMsg ; (r16, r17, X)
|
||||||
|
|
||||||
ldi r16, CPRO_CMD_FLASH_START
|
ldi r16, NETMSG_CMD_FLASH_START
|
||||||
rcall ioWaitForGivenMsg ; (r16, r17, r18, r19, r20, r22, X)
|
rcall ioWaitForGivenMsg ; (r16, r17, r18, r19, r20, r22, X)
|
||||||
brcc checkFlash_end
|
brcc checkFlash_end
|
||||||
|
|
||||||
cpi r16, CPRO_CMD_FLASH_START
|
cpi r16, NETMSG_CMD_FLASH_START
|
||||||
clc
|
clc
|
||||||
brne checkFlash_end ; no FLASH_START msg received
|
brne checkFlash_end ; no FLASH_START msg received
|
||||||
|
|
||||||
@@ -60,10 +60,6 @@ checkFlash:
|
|||||||
ldi xh, HIGH(flashRecvBuffer)
|
ldi xh, HIGH(flashRecvBuffer)
|
||||||
rcall flashProcessHandleFlashStart
|
rcall flashProcessHandleFlashStart
|
||||||
brcc checkFlash_end
|
brcc checkFlash_end
|
||||||
|
|
||||||
; prepare and send response
|
|
||||||
clr r16
|
|
||||||
rcall flashProcessSendFlashResponse ; (R15, R16, R17, R18, R19, R20, R21, R22, X)
|
|
||||||
sec
|
sec
|
||||||
checkFlash_end:
|
checkFlash_end:
|
||||||
ret
|
ret
|
||||||
@@ -77,21 +73,21 @@ checkFlash_end:
|
|||||||
; handling receiving FLASH_DATA and FLASH_END messages, flash new firmware
|
; handling receiving FLASH_DATA and FLASH_END messages, flash new firmware
|
||||||
;
|
;
|
||||||
; @return CFLAG set if okay, cleared otherwise
|
; @return CFLAG set if okay, cleared otherwise
|
||||||
; @clobbers r16, r20
|
; @clobbers r16, r20 (R0, R1, R15, R16, R17, R18, R19, R22, R24, Z)
|
||||||
|
|
||||||
flashProcess:
|
flashProcess:
|
||||||
rcall Flash_Init
|
rcall Flash_Init
|
||||||
flashProcess_loop1:
|
flashProcess_loop1:
|
||||||
; wait up to 10s for incoming FLASH_DATA message
|
; wait up to 10s for incoming FLASH_DATA message
|
||||||
ldi r16, CPRO_CMD_FLASH_DATA
|
ldi r16, NETMSG_CMD_FLASH_DATA
|
||||||
rcall ioWaitForGivenMsg ; (r16, r17, r18, r19, r20, r22, X)
|
rcall ioWaitForGivenMsg ; (r16, r17, r18, r19, r20, r22, X)
|
||||||
brcc flashProcess_end ; no FLASH_DATA or FLASH_END msg
|
brcc flashProcess_end ; no FLASH_DATA or FLASH_END msg
|
||||||
; either FLASH_DATA or FLASH_END received
|
; either FLASH_DATA or FLASH_END received
|
||||||
ldi xl, LOW(flashRecvBuffer)
|
ldi xl, LOW(flashRecvBuffer)
|
||||||
ldi xh, HIGH(flashRecvBuffer)
|
ldi xh, HIGH(flashRecvBuffer)
|
||||||
cpi r16, CPRO_CMD_FLASH_DATA ; not FLASH_DATA, flashing ended/aborted
|
cpi r16, NETMSG_CMD_FLASH_DATA ; not FLASH_DATA, flashing ended/aborted
|
||||||
brne flashProcess_endReceived ; FLASH_END received, done
|
brne flashProcess_endReceived ; FLASH_END received, done
|
||||||
rcall flashProcessHandleFlashData ; (R0, R1, R15, R16, R17, R18, R19, R20, Z)
|
rcall flashProcessHandleFlashData ; (R0, R1, R15, R16, R17, R18, R19, R20, R22, R24, Z)
|
||||||
rjmp flashProcess_loop1
|
rjmp flashProcess_loop1
|
||||||
flashProcess_endReceived:
|
flashProcess_endReceived:
|
||||||
rcall flashProcessHandleFlashEnd
|
rcall flashProcessHandleFlashEnd
|
||||||
@@ -161,27 +157,39 @@ flashProcessCheckFlashStart_notMe:
|
|||||||
;
|
;
|
||||||
; @return CFLAG set if okay, cleared otherwise
|
; @return CFLAG set if okay, cleared otherwise
|
||||||
; @param X buffer containing the message
|
; @param X buffer containing the message
|
||||||
; @clobbers R0, R1, R18, Z (R15, R16, R17, R19, R20)
|
; @clobbers R0, R1, R18, Z (R15, R16, R17, R19, R20, R22, R24)
|
||||||
|
|
||||||
flashProcessHandleFlashData:
|
flashProcessHandleFlashData:
|
||||||
mov yl, xl
|
mov yl, xl
|
||||||
mov yh, xh
|
mov yh, xh
|
||||||
adiw yh:yl, FLASH_MSG_OFFS_MSGLEN
|
ldd r17, Y+FLASH_MSG_OFFS_MSGLEN ; msg length
|
||||||
ld r17, Y ; length (subtract 6)
|
subi r17, 6 ; remaining length (sub cmd(1), src(1), addr(4))
|
||||||
cpi r17, 6 ; cmd(1), src(1), addr(4)
|
brcs flashProcessHandleFlashData_badData ; too few payload bytes
|
||||||
brcs flashProcessHandleFlashData_badData
|
breq flashProcessHandleFlashData_badData ; no payload bytes
|
||||||
subi r17, 6 ; remaining length
|
ldd zl, Y+FLASH_PACKET_DATA_OFFS_ADDR ; only read lower two address bytes
|
||||||
adiw yh:yl, FLASH_PACKET_DATA_OFFS_ADDR-FLASH_MSG_OFFS_MSGLEN
|
ldd zh, Y+(FLASH_PACKET_DATA_OFFS_ADDR+1)
|
||||||
ld zl, Y+ ; address (low)
|
adiw yh:yl, FLASH_PACKET_DATA_OFFS_ADDR+4
|
||||||
ld zh, Y+ ; address (high)
|
|
||||||
adiw yh:yl, 2 ; ignore high bytes, points to first data byte now
|
|
||||||
rcall Flash_WriteData ; (R0, R1, R16, R18, R19, R20, R24, R25, X)
|
rcall Flash_WriteData ; (R0, R1, R16, R18, R19, R20, R24, R25, X)
|
||||||
clr r16
|
clr r16
|
||||||
rjmp flashProcessHandleFlashData_sendResponse
|
rjmp flashProcessHandleFlashData_sendResponse
|
||||||
flashProcessHandleFlashData_badData:
|
flashProcessHandleFlashData_badData:
|
||||||
ldi r16, FLASH_ERROR_MSGERROR
|
ldi r16, FLASH_ERROR_MSGERROR
|
||||||
flashProcessHandleFlashData_sendResponse:
|
flashProcessHandleFlashData_sendResponse:
|
||||||
|
#if 0
|
||||||
|
push r16
|
||||||
|
; send flash message back (debugging)
|
||||||
|
ldi r24, 50
|
||||||
|
rcall flashWaitForMillisecs ; (R22, R24)
|
||||||
|
ldi xl, LOW(flashRecvBuffer)
|
||||||
|
ldi xh, HIGH(flashRecvBuffer)
|
||||||
|
rcall ioRawSendPacket ; (r16, r17, X)
|
||||||
|
pop r16
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ldi r24, 50
|
||||||
|
rcall flashWaitForMillisecs ; (R22, R24)
|
||||||
rcall flashProcessSendFlashResponse ; (R16, R17, R18, R19, R20, X)
|
rcall flashProcessSendFlashResponse ; (R16, R17, R18, R19, R20, X)
|
||||||
|
sbi LED_PIN, LED_PINNUM ; toggle
|
||||||
sec
|
sec
|
||||||
ret
|
ret
|
||||||
; @end
|
; @end
|
||||||
@@ -216,7 +224,7 @@ flashProcessHandleFlashEnd:
|
|||||||
; @clobbers X (R16, R17, R18, R19, R20)
|
; @clobbers X (R16, R17, R18, R19, R20)
|
||||||
|
|
||||||
flashProcessSendFlashResponse:
|
flashProcessSendFlashResponse:
|
||||||
; send flash ready message
|
; send flash response message
|
||||||
ldi xl, LOW(flashSendBuffer)
|
ldi xl, LOW(flashSendBuffer)
|
||||||
ldi xh, HIGH(flashSendBuffer)
|
ldi xh, HIGH(flashSendBuffer)
|
||||||
rcall flashProcessWriteFlashRsp ; (R16, R17, R18, R19, R20, X)
|
rcall flashProcessWriteFlashRsp ; (R16, R17, R18, R19, R20, X)
|
||||||
@@ -238,7 +246,7 @@ flashProcessWriteFlashRsp:
|
|||||||
st X+, r18 ; dest address (unused)
|
st X+, r18 ; dest address (unused)
|
||||||
ldi r18, 3 ; msg code+src address+one payload byte
|
ldi r18, 3 ; msg code+src address+one payload byte
|
||||||
st X+, r18 ; msg len
|
st X+, r18 ; msg len
|
||||||
ldi r17, CPRO_CMD_FLASH_RSP
|
ldi r17, NETMSG_CMD_FLASH_RSP
|
||||||
st X+, r17 ; msg code
|
st X+, r17 ; msg code
|
||||||
clr r17
|
clr r17
|
||||||
st X+, r17 ; src address (not used)
|
st X+, r17 ; src address (not used)
|
||||||
@@ -262,7 +270,7 @@ flashProcessWriteFlashReady:
|
|||||||
st X+, r16 ; dest address (unused)
|
st X+, r16 ; dest address (unused)
|
||||||
ldi r16, 20 ; msg code+src address+18 payload bytes
|
ldi r16, 20 ; msg code+src address+18 payload bytes
|
||||||
st X+, r16 ; msg len
|
st X+, r16 ; msg len
|
||||||
ldi r16, CPRO_CMD_FLASH_READY
|
ldi r16, NETMSG_CMD_FLASH_READY
|
||||||
st X+, r16 ; msg code
|
st X+, r16 ; msg code
|
||||||
ldi r16, COM2_MAINTENANCE_ADDR
|
ldi r16, COM2_MAINTENANCE_ADDR
|
||||||
st X+, r16 ; src address
|
st X+, r16 ; src address
|
||||||
|
|||||||
304
avr/modules/flash/flashxp.asm
Normal file
304
avr/modules/flash/flashxp.asm
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
; ***************************************************************************
|
||||||
|
; 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. *
|
||||||
|
; ***************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
; ***************************************************************************
|
||||||
|
; code
|
||||||
|
|
||||||
|
.cseg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine Flash_Init
|
||||||
|
;
|
||||||
|
; @clobbers R16
|
||||||
|
|
||||||
|
Flash_Init:
|
||||||
|
ldi r16, 0xff
|
||||||
|
sts flashPageStart, r16
|
||||||
|
sts flashPageStart+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 flashEndPage ; (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:
|
||||||
|
rcall flashWriteData ; (R0, R1, R16, R18, R19, R20, R24, R25, X)
|
||||||
|
tst r17
|
||||||
|
brne Flash_WriteData_loop
|
||||||
|
out SREG, r15
|
||||||
|
pop r15
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine flashWriteData
|
||||||
|
;
|
||||||
|
; Interrupts must be disabled!
|
||||||
|
;
|
||||||
|
; @return Z next dest position
|
||||||
|
; @return Y next source 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 flashCheckCurrentValid ; (r18, r19)
|
||||||
|
brcc flashWriteData_beginPage ; jump if this is the first call (no page in work)
|
||||||
|
|
||||||
|
rcall flashWriteCheckPage ; (r18, r19)
|
||||||
|
brcs flashWriteData_calcPosAndLength ; still inside current page, jump
|
||||||
|
rcall flashEndPage ; (R0, R1, R16, R18, R19, R20, R24, R25, X)
|
||||||
|
flashWriteData_beginPage:
|
||||||
|
rcall flashBeginPage ; (r16, r24, r25, X)
|
||||||
|
flashWriteData_calcPosAndLength:
|
||||||
|
rcall flashCalcPosAndLength ; r18=bytes_to_write, x=pos_in_buffer (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
|
||||||
|
; actually write data into buffer
|
||||||
|
flashWriteData_copyLoop:
|
||||||
|
ld r16, Y+
|
||||||
|
st X+, r16
|
||||||
|
dec r18
|
||||||
|
brne flashWriteData_copyLoop
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine flashCalcPosAndLength
|
||||||
|
;
|
||||||
|
; @param Z destination pos
|
||||||
|
; @param R17 number of bytes to write
|
||||||
|
; @return X absolute write position inside buffer
|
||||||
|
; @return R18 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 ; bytes to read > bytes left in page?
|
||||||
|
brcc flashCalcPosAndLength_l1 ; no: jump
|
||||||
|
mov r18, r25 ; yes: cut r18 to number of bytes left in page
|
||||||
|
flashCalcPosAndLength_l1:
|
||||||
|
ldi xl, LOW(flashPageBuffer) ; set X to pos within page buffer
|
||||||
|
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
|
||||||
|
; @param Z address to write to
|
||||||
|
; @clobbers r18, r19
|
||||||
|
|
||||||
|
flashWriteCheckPage:
|
||||||
|
; check low byte of page
|
||||||
|
mov r18, zl
|
||||||
|
lds r19, flashPageStart
|
||||||
|
eor r18, r19
|
||||||
|
cbr r18, LOW(FLASH_PAGESIZE-1)
|
||||||
|
brne flashWriteCheckPage_ClcRet
|
||||||
|
|
||||||
|
; check high byte of page
|
||||||
|
mov r18, zh
|
||||||
|
lds r19, flashPageStart+1
|
||||||
|
eor r18, r19
|
||||||
|
cbr r18, HIGH(FLASH_PAGESIZE-1)
|
||||||
|
brne flashWriteCheckPage_ClcRet
|
||||||
|
sec
|
||||||
|
ret
|
||||||
|
flashWriteCheckPage_ClcRet:
|
||||||
|
clc
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine flashCheckCurrentValid
|
||||||
|
;
|
||||||
|
; check whether the page buffer contains a valid page (e.g. flashPageStart is not 0xffff)
|
||||||
|
;
|
||||||
|
; @return CFLAG set if current page is valid, cleared otherwise
|
||||||
|
; @clobbers r18, r19
|
||||||
|
|
||||||
|
flashCheckCurrentValid:
|
||||||
|
lds r18, flashPageStart
|
||||||
|
lds r19, flashPageStart+1
|
||||||
|
and r18, r19
|
||||||
|
inc r18
|
||||||
|
breq flashCheckCurrentValid_ClcRet
|
||||||
|
sec
|
||||||
|
ret
|
||||||
|
flashCheckCurrentValid_ClcRet:
|
||||||
|
clc
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine flashBeginPage
|
||||||
|
;
|
||||||
|
; Interrupts must be disabled!
|
||||||
|
;
|
||||||
|
; @param Z Address to read from (byte address as for LPM!)
|
||||||
|
; @clobbers (r16, r24, r25, X)
|
||||||
|
|
||||||
|
flashBeginPage:
|
||||||
|
push zl
|
||||||
|
push zh
|
||||||
|
cbr zl, LOW(FLASH_PAGESIZE-1)
|
||||||
|
cbr zh, HIGH(FLASH_PAGESIZE-1)
|
||||||
|
sts flashPageStart, zl
|
||||||
|
sts flashPageStart+1, zh
|
||||||
|
rcall flashReadPageIntoSram ; (r16, r24, r25, X, Z)
|
||||||
|
pop zh
|
||||||
|
pop zl
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine flashEndPage
|
||||||
|
;
|
||||||
|
; Interrupts must be disabled!
|
||||||
|
;
|
||||||
|
; @clobbers (R0, R1, R16, R18, R19, R20, R24, R25, X)
|
||||||
|
|
||||||
|
flashEndPage:
|
||||||
|
rcall flashCheckCurrentValid ; (r18, r19)
|
||||||
|
brcs flashEndPage_write
|
||||||
|
ret
|
||||||
|
flashEndPage_write:
|
||||||
|
push zl
|
||||||
|
push zh
|
||||||
|
rcall flashErasePage ; (R16, R20, Z)
|
||||||
|
rcall flashWritePage ; (r0, r1, r20, r24, r25, X, Z)
|
||||||
|
pop zh
|
||||||
|
pop zl
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine flashReadPageIntoSram
|
||||||
|
;
|
||||||
|
; @param Z Address to read from (byte address as for LPM!)
|
||||||
|
; @clobbers r16, r24, X, Z
|
||||||
|
|
||||||
|
flashReadPageIntoSram:
|
||||||
|
ldi xl, LOW(flashPageBuffer)
|
||||||
|
ldi xh, HIGH(flashPageBuffer)
|
||||||
|
ldi r24, LOW(FLASH_PAGESIZE)
|
||||||
|
flashReadPageIntoSram_loop:
|
||||||
|
lpm r16, Z+
|
||||||
|
st X+, r16
|
||||||
|
; adiw ZH:ZL, 1
|
||||||
|
dec r24
|
||||||
|
brne flashReadPageIntoSram_loop
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine flashErasePage
|
||||||
|
;
|
||||||
|
; Interrupts must be disabled!
|
||||||
|
;
|
||||||
|
; @clobbers R16, R20, Z
|
||||||
|
|
||||||
|
flashErasePage:
|
||||||
|
lds zl, flashPageStart
|
||||||
|
lds zh, flashPageStart+1
|
||||||
|
ldi r20, (1<<PGERS) + (1<<SPMEN) ; enable next SPM, erase page (R1/R0 ignored)
|
||||||
|
rcall flashDoSpm ; (R16)
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine flashDoSpm
|
||||||
|
;
|
||||||
|
; wait until possible previous SPM finished and then issue another SPM.
|
||||||
|
;
|
||||||
|
; @param R20 value for register SPMCR
|
||||||
|
; @param R0 low value for SPM
|
||||||
|
; @param R1 high value for SPM
|
||||||
|
; @param Z address for SPM (byte address!)
|
||||||
|
; @clobbers 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
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
@@ -68,13 +68,25 @@ flashWaitForMulti100ms_loop:
|
|||||||
|
|
||||||
flashWaitFor100ms:
|
flashWaitFor100ms:
|
||||||
ldi r24, 100
|
ldi r24, 100
|
||||||
flashWaitFor100ms_loop:
|
rjmp flashWaitForMillisecs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine flashWaitForMillisecs
|
||||||
|
; wait for multiples of 100 milliseconds.
|
||||||
|
;
|
||||||
|
; @param R24 time to wait in milliseconds
|
||||||
|
; @clobbers R24 (R22)
|
||||||
|
|
||||||
|
flashWaitForMillisecs:
|
||||||
push r24
|
push r24
|
||||||
rcall flashWaitFor1ms ; (R22, R24)
|
rcall flashWaitFor1ms ; (R22, R24)
|
||||||
pop r24
|
pop r24
|
||||||
dec r24
|
dec r24
|
||||||
brne flashWaitFor100ms_loop
|
brne flashWaitForMillisecs
|
||||||
ret
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user