UART I/O





3
Date Submitted Mon. Nov. 26th, 2007 1:09 PM
Revision 1 of 1
Helper DrivingManiac
Tags UART
Comments 0 comments
Assemble
; ******************************************************************
; Lab 7
; ******************************************************************
; Name:   UART putChar, getChar, printString in assembly.
; Purpose:            Get, put, and printstring in assembly using the UART.
; Programmer:   Victor Prechtel (1330310)
; Date:                         10/29/2007
; ******************************************************************

; *********************************************************************************
; HW;4 - Assembly program to interact with a UART
; *********************************************************************************
; Name : HW;4
; Purpose : Show how to interact with UART (getting and printing characters).
; Notes : Has 5 functions:
; (1) Function to reset the UART
; * Uses function (5) to print out a message
; (2) Error-checking input/output routine
; * Uses function (3) and (4) to interact with the UART
; (3) Function to get a character from the UART
; (4) Function to send a character to the UART
; (5) Function to print NULL-terminated strings
; * Uses function (3) to send characters to the UART
; *********************************************************************************
; ************************
; UART Definitions
; ************************
.set ERROR_STATUS, 1
.set SUCCESS_STATUS, 0
.set UART_base, 0x40600000 /* UART base address */
.set TX_FIFO_FULL, 8 /* Bit-mask for checking TX-FIFO fullness */
.set TX_FIFO_EMPTY, 4 /* Bit-mask for checking TX-FIFO emptiness */
.set RX_FIFO_FULL, 2 /* Bit-mask for checking RX-FIFO fullness */
.set RX_FIFO_VALID, 1 /* Bit-mask for checking RX-FIFO emptiness (if it has valid data or not)*/
.set UART_RX_FIFO_OFFSET, 0 /* receive FIFO, read only */
.set UART_TX_FIFO_OFFSET, 4 /* transmit FIFO, write only */
.set UART_STATUS_REG_OFFSET, 8 /* status register, read only */
.set UART_CONTROL_REG_OFFSET, 12 /* control register, write only */
; ************************
; Pre-formatted strings
; ************************
$msgReset:
        .ascii "\r\n Resetting UART...\0\000"
        .text
        .align 2
       
$msgAsk:
        .ascii "\r\n Waiting for character...\0\000"
        .text
        .align 2

; ************************
; Main Program
; ************************
.globl main
main:
        ; ***************************************************************
        ; Reset the UART
        ; ***************************************************************
        ; Setup stack frame for a function call (save link register)
        addi r1, r1, -4
        swi r15, r1, 0
       
        ; Call print function (return address stored in r15)
        brlid r15, resetUART
        nop
       
        ; Restore link register
        lwi r15, r1, 0
        addi r1, r1, 4

REPEAT:
        ; ***************************************************************
        ; Print out a prompt telling the user to enter a character
        ; ***************************************************************
        ; Store string in r5
        addi r5, r0, $msgAsk
       
        ; Setup stack frame for a function call (save link register)
        addi r1, r1, -4
        swi r15, r1, 0

        ; Call print function (return address stored in r15)
        brlid r15, myPrintString
        nop

        ; Restore link register
        lwi r15, r1, 0
        addi r1, r1, 4

        ; ***************************************************************
        ; Call input/output routine
        ; ***************************************************************
        ; Setup stack frame for a function call (save link register)
        addi r1, r1, -4
        swi r15, r1, 0

        ; Call getChar function (return address stored in r15)
        brlid r15, myInputOutput
        nop
       
        ; Restore link register
        lwi r15, r1, 0
        addi r1, r1, 4

        ; ***************************************************************
        ; Check return value of input/output routine
        ; ***************************************************************
        ; Temporarily store flag value in r13
        addi r13, r3, 0

        ; If (r13 == ERROR_STATUS) then exit program, otherwise continue
        rsubi r13, r13, ERROR_STATUS
        beqi r13, EXIT_PROGRAM

        ; ************** Print carriage return (\r = 0x0d = 13) ****************
        ; Put carriage return in r5
        addi r5, r0, 13

        ; Setup stack frame for a function call (save link register)
        addi r1, r1, -4
        swi r15, r1, 0
       
        ; Call myPrintChar function (return address stored in r15)
        brlid r15, myPrintChar
        nop

        ; Restore link register
        lwi r15, r1, 0
        addi r1, r1, 4
       
        ; ************** Print newline (\n = 0x0a = 10) ****************
        ; Put newline in r5
        addi r5, r0, 10

        ; Setup stack frame for a function call (save link register)
        addi r1, r1, -4
        swi r15, r1, 0

        ; Call myPrintChar function (return address stored in r15)
        brlid r15, myPrintChar
        nop

        ; Restore link register
        lwi r15, r1, 0
        addi r1, r1, 4

        ; ***************************************************************
        ; Infinitely loop
        ; ***************************************************************
        brid REPEAT
        nop

EXIT_PROGRAM:
        ; Infinitely loop on exit
        brid EXIT_PROGRAM
        nop
       
        ; *************************************
        ; My FUNCTION Definitions
        ; *************************************
        ; ***************************************************************
        ; Name: resetUART
        ; Purpose: A routine to reset the UART
        ; Parameters:
        ; * NONE
        ; Return Values:
        ; * NONE
        ; Volatiles:
        ; * Blows away r5, r6, and r7
        ; ***************************************************************
.globl resetUART
resetUART:
        ; ********************************************************************
        ; Reset UART
        ; ********************************************************************
        ; Put UARTs base address into r6
        addi r6, r0, UART_base
       
        ; Turn off UART interrupt (set bit 27 to '1') and Reset Rx and Tx FIFOs (set bits 30 and 31 to '1')
        addi r7, r0, 0x13
        swi r7, r6, UART_CONTROL_REG_OFFSET

        ; ********************************************************************
        ; Print out a message telling the user that the UART is being reset
        ; ********************************************************************
        ; Store string in r5
        addi r5, r0, $msgReset

        ; Setup stack frame for a function call (save link register)
        addi r1, r1, -4
        swi r15, r1, 0

        ; Call print function (return address stored in r15)
        brlid r15, myPrintString
        nop

        ; Restore link register
        lwi r15, r1, 0
        addi r1, r1, 4

        ; Return from subroutine
        rtsd r15, 8
        nop

        ; ***************************************************************
        ; Name: myInputOutput
        ; Purpose: A routine to send/get characters from the UART (with error check)
        ; Parameters:
        ; * NONE
        ; Return Values:
        ; * r3 has return value flag
        ; Volatiles:
        ; * Blows away r5, r6, r7, r8
        ; ***************************************************************
.globl myInputOutput
myInputOutput:
        ; Put UART's base address into r6
        addi r6, r0, UART_base

        ; ****************************************************
        ; Check for errors (bits 24, 25, 26 of STATUS reg)
        ; ****************************************************
        lwi r7, r6, UART_STATUS_REG_OFFSET
        andi r7, r7, 0xE0

        ; If r7 == 0 then get a character
        beqi r7, PROCEED

        ; Otherwise reset the RxFIFO (bit 30)
        addi r7, r0, 0x02
        swi r7, r6, UART_CONTROL_REG_OFFSET

        ; Return with error status
        addi r3, r0, ERROR_STATUS
        rtsd r15, 8
        nop
       
PROCEED:
        ; ****************************************************
        ; Read in a character
        ; ****************************************************
       
        ; Save old link register
        addi r1, r1, -4
        swi r15, r1, 0

        ; Call myGetChar
        brlid r15, myGetChar
        nop

        ; Restore link register
        lwi r15, r1, 0
        addi r1, r1, 4

        ; ****************************************************
        ; Store character in r19 (Save old r19)
        ; ****************************************************
        ; Save old r19
        addi r1, r1, -4
        swi r19, r1, 0
       
        ; Move inputted character into r19
        addi r19, r3, 0

        ; ****************************************************
        ; Write character out
        ; ****************************************************
        ; Save old link register
        addi r1, r1, -4
        swi r15, r1, 0
       
        ; Put inputted character into r5 in order to pass to function
        addi r5, r19, 0

        ; Call myPrintChar
        brlid r15, myPrintChar
        nop

        ; Restore link register
        lwi r15, r1, 0
        addi r1, r1, 4
       
        ; ****************************************************
        ; Restore old r19 and return to callee
        ; ****************************************************
        ; Pop r19 off the stack
        lwi r19, r1, 0
        addi r1, r1, 4
       
        ; Return with success status
        addi r3, r0, SUCCESS_STATUS
        rtsd r15, 8
        nop
       
; ***************************************************************
; Name: myPrintChar
; Purpose: A routine to send a character/message to the UART
; Parameters:
; * r5 holds the character of interest
; Return Values:
; * NONE
; Volatiles:
; * Blows away r5, r6, r7, r8
; ***************************************************************
.globl myPrintChar
myPrintChar:
        ; Put UART's base address into r6
        addi r6, r0, UART_base
       
        ; Move character (byte) into r8 from character parameter (r5)
        addi r8, r5, 0
       
        ; Wait until UART's TX FIFO is not full
       
myPrintCharLoop:
        ; Look up FIFO status
        lwi r7, r6, UART_STATUS_REG_OFFSET

        ; Mask out the TX_FIFO_FLAG
        andi r7, r7, TX_FIFO_FULL

        ; Loop back if it is not-zero
        bnei r7 myPrintCharLoop
        nop
        ; Loop is over

        ; Send character to the FIFO
        swi r8, r6, UART_TX_FIFO_OFFSET
        ; Return from subroutine
        rtsd r15, 8
        nop
       
; ***************************************************************
; Name: myGetChar
; Purpose: A routine to get a character/message from the UART
; Parameters:
; * NONE
; Return Values:
; * r3 will hold the character read in on the UART
; Volatiles:
; * Blows away r5, r6, and r7
; ***************************************************************
.globl myGetChar
myGetChar:
        ; Put UART's base address into r6
        addi r6, r0, UART_base

; Wait until UART's RX FIFO is not empty
myGetCharLoop:
        ; Look up FIFO status
        lwi r7, r6, UART_STATUS_REG_OFFSET

        ; Mask out the RX_FIFO_DATA_VALID_FLAG
        andi r7, r7, RX_FIFO_VALID

        ; Loop back if it is zero
        beqi r7 myGetCharLoop
        nop

        ; Loop is over
        ; Get character from the RX-FIFO
        lwi r3, r6, UART_RX_FIFO_OFFSET

        ; Return from subroutine
        rtsd r15, 8
        nop

; ***********************************************************************************
; Name: myPrintString
; Purpose: A routine to send a string (NULL-terminated set of characters) to the UART
; Parameters:
; * r5 holds a pointer to the string of interest
; Volatiles:
; * Blows away r9, r10
; Notes: Uses myPrintChar to send individual characters to the UART
; *********************************************************************************
.globl myPrintString
myPrintString:
        ; Save r15 to stack (return address of original function call)
        addi r1, r1, -4
        swi r15,r1,0

        ; Save character pointer in r9
        addk r9, r5, r0

        ; Init r10 to first character of the string being passed in
        lbui r10, r9, 0

.globl stringCharLoop
stringCharLoop:
        ; Check loop condition (if r10 = null then function is finished)
        beqi r10, endStringCharLoop
        nop

        ; Increment character pointer (move to next character)
        addi r9, r9, 1
       
        ; Move character to print into r5
        addi r5, r10, 0

        ; Call print function (return address stored in r15)
        brlid r15, myPrintChar
        nop

        ; Load in new character to print (lookup [msgPointer + counter])
        lbui r10, r9, 0
        ; Branch back to loop condition
        bri stringCharLoop
        nop
; **** END OF LOOP ****

.globl endStringCharLoop
endStringCharLoop:
        ; Restore r15 from stack (restore original return address)
        lwi r15,r1,0
        addi r1, r1, 4

        ; Return from subroutine
        rtsd r15, 8
        nop 

Victor Prechtel

Comments

There are currently no comments for this snippet.

Voting

Votes Down