⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lh79520_uart_driver.c

📁 Sharp Lh79520 Uart驱动源码.
💻 C
📖 第 1 页 / 共 3 页
字号:
/***********************************************************************
 * $Workfile:   lh79520_uart_driver.c  $
 * $Revision:   1.0  $
 * $Author:   LiJ  $
 * $Date:   Jul 07 2003 16:40:02  $
 *
 * Project: LH79520 UART driver
 *
 * Description:
 *     This file contains driver support for the UART modules on the
 *     LH79520.
 *
 * Revision History:
 * $Log:   //smaicnt2/pvcs/VM/sharpmcu/archives/sharpmcu/software/csps/lh79520/source/lh79520_uart_driver.c-arc  $
 * 
 *    Rev 1.0   Jul 07 2003 16:40:02   LiJ
 * Initial revision.
 * 
 * 
 *
 ***********************************************************************
 * SHARP MICROELECTRONICS OF THE AMERICAS MAKES NO REPRESENTATION
 * OR WARRANTIES WITH RESPECT TO THE PERFORMANCE OF THIS SOFTWARE,
 * AND SPECIFICALLY DISCLAIMS ANY RESPONSIBILITY FOR ANY DAMAGES, 
 * SPECIAL OR CONSEQUENTIAL, CONNECTED WITH THE USE OF THIS SOFTWARE.
 *
 * SHARP MICROELECTRONICS OF THE AMERICAS PROVIDES THIS SOFTWARE SOLELY 
 * FOR THE PURPOSE OF SOFTWARE DEVELOPMENT INCORPORATING THE USE OF A 
 * SHARP MICROCONTROLLER OR SYSTEM-ON-CHIP PRODUCT. USE OF THIS SOURCE
 * FILE IMPLIES ACCEPTANCE OF THESE CONDITIONS.
 *
 * COPYRIGHT (C) 2001 SHARP MICROELECTRONICS OF THE AMERICAS, INC.
 *     CAMAS, WA
 **********************************************************************/

#include "lh79520_iocon.h"
#include "lh79520_rcpc.h"
#include "lh79520_uart_driver.h"

/***********************************************************************
 * UART driver private data and types
 **********************************************************************/

/* UART Ring buffer structure */
typedef struct
{
    UNS_8  tx[UART_RING_BUFSIZE];  /* UART Tx data ring buffer */
    UNS_8  rx[UART_RING_BUFSIZE];  /* UART Rx data ring buffer */
    INT_32 tx_head;                /* UART Tx ring buffer head index */
    INT_32 tx_tail;                /* UART Tx ring buffer tail index */
    INT_32 rx_head;                /* UART Rx ring buffer head index */
    INT_32 rx_tail;                /* UART Rx ring buffer tail index */
} UART_RING_BUFFER_T;

/* UART device configuration structure type */
typedef struct
{
    BOOL_32 init;          /* Device initialized flag */
    UART_RING_BUFFER_T rb; /* Device ring buffer */
    UART_REGS_T *regptr;   /* Pointer to UART registers */
} UART_CFG_T;

/* UART device configuration structure for UART 0 */
STATIC UART_CFG_T uart0cfg;
/* UART device configuration structure for UART 1 */
STATIC UART_CFG_T uart1cfg;
/* UART device configuration structure for UART 2 */
STATIC UART_CFG_T uart2cfg;

/***********************************************************************
 * UART driver private functions
 **********************************************************************/

/***********************************************************************
 *
 * Function: uart_standard_receive
 *
 * Purpose: Common UART receive function
 *
 * Processing:
 *     While the UART receive FIFO not empty status is set, read a data
 *     value from the FIFO and place it into the receive ring buffer
 *     indexed by the head pointer. Increment the head pointer and reset
 *     it to the start of the ring buffer if it overflows. Continue
 *     until the FIFO is empty.
 *
 * Parameters:
 *     uartcfg: Pointer to UART config structure
 *
 * Outputs: None
 *
 * Returns: Nothing
 *
 * Notes:
 *     There is no protection against overflowing the ring buffer.
 *     This function is called by UART interruption handler.
 *
 **********************************************************************/
