avr: more work on ardware uart code.
This commit is contained in:
@@ -129,7 +129,8 @@ devInfoVersion: .db DEVICEINFO_VERSION, DEVICEINFO_REVISION ; v
|
||||
firmwareVersion: .db FIRMWARE_VARIANT_TEMP_WINDOW, FIRMWARE_VERSION_MAJOR
|
||||
.db FIRMWARE_VERSION_MINOR, FIRMWARE_VERSION_PATCHLEVEL
|
||||
|
||||
;firmwareStart: rjmp main
|
||||
|
||||
|
||||
firmwareStart:
|
||||
cli
|
||||
; setup stack
|
||||
@@ -160,10 +161,11 @@ main_loop:
|
||||
and r16, r17
|
||||
ori r16, (1<<SE) ; sleep mode "idle", enable
|
||||
out MCUCR, r16
|
||||
sei ; make sure interrupts really are enabled
|
||||
sei ; make sure interrupts really are enabled
|
||||
sleep ; sleep, wait for interrupt
|
||||
|
||||
rcall BaseTimer_Run
|
||||
rcall TtyOnUart1_Run
|
||||
|
||||
rjmp main_loop
|
||||
|
||||
@@ -196,6 +198,7 @@ onSystemTimerTick:
|
||||
rcall LedSimple_Every100ms
|
||||
#endif
|
||||
|
||||
rcall TtyOnUart1_Periodically
|
||||
ret
|
||||
|
||||
|
||||
@@ -228,6 +231,7 @@ initModules:
|
||||
rcall BaseTimer_Init
|
||||
rcall LedSimple_Init
|
||||
rcall UART_HW_Init
|
||||
rcall TtyOnUart1_Init
|
||||
ret
|
||||
; @end
|
||||
|
||||
@@ -255,9 +259,11 @@ initModules:
|
||||
.include "modules/uart_hw/defs.asm"
|
||||
.include "modules/uart_hw/buffers.asm"
|
||||
.include "modules/uart_hw/lowlevel.asm"
|
||||
.include "modules/uart_hw/m_lowlevel_uart.asm"
|
||||
.include "modules/uart_hw/lowlevel_uart1.asm"
|
||||
.include "modules/uart_hw/msglevel_recv.asm"
|
||||
.include "modules/uart_hw/msglevel_send.asm"
|
||||
.include "modules/uart_hw/ttyonuart1.asm"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -10,26 +10,32 @@
|
||||
|
||||
.equ UART_HW_IFACE_READBUF_SIZE = 8
|
||||
.equ UART_HW_IFACE_WRITEBUF_SIZE = 8
|
||||
|
||||
.equ UART_HW_IFACE_OUTMSGBUF_SIZE = 4
|
||||
|
||||
.equ UART_HW_BUFFER_INUSE_BIT = 7
|
||||
.equ UART_HW_BUFFER_IFACENUM1_BIT = 1
|
||||
.equ UART_HW_BUFFER_IFACENUM0_BIT = 0
|
||||
|
||||
|
||||
.equ UART_HW_MODE_READMASK = 0x0f
|
||||
.equ UART_HW_MODE_WRITEMASK = 0xf0
|
||||
|
||||
.equ UART_HW_MODE_OFF = 0
|
||||
.equ UART_HW_MODE_IDLE = 1
|
||||
.equ UART_HW_MODE_READING = 2
|
||||
.equ UART_HW_MODE_WRITING = 4
|
||||
.equ UART_HW_MODE_SKIPPING = 8
|
||||
.equ UART_HW_MODE_WAITATTNLOW = 16 ; waiting after setting ATTN low
|
||||
.equ UART_HW_MODE_SKIPPING = 3
|
||||
|
||||
.equ UART_HW_MODE_W_IDLE = 0
|
||||
.equ UART_HW_MODE_WRITING = 8
|
||||
.equ UART_HW_MODE_WAITBUFFEREMPTY = 9
|
||||
.equ UART_HW_MODE_WRITEBUFFEREMPTY = 10
|
||||
|
||||
|
||||
.equ UART_HW_STATUS_UNDERRUN = 0x01
|
||||
.equ UART_HW_STATUS_OVERRUN = 0x02
|
||||
.equ UART_HW_STATUS_HWERR = 0x04
|
||||
.equ UART_HW_STATUS_SOFTERR = 0x08
|
||||
.equ UART_HW_STATUS_ATTN = 0x80
|
||||
.equ UART_HW_STATUS_UNDERRUN_BIT = 0
|
||||
.equ UART_HW_STATUS_OVERRUN_BIT = 1
|
||||
.equ UART_HW_STATUS_HWERR_BIT = 2
|
||||
.equ UART_HW_STATUS_SOFTERR_BIT = 3
|
||||
.equ UART_HW_STATUS_ATTN_BIT = 7
|
||||
|
||||
|
||||
.equ UART_HW_IFACE_OFFS_IFACENUM = 0 ; interface number (put into received messages)
|
||||
@@ -56,12 +62,22 @@
|
||||
.equ UART_HW_IFACE_OFFS_WRITEBUF_WRPOS = UART_HW_IFACE_OFFS_WRITEBUF+3
|
||||
.equ UART_HW_IFACE_OFFS_WRITEBUF_DATA = UART_HW_IFACE_OFFS_WRITEBUF+4
|
||||
|
||||
.equ UART_HW_IFACE_OFFS_READMSG = UART_HW_IFACE_OFFS_WRITEBUF_DATA+UART_HW_IFACE_WRITEBUF_SIZE
|
||||
; ringbuffer for outgoing messages
|
||||
.equ UART_HW_IFACE_OFFS_OUTMSGBUF = UART_HW_IFACE_OFFS_WRITEBUF_DATA+UART_HW_IFACE_WRITEBUF_SIZE
|
||||
.equ UART_HW_IFACE_OFFS_OUTMSGBUF_MAX = UART_HW_IFACE_OFFS_OUTMSGBUF
|
||||
.equ UART_HW_IFACE_OFFS_OUTMSGBUF_USED = UART_HW_IFACE_OFFS_OUTMSGBUF+1
|
||||
.equ UART_HW_IFACE_OFFS_OUTMSGBUF_RDPOS = UART_HW_IFACE_OFFS_OUTMSGBUF+2
|
||||
.equ UART_HW_IFACE_OFFS_OUTMSGBUF_WRPOS = UART_HW_IFACE_OFFS_OUTMSGBUF+3
|
||||
.equ UART_HW_IFACE_OFFS_OUTMSGBUF_DATA = UART_HW_IFACE_OFFS_OUTMSGBUF+4
|
||||
|
||||
; ref to recv buffer
|
||||
.equ UART_HW_IFACE_OFFS_READMSG = UART_HW_IFACE_OFFS_OUTMSGBUF_DATA+UART_HW_IFACE_OUTMSGBUF_SIZE
|
||||
.equ UART_HW_IFACE_OFFS_READMSG_BUFNUM = UART_HW_IFACE_OFFS_READMSG ; 1 byte
|
||||
.equ UART_HW_IFACE_OFFS_READMSG_PTR = UART_HW_IFACE_OFFS_READMSG+1 ; 2 bytes
|
||||
.equ UART_HW_IFACE_OFFS_READMSG_USED = UART_HW_IFACE_OFFS_READMSG+3 ; 1 byte
|
||||
.equ UART_HW_IFACE_OFFS_READMSG_LEFT = UART_HW_IFACE_OFFS_READMSG+4 ; 1 byte
|
||||
|
||||
; ref to transmit buffer
|
||||
.equ UART_HW_IFACE_OFFS_WRITEMSG = UART_HW_IFACE_OFFS_READMSG_LEFT+1
|
||||
.equ UART_HW_IFACE_OFFS_WRITEMSG_BUFNUM = UART_HW_IFACE_OFFS_WRITEMSG ; 1 byte
|
||||
.equ UART_HW_IFACE_OFFS_WRITEMSG_PTR = UART_HW_IFACE_OFFS_WRITEMSG+1 ; 2 bytes
|
||||
|
||||
@@ -57,17 +57,27 @@ UART_HW_InterfaceInit:
|
||||
ldi r17, UART_HW_IFACE_SIZE
|
||||
clr r16
|
||||
rcall Utils_FillSram ; (R17, X)
|
||||
; reset ringbuffer for recvd chars
|
||||
m_ringbuffer_y_reset UART_HW_IFACE_READBUF_SIZE, \
|
||||
UART_HW_IFACE_OFFS_READBUF_USED, \
|
||||
UART_HW_IFACE_OFFS_READBUF_RDPOS, \
|
||||
UART_HW_IFACE_OFFS_READBUF_WRPOS, \
|
||||
UART_HW_IFACE_OFFS_READBUF_DATA
|
||||
|
||||
; reset ringbuffer for chars to transmit
|
||||
m_ringbuffer_y_reset UART_HW_IFACE_WRITEBUF_SIZE, \
|
||||
UART_HW_IFACE_OFFS_WRITEBUF_USED, \
|
||||
UART_HW_IFACE_OFFS_WRITEBUF_RDPOS, \
|
||||
UART_HW_IFACE_OFFS_WRITEBUF_WRPOS, \
|
||||
UART_HW_IFACE_OFFS_WRITEBUF_DATA
|
||||
|
||||
; reset ringbuffer for messages to be sent
|
||||
m_ringbuffer_y_reset UART_HW_IFACE_OUTMSGBUF_SIZE, \
|
||||
UART_HW_IFACE_OFFS_OUTMSGBUF_USED, \
|
||||
UART_HW_IFACE_OFFS_OUTMSGBUF_RDPOS, \
|
||||
UART_HW_IFACE_OFFS_OUTMSGBUF_WRPOS, \
|
||||
UART_HW_IFACE_OFFS_OUTMSGBUF_DATA
|
||||
|
||||
ldi r16, 0xff
|
||||
std Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM, r16
|
||||
std Y+UART_HW_IFACE_OFFS_WRITEMSG_BUFNUM, r16
|
||||
@@ -156,7 +166,46 @@ UART_HW_InterfaceReadFromWriteBuffer:
|
||||
|
||||
|
||||
|
||||
UART_HW_Interface_Run:
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine UART_HW_InterfaceAddOutgoingMsgNum @global
|
||||
;
|
||||
; @return CFLAG on success, cleared on error
|
||||
; @param r16 byte to write
|
||||
; @param Y pointer to start of interface data
|
||||
; @clobbers R17, R18, X
|
||||
|
||||
UART_HW_InterfaceAddOutgoingMsgNum:
|
||||
push yl
|
||||
push yh
|
||||
adiw yh:yl, UART_HW_IFACE_OFFS_OUTMSGBUF
|
||||
rcall uartHwRingBufferWriteGuarded ; R17, R18, X
|
||||
pop yh
|
||||
pop yl
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine UART_HW_InterfaceGetNextOutgoingMsgNum @global
|
||||
;
|
||||
; @return CFLAG on success, cleared on error
|
||||
; @return R16 byte read
|
||||
; @param Y pointer to start of interface data
|
||||
; @clobbers R17, R18, X
|
||||
|
||||
UART_HW_InterfaceGetNextOutgoingMsgNum:
|
||||
push yl
|
||||
push yh
|
||||
adiw yh:yl, UART_HW_IFACE_OFFS_OUTMSGBUF
|
||||
rcall uartHwRingBufferReadGuarded ; R17, R18, X
|
||||
pop yh
|
||||
pop yl
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -20,26 +20,7 @@
|
||||
; @clobbers R16, R17, X
|
||||
|
||||
UART_HW_Uart1_Init:
|
||||
rcall UART_HW_InterfaceInit
|
||||
|
||||
; 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
|
||||
|
||||
sts UBRR1H, r17
|
||||
sts UBRR1L, r16
|
||||
|
||||
; set character format
|
||||
ldi r16, (1<<USBS1)|(3<<UCSZ10)
|
||||
sts UCSR1C, r16
|
||||
|
||||
M_UART_HW_Uart_Init 1
|
||||
ret
|
||||
; @end
|
||||
|
||||
@@ -51,9 +32,7 @@ UART_HW_Uart1_Init:
|
||||
; @clobbers none
|
||||
|
||||
UART_HW_Uart1_StartRx:
|
||||
lds r16, UCSR1B
|
||||
sbr r16, (1<<RXCIE1) | (1<<RXEN1) ; enable RX complete interrupt, enable receive
|
||||
sts UCSR1B, r16
|
||||
M_UART_HW_Uart_StartRx 1
|
||||
ret
|
||||
; @end
|
||||
|
||||
@@ -65,9 +44,7 @@ UART_HW_Uart1_StartRx:
|
||||
; @clobbers R16
|
||||
|
||||
UART_HW_Uart1_StopRx:
|
||||
lds r16, UCSR1B
|
||||
cbr r16, (1<<RXCIE1 | (1<<RXEN1)) ; disable RX complete interrupt, disable receive
|
||||
sts UCSR1B, r16
|
||||
M_UART_HW_Uart_StopRx 1
|
||||
ret
|
||||
; @end
|
||||
|
||||
@@ -80,9 +57,7 @@ UART_HW_Uart1_StopRx:
|
||||
; @clobbers R16
|
||||
|
||||
UART_HW_Uart1_StartTx:
|
||||
lds r16, UCSR1B
|
||||
sbr r16, (1<<UDRIE1) | (1<<TXEN1) ; enable TX data register empty interrupt, enable transceive
|
||||
sts UCSR1B, r16
|
||||
M_UART_HW_Uart_StartTx 1
|
||||
ret
|
||||
; @end
|
||||
|
||||
@@ -95,9 +70,21 @@ UART_HW_Uart1_StartTx:
|
||||
; @clobbers R16
|
||||
|
||||
UART_HW_Uart1_StopTx:
|
||||
lds r16, UCSR1B
|
||||
cbr r16, (1<<UDRIE1) | (1<<TXEN1) ; disable TX data register empty interrupt, disable transceive
|
||||
sts UCSR1B, r16
|
||||
M_UART_HW_Uart_StopTx 1
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine UART_HW_Uart1_Flush
|
||||
;
|
||||
; Flush receiption buffer.
|
||||
;
|
||||
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_MODE)
|
||||
; @clobbers R16
|
||||
|
||||
UART_HW_Uart1_Flush:
|
||||
M_UART_HW_Uart_Flush 1
|
||||
ret
|
||||
; @end
|
||||
|
||||
@@ -110,24 +97,22 @@ UART_HW_Uart1_StopTx:
|
||||
; @clobbers R16 (R17, R18, X)
|
||||
|
||||
UART_HW_Uart1_RxCharIsr:
|
||||
lds r16, UCSR1A ; check for errors
|
||||
andi r16, (1<<FE1) | (1<<DOR1) | (1<<UPE1)
|
||||
breq UART_HW_Uart1_RxCharIsr_recv ; no error, receive next char
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_STATUS ; set error status
|
||||
ori r16, UART_HW_STATUS_HWERR ; -> HWERR
|
||||
rjmp UART_HW_Uart1_RxCharIsr_setStatusAndEnd
|
||||
UART_HW_Uart1_RxCharIsr_recv:
|
||||
lds r16, UCSR1A
|
||||
sbrs r16, RXC1
|
||||
rjmp UART_HW_Uart1_RxCharIsr_end ; no data
|
||||
lds r16, UDR1
|
||||
rcall UART_HW_InterfaceWriteToReadBuffer ; (R17, R18, X)
|
||||
brcs UART_HW_Uart1_RxCharIsr_end
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_STATUS ; set overrun error
|
||||
ori r16, UART_HW_STATUS_OVERRUN ; -> OVERRUN
|
||||
UART_HW_Uart1_RxCharIsr_setStatusAndEnd:
|
||||
std Y+UART_HW_IFACE_OFFS_STATUS, r16
|
||||
UART_HW_Uart1_RxCharIsr_end:
|
||||
M_UART_HW_Uart_RxCharIsr 1
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine UART_HW_Uart1_TxUdreIsr @global
|
||||
;
|
||||
; 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, R18, X)
|
||||
|
||||
UART_HW_Uart1_TxUdreIsr:
|
||||
M_UART_HW_Uart_TxUdreIsr 1
|
||||
ret
|
||||
; @end
|
||||
|
||||
@@ -136,28 +121,14 @@ UART_HW_Uart1_RxCharIsr_end:
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine UART_HW_Uart1_TxCharIsr @global
|
||||
;
|
||||
; Handler for TXC1 interrupt called when a 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, R18, X)
|
||||
|
||||
UART_HW_Uart1_TxCharIsr:
|
||||
lds r16, UCSR1A
|
||||
sbrs r16,UDRE1
|
||||
rjmp UART_HW_Uart1_TxCharIsr_end ; not ready
|
||||
rcall UART_HW_InterfaceReadFromWriteBuffer ; (R17, R18, X)
|
||||
brcs UART_HW_Uart1_TxCharIsr_send ; got a byte, go send
|
||||
|
||||
; disable further DRE1 interrupts
|
||||
lds r16, UCSR1B
|
||||
cbr r16, (1<<UDRIE1) ; disable TX data register empty interrupt
|
||||
sts UCSR1B, r16
|
||||
; set underrun status (TODO: maybe change this later)
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_STATUS ; set underrun error
|
||||
ori r16, UART_HW_STATUS_UNDERRUN
|
||||
std Y+UART_HW_IFACE_OFFS_STATUS, r16
|
||||
rjmp UART_HW_Uart1_TxCharIsr_end
|
||||
UART_HW_Uart1_TxCharIsr_send:
|
||||
sts UDR1, r16
|
||||
UART_HW_Uart1_TxCharIsr_end:
|
||||
M_UART_HW_Uart_TxCharIsr 1
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
222
avr/modules/uart_hw/m_lowlevel_uart.asm
Normal file
222
avr/modules/uart_hw/m_lowlevel_uart.asm
Normal file
@@ -0,0 +1,222 @@
|
||||
; ***************************************************************************
|
||||
; 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. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @macro M_UART_HW_Uart_Init
|
||||
;
|
||||
; @param %0 UART number ("0" for UART0)
|
||||
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_STATE)
|
||||
; @clobbers R16, R17, X
|
||||
|
||||
.macro M_UART_HW_Uart_Init
|
||||
rcall UART_HW_InterfaceInit
|
||||
|
||||
; 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
|
||||
|
||||
sts UBRR@0H, r17
|
||||
sts UBRR@0L, r16
|
||||
|
||||
; set character format
|
||||
ldi r16, (1<<USBS@0)|(3<<UCSZ@00)
|
||||
sts UCSR@0C, r16
|
||||
.endmacro
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @macro M_UART_HW_Uart_StartRx
|
||||
;
|
||||
; @param %0 UART number ("0" for UART0)
|
||||
; @clobbers none
|
||||
|
||||
.macro M_UART_HW_Uart_StartRx
|
||||
lds r16, UCSR@0B
|
||||
sbr r16, (1<<RXCIE@0) | (1<<RXEN@0) ; enable RX complete interrupt, enable receive
|
||||
sts UCSR@0B, r16
|
||||
.endmacro
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @macro M_UART_HW_Uart_StopRx
|
||||
;
|
||||
; @param %0 UART number ("0" for UART0)
|
||||
; @clobbers R16
|
||||
|
||||
.macro M_UART_HW_Uart_StopRx
|
||||
lds r16, UCSR@0B
|
||||
cbr r16, (1<<RXCIE@0 | (1<<RXEN@0)) ; disable RX complete interrupt, disable receive
|
||||
sts UCSR@0B, r16
|
||||
.endmacro
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @macro M_UART_HW_Uart_StartTx
|
||||
;
|
||||
; @param %0 UART number ("0" for UART0)
|
||||
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_STATE)
|
||||
; @clobbers R16
|
||||
|
||||
.macro M_UART_HW_Uart_StartTx
|
||||
lds r16, UCSR@0A
|
||||
cbr r16, (1<<TXC@0) ; clear TXCn interrupt
|
||||
sts UCSR@0A, r16
|
||||
lds r16, UCSR@0B
|
||||
sbr r16, (1<<UDRIE@0) | (1<<TXC@0) | (1<<TXEN@0) ; enable TX UDRE and TXC1 interrupt, enable transceive
|
||||
sts UCSR@0B, r16
|
||||
.endmacro
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @macro M_UART_HW_Uart_StopTx
|
||||
;
|
||||
; @param %0 UART number ("0" for UART0)
|
||||
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_STATE)
|
||||
; @clobbers R16
|
||||
|
||||
.macro M_UART_HW_Uart_StopTx
|
||||
lds r16, UCSR@0B
|
||||
cbr r16, (1<<UDRIE@0) | (1<<TXC@0) | (1<<TXEN@0) ; disable TX UDRE and TXC1 interrupt, enable transceive
|
||||
sts UCSR@0B, r16
|
||||
.endmacro
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @macro M_UART_HW_Uart_Flush
|
||||
;
|
||||
; Flush receiption buffer.
|
||||
;
|
||||
; @param %0 UART number ("0" for UART0)
|
||||
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_MODE)
|
||||
; @clobbers R16
|
||||
|
||||
.macro M_UART_HW_Uart_Flush
|
||||
l_loop_%:
|
||||
lds r16, UCSR@0A
|
||||
sbrs r16, RXC@0
|
||||
rjmp l_end_%
|
||||
lds r16, UDR@0
|
||||
clr r16
|
||||
std Y+UART_HW_IFACE_OFFS_READTIMER, r16
|
||||
rjmp l_loop_%
|
||||
l_end_%:
|
||||
.endmacro
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @macro M_UART_HW_Uart_RxCharIsr
|
||||
;
|
||||
; @param %0 UART number ("0" for UART0)
|
||||
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_MODE)
|
||||
; @clobbers R16 (R17, R18, X)
|
||||
|
||||
.macro M_UART_HW_Uart_RxCharIsr
|
||||
lds r16, UCSR@0A ; check for errors
|
||||
andi r16, (1<<FE@0) | (1<<DOR@0) | (1<<UPE@0)
|
||||
breq l_recv_% ; no error, receive next char
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_STATUS ; set error status
|
||||
ori r16, (1<<UART_HW_STATUS_HWERR_BIT) ; -> HWERR
|
||||
rjmp l_setStatusAndEnd_%
|
||||
l_recv_%:
|
||||
lds r16, UCSR@0A
|
||||
sbrs r16, RXC@0
|
||||
rjmp l_end_% ; no data
|
||||
lds r16, UDR@0
|
||||
rcall UART_HW_InterfaceWriteToReadBuffer ; (R17, R18, X)
|
||||
brcc l_overrun_%
|
||||
clr r16
|
||||
std Y+UART_HW_IFACE_OFFS_READTIMER, r16 ; reset read timer
|
||||
rjmp l_end_%
|
||||
l_overrun_%:
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_STATUS ; set overrun error
|
||||
ori r16, (1<<UART_HW_STATUS_OVERRUN_BIT) ; -> OVERRUN
|
||||
l_setStatusAndEnd_%:
|
||||
std Y+UART_HW_IFACE_OFFS_STATUS, r16
|
||||
l_end_%:
|
||||
.endmacro
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @macro M_UART_HW_Uart_TxUdreIsr
|
||||
;
|
||||
; Handler for UDREn interrupt called when TX data register is empty.
|
||||
;
|
||||
; @param %0 UART number ("0" for UART0)
|
||||
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_MODE)
|
||||
; @clobbers R16, (R17, R18, X)
|
||||
|
||||
.macro M_UART_HW_Uart_TxUdreIsr
|
||||
lds r16, UCSR@0A
|
||||
sbrs r16,UDRE@0
|
||||
rjmp l_end_% ; not ready
|
||||
rcall UART_HW_InterfaceReadFromWriteBuffer ; (R17, R18, X)
|
||||
brcs l_send_% ; got a byte, go send
|
||||
|
||||
; disable further DRE1 interrupts
|
||||
lds r16, UCSR@0B
|
||||
cbr r16, (1<<UDRIE@0) ; disable TX data register empty interrupt
|
||||
sts UCSR@0B, r16
|
||||
rjmp l_end_%
|
||||
l_send_%:
|
||||
sts UDR@0, r16
|
||||
clr r16
|
||||
std Y+UART_HW_IFACE_OFFS_WRITETIMER, r16 ; reset write timer
|
||||
l_end_%:
|
||||
.endmacro
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @macro M_UART_HW_Uart_TxCharIsr
|
||||
;
|
||||
; Handler for TXCn interrupt called when a last byte has been completely sent and
|
||||
; the data register is empty..
|
||||
;
|
||||
; @param %0 UART number ("0" for UART0)
|
||||
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_MODE)
|
||||
; @clobbers R16, (R17, R18, X)
|
||||
|
||||
.macro M_UART_HW_Uart_TxCharIsr
|
||||
; disable further TXC1 interrupts
|
||||
lds r16, UCSR@0B
|
||||
cbr r16, (1<<TXC@0) ; disable TXC1 interrupt
|
||||
sts UCSR@0B, r16
|
||||
; set underrun status (TODO: maybe change this later)
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_STATUS ; set underrun error
|
||||
ori r16, (1<<UART_HW_STATUS_UNDERRUN_BIT)
|
||||
std Y+UART_HW_IFACE_OFFS_STATUS, r16
|
||||
.endmacro
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
; incoming message ringbuffer.
|
||||
;
|
||||
; @param Y pointer to start of interface data
|
||||
; @param X pointer to start of buffer
|
||||
; @param r16 buffer number
|
||||
; @clobbers R16, R17, R18, R19, R20, R21, X
|
||||
; @clobbers R16, R20 (R17, R18, R18, R19, R20, R21, X)
|
||||
|
||||
UART_HW_Interface_RunRead:
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM
|
||||
@@ -71,12 +69,12 @@ UART_HW_Interface_RunRead_HaveMsg:
|
||||
std Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM, r16
|
||||
rjmp UART_HW_Interface_RunRead_end
|
||||
UART_HW_Interface_RunRead_ovrError:
|
||||
rcall uartHwIncOvrCounter
|
||||
rcall uartHwReadResetBuffer
|
||||
rcall uartHwIncOvrCounter ; (R16)
|
||||
rcall uartHwReadResetBuffer ; (R16, X)
|
||||
rjmp UART_HW_Interface_RunRead_end
|
||||
UART_HW_Interface_RunRead_dataError:
|
||||
rcall uartHwIncContentCounter
|
||||
rcall uartHwResetBufferStartSkipping
|
||||
rcall uartHwIncContentCounter ; (R16)
|
||||
rcall uartHwResetBufferStartSkipping ; (R16, X)
|
||||
UART_HW_Interface_RunRead_end:
|
||||
ret
|
||||
; @end
|
||||
@@ -129,11 +127,11 @@ uartHwReadResetBuffer_haveBuffer:
|
||||
; @routine uartHwResetBufferStartSkipping
|
||||
;
|
||||
; @param Y pointer to start of interface data
|
||||
; @clobbers r16, X
|
||||
; @clobbers r16 (X)
|
||||
|
||||
uartHwResetBufferStartSkipping:
|
||||
; reset READ buffer settings, enter skip mode
|
||||
rcall uartHwReadResetBuffer
|
||||
rcall uartHwReadResetBuffer ; (R16, X)
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_MODE
|
||||
ori r16, UART_HW_MODE_SKIPPING
|
||||
std Y+UART_HW_IFACE_OFFS_MODE, r16
|
||||
|
||||
@@ -12,19 +12,19 @@
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine UART_HW_Interface_RunWrite @global
|
||||
; @routine UART_HW_Interface_RunWriting @global
|
||||
;
|
||||
; Get messages via @ref UART_HW_GetNextOutgoingMsgNum and fill them into
|
||||
; the outbound ringbuffer of this interface.
|
||||
; Write current message to ringbuffer.
|
||||
;
|
||||
; @param Y pointer to start of interface data
|
||||
; @clobbers r16, r19, X (R17, R18, R20, R21)
|
||||
|
||||
UART_HW_Interface_RunWrite:
|
||||
UART_HW_Interface_RunWriting:
|
||||
ldd r19, Y+UART_HW_IFACE_OFFS_WRITEMSG_BUFNUM
|
||||
cpi r19, 0xff
|
||||
breq UART_HW_Interface_RunWrite_end ; nothing to do
|
||||
cpi r19, 0xff ; invalid buffer number?
|
||||
breq UART_HW_Interface_RunWrite_end ; yes, invalid, nothing to do
|
||||
UART_HW_Interface_RunWrite_haveMsg:
|
||||
; there are still bytes left in the buffer, send them
|
||||
ldd r20, Y+UART_HW_IFACE_OFFS_WRITEMSG_LEFT
|
||||
rcall uartHwWriteUptoNumBytes ; (r16, r17, r18, r20, r21, X)
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_WRITEMSG_LEFT
|
||||
@@ -33,8 +33,12 @@ UART_HW_Interface_RunWrite_haveMsg:
|
||||
; message completely sent to interface, release buffer
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_WRITEMSG_BUFNUM
|
||||
rcall UART_HW_FixedBuffers_ReleaseByNum
|
||||
ldi r16, 0xff ; reset buffer number
|
||||
ldi r16, 0xff ; set invalid buffer number
|
||||
std Y+UART_HW_IFACE_OFFS_WRITEMSG_BUFNUM, r16
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_MODE
|
||||
cbr r16, UART_HW_MODE_WRITEMASK
|
||||
ori r16, UART_HW_MODE_WAITBUFFEREMPTY
|
||||
std Y+UART_HW_IFACE_OFFS_MODE, r16
|
||||
UART_HW_Interface_RunWrite_end:
|
||||
ret
|
||||
; @end
|
||||
@@ -47,6 +51,7 @@ UART_HW_Interface_RunWrite_end:
|
||||
; Set given fixed buffer as source for @ref UART_HW_Interface_RunWrite.
|
||||
;
|
||||
; @param r16 buffer num
|
||||
; @param Y pointer to start of interface data
|
||||
; @clobbers r16, r19, X
|
||||
|
||||
UART_HW_Interface_WriteSetBuffer:
|
||||
|
||||
334
avr/modules/uart_hw/ttyonuart1.asm
Normal file
334
avr/modules/uart_hw/ttyonuart1.asm
Normal file
@@ -0,0 +1,334 @@
|
||||
; ***************************************************************************
|
||||
; 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. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
.equ TTYONUART1_SKIPTIME = 2
|
||||
.equ TTYONUART1_IFACENUM = 2
|
||||
|
||||
|
||||
.dseg
|
||||
|
||||
ttyOnUart1_iface: .byte UART_HW_IFACE_SIZE
|
||||
|
||||
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine TtyOnUart1_Init @global
|
||||
;
|
||||
; @clobbers Y (R16, R17, X)
|
||||
|
||||
TtyOnUart1_Init:
|
||||
ldi yl, LOW(ttyOnUart1_iface)
|
||||
ldi yh, HIGH(ttyOnUart1_iface)
|
||||
rcall UART_HW_Uart1_Init ; (R16, R17, X)
|
||||
ldi r16, TTYONUART1_IFACENUM
|
||||
std Y+UART_HW_IFACE_OFFS_IFACENUM, r16
|
||||
ldi r16, UART_HW_MODE_IDLE | UART_HW_MODE_W_IDLE ; start in full idle mode
|
||||
std Y+UART_HW_IFACE_OFFS_MODE, r16
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine TtyOnUart1_Periodically @global
|
||||
;
|
||||
; @clobbers R16, Y
|
||||
|
||||
TtyOnUart1_Periodically:
|
||||
ldi yl, LOW(ttyOnUart1_iface)
|
||||
ldi yh, HIGH(ttyOnUart1_iface)
|
||||
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_READTIMER
|
||||
inc r16
|
||||
breq TtyOnUart1_Periodically_l1
|
||||
std Y+UART_HW_IFACE_OFFS_READTIMER, r16
|
||||
TtyOnUart1_Periodically_l1:
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_WRITETIMER
|
||||
inc r16
|
||||
breq TtyOnUart1_Periodically_l2
|
||||
std Y+UART_HW_IFACE_OFFS_WRITETIMER, r16
|
||||
TtyOnUart1_Periodically_l2:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine TtyOnUart1_RxCharIsr @global @isr
|
||||
;
|
||||
; @clobbers none
|
||||
|
||||
TtyOnUart1_RxCharIsr:
|
||||
push r15
|
||||
in r15, SREG
|
||||
push r16
|
||||
push r17
|
||||
push r18
|
||||
push xl
|
||||
push xh
|
||||
push yl
|
||||
push yh
|
||||
ldi yl, LOW(ttyOnUart1_iface)
|
||||
ldi yh, HIGH(ttyOnUart1_iface)
|
||||
rcall UART_HW_Uart1_RxCharIsr ; (R16, R17, R18, X)
|
||||
pop yh
|
||||
pop yl
|
||||
pop xh
|
||||
pop xl
|
||||
pop r18
|
||||
pop r17
|
||||
pop r16
|
||||
out SREG, r15
|
||||
pop r15
|
||||
reti
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine TtyOnUart1_TxUdreIsr @global @isr
|
||||
;
|
||||
; @clobbers none
|
||||
|
||||
TtyOnUart1_TxUdreIsr:
|
||||
push r15
|
||||
in r15, SREG
|
||||
push r16
|
||||
push r17
|
||||
push r18
|
||||
push xl
|
||||
push xh
|
||||
push yl
|
||||
push yh
|
||||
ldi yl, LOW(ttyOnUart1_iface)
|
||||
ldi yh, HIGH(ttyOnUart1_iface)
|
||||
rcall UART_HW_Uart1_TxUdreIsr ; (R16, R17, R18, X)
|
||||
pop yh
|
||||
pop yl
|
||||
pop xh
|
||||
pop xl
|
||||
pop r18
|
||||
pop r17
|
||||
pop r16
|
||||
out SREG, r15
|
||||
pop r15
|
||||
reti
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine TtyOnUart1_TxCharIsr @global @isr
|
||||
;
|
||||
; @clobbers none
|
||||
|
||||
TtyOnUart1_TxCharIsr:
|
||||
push r15
|
||||
in r15, SREG
|
||||
push r16
|
||||
push r17
|
||||
push r18
|
||||
push xl
|
||||
push xh
|
||||
push yl
|
||||
push yh
|
||||
ldi yl, LOW(ttyOnUart1_iface)
|
||||
ldi yh, HIGH(ttyOnUart1_iface)
|
||||
rcall UART_HW_Uart1_TxCharIsr ; (R16, R17, R18, X)
|
||||
pop yh
|
||||
pop yl
|
||||
pop xh
|
||||
pop xl
|
||||
pop r18
|
||||
pop r17
|
||||
pop r16
|
||||
out SREG, r15
|
||||
pop r15
|
||||
reti
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine TtyOnUart1_Run @global
|
||||
;
|
||||
; @clobbers all
|
||||
|
||||
TtyOnUart1_Run:
|
||||
ldi yl, LOW(ttyOnUart1_iface)
|
||||
ldi yh, HIGH(ttyOnUart1_iface)
|
||||
|
||||
rcall ttyOnUart1RunWriteModes
|
||||
rcall ttyOnUart1RunReadModes
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine ttyOnUart1RunWriteModes
|
||||
;
|
||||
; @clobbers all, !Y
|
||||
|
||||
ttyOnUart1RunWriteModes:
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_MODE ; handle write functions
|
||||
cbr r16, UART_HW_MODE_READMASK
|
||||
cpi r16, UART_HW_MODE_W_IDLE
|
||||
breq ttyOnUart1RunWIdle
|
||||
cpi r16, UART_HW_MODE_WRITING
|
||||
breq ttyOnUart1RunWriting
|
||||
cpi r16, UART_HW_MODE_WAITBUFFEREMPTY
|
||||
breq ttyOnUart1RunWaitBufferEmpty
|
||||
cpi r16, UART_HW_MODE_WRITEBUFFEREMPTY
|
||||
breq ttyOnUart1RunWriteBufferEmpty
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine ttyOnUart1RunWIdle
|
||||
;
|
||||
; @clobbers all, !Y
|
||||
|
||||
ttyOnUart1RunWIdle:
|
||||
rcall UART_HW_InterfaceGetNextOutgoingMsgNum ; (R17, R18, X)
|
||||
brcc ttyOnUart1RunWIdle_end
|
||||
rcall UART_HW_Interface_WriteSetBuffer ; (r16, r19, X)
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_MODE
|
||||
cbr r16, UART_HW_MODE_WRITEMASK
|
||||
ori r16, UART_HW_MODE_WRITING
|
||||
std Y+UART_HW_IFACE_OFFS_MODE, r16
|
||||
rcall ttyOnUart1RunWriting ; fill ringbuffer
|
||||
rcall UART_HW_Uart1_StartTx ; enable transceiver and interrupts
|
||||
ttyOnUart1RunWIdle_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine ttyOnUart1RunWriting
|
||||
;
|
||||
; @clobbers all, !Y
|
||||
|
||||
ttyOnUart1RunWriting:
|
||||
rjmp UART_HW_Interface_RunWriting ; (R16, R17, R18, R19, R20, R21, X)
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine ttyOnUart1RunWaitBufferEmpty
|
||||
;
|
||||
; @clobbers all, !Y
|
||||
|
||||
ttyOnUart1RunWaitBufferEmpty:
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_STATUS
|
||||
sbrs r16, UART_HW_STATUS_UNDERRUN_BIT ; underrun bit set?
|
||||
ret ; return if bit still clear
|
||||
cbr r16, (1<<UART_HW_STATUS_UNDERRUN_BIT)
|
||||
std Y+UART_HW_IFACE_OFFS_STATUS, r16
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_MODE ; change mode to WRITEBUFFEREMPTY and go handle that
|
||||
cbr r16, UART_HW_MODE_WRITEMASK
|
||||
ori r16, UART_HW_MODE_WRITEBUFFEREMPTY
|
||||
std Y+UART_HW_IFACE_OFFS_MODE, r16
|
||||
rjmp ttyOnUart1RunWriteBufferEmpty
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine ttyOnUart1RunWriteBufferEmpty
|
||||
;
|
||||
; @clobbers all, !Y
|
||||
|
||||
ttyOnUart1RunWriteBufferEmpty:
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_MODE
|
||||
cbr r16, UART_HW_MODE_WRITEMASK
|
||||
ori r16, UART_HW_MODE_W_IDLE
|
||||
std Y+UART_HW_IFACE_OFFS_MODE, r16
|
||||
rcall UART_HW_Uart1_StopTx ; disable transceiver and interrupts
|
||||
rjmp ttyOnUart1RunWIdle
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine ttyOnUart1RunReadModes
|
||||
;
|
||||
; @clobbers all, !Y
|
||||
|
||||
ttyOnUart1RunReadModes:
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_MODE ; handle read functions
|
||||
cbr r16, UART_HW_MODE_WRITEMASK
|
||||
cpi r16, UART_HW_MODE_IDLE
|
||||
breq ttyOnUart1RunIdle
|
||||
cpi r16, UART_HW_MODE_READING
|
||||
breq ttyOnUart1RunReading
|
||||
cpi r16, UART_HW_MODE_SKIPPING
|
||||
breq ttyOnUart1RunSkipping
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine ttyOnUart1RunIdle
|
||||
;
|
||||
; @clobbers all, !Y
|
||||
|
||||
ttyOnUart1RunIdle:
|
||||
rcall UART_HW_Uart1_StartRx
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_MODE
|
||||
cbr r16, UART_HW_MODE_READMASK
|
||||
ori r16, UART_HW_MODE_READING
|
||||
std Y+UART_HW_IFACE_OFFS_MODE, r16
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine ttyOnUart1RunReading
|
||||
;
|
||||
; @clobbers all, !Y
|
||||
|
||||
ttyOnUart1RunReading:
|
||||
rjmp UART_HW_Interface_RunRead ; (R16, R17, R18, R18, R19, R20, R21, X)
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine ttyOnUart1RunSkipping
|
||||
;
|
||||
; @clobbers all, !Y
|
||||
|
||||
ttyOnUart1RunSkipping:
|
||||
rcall UART_HW_Uart1_Flush ; (R16)
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_READTIMER
|
||||
cpi r16, TTYONUART1_SKIPTIME
|
||||
brcs ttyOnUart1RunSkipping_end
|
||||
ldd r16, Y+UART_HW_IFACE_OFFS_MODE
|
||||
cbr r16, UART_HW_MODE_READMASK
|
||||
ori r16, UART_HW_MODE_READING
|
||||
std Y+UART_HW_IFACE_OFFS_MODE, r16
|
||||
ttyOnUart1RunSkipping_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user