From c390b1059cf83cac94f86672261b760b4a5507e6 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Sun, 19 Jan 2025 15:44:46 +0100 Subject: [PATCH] avr: updated flash procedure code. --- avr/modules/flash/0BUILD | 1 + avr/modules/flash/bootloader2.asm | 81 ++++++++ avr/modules/flash/defs.asm | 33 +++ avr/modules/flash/flash.asm | 20 +- avr/modules/flash/flash_ready.asm | 10 +- avr/modules/flash/flash_rsp.asm | 2 + avr/modules/flash/flashprocess.asm | 285 ++++++++++++++++++++++++++ avr/modules/flash/hdl_flash_start.asm | 60 +++--- avr/modules/flash/io.asm | 56 +++++ avr/modules/flash/io_attn.asm | 70 +++++++ avr/modules/flash/io_uart1.asm | 74 +++++++ avr/modules/flash/recv.asm | 28 --- 12 files changed, 653 insertions(+), 67 deletions(-) create mode 100644 avr/modules/flash/bootloader2.asm create mode 100644 avr/modules/flash/defs.asm create mode 100644 avr/modules/flash/flashprocess.asm create mode 100644 avr/modules/flash/io.asm create mode 100644 avr/modules/flash/io_attn.asm create mode 100644 avr/modules/flash/io_uart1.asm diff --git a/avr/modules/flash/0BUILD b/avr/modules/flash/0BUILD index 37e07bc..9465679 100644 --- a/avr/modules/flash/0BUILD +++ b/avr/modules/flash/0BUILD @@ -4,6 +4,7 @@ bootloader.asm + defs.asm flash.asm flash_ready.asm flash_rsp.asm diff --git a/avr/modules/flash/bootloader2.asm b/avr/modules/flash/bootloader2.asm new file mode 100644 index 0000000..d88ef84 --- /dev/null +++ b/avr/modules/flash/bootloader2.asm @@ -0,0 +1,81 @@ +; *************************************************************************** +; 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. * +; *************************************************************************** + + + +; *************************************************************************** +; data + + +.dseg + +flashDataBegin: + flashUid: .byte 4 + flashSendBuffer: .byte 32 + flashRecvBuffer: .byte FLASH_RECVBUFFER_MAXLEN +flashDataEnd: + + + + +; *************************************************************************** +; code + + +.cseg + + + +FLASH_PROTO_BEGIN: + + + + +bootLoader: +; rcall watchdogOff ; turn off watchdog timer (sometimes it stays on after reboot) + + sbi LED_DDR, LED_PINNUM ; out + cbi LED_PORT, LED_PINNUM ; on + ldi r16, 30 + rcall flashWaitForMulti100ms + rcall flashReadUidIntoSdram ; R16, X, Y + rcall checkFlash ; (r16, r17, r18, r19, r20, r22, x, y, z) + brcc bootLoader_startFirmware ; no flash process, try to start installed firmware + rcall flashProcess ; received a FLASH START msg, handle flashing + brcc bootLoader_waitAndRestartBootLoader + ; try to start firmware +bootLoader_startFirmware: + cbi LED_PORT, LED_PINNUM ; on + rjmp firmwareStart +bootLoader_waitAndRestartBootLoader: + sbi LED_PORT, LED_PINNUM ; off + ldi r16, 20 + rcall flashWaitForMulti100ms + rjmp bootLoader + + + +bootClcRet: + clc +bootRet: + ret + +bootSecRet: + sec + ret + + + + + + +FLASH_PROTO_END: +.equ MODULE_SIZE_FLASH_PROTO = FLASH_PROTO_END-FLASH_PROTO_BEGIN + + diff --git a/avr/modules/flash/defs.asm b/avr/modules/flash/defs.asm new file mode 100644 index 0000000..264d82d --- /dev/null +++ b/avr/modules/flash/defs.asm @@ -0,0 +1,33 @@ +; *************************************************************************** +; 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_ERROR_NONE = 0 +.equ FLASH_ERROR_MSGERROR = 1 + +.equ FLASH_RECVBUFFER_MAXLEN = 128 +.equ FLASH_CMD_FLASH_RSP = 74 + + +.equ FLASH_MSG_OFFS_DESTADDR = 0 +.equ FLASH_MSG_OFFS_MSGLEN = 1 +.equ FLASH_MSG_OFFS_MSGDATA = 2 +.equ FLASH_MSG_OFFS_CMD = 2 ; first at COM2_MSG_OFFS_MSGDATA +.equ FLASH_MSG_OFFS_SRCADDR = 3 +.equ FLASH_MSG_OFFS_PAYLOAD = 4 ; payload for the cmd follows here + + +.equ FLASH_PACKET_DATA_OFFS_ADDR = FLASH_MSG_OFFS_PAYLOAD+0 ; 4 bytes +.equ FLASH_PACKET_DATA_OFFS_DATA = FLASH_MSG_OFFS_PAYLOAD+4 ; n bytes + +.equ FLASH_PACKET_START_OFFS_UID = FLASH_MSG_OFFS_PAYLOAD+0 ; 4 bytes + + + diff --git a/avr/modules/flash/flash.asm b/avr/modules/flash/flash.asm index faf51ab..0210efe 100644 --- a/avr/modules/flash/flash.asm +++ b/avr/modules/flash/flash.asm @@ -198,32 +198,32 @@ flashReadEepromIncr: ; --------------------------------------------------------------------------- -; flashReadUid +; @routine flashReadUidIntoSdram ; ; Read UID from EEPROM. ; -; IN: -; OUT: -; - R18:R19:R20:R21: UID -; REGS: R16, X +; @clobbers R16, X, Y -flashReadUid: +flashReadUidIntoSdram: + ldi yh, HIGH(flashUid) + ldi yl, LOW(flashUid) push r15 in r15, SREG cli ldi xl, LOW(EEPROM_OFFS_UUID) ldi xh, HIGH(EEPROM_OFFS_UUID) rcall flashReadEepromIncr ; (R16) - mov r18, r16 + st Y+, r16 rcall flashReadEepromIncr ; (R16) - mov r19, r16 + st Y+, r16 rcall flashReadEepromIncr ; (R16) - mov r20, r16 + st Y+, r16 rcall flashReadEepromIncr ; (R16) - mov r21, r16 + st Y+, r16 out SREG, r15 pop r15 ret +; @end diff --git a/avr/modules/flash/flash_ready.asm b/avr/modules/flash/flash_ready.asm index 8194e7d..c01d1ed 100644 --- a/avr/modules/flash/flash_ready.asm +++ b/avr/modules/flash/flash_ready.asm @@ -40,18 +40,18 @@ flashWriteFlashReady: ldi yh, HIGH(flashUid) ; 4 bytes ldi yl, LOW(flashUid) ldi r18, 4 - rcall Utils_Copy_SDRAM - - ldi zl, low(devInfoBlock*2) ; 12 bytes + rcall Utils_Copy_SDRAM ; (R17, R18, X, Y) + + ldi zl, LOW(devInfoBlock*2) ; 12 bytes ldi zh, HIGH(devInfoBlock*2) ldi r18, 12 - rcall Utils_CopyFromFlash + rcall Utils_CopyFromFlash ; (R16, R18, X, Z) ldi r16, LOW(PAGESIZE*2) ; 2 bytes st X+, r16 ldi r16, HIGH(PAGESIZE*2) st X+, r16 - + sbiw xh:xl, 22 ; go back to beginning of message rcall com2CalcAndAddChecksumByte ; (R16, R17, R18, R19, R20, X) sbiw xh:xl, 23 ; go back to beginning of message diff --git a/avr/modules/flash/flash_rsp.asm b/avr/modules/flash/flash_rsp.asm index 49b6936..6fb1423 100644 --- a/avr/modules/flash/flash_rsp.asm +++ b/avr/modules/flash/flash_rsp.asm @@ -16,6 +16,7 @@ .cseg +#if 0 ; --------------------------------------------------------------------------- ; Create and send a FLASH RESPONSE packet ; @@ -31,6 +32,7 @@ flashSendFlashResponse: ldi xh, HIGH(flashSendBuffer) rcall flashWriteFlashRsp ; (R16, R17, R18, R19, R20) rjmp flashSendPacketUntilSuccess ; (R15, R16, R17, R21, R22, X) +#endif diff --git a/avr/modules/flash/flashprocess.asm b/avr/modules/flash/flashprocess.asm new file mode 100644 index 0000000..919e694 --- /dev/null +++ b/avr/modules/flash/flashprocess.asm @@ -0,0 +1,285 @@ +; *************************************************************************** +; 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. * +; *************************************************************************** + + + +.cseg + + +; --------------------------------------------------------------------------- +; @routine checkFlash +; +; Send a FLASH_READY message and wait for about 10s for incoming FLASH_START +; which is then handled (i.e. FLASH_RESPONSE send). +; +; @return CFLAG set if incoming flash request received, cleared otherwise +; @return R16 message type received (if CFLAG set) +; @clobbers r16, r20, X, (r17, r18, r19, r22, y, z) + +checkFlash: + rcall flashInitIo ; (R16, R17) + ldi xl, LOW(flashSendBuffer) + ldi xh, HIGH(flashSendBuffer) + rcall flashProcessWriteFlashReady ; (R16, R17, R18, R19, R20, Y, Z) + rcall flashRawSendMsg ; (r16, r17, X) + + ldi r16, CPRO_CMD_FLASH_START + ldi r20, 10 ; wait for up to 10s + rcall flashWaitForGivenMsg ; (r16, r17, r18, r19, r20, r22, X) + brcc checkFlash_end + + cpi r16, CPRO_CMD_FLASH_START + clc + brne checkFlash_end ; no FLASH_START msg received + + ; check flashStart message (for us?) + ldi xl, LOW(flashRecvBuffer) + ldi xh, HIGH(flashRecvBuffer) + rcall flashProcessHandleFlashStart + brcc checkFlash_end + + ; prepare and send response + clr r16 + rcall flashProcessSendFlashResponse ; (R15, R16, R17, R18, R19, R20, R21, R22, X) + sec +checkFlash_end: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine flashProcess +; +; handling receiving FLASH_DATA and FLASH_END messages, flash new firmware +; +; @return CFLAG set if okay, cleared otherwise +; @clobbers r16, r20 + +flashProcess: +flashProcess_loop1: + ; wait up to 10s for incoming FLASH_DATA message + ldi r16, CPRO_CMD_FLASH_DATA + ldi r20, 5 ; wait for 5s + rcall flashWaitForGivenMsg ; (r16, r17, r18, r19, r20, r22, X) + brcc flashProcess_end ; no FLASH_DATA or FLASH_END msg + ; either FLASH_DATA or FLASH_END received + ldi xl, LOW(flashRecvBuffer) + ldi xh, HIGH(flashRecvBuffer) + cpi r16, CPRO_CMD_FLASH_DATA ; not FLASH_DATA, flashing ended/aborted + brne flashProcess_endReceived ; FLASH_END received, done + rcall flashProcessHandleFlashData ; (R0, R1, R15, R16, R17, R18, R19, R20, Z) + rjmp flashProcess_loop1 +flashProcess_endReceived: + rjmp flashProcessHandleFlashEnd +flashProcess_end: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine flashProcessHandleFlashStart +; Handle FLASH START packet. +; +; @return CFLAG set if message is for us, cleared otherwise +; @param X buffer containing the message +; @clobbers r16, (R15, R17, R18, R19, R20, R21, R22, X) + +flashProcessHandleFlashStart: + rcall flashProcessCheckFlashStart + brcc flashProcessHandleFlashStart_notMe + ; okay, flash start message is for us + rcall flashWaitFor100ms ; TODO: Shorten wait time!! + clr r16 + rcall flashProcessSendFlashResponse ; (R15, R16, R17, R18, R19, R20, R21, R22, X) + sec +flashProcessHandleFlashStart_notMe: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine flashProcessCheckFlashStart +; +; Check whether the UID in the given msg matches our UID. +; +; @return CFLAG set if message is for us, cleared otherwise +; @param X buffer containing the message +; @clobbers r16, r17, r18, X, Y + +flashProcessCheckFlashStart: + ldi yh, HIGH(flashUid) + ldi yl, LOW(flashUid) + adiw xh:xl, FLASH_PACKET_START_OFFS_UID + ldi r18, 4 +flashProcessCheckFlashStart_loop: + ld r16, X+ + ld r17, Y+ + cp r16, r17 + brne flashProcessCheckFlashStart_notMe + dec r18 + brne flashProcessCheckFlashStart_loop + sec + ret +flashProcessCheckFlashStart_notMe: + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine flashProcessHandleFlashData + +; Handle FLASH DATA packet. +; +; @return CFLAG set if okay, cleared otherwise +; @param X buffer containing the message +; @clobbers R0, R1, R18, Z (R15, R16, R17, R19, R20) + +flashProcessHandleFlashData: + adiw xh:xl, FLASH_MSG_OFFS_MSGLEN + ld r18, X ; length (subtract 6) + cpi r18, 6 ; cmd(1), src(1), addr(4) + brcs flashProcessHandleFlashData_badData + subi r18, 6 ; remaining length + adiw xh:xl, FLASH_PACKET_DATA_OFFS_ADDR-FLASH_MSG_OFFS_MSGLEN + ld zl, X+ ; address (low) + ld zh, X+ ; address (high) + adiw xh:xl, 2 ; ignore high bytes, points to first data byte now + + push zl + push zh +flashProcessHandleFlashData_loop: + ld r0, X+ + ld r1, X+ + rcall Flash_WriteIntoPage ; (R15, R16, Z+) + subi r18, 2 + brne flashProcessHandleFlashData_loop + pop zh + pop zl + rcall Flash_FinishPage ; (R15, R16, R20) + clr r16 + rjmp flashProcessHandleFlashData_sendResponse +flashProcessHandleFlashData_badData: + ldi r16, FLASH_ERROR_MSGERROR +flashProcessHandleFlashData_sendResponse: + rcall flashProcessSendFlashResponse ; (R16, R17, R18, R19, R20, X) + sec + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine flashProcessHandleFlashEnd +; +; Handle FLASH END packet. +; +; @return CFLAG set if okay, cleared otherwise +; @param X buffer containing the message +; @clobbers r16, X (R17, R18, R19, R20) + +flashProcessHandleFlashEnd: + rcall flashWaitFor100ms + clr r16 + rcall flashProcessSendFlashResponse ; (R16, R17, R18, R19, R20, X) + sec + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine flashProcessSendFlashResponse +; Create and send a FLASH RESPONSE packet +; +; @param R16 response code to send +; @clobbers X (R16, R17, R18, R19, R20) + +flashProcessSendFlashResponse: + ; send flash ready message + ldi xl, LOW(flashSendBuffer) + ldi xh, HIGH(flashSendBuffer) + rcall flashProcessWriteFlashRsp ; (R16, R17, R18, R19, R20, X) + rjmp flashRawSendMsg ; (R16, R17, X) +; @end + + + +; --------------------------------------------------------------------------- +; @routine flashProcessWriteFlashRsp +; Write a FLASH_RESPONSE packet. +; +; @param R16 response code (0 if ok, error code otherwise) +; @param X buffer to write to +; @clobbers R18 (R16, R17, R19, R20, X) + +flashProcessWriteFlashRsp: + clr r18 + st X+, r18 ; dest address (unused) + ldi r18, 3 ; msg code+src address+one payload byte + st X+, r18 ; msg len + ldi r17, CPRO_CMD_FLASH_RSP + st X+, r17 ; msg code + clr r17 + st X+, r17 ; src address (not used) + st X+, r16 ; payload byte + sbiw xh:xl, 5 + rcall com2CalcAndAddChecksumByte ; (R16, R17, R18, R19, R20, X) + sbiw xh:xl, 6 + ret +; @end + + + +; --------------------------------------------------------------------------- +; Write a FLASH_READY packet. +; +; @param X buffer to write to +; @clobbers R16, R18, Y, Z (R17, R19, R20) + +flashProcessWriteFlashReady: + ldi r16, 0xff + st X+, r16 ; dest address (unused) + ldi r16, 20 ; msg code+src address+18 payload bytes + st X+, r16 ; msg len + ldi r16, CPRO_CMD_FLASH_READY + st X+, r16 ; msg code + ldi r16, COM2_MAINTENANCE_ADDR + st X+, r16 ; src address + + ; payload + ldi yh, HIGH(flashUid) ; 4 bytes + ldi yl, LOW(flashUid) + ldi r18, 4 + rcall Utils_Copy_SDRAM ; (R17, R18, X, Y) + + ldi zl, LOW(devInfoBlock*2) ; 12 bytes + ldi zh, HIGH(devInfoBlock*2) + ldi r18, 12 + rcall Utils_CopyFromFlash ; (R16, R18, X, Z) + + ldi r16, LOW(PAGESIZE*2) ; 2 bytes + st X+, r16 + ldi r16, HIGH(PAGESIZE*2) + st X+, r16 + + sbiw xh:xl, 22 ; go back to beginning of message + rcall com2CalcAndAddChecksumByte ; (R16, R17, R18, R19, R20, X) + sbiw xh:xl, 23 ; go back to beginning of message + ret +; @end + + + + + diff --git a/avr/modules/flash/hdl_flash_start.asm b/avr/modules/flash/hdl_flash_start.asm index b28dbf6..1d2fdbb 100644 --- a/avr/modules/flash/hdl_flash_start.asm +++ b/avr/modules/flash/hdl_flash_start.asm @@ -19,34 +19,16 @@ ; --------------------------------------------------------------------------- +; @routine flashHandleFlashStart ; Handle FLASH START packet. ; -; IN: -; - X : buffer containing the message -; OUT: -; - CFLAG: set if message is for us, cleared otherwise -; REGS: r16, r18, r19, r20, r21, X, Y (R15, R17, R22) +; @return CFLAG set if message is for us, cleared otherwise +; @param X buffer containing the message +; @clobbers r16, (R15, R17, R18, R19, R20, R21, R22, X) flashHandleFlashStart: - ldi yh, HIGH(flashUid) - ldi yl, LOW(flashUid) - ld r18, Y+ - ld r19, Y+ - ld r20, Y+ - ld r21, Y - adiw xh:xl, FLASH_PACKET_START_OFFS_UID - ld r16, X+ - cp r16, r18 - brne flashHandleFlashStart_notMe - ld r16, X+ - cp r16, r19 - brne flashHandleFlashStart_notMe - ld r16, X+ - cp r16, r20 - brne flashHandleFlashStart_notMe - ld r16, X - cp r16, r21 - brne flashHandleFlashStart_notMe + rcall flashCheckFlashStart + brcc flashHandleFlashStart_notMe ; okay, flash start message is for us rcall flashWaitFor100ms clr r16 @@ -54,8 +36,38 @@ flashHandleFlashStart: sec ret flashHandleFlashStart_notMe: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine flashCheckFlashStart +; +; Check whether the UID in the given msg matches our UID. +; +; @return CFLAG set if message is for us, cleared otherwise +; @param X buffer containing the message +; @clobbers r16, r17, r18, X, Y + +flashCheckFlashStart: + ldi yh, HIGH(flashUid) + ldi yl, LOW(flashUid) + adiw xh:xl, FLASH_PACKET_START_OFFS_UID + ldi r18, 4 +flashCheckFlashStart_loop: + ld r16, X+ + ld r17, Y+ + cp r16, r17 + brne flashCheckFlashStart_notMe + dec r18 + brne flashCheckFlashStart_loop + sec + ret +flashCheckFlashStart_notMe: clc ret +; @end diff --git a/avr/modules/flash/io.asm b/avr/modules/flash/io.asm new file mode 100644 index 0000000..f51a539 --- /dev/null +++ b/avr/modules/flash/io.asm @@ -0,0 +1,56 @@ +; *************************************************************************** +; 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 flashWaitForGivenMsg +; Wait for incoming msg with given command +; +; @return CFLAG set if okay (packet received), cleared on error +; @return r16 code of received msg +; @param r16 command to wait for +; @param r20 time in seconds to wait for a message +; @clobbers: r16, r17, r20, X (r18, r19, r22) + +flashWaitForGivenMsg: +flashWaitForGivenMsg_loop: + push r16 + rcall flashRawWaitForValidMsg ; (r16, r17, r18, r19, r22, X) + pop r16 + brcc flashWaitForGivenMsg_end + ldi xl, LOW(flashRecvBuffer) + ldi xh, HIGH(flashRecvBuffer) + adiw xh:xl, COM2_MSG_OFFS_CMD + ld r17, X + sbiw xh:xl, COM2_MSG_OFFS_CMD + cp r16, r17 + breq flashWaitForGivenMsg_gotIt + cpi r16, CPRO_CMD_FLASH_END + breq flashWaitForGivenMsg_gotIt + dec r20 + brne flashWaitForGivenMsg_loop + clc + rjmp flashWaitForGivenMsg_end +flashWaitForGivenMsg_gotIt: + sec +flashWaitForGivenMsg_end: + ret +; @end + + + + + diff --git a/avr/modules/flash/io_attn.asm b/avr/modules/flash/io_attn.asm new file mode 100644 index 0000000..e5bb1e3 --- /dev/null +++ b/avr/modules/flash/io_attn.asm @@ -0,0 +1,70 @@ +; *************************************************************************** +; 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 flashWaitForAttnState +; +; @param r16 expected state (0x00 or 0xff) +; @param r17 time to wait for expected state (in milliseconds) +; @clobbers + +flashWaitForAttnState: +flashWaitForAttnState_loop: + rcall flashWaitForAttnState1ms ; (R22, R24) + brcs flashWaitForAttnState_stateReached + dec r17 + brne flashWaitForAttnState_loop + clc + ret +flashWaitForAttnState_stateReached: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine flashWaitForAttnState1ms +; +; Wait for up to 1ms for ATTN line to reach the given state +; +; @return CFLAG set if state reached, cleared otherwise +; @param R16 expected state (0xff for high, 0 for low) +; @clobbers R24 (R22) + +flashWaitForAttnState1ms: + cbi COM_ATTN_DDR, COM_ATTN_PIN ; set ATTN port as input + cbi COM_ATTN_OUTPUT, COM_ATTN_PIN ; disable internal pullup for ATTN + ldi r24, 100 +flashWaitForAttnState1ms_loop: + push r17 + in r17, COM_ATTN_INPUT + eor r17, r16 + andi r17, (1<