OpenCores
URL https://opencores.org/ocsvn/thor/thor/trunk

Subversion Repositories thor

[/] [thor/] [trunk/] [software/] [source/] [serial.asm] - Rev 30

Go to most recent revision | Compare with Previous | Blame | View Log

UART            EQU     0xC0A00
UART_TX         EQU     0xC0A00
UART_RX         EQU     0xC0A00
UART_LS         EQU     0xC0A01
UART_MS         EQU     0xC0A02
UART_IS         EQU     0xC0A03
UART_IE         EQU     0xC0A04
UART_FF         EQU     0xC0A05
UART_MC         EQU     0xC0A06
UART_CTRL       EQU     0xC0A07
UART_CM0        EQU     0xC0A08
UART_CM1        EQU     0xC0A09
UART_CM2        EQU     0xC0A0A
UART_CM3        EQU     0xC0A0B
UART_SPR        EQU     0xC0A0F

;------------------------------------------------------------------------------
;------------------------------------------------------------------------------

;==============================================================================
; Serial port
;==============================================================================
        code
;------------------------------------------------------------------------------
; Initialize UART
;------------------------------------------------------------------------------

                align   8
ser_jmp:
                jmp             SerialIRQ[c0]

SerialInit:
                addui   sp,sp,#-8
                sws             c1,[sp]
                ldis    hs,#$FFD00000
                ldis    hs.lmt,#$100000
;               ldi             r1,#$0218DEF4   ; constant for clock multiplier with 18.75MHz clock for 9600 baud
;               ldi             r1,#$03254E6E   ; constant for clock multiplier with 12.5MHz clock for 9600 baud
                ldi             r1,#$00C9539B   ; constant for clock multiplier with 50.0MHz clock for 9600 baud
                shrui   r1,r1,#8          ; drop the LSB (not used)
                sb      r1,hs:UART_CM1
                shrui   r1,r1,#8
                sb      r1,hs:UART_CM2
                shrui   r1,r1,#8
                sb      r1,hs:UART_CM3
                sb      r0,hs:UART_CTRL     ; no hardware flow control
                sc              r0,Uart_rxhead          ; reset buffer indexes
                sc              r0,Uart_rxtail
                ldi             r1,#0x1f0
                sc              r1,Uart_foff            ; set threshold for XOFF
                ldi             r1,#0x010
                sc              r1,Uart_fon                     ; set threshold for XON
                ldi             r1,#1
                sb              r1,hs:UART_IE           ; enable receive interrupt only
                sb              r0,Uart_rxrts           ; no RTS/CTS signals available
                sb              r0,Uart_txrts           ; no RTS/CTS signals available
                sb              r0,Uart_txdtr           ; no DTR signals available
                sb              r0,Uart_rxdtr           ; no DTR signals available
                ldi             r1,#1
                sb              r1,Uart_txxon           ; for now
                ldi             r1,#1
;               sb              r1,SERIAL_SEMA
                ; setup IRQ vector
                lla             r1,cs:ser_jmp
                ldi             r2,#199
                bsr             set_vector
                lws             c1,[sp]
                addui   sp,sp,#8
                rts

;---------------------------------------------------------------------------------
; Get character directly from serial port. Blocks until a character is available.
;---------------------------------------------------------------------------------
;
SerialGetCharDirect:
sgc1:
                lvb             r1,hs:UART_LS   ; uart status
                biti    p0,r1,#1                ; is there a char available ?
p0.eq   br              sgc1
                lvb             r1,hs:UART_RX
                rts

;------------------------------------------------
; Check for a character at the serial port
; returns r1 = 1 if char available, 0 otherwise
;------------------------------------------------
;
SerialCheckForCharDirect:
                lvb             r1,hs:UART_LS                   ; uart status
                andi    r1,r1,#rxfull                   ; is there a char available ?
                rts

;-----------------------------------------
; Put character to serial port
; r1 = char to put
;-----------------------------------------
;
SerialPutChar:
                addui   sp,sp,#-48
                sw              r2,[sp]
                sw              r3,8[sp]
                sw              r4,16[sp]
                sw              r5,24[sp]
                sws             p0,32[sp]
                sws             lc,40[sp]
                lvb             r2,hs:UART_MC
                ori             r2,r2,#3                ; assert DTR / RTS
                sb              r2,hs:UART_MC
                lb              r2,Uart_txrts
                tst             p0,r2
