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,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