try new implementation of UART code for m8515.

This commit is contained in:
Martin Preuss
2025-05-18 00:59:19 +02:00
parent b6800e538d
commit cf1eba68f0
10 changed files with 861 additions and 8 deletions

View File

@@ -0,0 +1,102 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine ATTN_Init @global
;
; @clobbers R16
ATTN_Init:
.ifdef INT0
.if COM_IRQ_BIT_ATTN == INT0
M_IO_READ r16, MCUCR
cbr r16, (1<<ISC01) | (1<<ISC00)
sbr r16, (1<<ISC01) | (0<<ISC00) ; falling edge of ATTN
; sbr r16, (0<<ISC01) | (0<<ISC00) ; low level triggers
rcall ATTN_SetHighEnableIrq
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_SetLowDisableIrq @global
;
; @clobbers R16
ATTN_SetLowDisableIrq:
.ifdef INT0
.if COM_IRQ_BIT_ATTN == INT0
M_IO_READ r16, COM_IRQ_ADDR_ATTN ; disable irq for ATTN line
cbr r16, (1<<COM_IRQ_BIT_ATTN)
M_IO_WRITE COM_IRQ_ADDR_ATTN, r16
.endif
.endif
sbi COM_ATTN_DDR, COM_ATTN_PIN ; set ATTN as output
cbi COM_ATTN_OUTPUT, COM_ATTN_PIN ; set ATTN low
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_SetHighEnableIrq @global
;
; @clobbers R16
ATTN_SetHighEnableIrq:
cbi COM_ATTN_DDR, COM_ATTN_PIN ; set ATTN as input
.ifdef COM_ATTN_PUE
cbi COM_ATTN_PUE, COM_ATTN_PIN ; disable pullup on ATTN
.else
cbi COM_ATTN_OUTPUT, COM_ATTN_PIN ; disable pullup on ATTN
.endif
.ifdef INT0
.if COM_IRQ_BIT_ATTN == INT0
M_IO_READ r16, COM_IRQ_ADDR_ATTN ; enable irq for ATTN line
sbr r16, (1<<COM_IRQ_BIT_ATTN)
M_IO_WRITE COM_IRQ_ADDR_ATTN, r16
.endif
.endif
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_IsHigh @global
;
; @return CFLAG set if ATTN is high
; @clobbers none
ATTN_IsHigh:
clc
sbic COM_ATTN_INPUT, COM_ATTN_PIN ; ATTN low?
sec ; yes, set CF
ret
; @end

View File

@@ -85,6 +85,7 @@ UART_HW_Interface_SetWriteBuffer:
; ---------------------------------------------------------------------------
; @routine UART_HW_Interface_EnsureReadBuffer
;
; @return CFLAG set if okay, cleared on error
; @clobbers R16 (R17, R24, R25, X)
UART_HW_Interface_EnsureReadBuffer:

View File