p0.eq   br              spcb1
                lw              r4,Milliseconds
                ldis    lc,#999                 ; delay count (1 s)
spcb3:
                lvb             r2,hs:UART_MS
                biti    p0,r2,#$10              ; is CTS asserted ?
p0.ne   br              spcb1
                lw              r5,Milliseconds
                cmp             p0,r4,r5
p0.eq   br              spcb3
                mov             r4,r5
                loop    spcb3
                br              spcabort
spcb1:
                lb              r2,Uart_txdtr
                tst             p0,r2
p0.eq   br              spcb2
                lw              r4,Milliseconds
                ldis    lc,#999         ; delay count
spcb4:
                lvb             r2,hs:UART_MS
                biti    p0,r2,#$20              ; is DSR asserted ?
p0.ne   br              spcb2
                lw              r5,Milliseconds
                cmp             p0,r4,r5
p0.eq   br              spcb4
                mov             r4,r5
                loop    spcb4
                br              spcabort
spcb2:  
                lb              r2,Uart_txxon
                tst             p0,r2
p0.eq   br              spcb5
spcb6:
                lb              r2,Uart_txxonoff
                tst             p0,r2
p0.eq   br              spcb5
                lvb             r4,hs:UART_MS
                biti    p0,r4,#0x80             ; DCD ?
p0.ne   br              spcb6
spcb5:
                lw              r4,Milliseconds
                ldis    lc,#999         ; wait up to 1s
spcb8:
                lvb             r2,hs:UART_LS
                biti    p0,r2,#0x20                     ; tx not full ?
p0.ne   br              spcb7
                lw              r5,Milliseconds
                cmp             p0,r4,r5
p0.eq   br              spcb8
                mov             r4,r5
                loop    spcb8
                br              spcabort
spcb7:
                sb              r1,hs:UART_TX
spcabort:
                lw              r2,[sp]
                lw              r3,8[sp]
                lw              r4,16[sp]
                lw              r5,24[sp]
                lws             p0,32[sp]
                lws             lc,40[sp]
                addui   sp,sp,#40
                rts

;-------------------------------------------------
; Compute number of characters in recieve buffer.
; r4 = number of chars
;-------------------------------------------------
CharsInRxBuf:
                lcu             r4,Uart_rxhead
                lcu             r3,Uart_rxtail
                subu    r4,r4,r3
                tst             p0,r4
p0.gt   br              cirxb1
                ldi             r4,#0x200
                addu    r4,r4,r3
                lcu             r3,Uart_rxhead
                subu    r4,r4,r3
cirxb1:
                rts

;----------------------------------------------
; Get character from rx fifo
; If the fifo is empty enough then send an XON
;----------------------------------------------
;
SerialGetChar:
                addui   sp,sp,#-40
                sw              r2,[sp]
                sw              r3,8[sp]
                sw              r4,16[sp]
                sw              r5,24[sp]
                sws             c1,32[sp]
                lcu             r3,Uart_rxhead
                lcu             r2,Uart_rxtail
                cmp             p0,r2,r3
p0.eq   br              sgcfifo1                ; is there a char available ?
                lbu             r1,Uart_rxfifo[r2]      ; get the char from the fifo into r1
                addui   r2,r2,#1                ; increment the fifo pointer
                andi    r2,r2,#$1ff
                sc              r2,Uart_rxtail
                lb              r2,Uart_rxflow          ; using flow control ?
                tst             p0,r2
p0.eq   br              sgcfifo2
                lcu             r3,Uart_fon             ; enough space in Rx buffer ?
                bsr             CharsInRxBuf
                cmp             p0,r4,r3
p0.gt   br              sgcfifo2
                sb              r0,Uart_rxflow          ; flow off
                lb              r4,Uart_rxrts
                tst             p0,r4
p0.eq   br              sgcfifo3
                lb              r4,hs:UART_MC           ; set rts bit in MC
                ori             r4,r4,#2
                sb              r4,hs:UART_MC
sgcfifo3:
                lb              r4,Uart_rxdtr
                tst             p0,r4
p0.eq   br              sgcfifo4
                lb              r4,hs:UART_MC           ; set DTR
                ori             r4,r4,#1
                sb              r4,hs:UART_MC
sgcfifo4:
                lb              r4,Uart_rxxon
                tst             p0,r4
