Files
aqhomecontrol/avr/modules/flash/flashprocess.asm
2025-03-25 00:38:12 +01:00

296 lines
8.4 KiB
NASM

; ***************************************************************************
; 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, CPRO_CMD_FLASH_START
rcall ioWaitForGivenMsg ; (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:
rcall Flash_Init
flashProcess_loop1:
; wait up to 20s for incoming FLASH_DATA message
ldi r16, CPRO_CMD_FLASH_DATA
rcall ioWaitForGivenMsg ; (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:
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)
flashProcessHandleFlashData:
mov yl, xl
mov yh, xh
adiw yh:yl, FLASH_MSG_OFFS_MSGLEN
ld r17, Y ; length (subtract 6)
cpi r17, 6 ; cmd(1), src(1), addr(4)
brcs flashProcessHandleFlashData_badData
subi r17, 6 ; remaining length
adiw yh:yl, FLASH_PACKET_DATA_OFFS_ADDR-FLASH_MSG_OFFS_MSGLEN
ld zl, Y+ ; address (low)
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)
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 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 ready 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, 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 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, 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 NETMSG_CalcAndAddChecksumByte ; (R16, R17, R18, R19, R20, X)
sbiw xh:xl, 23 ; go back to beginning of message
ret
; @end