flashing older nodes across t03 now works!

older nodes need the new bootloader which doesn't depend on pagesize because
those older nodes used quite large message sizes which are not supported
across t03 nodes (we would need to much RAM on t03 for this).
This commit is contained in:
Martin Preuss
2025-03-23 22:40:34 +01:00
parent 24dc3e1c0a
commit 0165b02310
3 changed files with 359 additions and 15 deletions

View File

@@ -28,9 +28,11 @@ ioWaitForGivenMsg:
ldi r20, 10 ; number of tries ldi r20, 10 ; number of tries
ioWaitForGivenMsg_loop: ioWaitForGivenMsg_loop:
push r16 push r16
rcall ioRawWaitForValidMsg ; (r16, r17, r18, r19, r22, X) push r20
pop r17 ; pop into r17 (from r16) rcall ioRawWaitForValidMsg ; (r16, r17, r18, r19, r20, r21, r22, X)
brcc ioWaitForGivenMsg_end pop r20
pop r17 ; pop expected code to r17!
brcc ioWaitForGivenMsg_loopEnd
ldi xl, LOW(flashRecvBuffer) ldi xl, LOW(flashRecvBuffer)
ldi xh, HIGH(flashRecvBuffer) ldi xh, HIGH(flashRecvBuffer)
adiw xh:xl, COM2_MSG_OFFS_CMD adiw xh:xl, COM2_MSG_OFFS_CMD
@@ -40,7 +42,8 @@ ioWaitForGivenMsg_loop:
breq ioWaitForGivenMsg_gotIt breq ioWaitForGivenMsg_gotIt
cpi r16, CPRO_CMD_FLASH_END cpi r16, CPRO_CMD_FLASH_END
breq ioWaitForGivenMsg_gotIt breq ioWaitForGivenMsg_gotIt
mov r16, r17 ; put expected msg code back into r16 for next loop ioWaitForGivenMsg_loopEnd:
mov r17, r16 ; move expected code back to r16
dec r20 dec r20
brne ioWaitForGivenMsg_loop brne ioWaitForGivenMsg_loop
clc clc
@@ -52,6 +55,3 @@ ioWaitForGivenMsg_end:
; @end ; @end

View File

@@ -23,6 +23,8 @@
; @clobbers R17 (R22, R24) ; @clobbers R17 (R22, R24)
ioWaitForAttnState100ms: ioWaitForAttnState100ms:
cbi COM_ATTN_DDR, COM_ATTN_PIN ; set ATTN port as input
cbi COM_ATTN_OUTPUT, COM_ATTN_PIN ; disable internal pullup for ATTN
ioWaitForAttnState100ms_loop: ioWaitForAttnState100ms_loop:
push r17 push r17
ldi r17, 100 ldi r17, 100
@@ -32,7 +34,6 @@ ioWaitForAttnState100ms_loop:
dec r17 dec r17
brne ioWaitForAttnState100ms_loop brne ioWaitForAttnState100ms_loop
clc clc
ret
ioWaitForAttnState100ms_stateReached: ioWaitForAttnState100ms_stateReached:
ret ret
; @end ; @end
@@ -53,7 +54,6 @@ ioWaitForAttnStateMilliSeconds_loop:
dec r17 dec r17
brne ioWaitForAttnStateMilliSeconds_loop brne ioWaitForAttnStateMilliSeconds_loop
clc clc
ret
ioWaitForAttnStateMilliSeconds_stateReached: ioWaitForAttnStateMilliSeconds_stateReached:
ret ret
; @end ; @end
@@ -70,8 +70,6 @@ ioWaitForAttnStateMilliSeconds_stateReached:
; @clobbers R24 (R22) ; @clobbers R24 (R22)
ioWaitForAttnState1ms: ioWaitForAttnState1ms:
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 ldi r24, 100
ioWaitForAttnState1ms_loop: ioWaitForAttnState1ms_loop:
push r17 push r17

View File