STATIC void uart_standard_receive(UART_CFG_T *uartcfg)
{
    UART_REGS_T *uartregs = uartcfg->regptr;

    /* Continue stuffing the receive ring FIFO until the receive FIFO
       is empty */
    while ((uartregs->fr & UARTFR_RXFE) == 0)
    {
        uartcfg->rb.rx[uartcfg->rb.rx_head] = 
            (UNS_8) (uartregs->dr & UARTDR_DATA);

        /* Increment receive ring buffer head pointer */
        uartcfg->rb.rx_head++;
        if (uartcfg->rb.rx_head >= UART_RING_BUFSIZE)
        {
            uartcfg->rb.rx_head = 0;
        }
    }
}

/***********************************************************************
 *
 * Function: uart_standard_transmit
 *
 * Purpose: Common UART transmit function
 *
 * Processing:
 *     While the UART transmit FIFO not full status is set and there is
 *     data to transmit in the ring buffer, write a data value from the
 *     ring buffer into the transmit FIFO. Increment the transmit ring
 *     buffer tail pointer and reset it to the start of the ring buffer
 *     if it overflows. Continue until the transmit FIFO is full or the
 *     ring buffer is empty. If all the data has been transmitted from
 *     the ring buffer, disable the transmit interrupt, otherwise
 *     (re)enable it.
 *
 * Parameters:
 *     uartcfg: Pointer to UART config structure
 *
 * Outputs: None
 *
 * Returns: Nothing
 *
 * Notes: None
 *
 **********************************************************************/
STATIC void uart_standard_transmit(UART_CFG_T *uartcfg)
{
    UART_REGS_T *uartregs = uartcfg->regptr;

    /* Continue stuffing the transmit FIFO until it is full, or until
       the ring buffers are empty */
    while ((uartcfg->rb.tx_head != uartcfg->rb.tx_tail)
        && ((uartregs->fr & UARTFR_TXFF) == 0))
    {
        /* Move a piece of data into the transmit FIFO */
        uartregs->dr = (UNS_32)
            uartcfg->rb.tx[uartcfg->rb.tx_tail];

        /* Update transmit ring FIFO tail pointer */
        uartcfg->rb.tx_tail++;
        if (uartcfg->rb.tx_tail >= UART_RING_BUFSIZE)
        {
            uartcfg->rb.tx_tail = 0;
        }
    }

    /* If there is no more data to send, disable the transmit
       interrupt - else enable it or keep it enabled */
    if (uartcfg->rb.tx_head == uartcfg->rb.tx_tail)
    {
        uartregs->imsc &= ~UARTINT_TX;
    }
    else
    {
        uartregs->imsc |= UARTINT_TX;
    }
}

/***********************************************************************
 *
 * Function: uart_standard_interrupt
 *
 * Purpose: Common UART interrupt function
 *
 * Processing:
 *     If the UART receive interrupt or receive timeout interrupt has
 *     occurred, call the uart_standard_receive function. If the UART
 *     transmit interrupt has occurred, call the uart_standard_transmit
 *     function. If the UART modem status interrupt has occurred,
 *     disable the modem status interrupt.
 *
 * Parameters:
 *     uartcfg: Pointer to UART config structure
 *
 * Outputs: None
 *
 * Returns: Nothing
 *
 * Notes: None
 *
 **********************************************************************/
STATIC void uart_standard_interrupt(UART_CFG_T *uartcfg)
{
    UART_REGS_T *uartregs = uartcfg->regptr;

    /* Interrupt was due to a receive data FIFO service request */
    if ((uartregs->mis & (UARTINT_RX | UARTINT_RT)) != 0)
    {
        uart_standard_receive(uartcfg);
    }

    /* Interrupt was due to a transmit data FIFO service request */
    if ((uartregs->mis & UARTINT_TX) != 0)
    {
        uart_standard_transmit(uartcfg);
    }
}