@@ -86,6 +86,7 @@
M_IO_READ r16, UCSR@0A
cbr r16, (1<<TXC@0) ; clear TXCn interrupt
M_IO_WRITE UCSR@0A, r16
M_IO_READ r16, UCSR@0B
sbr r16, (1<<UDRIE@0) | (1<<TXC@0) | (1<<TXEN@0) ; enable TX UDRE and TXC1 interrupt, enable transceive
M_IO_WRITE UCSR@0B, r16
@@ -207,6 +208,9 @@ l_msgFinished_%:
ldi r17, UART_HW_READMODE_MSGRECEIVED
rjmp l_incCounterAndEnterMode_%
l_hwerr_%:
sbrc r16, DOR ; (1<<FE@0) | (1<<DOR@0) | (1<<UPE@0)
rjmp DEBUG2
ldi r16, NET_IFACE_OFFS_ERR_IO_LOW
rjmp l_incCounterAndEnterSkipping_%
l_econtent_%:
@@ -227,6 +231,90 @@ l_end_%:
; ---------------------------------------------------------------------------
; @macro M_UART_HW_Uart_EnterReceivedChar
;
; @param %0 UART number ("0" for UART0)
; @param r16 received char
; @param Y pointer to interface data in SRAM
; @clobbers R16 (R17, R18, R24, R25, X)
.macro M_UART_HW_Uart_EnterReceivedChar
; check read mode
ldd r17, Y+UART_HW_IFACE_OFFS_READMODE
cpi r17, UART_HW_READMODE_READING
breq l_storeChar_%
cpi r17, UART_HW_READMODE_SKIPPING
breq l_skipChar_%
rjmp l_overrun_% ; neither read nor skip mode
l_skipChar_%:
clr r16
std Y+NET_IFACE_OFFS_READTIMER, r16 ; reset read timer
rjmp l_end_%
l_storeChar_%:
mov r18, r16 ; r18=received char
; check buffer
ldd r16, Y+UART_HW_IFACE_OFFS_READBUFNUM
cpi r16, 0xff
breq l_overrun_%
; check for buffer overrun
ldd r17, Y+UART_HW_IFACE_OFFS_READBUFLEFT ; r17=bytes left
tst r17
breq l_econtent_% ; msg too long
; actually store byte, increment/decrement counters and pos
ldd xl, Y+UART_HW_IFACE_OFFS_READBUFPOS_LOW
ldd xh, Y+UART_HW_IFACE_OFFS_READBUFPOS_HIGH
st X+, r18 ; r18=byte to store
clr r16
std Y+NET_IFACE_OFFS_READTIMER, r16 ; reset read timer
std Y+UART_HW_IFACE_OFFS_READBUFPOS_LOW, xl
std Y+UART_HW_IFACE_OFFS_READBUFPOS_HIGH, xh
ldd r18, Y+UART_HW_IFACE_OFFS_READBUFUSED ; r18=bytes in buffer
inc r18
std Y+UART_HW_IFACE_OFFS_READBUFUSED, r18
dec r17
std Y+UART_HW_IFACE_OFFS_READBUFLEFT, r17
breq l_msgFinished_%
; check msg size
cpi r18, 2 ; bytes in buffer, exactly 2?
brne l_end_% ; nope, done
sbiw xh:xl, 1 ; yes, determine message length (msgLen at previous pos)
ld r16, X+ ; read payload length byte
inc r16 ; + dest addr
inc r16 ; + msg length
inc r16 ; + CRC byte
cpi r16, (NET_BUFFERS_SIZE-2) ; total msg length ok? (subtract 1 for buffer header byte)
brcc l_econtent_% ; content error (msg too long)
subi r16, 2 ; subtract bytes already received
std Y+UART_HW_IFACE_OFFS_READBUFLEFT, r16 ; set new number of bytes left
brne l_end_% ; jmp if still bytes left to receive
l_msgFinished_%:
M_UART_HW_Uart_StopRx @0 ; (R16)
ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW
ldi r17, UART_HW_READMODE_MSGRECEIVED
rjmp l_incCounterAndEnterMode_%
l_econtent_%:
ldi r16, NET_IFACE_OFFS_ERR_CONTENT_LOW
rjmp l_incCounterAndEnterSkipping_%
l_overrun_%:
ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
l_incCounterAndEnterSkipping_%:
M_UART_HW_Uart_StopRx @0 ; (R16)
ldi r17, UART_HW_READMODE_SKIPPING
l_incCounterAndEnterMode_%:
rcall NET_Interface_IncCounter16 ; (R24, R25)
std Y+UART_HW_IFACE_OFFS_READMODE, r17 ; set read mode
l_end_%:
.endmacro
; @end
; ---------------------------------------------------------------------------
; @macro M_UART_HW_Uart_RxCharFullDuplexIsr
;

View File

