; *************************************************************************** ; 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 ; --------------------------------------------------------------------------- ; @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 flashReadUidIntoSdram ; R16, X, Y rcall ioRawInit ; (R16, R17) ldi xl, LOW(flashSendBuffer) ldi xh, HIGH(flashSendBuffer) rcall flashProcessWriteFlashReady ; (R16, R17, R18, R19, R20, Y, Z) rcall ioRawSendMsg ; (r16, r17, X) ldi r16, NETMSG_CMD_FLASH_START ldi r20, FLASH_WAITFORSTART_TRIES rcall ioWaitForGivenMsg ; (r16, r17, r18, r19, r20, r22, X) brcc checkFlash_end cpi r16, NETMSG_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 ; 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 (R0, R1, R15, R16, R17, R18, R19, R22, R24, Z) flashProcess: rcall Flash_Init flashProcess_loop1: ; wait up to 10s for incoming FLASH_DATA message ldi r16, NETMSG_CMD_FLASH_DATA ldi r20, FLASH_WAITFORDATA_TRIES rcall ioWaitForGivenMsg ; (r16, r17, r18, r19, r20, r22, X) ; brcc flashProcess_end ; no FLASH_DATA or FLASH_END msg brcc flashProcess_loop1end ; no FLASH_DATA or FLASH_END msg, retry indefinately ; either FLASH_DATA or FLASH_END received ldi xl, LOW(flashRecvBuffer) ldi xh, HIGH(flashRecvBuffer) cpi r16, NETMSG_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, R22, R24, Z) flashProcess_loop1end: rjmp flashProcess_loop1 flashProcess_endReceived: rcall flashProcessHandleFlashEnd sec 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, R22, R24) flashProcessHandleFlashData: mov yl, xl mov yh, xh ldd r17, Y+FLASH_MSG_OFFS_MSGLEN ; msg length subi r17, 6 ; remaining length (sub cmd(1), src(1), addr(4)) brcs flashProcessHandleFlashData_badData ; too few payload bytes breq flashProcessHandleFlashData_badData ; no payload bytes ldd zl, Y+FLASH_PACKET_DATA_OFFS_ADDR ; only read lower two address bytes ldd zh, Y+(FLASH_PACKET_DATA_OFFS_ADDR+1) adiw yh:yl, FLASH_PACKET_DATA_OFFS_ADDR+4 rcall Flash_WriteData ; (R0, R1, R16, R18, R19, R20, R24, R25, X) clr r16 rjmp flashProcessHandleFlashData_sendResponse flashProcessHandleFlashData_badData: ldi r16, FLASH_ERROR_MSGERROR flashProcessHandleFlashData_sendResponse: #if 0 push r16 ; send flash message back (debugging) ; ldi r24, 2 ; rcall flashWaitForMillisecs ; (R22, R24) ldi xl, LOW(flashRecvBuffer) ldi xh, HIGH(flashRecvBuffer) rcall ioRawSendPacket ; (r16, r17, X) pop r16 #endif ; ldi r24, 2 ; rcall flashWaitForMillisecs ; (R22, R24) rcall flashProcessSendFlashResponse ; (R16, R17, R18, R19, R20, X) sbi LED_PIN, LED_PINNUM ; toggle 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 Flash_Fini ; flash pending data 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 response message ldi xl, LOW(flashSendBuffer) ldi xh, HIGH(flashSendBuffer) rcall flashProcessWriteFlashRsp ; (R16, R17, R18, R19, R20, X) rjmp ioRawSendMsg ; (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, NETMSG_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 NETMSG_CalcAndAddChecksumByte ; (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, NETMSG_CMD_FLASH_READY st X+, r16 ; msg code ldi r16, NET_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 NETMSG_CalcAndAddChecksumByte ; (R16, R17, R18, R19, R20, X) sbiw xh:xl, 23 ; go back to beginning of message ret ; @end