p0.eq   br              sgcfifo5
                ldi             r4,#XON
                sb              r4,hs:UART
sgcfifo5:
sgcfifo2:                                       ; return with char in r1
                lw              r2,[sp]
                lw              r3,8[sp]
                lw              r4,16[sp]
                lw              r5,24[sp]
                lws             c1,32[sp]
                addui   sp,sp,#40
                rts
sgcfifo1:
                ldi             r1,#-1                          ; no char available
                lw              r2,[sp]
                lw              r3,8[sp]
                lw              r4,16[sp]
                lw              r5,24[sp]
                lws             c1,32[sp]
                addui   sp,sp,#40
                rts


;-----------------------------------------
; Serial port IRQ
;-----------------------------------------
;
SerialIRQ:
                sync
                addui   r31,r31,#-64
                sw              r1,[r31]
                sw              r2,8[r31]
                sw              r4,16[r31]
                sws             p0,24[r31]
                sw              r3,32[r31]
                sws             c1,40[r31]
                sws             hs,48[r31]
                sws             hs.lmt,56[r31]
                ldis    hs,#$FFD00000
                ldis    hs.lmt,#$100000

                lb      r1,hs:UART_IS  ; get interrupt status
                tst             p0,r1
p0.gt   br              sirq1                   ; no interrupt
                andi    r1,r1,#0x7f     ; switch on interrupt type
                biti    p0,r1,#4
p0.ne   br              srxirq
                biti    p0,r1,#$0C
p0.ne   br              stxirq
                biti    p0,r1,#$10
p0.ne   br              smsirq
                ; unknown IRQ type
sirq1:
                lw              r1,[r31]
                lw              r2,8[r31]
                lw              r4,16[r31]
                lws             p0,24[r31]
                lw              r3,32[r31]
                lws             c1,40[r31]
                lws             hs,48[r31]
                lws             hs.lmt,56[r31]
                addui   r31,r31,#64
                sync
                rti

; Get the modem status and record it
smsirq:
                lbu     r1,hs:UART_MS
                sb      r1,Uart_ms
                br              sirq1

stxirq:
                br              sirq1

; Get a character from the uart and store it in the rx fifo
srxirq:
srxirq1:
                lbu     r1,hs:UART_RX      ; get the char (clears interrupt)
                lbu     r3,Uart_txxon
                tst             p0,r3
p0.eq   br              srxirq3
                cmpi    p0,r1,#XOFF
p0.ne   br              srxirq2
                ldi     r1,#1
                sb              r1,Uart_txxonoff
                br              srxirq5
srxirq2:
                cmpi    p0,r1,#XON
p0.ne   br              srxirq3
                sb              r0,Uart_txxonoff
                br              srxirq5
srxirq3:
                sb              r0,Uart_txxonoff
                lcu             r4,Uart_rxhead
                sb              r1,Uart_rxfifo[r4]  ; store in buffer
                addui   r4,r4,#1
                andi    r4,r4,#$1ff
                sc              r4,Uart_rxhead
srxirq5:
                lb      r1,hs:UART_LS   ; check for another ready character
                biti    p0,r1,#1        ; check rxfull bit
p0.ne   br              srxirq1                 ; loop back for another character
                lb              r1,Uart_rxflow          ; are we using flow controls?
                tst             p0,r1
p0.ne   br              srxirq8
                bsr             CharsInRxBuf
                lb              r1,Uart_foff
                cmp             p0,r4,r1
p0.lt   br              srxirq8
                ldi             r1,#1
                sb              r1,Uart_rxflow
                lb              r1,Uart_rxrts
                tst             p0,r1
p0.eq   br              srxirq6
                lb              r1,hs:UART_MC
                andi    r1,r1,#$FD              ; turn off RTS
                sb              r1,hs:UART_MC
srxirq6:
                lb              r1,Uart_rxdtr
                tst             p0,r1

 p0.eq  br              srxirq7
                lb              r1,hs:UART_MC
                andi    r1,r1,#$FE              ; turn off DTR
                sb              r1,hs:UART_MC
srxirq7:
                lb              r1,Uart_rxxon
                tst             p0,r1
p0.eq   br              srxirq8
                ldi             r1,#XOFF
                sb              r1,hs:UART_TX
srxirq8:
                br              sirq1

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.