; *************************************************************************** ; 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_BAD_MSGNUM = 1 .equ FLASH_ERROR_BAD_ADDR = 2 .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 ; 2 bytes .equ FLASH_PACKET_DATA_OFFS_DATA = FLASH_MSG_OFFS_PAYLOAD+2 ; n bytes ; *************************************************************************** ; data .dseg flashDataBegin: flashUid: .byte 4 flashSendBuffer: .byte 64 flashRecvBuffer: .byte 64 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 sbi DDRA, PORTA3 ; out ; sbi PINA, PORTA3 ; toggle cbi PORTA, PORTA3 ; on ; sbi PORTA, PORTA3 ; off rcall flashReadUid sts flashUid, r18 sts flashUid+1, r19 sts flashUid+2, r20 sts flashUid+3, r21 ; send flash ready message ldi xl, LOW(flashSendBuffer) ldi xh, HIGH(flashSendBuffer) rcall flashWriteFlashReady rcall flashSendPacketUntilSuccess ; wait up to 10s for incoming FLASH_START message ldi r16, CPRO_CMD_FLASH_START ldi r17, 100 ; 100*100ms=10s rcall flashWaitForSpecificMessageWithLed brcc bootLoader_startFirmware ; either FLASH_START or FLASH_END received cpi r16, CPRO_CMD_FLASH_START ; not FLASH_START, no flashing requested brne bootLoader_startFirmware ; receive and flash new firmware ; try to start firmware bootLoader_startFirmware: lds r20, firmwareStart lds r21, firmwareStart+1 mov r16, r20 or r16, r21 breq bootLoader ; restart boot loader ; jmp via stack push r20 push r21 ret ; --------------------------------------------------------------------------- ; wait for a specific message to arrive within given time, flashing LED ; ; IN: ; - R16: message type to receive ; - R17: wait time in 100ms (1=100ms, 2=200ms etc.) ; OUT: ; - CFLAG: set if msg received (either expected msg or FLASH_END), cleared otherwise ; - R16: message type received (if CFLAG set) ; REGS: R2, R16, R17 (R1, R24, R25, X) flashWaitForSpecificMessageWithLed: mov r2, r16 sbi PORTA, PORTA3 ; LED off flashWaitForSpecificMessageWithLed_loop: sbi PINA, PORTA3 ; toggle LED mov r16, r2 push r17 ldi r17, 100 ; wait up to 100ms rcall flashWaitForSpecificMessage ; (R1, R16, R17, R24, R25, X) pop r17 brcs flashWaitForSpecificMessageWithLed_received dec r17 brne flashWaitForSpecificMessageWithLed_loop sbi PORTA, PORTA3 ; off clc ret flashWaitForSpecificMessageWithLed_received: sbi PORTA, PORTA3 ; off sec ret ; --------------------------------------------------------------------------- ; wait for a specific message to arrive within given time. ; ; IN: ; - R16: msg command to wait for ; - R17: time to wait for packet (in milliseconds) (low) ; OUT: ; - CFLAG: set if msg received, cleared on timeout ; - R16 : message type received ; REGS: R1, R16, R17, X (R24, R25) flashWaitForSpecificMessage: mov r1, r16 ; expected message type ; wait for ATTN to go low flashWaitForSpecificMessage_loop1: ldi r16, 0 ; wait for low rcall flashWaitForAttnState1ms ; (R24, R25) brcs flashWaitForSpecificMessage_isLow dec r17 brne flashWaitForSpecificMessage_loop1 rjmp flashWaitForSpecificMessage_timeout ; receive message flashWaitForSpecificMessage_isLow: ; is low, receive message, check for msg type push r17 ldi r16, COM2_MAINTENANCE_ADDR ldi xl, LOW(flashRecvBuffer) ldi xh, HIGH(flashRecvBuffer) rcall com2ReceivePacketRaw pop r17 brcc flashWaitForSpecificMessage_waitAttnHigh ldi xl, LOW(flashRecvBuffer) ldi xh, HIGH(flashRecvBuffer) adiw xh:xl, COM2_MSG_OFFS_CMD ld r16, X sbiw xh:xl, COM2_MSG_OFFS_CMD cp r16, r1 breq flashWaitForSpecificMessage_received cpi r16, CPRO_CMD_FLASH_END breq flashWaitForSpecificMessage_received flashWaitForSpecificMessage_waitAttnHigh: dec r17 breq flashWaitForSpecificMessage_timeout ; wait for ATTN to go high flashWaitForSpecificMessage_loop2: ldi r16, 0xff ; wait for high rcall flashWaitForAttnState1ms ; (R24, R25) brcs flashWaitForSpecificMessage_isHigh dec r17 brne flashWaitForSpecificMessage_loop2 rjmp flashWaitForSpecificMessage_timeout flashWaitForSpecificMessage_isHigh: rjmp flashWaitForSpecificMessage_loop1 flashWaitForSpecificMessage_received: ; R16 contains message type sec ret flashWaitForSpecificMessage_timeout: clc ret ; --------------------------------------------------------------------------- ; Wait for up to 1ms for ATTN line to reach the given state ; ; IN: ; - R16: expected state (0xff for high, 0 for low) ; OUT: ; - CFLAG: set if state reached, cleared otherwise ; REGS: R24, R25 flashWaitForAttnState1ms: ldi r24, LOW(1000) ldi r25, HIGH(1000) flashWaitForAttnState1ms_loop: in r17, COM_PIN_ATTN eor r17, r16 andi r17, (1<