r05, comOnUart0 and comOnUart1 work!

This commit is contained in:
Martin Preuss
2025-07-06 17:19:59 +02:00
parent 439e787d37
commit 81b008af0c
5 changed files with 302 additions and 566 deletions

View File

@@ -33,21 +33,12 @@ ComOnUart1_Init:
ldi yl, LOW(comOnUart1_iface)
ldi yh, HIGH(comOnUart1_iface)
rcall NET_Interface_Init ; (R16, R17, X)
ldi r16, 0xff
std Y+UART_HW2_IFACE_OFFS_WRITEBUFNUM, r16
ldi r16, UART_HW2_MODE_IDLE
std Y+UART_HW2_IFACE_OFFS_MODE, r16
clr r16
std Y+NET_IFACE_OFFS_IFACENUM, r16
rcall comOnUart1SetAttnInput
.ifdef COM_ATTN1_PUE
inr r16, COM_ATTN1_PUE
cbr r16, (1<<COM_ATTN1_PIN)
outr COM_ATTN1_PUE, r16
.endif
inr r16, COM_IRQ_ADDR_ATTN1
sbr r16, (1<<COM_IRQ_BIT_ATTN1) ; enable pin change irq for ATTN line
outr COM_IRQ_ADDR_ATTN1, r16
@@ -153,84 +144,12 @@ comOnUart1StartReading:
; ---------------------------------------------------------------------------
; @routine comOnUart1StartWriting
;
; @param Y pointer to interface data in SRAM
; @param R16 buffer number
; @return CFLAG set if writing started, cleared otherwise
; @clobbers R16, R17, X, Z (R22, R24, R25)
comOnUart1StartWriting:
push r15
inr r15, SREG
cli
rcall comOnUart1StartWriting_noIrq
brcc comOnUart1StartWriting_clc
outr SREG, r15
pop r15
sec
ret
comOnUart1StartWriting_clc:
outr SREG, r15
pop r15
clc
ret
comOnUart1StartWriting_noIrq:
rcall comOnUart1AcquireAttn ; (R22)
brcc comOnUart1StartWriting_ebusy
; copy buffer
rcall NET_Buffer_Locate ; (R17)
std Y+UART_HW2_IFACE_OFFS_WRITEBUFNUM, r16
adiw xh:xl, NETMSG_OFFS_MSGLEN+1
ld r17, X
sbiw xh:xl, NETMSG_OFFS_MSGLEN+1
subi r17, -3 ; add dest addr, msglen, crc
; TODO: check size!
std Y+UART_HW2_IFACE_OFFS_BUFUSED, r17
std Y+UART_HW2_IFACE_OFFS_BUFLEFT, r17
; copy into IFACE buffer
mov zl, yl
mov zh, yh
adiw zh:zl, UART_HW2_IFACE_OFFS_BUFFER ; dest
std Y+UART_HW2_IFACE_OFFS_BUFPOS_LOW, zl
std Y+UART_HW2_IFACE_OFFS_BUFPOS_HIGH, zh
adiw xh:xl, 1 ; src (skip buffer header)
comOnUart1StartWriting_loop:
ld r16, X+
st Z+, r16
dec r17
brne comOnUart1StartWriting_loop
ldi r16, UART_HW2_MODE_WRITING
rcall comOnUart1SetMode ; (R17)
rcall comOnUart1StartTx ; should be the last call here (R16)
sec
rjmp comOnUart1StartWriting_end
comOnUart1StartWriting_ebusy:
ldi r16, NET_IFACE_OFFS_ERR_BUSY_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
clc
comOnUart1StartWriting_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine ComOnUart1_Run @global
;
; @clobbers all
ComOnUart1_Run:
push r15
inr r15, SREG
cli
rcall ComOnUart1_Run_noirq
outr SREG, r15
pop r15
ret
ComOnUart1_Run_noirq:
ldi yl, LOW(comOnUart1_iface)
ldi yh, HIGH(comOnUart1_iface)
ldd r16, Y+UART_HW2_IFACE_OFFS_MODE
@@ -269,10 +188,7 @@ comOnUart1ModeJumpTable:
rjmp comOnUart1RunIdle
rjmp comOnUart1RunReading
rjmp comOnUart1RunSkipping
rjmp comOnUart1RunMsgReceived
rjmp comOnUart1RunWriting
rjmp comOnUart1RunWaitBufferEmpty
rjmp comOnUart1RunMsgSent
; @end
@@ -281,15 +197,48 @@ comOnUart1ModeJumpTable:
; @routine comOnUart1RunIdle
;
; @param Y pointer to interface data in SRAM
; @clobbers R16, R17, R24, R25, X, Z
; @clobbers R16, R17, R22, R24, R25, X
comOnUart1RunIdle:
; look for outbound message
rcall NET_Interface_PeekNextOutgoingMsgNum ; r16=msgNum
brcc comOnUart1RunIdle_end ; no outmsg in queue
rcall comOnUart1StartWriting ; (R16, R17, R22, R24, R25, X, Z)
push r15
inr r15, SREG
cli
; look for outbound message
rcall NET_Interface_PeekNextOutgoingMsgNum ; r16=msgNum
brcs comOnUart1RunIdle_haveMsg
out SREG, r15
pop r15
rjmp comOnUart1RunIdle_end
comOnUart1RunIdle_haveMsg:
mov r24, r16
ldi r16, UART_HW2_MODE_WRITING
rcall comOnUart1SetMode ; (R17)
mov r16, r24
out SREG, r15
pop r15
push r16
rcall NET_Buffer_Locate ; (R17)
adiw xh:xl, 1
rcall comOnUart1SendMsg ; (R16, R17, R22, R24, R25, X)
push r15
inr r15, SREG ; save SREG (no CLI, we want to save CFLAG only)
ldi r16, UART_HW2_MODE_IDLE
rcall comOnUart1SetMode ; (R17)
out SREG, r15 ; restore SREG
pop r15
pop r16
brcc comOnUart1RunIdle_end
rcall NET_Interface_GetNextOutgoingMsgNum ; take current msg off the queue
push r15
inr r15, SREG
cli
rcall NET_Interface_GetNextOutgoingMsgNum ; take current msg off the queue
rcall NET_Buffer_ReleaseByNum ; (R16, X)
out SREG, r15
pop r15
sec
comOnUart1RunIdle_end:
ret
; @end
@@ -326,12 +275,12 @@ comOnUart1RunSkipping_end:
; ---------------------------------------------------------------------------
; @routine comOnUart1RunMsgReceived
; @routine comOnUart1HandleMsgReceived
;
; @param Y pointer to interface data in SRAM
; @clobbers R16, R17, R18, X, Z (R19, R20, R24, R25)
comOnUart1RunMsgReceived:
comOnUart1HandleMsgReceived:
mov xl, yl
mov xh, yh
adiw xh:xl, UART_HW2_IFACE_OFFS_BUFFER
@@ -389,42 +338,6 @@ comOnUart1RunWriting:
; ---------------------------------------------------------------------------
; @routine comOnUart1RunWaitBufferEmpty
;
; @clobbers none
comOnUart1RunWaitBufferEmpty:
; TODO: check for timeout etc.
ret
; @end
; ---------------------------------------------------------------------------
; @routine comOnUart1RunWriting
;
; @param Y pointer to interface data in SRAM
; @clobbers R16 (R17, R22, R24, R25, X)
comOnUart1RunMsgSent:
ldd r16, Y+UART_HW2_IFACE_OFFS_WRITEBUFNUM
rcall NET_Buffer_ReleaseByNum ; (R16, X)
ldi r16, 0xff
std Y+UART_HW2_IFACE_OFFS_WRITEBUFNUM, r16
ldi r16, NET_IFACE_OFFS_PACKETSOUT_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
ldi r16, UART_HW2_MODE_IDLE
rcall comOnUart1SetMode ; (R17)
rcall comOnUart1SetAttnInput ; release ATTN (none)
rcall Utils_WaitFor10MicroSecs ; make sure ATTN is at least high for a short period (R22)
ret
; @end
; ---------------------------------------------------------------------------
; @routine comOnUart1AcquireAttn
;
@@ -485,10 +398,11 @@ comOnUart1StopRx:
comOnUart1StartTx:
inr r16, UCSR1A
cbr r16, (1<<TXC1) ; clear TXCn interrupt
cbr r16, (1<<TXC1) ; clear TXCn interrupt
outr UCSR1A, r16
inr r16, UCSR1B
sbr r16, (1<<UDRIE1) | (1<<TXCIE1) | (1<<TXEN1) ; enable TX UDRE and TXC0 interrupt, enable transceive
cbr r16, (1<<UDRIE1) | (1<<TXCIE1) ; disable TX UDRE and TXC0 interrupt, enable transceive
sbr r16, (1<<TXEN1) ; enable TX UDRE and TXC0 interrupt, enable transceive
outr UCSR1B, r16
ret
; @end
@@ -502,7 +416,7 @@ comOnUart1StartTx:
comOnUart1StopTx:
inr r16, UCSR1B
cbr r16, (1<<UDRIE1) | (1<<TXCIE1) | (1<<TXEN1) ; disable TX UDRE and TXC0 interrupt, enable transceive
cbr r16, (1<<UDRIE1) | (1<<TXCIE1) | (1<<TXEN1) ; disable TX UDRE and TXC0 interrupt, disable transceive
outr UCSR1B, r16
ret
; @end
@@ -520,10 +434,17 @@ comOnUart1StopTx:
comOnUart1SetAttnInput:
cbi COM_ATTN1_DDR, COM_ATTN1_PIN ; set ATTN as input
.ifdef COM_ATTN1_PUE
; cbi COM_ATTN1_PUE, COM_ATTN_PIN ; disable pullup on ATTN
; cbi COM_ATTN1_PUE, COM_ATTN_PIN ; disable pullup on ATTN
.else
cbi COM_ATTN1_OUTPUT, COM_ATTN1_PIN ; disable pullup on ATTN
.endif
push r16
inr r16, COM_IRQ_ADDR_ATTN1
sbr r16, (1<<COM_IRQ_BIT_ATTN1) ; enable pin change irq for ATTN line
outr COM_IRQ_ADDR_ATTN1, r16
pop r16
ret
; @end
@@ -537,8 +458,13 @@ comOnUart1SetAttnInput:
; @clobbers none
comOnUart1SetAttnLow:
sbi COM_ATTN1_DDR, COM_ATTN1_PIN ; set ATTN as output
cbi COM_ATTN1_OUTPUT, COM_ATTN1_PIN ; set ATTN low
push r16
inr r16, COM_IRQ_ADDR_ATTN1
cbr r16, (1<<COM_IRQ_BIT_ATTN1) ; disable pin change irq for ATTN line
outr COM_IRQ_ADDR_ATTN1, r16
pop r16
sbi COM_ATTN1_DDR, COM_ATTN1_PIN ; set ATTN as output
cbi COM_ATTN1_OUTPUT, COM_ATTN1_PIN ; set ATTN low
ret
; @end
@@ -570,21 +496,29 @@ ComOnUart1_RxCharIsr:
push r16
push r17
push r18
push r24
push r25
push xl
push xh
push yl
push yh
ldi yl, LOW(comOnUart1_iface)
ldi yh, HIGH(comOnUart1_iface)
rcall comOnUart1RxCharIsr ; (R16, R17, R18, R24, R25, X)
pop yh
pop yl
pop xh
pop xl
pop r25
pop r24
push r19
push r20
push r24
push r25
push xl
push xh
push yl
push yh
push zl
push zh
ldi yl, LOW(comOnUart1_iface)
ldi yh, HIGH(comOnUart1_iface)
rcall comOnUart1RxCharIsr ; (R16, R17, R18, R19, R20, R24, R25, X, Z)
pop zh
pop zl
pop yh
pop yl
pop xh
pop xl
pop r25
pop r24
pop r20
pop r19
pop r18
pop r17
pop r16
@@ -595,62 +529,6 @@ ComOnUart1_RxCharIsr:
; ---------------------------------------------------------------------------
; @routine ComOnUart1_TxUdreIsr @global @isr
;
; @clobbers none
ComOnUart1_TxUdreIsr:
push r15
in r15, SREG
push r16
push r17
push xl
push xh
push yl
push yh
ldi yl, LOW(comOnUart1_iface)
ldi yh, HIGH(comOnUart1_iface)
rcall comOnUart1TxUdreIsr ; (R16, R17, X)
pop yh
pop yl
pop xh
pop xl
pop r17
pop r16
out SREG, r15
pop r15
reti
; @end
; ---------------------------------------------------------------------------
; @routine ComOnUart1_TxCharIsr @global @isr
;
; @clobbers none
ComOnUart1_TxCharIsr:
push r15
in r15, SREG
push r16
push r17
push yl
push yh
ldi yl, LOW(comOnUart1_iface)
ldi yh, HIGH(comOnUart1_iface)
rcall comOnUart1TxCharIsr ; (R16, R17)
pop yh
pop yl
pop r17
pop r16
out SREG, r15
pop r15
reti
; @end
; ---------------------------------------------------------------------------
; @routine ComOnUart1AttnChangeIsr @global @isr
;
@@ -701,10 +579,10 @@ ComOnUart1_HandleAttnChange:
; @clobbers R16 (R17, X)
comOnUart1ActOnAttn:
ldd r16, Y+UART_HW2_IFACE_OFFS_MODE
rcall comOnUart1IsAttnLow ; (none)
brcc comOnUart1ActOnAttn_attnHigh
; ATTN low
ldd r16, Y+UART_HW2_IFACE_OFFS_MODE
cpi r16, UART_HW2_MODE_IDLE
brne comOnUart1ActOnAttn_end ; not idle
rcall comOnUart1StartReading ; (R16, R17, X)
@@ -725,7 +603,7 @@ comOnUart1ActOnAttn_end:
; @routine comOnUart1RxCharIsr @global
;
; @param Y pointer to interface data in SRAM
; @clobbers R16, R17, R18, R24, R25, X
; @clobbers R16, R17, R18, R19, R20, R24, R25, X, Z
comOnUart1RxCharIsr:
; check for errors
@@ -767,8 +645,8 @@ comOnUart1RxCharIsr:
brne comOnUart1RxCharIsr_end ; jmp if still bytes left to receive
comOnUart1RxCharIsr_complete:
rcall comOnUart1StopRx
ldi r16, UART_HW2_MODE_MSGRECEIVED
rcall comOnUart1SetMode ; (R17)
rcall comOnUart1HandleMsgReceived ; (R16, R17, R18, R19, R20, R24, R25, X, Z)
rjmp comOnUart1RxCharIsr_end
comOnUart1RxCharIsr_hwerr:
ldi r16, NET_IFACE_OFFS_ERR_IO_LOW
@@ -790,76 +668,54 @@ comOnUart1RxCharIsr_end:
; ---------------------------------------------------------------------------
; @routine comOnUart1TxUdreIsr @global
; @routine comOnUart1SendMsg
;
; Handler for UDRE1 interrupt called when TX data register is empty.
;
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_MODE)
; @clobbers R16, R17, X
; @param Y pointer to interface data in SRAM
; @param X pointer to buffer to send
; @return CFLAG set if writing started, cleared otherwise
; @clobbers R16, R17, X (R22, R24, R25)
comOnUart1TxUdreIsr:
inr r16, UCSR1A
sbrs r16, UDRE1
rjmp comOnUart1TxUdreIsr_disable_irq ; not ready
; check bytes left
ldd r17, Y+UART_HW2_IFACE_OFFS_BUFLEFT
tst r17
breq comOnUart1TxUdreIsr_finished
; read byte
ldd xl, Y+UART_HW2_IFACE_OFFS_BUFPOS_LOW
ldd xh, Y+UART_HW2_IFACE_OFFS_BUFPOS_HIGH
ld r16, X+
std Y+UART_HW2_IFACE_OFFS_BUFPOS_LOW, xl
std Y+UART_HW2_IFACE_OFFS_BUFPOS_HIGH, xh
; send byte
outr UDR1, r16 ; send byte
; decreased counter
dec r17
std Y+UART_HW2_IFACE_OFFS_BUFLEFT, r17
brne comOnUart1TxUdreIsr_end ; still bytes left to send, jump
comOnUart1TxUdreIsr_finished:
ldi r16, UART_HW2_MODE_WAITBUFFEREMPTY
rcall comOnUart1SetMode ; (R17)
comOnUart1TxUdreIsr_disable_irq:
; disable further DRE interrupts
inr r16, UCSR1B
cbr r16, (1<<UDRIE1) ; disable TX data register empty interrupt
outr UCSR1B, r16
comOnUart1TxUdreIsr_end:
comOnUart1SendMsg:
rcall comOnUart1AcquireAttn ; (R22)
brcc comOnUart1SendMsg_ebusy
adiw xh:xl, NETMSG_OFFS_MSGLEN
ld r17, X
sbiw xh:xl, NETMSG_OFFS_MSGLEN
subi r17, -3 ; add dest addr, msglen, crc
rcall comOnUart1StartTx ; (R16)
; TODO: check size!
; r17=number of bytes to write, X=buffer
comOnUart1SendMsg_loop:
; wait until transceiver ready
inr r16, UCSR1A
sbrs r16, UDRE1
rjmp comOnUart1SendMsg_loop
; clear TXC flag by sending a 1
sbr r16, (1<<TXC1)
outr UCSR1A, r16
; write byte to uart data register
ld r16, X+
outr UDR1, r16
dec r17
brne comOnUart1SendMsg_loop
; wait until all data send (i.e. send buffer empty and all bits shifted out)
comOnUart1SendMsg_loopComplete:
inr r16, UCSR1A
sbrs r16, TXC1
rjmp comOnUart1SendMsg_loopComplete
rcall comOnUart1StopTx ; (R16)
rcall comOnUart1SetAttnInput ; release ATTN (none)
rcall Utils_WaitFor10MicroSecs ; make sure ATTN is at least high for a short period (R22)
sec
rjmp comOnUart1SendMsg_end
comOnUart1SendMsg_ebusy:
ldi r16, NET_IFACE_OFFS_ERR_BUSY_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
clc
comOnUart1SendMsg_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine comOnUart1TxCharIsr @global
;
; Handler for TXC0 interrupt called when the last byte has been completely sent and
; the data register is empty.
;
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_MODE)
; @clobbers R16, R17
comOnUart1TxCharIsr:
; disable further TXC interrupts
inr r16, UCSR1B
cbr r16, (1<<TXCIE1) ; disable TXC1 interrupt
outr UCSR1B, r16
rcall comOnUart1StopTx ; (R16)
ldi r16, UART_HW2_MODE_MSGSENT
rcall comOnUart1SetMode ; (R17)
ret
; @end
#endif ; AVR_MODULES_UART_HW2_COMONUART1_H