@@ -0,0 +1,240 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
; ***************************************************************************
; defines
.equ NET_UART_MSG_INTERVAL = 1
; ***************************************************************************
; data
.dseg
netUartIface: .byte UART_HW_IFACE_SIZE
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine ComOnUart0_Init @global
;
NET_Uart_Init:
ldi yl, LOW(netUartIface)
ldi yh, HIGH(netUartIface)
rcall UART_HW_Interface_Init
rcall UART_Init
rcall ATTN_Init
ret
; @end
; ---------------------------------------------------------------------------
; @routine NET_Uart_Run @global
;
; @clobbers all
NET_Uart_Run:
push r15
in r15, SREG
cli
ldi yl, LOW(netUartIface)
ldi yh, HIGH(netUartIface)
rcall netUartRunReadModes
ldd r16, Y+UART_HW_IFACE_OFFS_READMODE ; test for active read mode
cpi r16, UART_HW_READMODE_IDLE
brne NET_Uart_Run_end
rcall netUartRunWriteModes ; only call write routine if read idle
NET_Uart_Run_end:
pop r15
out SREG, r15
ret
; @end
; ---------------------------------------------------------------------------
; @routine NET_Uart_Periodically
;
; @clobbers all, !Y
NET_Uart_Periodically:
ldi yl, LOW(netUartIface)
ldi yh, HIGH(netUartIface)
rjmp NET_Interface_Periodically
; @end
; ---------------------------------------------------------------------------
; @routine netUartRunWriteModes
;
; @clobbers all, !Y
netUartRunWriteModes:
ldd r16, Y+UART_HW_IFACE_OFFS_WRITEMODE ; handle write functions
cpi r16, UART_HW_WRITEMODE_IDLE
breq netUartRunWriteIdle
cpi r16, UART_HW_WRITEMODE_WRITING
breq netUartRunWriting
cpi r16, UART_HW_WRITEMODE_WAITBUFFEREMPTY
breq netUartRunWaitBufferEmpty
cpi r16, UART_HW_WRITEMODE_WRITEBUFFEREMPTY
breq netUartRunWriteBufferEmpty
ret
; @end
netUartRunWaitBufferEmpty:
rcall UART_GetFlags ; (none)
ldi r17, (1<<UART_FLAGS_LASTBYTESENT_BIT) | (1<<UART_FLAGS_SWUNDERRUN_BIT)
eor r16, r17
andi r16, (1<<UART_FLAGS_LASTBYTESENT_BIT) | (1<<UART_FLAGS_SWUNDERRUN_BIT)
brne netUartRunWaitBufferEmpty_end
rcall UART_StopTx
ldi r16, UART_HW_WRITEMODE_WRITEBUFFEREMPTY
std Y+UART_HW_IFACE_OFFS_WRITEMODE, r16
rjmp netUartRunWriteBufferEmpty ; we just entered new write mode
netUartRunWaitBufferEmpty_end:
ret
; @end
netUartRunWriteBufferEmpty:
ldd r16, Y+UART_HW_IFACE_OFFS_WRITEBUFNUM
rcall NET_Buffer_ReleaseByNum ; (R16, X)
ldi r16, 0xff
std Y+UART_HW_IFACE_OFFS_WRITEBUFNUM, r16
rcall ATTN_SetHighEnableIrq ; release bus
ldi r16, UART_HW_WRITEMODE_IDLE
std Y+UART_HW_IFACE_OFFS_WRITEMODE, r16
ret
; @end
netUartRunWriteIdle:
ldd r16, Y+NET_IFACE_OFFS_WRITETIMER
cpi r16, NET_UART_MSG_INTERVAL ; wait a bit between messages
brcs netUartRunWriteIdle_end
rcall NET_Interface_PeekNextOutgoingMsgNum ; r16=msgNum
brcc netUartRunWriteIdle_end ; no outmsg in queue
rcall ATTN_IsHigh
brcc netUartRunWriteIdle_end ; ATTN low, jmp
mov r17, r16
rcall ATTN_SetLowDisableIrq ; reserve bus as soon as possible (R16)
Utils_WaitNanoSecs COM_BIT_LENGTH, 0, r22 ; wait for one bit duration
Utils_WaitNanoSecs COM_BIT_LENGTH, 0, r22 ; wait for one bit duration
mov r16, r17
rcall NET_Buffer_Locate ; (R17)
rcall UART_HW_Interface_SetWriteBuffer
ldi r17, UART_HW_WRITEMODE_WRITING
std Y+UART_HW_IFACE_OFFS_WRITEMODE, r17
rcall NET_Interface_GetNextOutgoingMsgNum ; take msg from queue (R17, R18, X)
rjmp netUartRunWriting ; just entered writing mode
netUartRunWriteIdle_end:
ret
; @end
netUartRunWriting:
ldd r19, Y+UART_HW_IFACE_OFFS_WRITEBUFLEFT
tst r19
breq netUartRunWriting_checkTxEn
rcall UART_GetFlags ; r16=flags (none)
andi r16, (1<<UART_FLAGS_SWUNDERRUN_BIT) | (1<<UART_FLAGS_LASTBYTESENT_BIT)
brne netUartRunWriting_error ; got an error while still bytes to send
push yl
push yh
push zl
push zh
ldd zl, Y+UART_HW_IFACE_OFFS_WRITEBUFPOS_LOW
ldd zh, Y+UART_HW_IFACE_OFFS_WRITEBUFPOS_HIGH
clr r16
std Y+NET_IFACE_OFFS_WRITETIMER, r16
netUartRunWriting_loop:
ld r16, Z
rcall UART_WriteByte ; (R17, R18, X, Y)
brcc netUartRunWriting_loopEnd
adiw zh:zl, 1
dec r19
brne netUartRunWriting_loop
netUartRunWriting_loopEnd:
pop zl
pop zh
pop yh
pop yl
std Y+UART_HW_IFACE_OFFS_WRITEBUFPOS_LOW, zl
std Y+UART_HW_IFACE_OFFS_WRITEBUFPOS_HIGH, zh
std Y+UART_HW_IFACE_OFFS_WRITEBUFLEFT, r19
netUartRunWriting_checkTxEn:
rcall UART_GetFlags ; (none)
sbrs r16, UART_FLAGS_TXEN_BIT
rcall UART_StartTx ; (R16)
tst r19
brne netUartRunWriting_end
ldi r16, UART_HW_WRITEMODE_WAITBUFFEREMPTY
std Y+UART_HW_IFACE_OFFS_WRITEMODE, r16
rjmp netUartRunWaitBufferEmpty ; we just entered new write mode
netUartRunWriting_error:
ldi r16, NET_IFACE_OFFS_ERR_BUSY_LOW
rcall netUartAbortTx
netUartRunWriting_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine netUartAbortTx
;
; @clobbers all, !Y
netUartAbortTx:
rcall NET_Interface_IncCounter16
rcall UART_StopTx
rcall UART_ResetWriteBuffer
rcall ATTN_SetHighEnableIrq
ldi r16, UART_HW_WRITEMODE_IDLE
std Y+UART_HW_IFACE_OFFS_WRITEMODE, r16
ldi r17, 0xff
ldd r16, Y+UART_HW_IFACE_OFFS_WRITEBUFNUM
std Y+UART_HW_IFACE_OFFS_WRITEBUFNUM, r17
rjmp NET_Buffer_ReleaseByNum
; @end
netUartRunReadModes:
ret
; @end