@@ -8,6 +8,65 @@
; *************************************************************************** ; ***************************************************************************
; ***************************************************************************
; macros
; ---------------------------------------------------------------------------
; @macro UART_BB_M_WAIT_FOR_PIN_LOW IN_REG_DATA, IN_PINNUM
; 0 1
; Wait for a pin to become low
; @param %0 DATA register for input pin (e.g. PINB)
; @param %1 pin number for input (e.g. PORTB1)
; @return CFLAG set if okay, clear otherwise
; @clobbers R17, R22
.macro UART_BB_M_WAIT_FOR_PIN_LOW
ldi r17, 200
l_loop:
sbis @0, @1
rjmp l_reached
Utils_WaitNanoSecs 5000, 0, r22 ; wait for 5us
dec r17
brne l_loop
clc
rjmp l_end
l_reached:
sec
l_end:
.endmacro
; @end
; ---------------------------------------------------------------------------
; @macro UART_BB_M_WAIT_FOR_PIN_HIGH IN_REG_DATA, IN_PINNUM
; 0 1
; Wait for a pin to become high (up to 1ms)
; @param %0 DATA register for input pin (e.g. PINB)
; @param %1 pin number for input (e.g. PORTB1)
; @return CFLAG set if okay, clear otherwise
; @clobbers R17, R22
.macro UART_BB_M_WAIT_FOR_PIN_HIGH
ldi r17, 200
l_loop:
sbic @0, @1
rjmp l_reached
Utils_WaitNanoSecs 5000, 0, r22 ; wait for 5us
dec r17
brne l_loop
clc
rjmp l_end
l_reached:
sec
l_end:
.endmacro
; @end
; *************************************************************************** ; ***************************************************************************
; code ; code
@@ -49,7 +108,7 @@ ioRawSendMsg_loop:
ioRawSendMsg_attnHigh: ioRawSendMsg_attnHigh:
ldi xl, LOW(flashSendBuffer) ldi xl, LOW(flashSendBuffer)
ldi xh, HIGH(flashSendBuffer) ldi xh, HIGH(flashSendBuffer)
rcall uartBitbang_SendPacket ; R16, R22 (R17, R21, X) rcall ioRawSendPacket ; R16, R22 (R17, R21, X)
brcc ioRawSendMsg_loop brcc ioRawSendMsg_loop
ret ret
; @end ; @end
@@ -61,7 +120,7 @@ ioRawSendMsg_attnHigh:
; Wait for valid incoming msg ; Wait for valid incoming msg
; ;
; @return CFLAG set if okay (packet received), cleared on error ; @return CFLAG set if okay (packet received), cleared on error
; @clobbers: ; @clobbers: r16, r17 (r18, r19, r20, r21, r22, X)
ioRawWaitForValidMsg: ioRawWaitForValidMsg:
ldi r16, 0 ; expect ATTN low ldi r16, 0 ; expect ATTN low
@@ -74,14 +133,301 @@ ioRawWaitForValidMsg_attnLow:
ldi xh, HIGH(flashRecvBuffer) ldi xh, HIGH(flashRecvBuffer)
ldi r16, COM2_MAINTENANCE_ADDR ldi r16, COM2_MAINTENANCE_ADDR
ldi r17, FLASH_RECVBUFFER_MAXLEN-3 ldi r17, FLASH_RECVBUFFER_MAXLEN-3
rcall uartBitbang_ReceivePacketIntoBuffer rcall ioRawReceivePacketIntoBuffer
brcs ioRawWaitForValidMsg_packetReceived brcs ioRawWaitForValidMsg_packetReceived
ret ret
ioRawWaitForValidMsg_packetReceived: ioRawWaitForValidMsg_packetReceived:
ldi r16, 0xff ; expect ATTN high ldi r16, 0xff ; expect ATTN high
ldi r17, 100 ldi r17, 100
rjmp ioWaitForAttnState100ms ; wait for up to 10s rcall ioWaitForAttnState100ms ; wait for up to 10s
brcc ioRawWaitForValidMsg_end
ldi xl, LOW(flashRecvBuffer)
ldi xh, HIGH(flashRecvBuffer)
rcall com2CheckMessageInBuffer ; (R16, R17, R18, R19, R20, X)
ioRawWaitForValidMsg_end:
ret
; @end ; @end
; ---------------------------------------------------------------------------
; @routine ioRawReceivePacketIntoBuffer
;
; Receive a packet into buffer pointed to by X.
; Expects interrupts to be disabled.
;
; @param R16 COM address to listen to
; @param R17 maximum value for accepted msg data (i.e. buffersize minus 3)
; @param X buffer to receive to
; @return CFLAG set if okay (packet received), cleared on error
; @return R16 error code if CFLAG is cleared (COM2_ERROR_NOTFORME, COM2_ERROR_IOERROR, COM2_ERROR_DATAERROR)
; @clobbers: r16, r17, r18, X (r19, r20, r21, r22)
ioRawReceivePacketIntoBuffer:
mov r18, r17
push r16
; read destination address
rcall ioRawReceiveByte ; read byte (R16, R17, R20, R21, R22)
pop r17 ; pop from R16 to R17
brcc ioRawReceivePacketIntoBuffer_ioError
#ifndef COM_ACCEPT_ALL_DEST ; accept every destination address
; compare destination address (accept "FF" and own address)
cp r16, r17
breq ioRawReceivePacketIntoBuffer_acceptAddr
cpi r16, 0xff
breq ioRawReceivePacketIntoBuffer_acceptAddr
ldi r16, COM2_ERROR_NOTFORME
rjmp ioRawReceivePacketIntoBuffer_error ; clc/ret
#endif
ioRawReceivePacketIntoBuffer_acceptAddr:
st X+, r16 ; store dest address, lock buffer
; read msg length
rcall ioRawReceiveByte ; read packet length (R16, R17, R20, R21, R22)
brcc ioRawReceivePacketIntoBuffer_ioError
st X+, r16
cp r16, r18 ; (COM2_BUFFER_SIZE-3)
brcc ioRawReceivePacketIntoBuffer_contentError ; packet too long
inc r16 ; account for checksum byte
mov r17, r16
ioRawReceivePacketIntoBuffer_loop:
push r17
rcall ioRawReceiveByte ; read byte (R16, R17, R20, R21, R22)
pop r17
brcc ioRawReceivePacketIntoBuffer_ioError
st X+, r16
dec r17
brne ioRawReceivePacketIntoBuffer_loop
sec
ret
ioRawReceivePacketIntoBuffer_ioError:
ldi r16, COM2_ERROR_IOERROR
rjmp ioRawReceivePacketIntoBuffer_error
ioRawReceivePacketIntoBuffer_contentError:
ldi r16, COM2_ERROR_DATAERROR
ioRawReceivePacketIntoBuffer_error:
clc
ret
; @end
; ---------------------------------------------------------------------------
; @routine ioRawReceiveByte
;
; Read a byte.
; Expects interrupts to be disabled.
;
; @return CFLAG set if okay, clear otherwise
; @return R16 byte received
; @clobbers R16, R20, R21, R22 (R17)
ioRawReceiveByte:
cbi COM_DATA_DDR, COM_DATA_PIN ; set DATA port as input
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; disable internal pullup for RXD
ldi r21, 8 ; bits left
clr r20 ; byte currently receiving
; wait for startbit
rcall ioRawWaitForDataLow ; (R17, R22)
brcc ioRawReceiveByte_error
Utils_WaitNanoSecs COM_HALFBIT_LENGTH, 10, r22 ; goto middle of startbit to maximize sync stability
ioRawReceiveByte_loop:
Utils_WaitNanoSecs COM_BIT_LENGTH, 8, r22 ; 8 cycles used in the complete loop between waits
sec ; +1
sbic COM_DATA_INPUT, COM_DATA_PIN ; LOW: +2, HIGH: +1
rjmp ioRawReceiveByte_shiftIn ; HIGH: +2, rjmp, use set CFLAG
clc ; LOW: +1
ioRawReceiveByte_shiftIn:
ror r20 ; +1
dec r21 ; +1
brne ioRawReceiveByte_loop ; +2, sum per loop: 8 cycles
rcall ioRawWaitForDataHigh ; wait for start of stopbit
brcc ioRawReceiveByte_error
mov r16, r20
sec
ret
ioRawReceiveByte_error:
clc
ret
; @end
; ---------------------------------------------------------------------------
; @routine ioRawSendPacket
;
; Send packet over wire, handle ATTN line.
;
; @param X ptr to buffer to send
; @return CFLAGS set if okay, cleared otherwise (errorcode in R16)
; @clobbers R16, R22 (R17, R21, X)
ioRawSendPacket:
rcall ioRawAcquireBus
brcc ioRawSendPacket_lineBusyError
rcall ioRawWaitForOneBitLength ; wait for one bit duration (R22)
rcall ioRawWaitForOneBitLength ; wait for one bit duration (R22)
adiw xh:xl, COM2_MSG_OFFS_MSGLEN
ld r17, X
sbiw xh:xl, COM2_MSG_OFFS_MSGLEN
inc r17 ; account for dest addr
inc r17 ; account for msglen byte
inc r17 ; account for crc byte
ioRawSendPacket_loop:
ld r16, X+
rcall ioRawSendByte ; send byte (R16, R21, R22)
brcc ioRawSendPacket_releaseBusRet
dec r17
brne ioRawSendPacket_loop
sec
ioRawSendPacket_releaseBusRet:
cbi COM_ATTN_DDR, COM_ATTN_PIN ; release ATTN line (by setting direction to IN)
brcc ioRawSendPacket_ioError
; packet successfully sent
ret
ioRawSendPacket_ioError:
ldi r16,COM2_ERROR_COLLISION
ret
ioRawSendPacket_lineBusyError:
ldi r16,COM2_ERROR_BUSY
ret
; @end
; ---------------------------------------------------------------------------
; @routine ioRawAcquireBus
;
; Reserve bus if free (otherwise return error)
; Expects interrupts to be disabled.
;
; @return CFLAG set if okay (bus acquired), cleared on error
; @clobbers: none
ioRawAcquireBus:
; check for ATTN line: busy?
cbi COM_ATTN_DDR, COM_ATTN_PIN ; set ATTN as input
cbi COM_ATTN_OUTPUT, COM_ATTN_PIN ; disable pullup on ATTN
nop ; needed to sample current input
sbis COM_ATTN_INPUT, COM_ATTN_PIN ; ATTN low?
rjmp ioRawAcquireBus_busy ; jump if it is
sbi COM_ATTN_DDR, COM_ATTN_PIN ; set ATTN as output
cbi COM_ATTN_OUTPUT, COM_ATTN_PIN ; set ATTN low
sec
ret
ioRawAcquireBus_busy:
clc
ret
; @end
; ---------------------------------------------------------------------------
; @routine ioRawWaitForOneBitLength
;
; wait for one bit length (minus cycles for call and ret).
;
; @clobbers r22
ioRawWaitForOneBitLength:
Utils_WaitNanoSecs COM_BIT_LENGTH, 7, r22 ; wait for one bit duration (minus RCALL/RET)
ret
; @end
; ---------------------------------------------------------------------------
; @routine ioRawSendByte
;
; Send a byte.
; We only set the data pin to low at the beginning for the startbit. After that
; we only change the pin direction (e.g. input vs output):
; - for 0 bit: set DDR to output, forcing the data line low
; - for 1 bit: set DDR to input, letting the external pullup R pull the data line to HIGH
; since the output pin is still set to 0 the internal pullup is disabled
; Expects interrupts to be disabled.
;
; @param R16 byte to send
; @return CFLAG set if okay, clear otherwise
; @clobbers R16, R21, R22
ioRawSendByte:
cbi COM_DATA_DDR, COM_DATA_PIN ; set DATA port as input
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; disable internal pullup for DATA
ldi r21, 8 ; +1 bits left
; send startbit
sbi COM_DATA_DDR, COM_DATA_PIN ; +2 set DATA as output
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; +2 set DATA low
Utils_WaitNanoSecs COM_BIT_LENGTH, 1, r22 ; wait for one bit duration
; send data bits
ioRawSendByte_loop: ; 9 for low bit
lsr r16 ; 1+ bit to send -> CARRY
brcs ioRawSendByte_setHigh ; HI: +2, LO: +1
ioRawSendByte_setLow:
sbi COM_DATA_DDR, COM_DATA_PIN ; +2 set DATA as output
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; +2 set DATA low
Utils_WaitNanoSecs COM_BIT_LENGTH, 11, r22
rjmp ioRawSendByte_loopEnd ; +2
ioRawSendByte_setHigh:
cbi COM_DATA_DDR, COM_DATA_PIN ; +2 set DATA as input, pullup R makes it ONE
nop ; +1 (to make pin change available)
Utils_WaitNanoSecs COM_HALFBIT_LENGTH, 0, r22 ; wait for half a bit length for line to safely settle
sbis COM_DATA_INPUT, COM_DATA_PIN ; +1 if no skip, +2 if skipped
rjmp ioRawSendByte_error ; +2 if error (collision: we wanted line to be high but it is low)
Utils_WaitNanoSecs COM_HALFBIT_LENGTH, 11, r22
ioRawSendByte_loopEnd:
dec r21 ; +1
brne ioRawSendByte_loop ; +2, sum per loop: 10 cycles
; send stopbit
cbi COM_DATA_DDR, COM_DATA_PIN ; +2 set DATA as input, pullup R makes it ONE
Utils_WaitNanoSecs COM_BIT_LENGTH, 0, r22 ; wait for one bit length
sec
ret
ioRawSendByte_error:
clc
ret
; @end
; ---------------------------------------------------------------------------
; @routine ioRawWaitForDataLow
;
; Wait up to 1ms for data pin to become low
; @return CFLAG set if okay, clear otherwise
; @clobbers R17, R22
ioRawWaitForDataLow:
cbi COM_DATA_DDR, COM_DATA_PIN ; set DATA port as input
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; disable internal pullup for TXD
UART_BB_M_WAIT_FOR_PIN_LOW COM_DATA_INPUT, COM_DATA_PIN
ret
; @end
; ---------------------------------------------------------------------------
; @routine ioRawWaitForDataHigh
;
; Wait up to 1ms for data pin to become high
; @return CFLAG set if okay, clear otherwise
; @clobbers R17, R22
ioRawWaitForDataHigh:
cbi COM_DATA_DDR, COM_DATA_PIN ; set DATA port as input
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; disable internal pullup for TXD
UART_BB_M_WAIT_FOR_PIN_HIGH COM_DATA_INPUT, COM_DATA_PIN
ret
; @end