From e25b0ad69d5b17aa75c91513280ddcc74399282f Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Sun, 4 May 2025 03:32:53 +0200 Subject: [PATCH] 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!!! --- avr/modules/flash/defs.asm | 2 +- avr/modules/flash/flash1p.asm | 305 ++------------------------- avr/modules/flash/flash4p.asm | 323 ++--------------------------- avr/modules/flash/flashprocess.asm | 54 +++-- avr/modules/flash/flashxp.asm | 304 +++++++++++++++++++++++++++ avr/modules/flash/wait.asm | 16 +- 6 files changed, 385 insertions(+), 619 deletions(-) create mode 100644 avr/modules/flash/flashxp.asm diff --git a/avr/modules/flash/defs.asm b/avr/modules/flash/defs.asm index 264d82d..ffc904f 100644 --- a/avr/modules/flash/defs.asm +++ b/avr/modules/flash/defs.asm @@ -12,7 +12,7 @@ .equ FLASH_ERROR_NONE = 0 .equ FLASH_ERROR_MSGERROR = 1 -.equ FLASH_RECVBUFFER_MAXLEN = 128 +.equ FLASH_RECVBUFFER_MAXLEN = 32 .equ FLASH_CMD_FLASH_RSP = 74 diff --git a/avr/modules/flash/flash1p.asm b/avr/modules/flash/flash1p.asm index 05fcf48..9e64ffc 100644 --- a/avr/modules/flash/flash1p.asm +++ b/avr/modules/flash/flash1p.asm @@ -16,7 +16,7 @@ .dseg - flashPageNum: .byte 2 + flashPageStart: .byte 2 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 ; @@ -283,58 +36,30 @@ flash1pReadPageIntoSram_loop: ; @clobbers r0, r1, r20, r24, r25, X, Z flash1pWritePage: - lds zl, flashPageNum - lds zh, flashPageNum+1 - ; erase page - ldi r20, (1< 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<