View File

@@ -0,0 +1,398 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
; ***************************************************************************
; defines
.equ UART_RINGBUFFER_IN_SIZE = 24
.equ UART_RINGBUFFER_OUT_SIZE = 24
.equ UART_FLAGS_TXEN_BIT = 7
.equ UART_FLAGS_RXEN_BIT = 6
.equ UART_FLAGS_HWOVERRUN_BIT = 5
.equ UART_FLAGS_FRAMEERROR_BIT = 4
.equ UART_FLAGS_SWOVERRUN_BIT = 3
.equ UART_FLAGS_SWUNDERRUN_BIT = 2
.equ UART_FLAGS_LASTBYTESENT_BIT = 1
; ***************************************************************************
; data
.dseg
uartFlags: .byte 1
uartRingbufferIn: .byte RINGBUFFERY_SIZE+UART_RINGBUFFER_IN_SIZE
uartRingbufferOut: .byte RINGBUFFERY_SIZE+UART_RINGBUFFER_OUT_SIZE
; ***************************************************************************
; code
.cseg
UART_Init:
clr r16
sts uartFlags, r16
ldi r16, UART_RINGBUFFER_IN_SIZE
ldi yl, LOW(uartRingbufferIn)
ldi yh, HIGH(uartRingbufferIn)
rcall RingBufferY_Init
ldi r16, UART_RINGBUFFER_OUT_SIZE
ldi yl, LOW(uartRingbufferOut)
ldi yh, HIGH(uartRingbufferOut)
rcall RingBufferY_Init
; set baudrate
.if clock == 8000000
ldi r16, 25 ; (19.2Kb/s at 8MHz)
ldi r17, 0
.endif
.if clock == 1000000
ldi r16, 2 ; (19.2Kb/s at 1MHz)
ldi r17, 0
.endif
M_IO_WRITE UBRRH, r17
M_IO_WRITE UBRRL, r16
; set character format
.ifdef URSEL
ldi r16, (1<<URSEL) | (1<<USBS) | (1<<UCSZ1) | (1<<UCSZ0)
.else
ldi r16, (1<<USBS) | (1<<UCSZ1) | (1<<UCSZ0)
.endif
M_IO_WRITE UCSRC, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine UART_StartRx @global
;
; @clobbers R16
UART_StartRx:
; clear read error flags
lds r16, uartFlags
cbr r16, (1<<UART_FLAGS_HWOVERRUN_BIT) | (1<<UART_FLAGS_FRAMEERROR_BIT) | (1<<UART_FLAGS_SWOVERRUN_BIT)
sbr r16, (1<<UART_FLAGS_RXEN_BIT)
sts uartFlags, r16
M_IO_READ r16, UCSRA ; clear errors
cbr r16,(1<<RXC) | (1<<FE) | (1<<DOR) | (1<<UPE)
M_IO_WRITE UCSRA, r16
M_IO_READ r16, UCSRB
sbr r16, (1<<RXCIE) | (1<<RXEN) ; enable RX complete interrupt, enable receive
M_IO_WRITE UCSRB, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine UART_StopRx @global
;
; @clobbers R16
UART_StopRx:
lds r16, uartFlags
cbr r16, (1<<UART_FLAGS_RXEN_BIT)
sts uartFlags, r16
M_IO_READ r16, UCSRB
cbr r16, (1<<RXCIE | (1<<RXEN)) ; disable RX complete interrupt, disable receive
M_IO_WRITE UCSRB, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine UART_StartTx @global
;
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_STATE)
; @clobbers R16
UART_StartTx:
; clear write error flags
lds r16, uartFlags
cbr r16, (1<<UART_FLAGS_SWUNDERRUN_BIT) | (1<<UART_FLAGS_LASTBYTESENT_BIT)
sbr r16, (1<<UART_FLAGS_TXEN_BIT)
sts uartFlags, r16
M_IO_READ r16, UCSRA
cbr r16, (1<<TXC) ; clear TXC interrupt
M_IO_WRITE UCSRA, r16
M_IO_READ r16, UCSRB
sbr r16, (1<<UDRIE) | (1<<TXC) | (1<<TXEN) ; enable TX UDRE and TXC1 interrupt, enable transceive
M_IO_WRITE UCSRB, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine UART_StopTx @global
;
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_STATE)
; @clobbers R16
UART_StopTx:
lds r16, uartFlags
cbr r16, (1<<UART_FLAGS_TXEN_BIT)
sts uartFlags, r16
M_IO_READ r16, UCSRB
cbr r16, (1<<UDRIE) | (1<<TXC) | (1<<TXEN) ; disable TX UDRE and TXC1 interrupt, enable transceive
M_IO_WRITE UCSRB, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine UART_ReadByte @global
;
; @return CFLAG on success, cleared on error
; @return r16 byte read
; @clobbers (R17, R18, X, Y)
UART_ReadByte:
ldi yl, LOW(uartRingbufferIn)
ldi yh, HIGH(uartRingbufferIn)
rjmp RingBufferY_ReadByteGuarded ; (R17, R18, X)
; @end
; ---------------------------------------------------------------------------
; @routine UART_WriteByte @global
;
; @clobbers (R17, R18, X, Y)
UART_WriteByte:
ldi yl, LOW(uartRingbufferOut)
ldi yh, HIGH(uartRingbufferOut)
rjmp RingBufferY_WriteByteGuarded ; (R17, R18, X)
; @end
; ---------------------------------------------------------------------------
; @routine UART_ResetWriteBuffer @global
;
; @clobbers (R17)
UART_ResetWriteBuffer:
ldi yl, LOW(uartRingbufferOut)
ldi yh, HIGH(uartRingbufferOut)
rjmp RingBufferY_Reset ; (R17)
; @end
; ---------------------------------------------------------------------------
; @routine UART_GetFlags @global
;
; @return r16 flags
; @clobbers none
UART_GetFlags:
lds r16, uartFlags
ret
; @end
; ---------------------------------------------------------------------------
; @routine UART_RxCharIsr @isr
;
UART_RxCharIsr:
push r15
in r15, SREG
push r16
push r17
push r18
push xl
push xh
push yl
push yh
rcall uartHandleRxChar
pop yh
pop yl
pop xh
pop xl
pop r18
pop r17
pop r16
out SREG, r15
pop r15
reti
; @end
; ---------------------------------------------------------------------------
; @routine UART_TxCharIsr @isr
;
UART_TxCharIsr:
push r15
in r15, SREG
push r16
rcall uartHandleTxChar ; (R16)
pop r16
out SREG, r15
pop r15
reti
; @end
; ---------------------------------------------------------------------------
; @routine UART_UdreIsr @isr
;
UART_UdreIsr:
push r15
in r15, SREG
push r16
push r17
push r18
push xl
push xh
push yl
push yh
rcall uartHandleUdre
pop yh
pop yl
pop xh
pop xl
pop r18
pop r17
pop r16
out SREG, r15
pop r15
reti
; @end
; ---------------------------------------------------------------------------
; @routine uartHandleRxChar
;
; @clobbers R16, R17, Y (R18, X)
uartHandleRxChar:
; check for errors
M_IO_READ r16, UCSRA
sbrc r16, FE
rjmp uartHandleRxChar_hwErrFe
sbrc r16, DOR
rjmp uartHandleRxChar_hwErrDor
; have char?
sbrs r16, RXC
rjmp uartHandleRxChar_end ; no data
; read char
M_IO_READ r16, UDR ; r16=received char
ldi yl, LOW(uartRingbufferIn)
ldi yh, HIGH(uartRingbufferIn)
rcall RingBufferY_WriteByte ; (R17, R18, X)
brcs uartHandleRxChar_end
lds r16, UART_FLAGS_SWOVERRUN_BIT
rjmp uartHandleRxChar_storeErrorFlags
uartHandleRxChar_hwErrFe:
lds r16, UART_FLAGS_FRAMEERROR_BIT
rjmp uartHandleRxChar_storeErrorFlags
uartHandleRxChar_hwErrDor:
lds r16, UART_FLAGS_HWOVERRUN_BIT
rjmp uartHandleRxChar_storeErrorFlags
uartHandleRxChar_storeErrorFlags:
lds r17, uartFlags
or r17, r16
sts uartFlags, r17
uartHandleRxChar_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine uartHandleUdre
;
; @clobbers R16, Y (R17, R18, X)
uartHandleUdre:
M_IO_READ r16, UCSRA
sbrs r16, UDRE
; rjmp uartHandleUdre_disableUdre ; not ready, SNH!
rjmp uartHandleUdre_end ; not ready, SNH!
ldi yl, LOW(uartRingbufferOut)
ldi yh, HIGH(uartRingbufferOut)
rcall RingBufferY_ReadByte ; (R17, R18, X)
brcc uartHandleUdre_underrun
M_IO_WRITE UDR, r16
rjmp uartHandleUdre_end
uartHandleUdre_underrun:
lds r16, uartFlags
sbr r16, (1<<UART_FLAGS_SWUNDERRUN_BIT)
sts uartFlags, r16
uartHandleUdre_disableUdre:
M_IO_READ r16, UCSRB
cbr r16, (1<<UDRIE) ; disable TX UDRE interrupt
M_IO_WRITE UCSRB, r16
uartHandleUdre_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine uartHandleTxChar
;
; @clobbers R16
uartHandleTxChar:
lds r16, uartFlags
sbr r16, (1<<UART_FLAGS_LASTBYTESENT_BIT)
sts uartFlags, r16
M_IO_READ r16, UCSRB
cbr r16, (1<<TXC) ; disable TXC interrupt
M_IO_WRITE UCSRB, r16
ret
; @end