From 9719063a21b8fdf3ae6764e599b415a0eb32d918 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Sun, 9 Feb 2025 21:04:30 +0100 Subject: [PATCH] avr: adapted flash4p code for single page erasing mcu. --- avr/modules/flash/flash1p.asm | 335 ++++++++++++++++++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 avr/modules/flash/flash1p.asm diff --git a/avr/modules/flash/flash1p.asm b/avr/modules/flash/flash1p.asm new file mode 100644 index 0000000..128222f --- /dev/null +++ b/avr/modules/flash/flash1p.asm @@ -0,0 +1,335 @@ +; *************************************************************************** +; 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) + + +; *************************************************************************** +; 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 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 flashWriteCheckPage ; (r18, r19) + brcs flashWriteData_calcPosAndLength + rcall flash1pEndPage ; (R0, R1, R16, R18, R19, R20, R24, R25, X) + rcall flash1pBeginPage ; (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 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 +; +; Interrupts must be disabled! +; +; @clobbers r0, r1, r20, r24, r25, X, Z + +flash1pWritePage: + lds zl, flashPageNum + lds zh, flashPageNum+1 + ; erase page + ldi r20, (1<