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