Files
aqhomecontrol/avr/modules/flash/bootloader.asm

200 lines
5.1 KiB
NASM

; ***************************************************************************
; copyright : (C) 2023 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
; ***************************************************************************
; data
.dseg
flashDataBegin:
flashUid: .byte 4
flashSendBuffer: .byte 32
flashRecvBuffer: .byte FLASH_RECVBUFFER_MAXLEN
flashDataEnd:
; ***************************************************************************
; code
.cseg
FLASH_PROTO_BEGIN:
bootLoader:
cli ; disable interrupts throughout the whole process
; setup stack
.ifdef SPH ; if SPH is defined
ldi r16, High(RAMEND)
out SPH, r16 ; init MSB stack pointer
.endif
ldi r16, Low(RAMEND)
out SPL, r16 ; init LSB stack pointer
; rcall watchdogOff ; turn off watchdog timer (sometimes it stays on after reboot)
; setup pins and interrupts
cbi COM_TXD_DATA, COM_TXD_PIN ; disable internal pullup for DATA
cbi COM_TXD_DDR, COM_TXD_PIN ; set DATA port as input
cbi COM_ATTN_OUTPUT, COM_ATTN_PIN ; disable internal pullup for ATTN
cbi COM_ATTN_DDR, COM_ATTN_PIN ; set ATTN port as input
sbi LED_DDR, LED_PINNUM ; out
cbi LED_PORT, LED_PINNUM ; on
rcall flashReadUid
ldi xh, HIGH(flashUid)
ldi xl, LOW(flashUid)
st X+, r18
st X+, r19
st X+, r20
st X+, r21
; wait for 3 secs before doing anything else
ldi r16, 30
rcall flashWaitForMulti100ms
rcall bootCheckFlash
brcc bootLoader_startFirmware ; no flash process, try start installed firmware
rcall bootLoaderFlash ; received a FLASH START msg, handle flashing
brcc bootLoader_waitAndRestartBootLoader
; try to start firmware
bootLoader_startFirmware:
cbi LED_PORT, LED_PINNUM ; on
ldi r16, 10
rcall flashWaitForMulti100ms
sbi LED_PORT, LED_PINNUM ; off
ldi r16, 3
rcall flashWaitForMulti100ms
cbi LED_PORT, LED_PINNUM ; on
ldi r16, 10
rcall flashWaitForMulti100ms
sbi LED_PORT, LED_PINNUM ; off
rjmp firmwareStart
bootLoader_waitAndRestartBootLoader:
sbi LED_PORT, LED_PINNUM ; off
ldi r16, 20
rcall flashWaitForMulti100ms
rjmp bootLoader
; ---------------------------------------------------------------------------
; check for incoming flash request
;
; send a FLASH_READY message and wait for about 10s for incoming FLASH_START which is then handled.
;
; IN:
; - R16: message type to receive
; - R17: wait time in 100ms (1=100ms, 2=200ms etc.)
; OUT:
; - CFLAG: set if incoming flash request received, cleared otherwise
; - R16: message type received (if CFLAG set)
; REGS: R16, R17, X, Y, (R1, R2, R18, R19, R20, R21, R22, R24, R25)
bootCheckFlash:
; send flash ready message
ldi xl, LOW(flashSendBuffer)
ldi xh, HIGH(flashSendBuffer)
rcall flashWriteFlashReady ; (R16, R17, R18, R19, R20, Y, Z)
rcall flashSendPacketUntilSuccess ; (R16, R17, R18, R21, R22, R24, R25, X)
bootCheckFlash_loop:
; wait up to 10s for incoming FLASH_START message
ldi r16, CPRO_CMD_FLASH_START
ldi r17, 100 ; 100*100ms=10s
rcall flashWaitForSpecificMessageWithLed ; R2, R16, R17 (R1, R24, R25, X)
brcc bootRet
; either FLASH_START or FLASH_END received
cpi r16, CPRO_CMD_FLASH_START ; not FLASH_START, no flashing requested
brne bootClcRet
; received FLASH_START
rcall flashHandleFlashStart
brcc bootCheckFlash_loop
ret ; ret with CARRY flag set
bootLoaderFlash:
bootLoaderFlash_loop1:
; wait up to 10s for incoming FLASH_DATA message
ldi r16, CPRO_CMD_FLASH_DATA
ldi r17, 100 ; 100*100ms=10s
rcall flashWaitForSpecificMessageWithLed
brcc bootRet
; either FLASH_DATA or FLASH_END received
cpi r16, CPRO_CMD_FLASH_DATA ; not FLASH_DATA, flashing ended/aborted
brne bootSecRet ; FLASH_END received, done
; flash data
rcall flashHandleFlashData
rjmp bootLoaderFlash_loop1
bootLoaderFlash_endReceived:
rjmp flashHandleFlashEnd
bootClcRet:
clc
bootRet:
ret
bootSecRet:
sec
ret
FLASH_PROTO_END:
.equ MODULE_SIZE_FLASH_PROTO = FLASH_PROTO_END-FLASH_PROTO_BEGIN