try new implementation of UART code for m8515.
This commit is contained in:
@@ -53,6 +53,15 @@
|
||||
.include "modules/uart_bitbang2/lowlevel.asm"
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_UART_HW
|
||||
.include "modules/uart_hw/defs.asm"
|
||||
.include "modules/uart_hw/lowlevel.asm"
|
||||
.include "modules/uart_hw/uart.asm"
|
||||
.include "modules/uart_hw/attn.asm"
|
||||
.include "modules/uart_hw/net_uart.asm"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MODULES_COMONUART0
|
||||
.include "modules/uart_hw/defs.asm"
|
||||
.include "modules/uart_hw/lowlevel.asm"
|
||||
|
||||
@@ -94,6 +94,10 @@ onSystemTimerTick:
|
||||
rcall UART_BitBang_Every100ms
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_UART_HW
|
||||
rcall NET_Uart_Periodically
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_TTYONUART1
|
||||
rcall TtyOnUart1_Periodically
|
||||
#endif
|
||||
|
||||
@@ -61,6 +61,10 @@ initModules:
|
||||
rcall UART_BitBang_Init
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_UART_HW
|
||||
rcall NET_Uart_Init
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_TTYONUART1
|
||||
rcall TtyOnUart1_Init
|
||||
#endif
|
||||
@@ -165,6 +169,10 @@ runModules_Com:
|
||||
runModules_ComEnd:
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_UART_HW
|
||||
rcall NET_Uart_Run
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_TTYONUART1
|
||||
rcall TtyOnUart1_Run
|
||||
#endif
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
; ---------------------------------------------------------------------------
|
||||
; generic
|
||||
|
||||
.equ NET_BUFFERS_NUM = 6
|
||||
.equ NET_BUFFERS_NUM = 8
|
||||
.equ NET_BUFFERS_SIZE = 32
|
||||
|
||||
|
||||
@@ -50,7 +50,9 @@
|
||||
#define MODULES_XRAM
|
||||
#define MODULES_LED_SIMPLE
|
||||
#define MODULES_NETWORK
|
||||
#define MODULES_COMONUART0
|
||||
;#define MODULES_COMONUART0
|
||||
#define MODULES_UART_HW
|
||||
|
||||
;#define MODULES_UART_BITBANG
|
||||
;#define MODULES_TWI_MASTER
|
||||
;#define MODULES_LCD
|
||||
@@ -107,7 +109,8 @@
|
||||
; ---------------------------------------------------------------------------
|
||||
; Reset and interrupt vectors
|
||||
rjmp BOOTLOADER_ADDR ; 1: Reset vector RESET
|
||||
rjmp ComOnUart0_AttnChangeIsr ; 2: INT0 External Interrupt Request 0
|
||||
; rjmp ComOnUart0_AttnChangeIsr ; 2: INT0 External Interrupt Request 0
|
||||
reti
|
||||
reti ; 3: INT1 External Interrupt Request 1
|
||||
reti ; 4: TIMER1_CAPT Timer/Counter1 Capture Event
|
||||
reti ; 5: TIMER1_COMPA Timer/Counter1 Compare Match A
|
||||
@@ -115,9 +118,9 @@
|
||||
reti ; 7: TIMER1_OVF Timer/Counter1 Overflow
|
||||
reti ; 8: TIMER0_OVF Timer/Counter0 Overflow
|
||||
reti ; 9: SPI_STC Serial Transfer Complete
|
||||
rjmp ComOnUart0_RxCharIsr ; 10: USART_RXC USART Rx Complete
|
||||
rjmp ComOnUart0_TxUdreIsr ; 11: USART_UDRE USART Data Register Empty
|
||||
rjmp ComOnUart0_TxCharIsr ; 12: USART_TXC USART Tx Complete
|
||||
rjmp Uart_RxCharIsr ; 10: USART_RXC USART Rx Complete
|
||||
rjmp Uart_UdreIsr ; 11: USART_UDRE USART Data Register Empty
|
||||
rjmp Uart_TxCharIsr ; 12: USART_TXC USART Tx Complete
|
||||
reti ; 13: ANA_COMP Analog Comparator
|
||||
reti ; 14: INT2 External Interrupt Request 2
|
||||
rjmp baseTimerIrqOC0A ; 15: TIMER0_COMP Timer/Counter0 Compare Match
|
||||
@@ -206,7 +209,7 @@ onEveryLoop:
|
||||
; ---------------------------------------------------------------------------
|
||||
; defines for network interface
|
||||
|
||||
.equ netInterfaceData = comonuart0_iface
|
||||
.equ netInterfaceData = netUartIface
|
||||
|
||||
|
||||
|
||||
|
||||
102
avr/modules/uart_hw/attn.asm
Normal file
102
avr/modules/uart_hw/attn.asm
Normal 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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
;
|
||||
|
||||
240
avr/modules/uart_hw/net_uart.asm
Normal file
240
avr/modules/uart_hw/net_uart.asm
Normal 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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
398
avr/modules/uart_hw/uart.asm
Normal file
398
avr/modules/uart_hw/uart.asm
Normal 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
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user