/***********************************************************************
 *
 * Function: uart_get_free_tx_count
 *
 * Purpose: Return the amount of free space in the transmit ring buffer
 *
 * Processing:
 *     Compute a count value by subtracting the transmit ring buffer
 *     tail index from the head index. If the value is less than 0,
 *     then recompute the count value adding the head index to the
 *     total ring buffer size minus the tail index. Return the number
 *     of free entries left in the ring buffer by subtracting the
 *     (count + 1) from the total ring buffer size.
 *
 * Parameters:
 *     uartcfg: Pointer to UART config structure
 *
 * Outputs: None
 *
 * Returns: The number of free bytes in the transmit ring buffer
 *
 * Notes: None
 *
 **********************************************************************/
STATIC INT_32 uart_get_free_tx_count(UART_CFG_T *uartcfg)
{
    INT_32 count = 0;

    count = uartcfg->rb.tx_head - uartcfg->rb.tx_tail;
    if (count < 0)
    {
        /* head pointer has flipped to start of ring */
        count = (UART_RING_BUFSIZE - uartcfg->rb.tx_tail) +
            uartcfg->rb.tx_head;
    }

    return (UART_RING_BUFSIZE - count - 1);
}

/***********************************************************************
 * UART driver public functions
 **********************************************************************/

/***********************************************************************
 *
 * Function: uart_open
 *
 * Purpose: Open a UART
 *
 * Processing:
 *     Determine the UART configuration structure to use based on the
 *     paseed arg value. If the arg value doesn't match an available
 *     UART, return NULL to the caller. Otherwise, check the status of
 *     the init flag. If it is TRUE, return NULL to the caller.
 *     Otherwise, set init to TRUE and save the pointe to the UART
 *     registers. Disable the UART to clear the UART FIFOs. Re-enable
 *     the UART is UART mode (vs SIR mode). Disable UART interrupts.
 *     Set the receive and reansmit ring buffers to empty by setting
 *     the head and tail pointers to 0. Enable the UART is 9600-N-8-1
 *     mode with FIFOs enabled and return the pointer to the UART
 *     config structure to the caller.
 *
 * Parameters:
 *     ipbase: UART descriptor device address
 *     arg   : Not used
 *
 * Outputs: None
 *
 * Returns: The pointer to a UART config structure or 0
 *
 * Notes: None
 *
 **********************************************************************/
INT_32 uart_open(void *ipbase, INT_32 arg)
{
    UART_CFG_T *uartcfg;

    /* Invalid or disabled UART */
    uartcfg = (UART_CFG_T *)(0x0);

    if ((UART_REGS_T *) ipbase == UART0)
    {
        /* UART 0 selected */
        uartcfg = &uart0cfg;
    }
    
    if ((UART_REGS_T *) ipbase == UART1)
    {
        /* UART 1 selected */
        uartcfg = &uart1cfg;
    }
    
    if ((UART_REGS_T *) ipbase == UART2)
    {
        /* UART 2 selected */
        uartcfg = &uart2cfg;
    }
    
    if (uartcfg != (UART_CFG_T *)(0x0))
    {
        /* Valid UART selected, has it been previously initialized? */
        if (uartcfg->init == FALSE)
        {
            /* Device not initialized and it is usable, so set it to
               used */
            uartcfg->init = TRUE;

            /* Save address of register block */
            uartcfg->regptr = (UART_REGS_T *) ipbase;

            if ((UART_REGS_T *) ipbase == UART0)
            {
                /* UART0 selected */
                /* Enable UART pins on muxed lines for UART0 
                (make sure they are not SIR) */
                IOCON->uartmux = IOCON->uartmux |
                    (UARTMUX_U0RXD | UARTMUX_U0TXD);
                /* Enable the selected UART clock in the RCPC. The 
                clock selection is the internal clock (14.7x MHz / 2) */
                RCPC->periphclkctrl = RCPC->periphclkctrl &
                    ~(0x1 << 0);
                RCPC->periphclksel = RCPC->periphclksel &
                    ~(0x1 << 0);
            }
            else if ((UART_REGS_T *) ipbase == UART1)
            {
                /* UART1 selected */
                /* Enable UART pins on muxed lines for UART1 */
                IOCON->uartmux = IOCON->uartmux |
                    (UARTMUX_U1RXD | UARTMUX_U1TXD);
                /* Enable the selected UART clock in the RCPC. The 
                clock selection is the internal clock (14.7x MHz / 2) */
                RCPC->periphclkctrl = RCPC->periphclkctrl &
                    ~(0x1 << 1);
                RCPC->periphclksel = RCPC->periphclksel &
                    ~(0x1 << 1);
            }
            else
            {
                /* UART2 selected */
                /* Enable UART pins on muxed lines for UART2 */
                IOCON->ssimux = IOCON->ssimux |
                    (SSIMUX_UT2RXD | SSIMUX_UT2TXD);
                /* Enable the selected UART clock in the RCPC. The 
                clock selection is the internal clock (14.7x MHz / 2) */
                RCPC->periphclkctrl = RCPC->periphclkctrl &
                    ~(0x1 << 2);
                RCPC->periphclksel = RCPC->periphclksel &
                    ~(0x1 << 2);
            }

            /* Set default baud rate as 115200 bps */
            uartcfg->regptr->ibrd = UARTBRINT_115200;
            uartcfg->regptr->fbrd = 0;

            /* Set 1 stop bits, 8-bit word length, No parity, stick 
            parity disabled, FIFO enabled */
            uartcfg->regptr->lcr_h = UARTLCR_FEN | UARTLCR_WLEN8;
                                        
            /* Set RX and TX interrupt FIFO levels to 50% */
            uartcfg->regptr->ifls = UARTIFLS_TX (2) | UARTIFLS_RX (2);
            
            /* Clear any pending interrupts for the UART */
            uartcfg->regptr->icr = (UARTINT_RX | UARTINT_TX |
                UARTINT_RT | UARTINT_FE | UARTINT_PE | UARTINT_BE | 
                UARTINT_OE);
            
            /* Disable all the UART interrupt by default */
            uartcfg->regptr->imsc = 0;
            
            /* Disable CTS/RTS flow control, enable receiver/
            transmitter, enable UART */
            uartcfg->regptr->cr = UARTCR_TXE | UARTCR_RXE |
                UARTCR_ENABLE;
            
            /* Initialize the ring buffers */
            uartcfg->rb.tx_head = uartcfg->rb.tx_tail = 0;
            uartcfg->rb.rx_head = uartcfg->rb.rx_tail = 0;

        }
    }

    return (INT_32) uartcfg;
}

/***********************************************************************
 *
 * Function: uart_close
 *
 * Purpose: Close a UART
 *
 * Processing:
 *     If init is not TRUE, then return _ERROR to the caller as the
 *     device was not previously opened. Otherwise, disable the UART,
 *     set init to FALSE, and return _NO_ERROR to the caller.
 *
 * Parameters:
 *     devid: Pointer to UART config structure
 *
 * Outputs: None
 *
 * Returns: The status of the close operation
 *
 * Notes: None
 *
 **********************************************************************/
STATUS uart_close(INT_32 devid)
{
    UART_CFG_T *uartcfgptr = (UART_CFG_T *) devid;
    STATUS status = _ERROR;

    if (uartcfgptr->init == TRUE)
    {
        /* Clear any pending interrupts for the UART */
        uartcfgptr->regptr->icr = 0xff;
            
        /* Disable all the UART interrupts */
        uartcfgptr->regptr->imsc = 0;
            
        /* Disable UART */
        uartcfgptr->regptr->cr = 0;
        
        if ((UART_REGS_T *) uartcfgptr->regptr == UART0)
        {
            /* UART0 selected */
            /* Disable UART pins on muxed lines for UART0 */
            IOCON->uartmux &= ~(UARTMUX_U0RXD | UARTMUX_U0TXD);
            /* Disable the selected UART clock in the RCPC. */
            RCPC->periphclkctrl = RCPC->periphclkctrl | (0x1 << 0);
        }
        else if ((UART_REGS_T *) uartcfgptr->regptr == UART1)
        {
            /* UART1 selected */
            /* Disable UART pins on muxed lines for UART1 */
            IOCON->uartmux &= ~(UARTMUX_U1RXD | UARTMUX_U1TXD);
            /* Disable the selected UART clock in the RCPC. */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -