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

📄 lh7a404_uart_driver.c

📁 在sharp 404开发板的串口测试代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/***********************************************************************
 * $Workfile:   lh7a404_uart_driver.c  $
 * $Revision:   1.1  $
 * $Author:   WellsK  $
 * $Date:   Mar 29 2004 14:58:54  $
 *
 * Project: LH7A404 UART driver
 *
 * Description:
 *     This file contains driver support for the UART modules on the
 *     LH7A404
 *
 * Revision History:
 * $Log:   //smaicnt2/pvcs/VM/sharpmcu/archives/sharpmcu/software/csps/lh7a404/source/lh7a404_uart_driver.c-arc  $
 * 
 *    Rev 1.1   Mar 29 2004 14:58:54   WellsK
 * Corrected an issue on transmit where the transmit interrupt
 * would quit working if the transmit FIFO was completely filled.
 * 
 *    Rev 1.0   Jul 01 2003 12:04:26   WellsK
 * 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 "lh7a404_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 1 */
#if UART_1_ENABLE == 1
STATIC UART_CFG_T uart1cfg;
#endif

/* UART device configuration structure for UART 2 */
#if UART_2_ENABLE == 1
STATIC UART_CFG_T uart2cfg;
#endif

/* UART device configuration structure for UART 3 */
#if UART_3_ENABLE == 1
STATIC UART_CFG_T uart3cfg;
#endif

/***********************************************************************
 * 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.
 *
 **********************************************************************/
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->status & UART_STATUS_RXFE) == 0)   ///==0 is not empty
    {
        uartcfg->rb.rx[uartcfg->rb.rx_head] =
            (UNS_8) (uartregs->data & UART_DATA_MASK);

        /* 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->status & UART_STATUS_TXFF) == 0))
    {
        /* Move a piece of data into the transmit FIFO */
        uartregs->data = (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->inte &= ~UART_INTR_TI;
    }
    else
    {
        uartregs->inte |= UART_INTR_TI;
    }
}

/***********************************************************************
 *
 * 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->intr & (UART_INTR_RTI | UART_INTR_RI)) != 0)
    {
        uart_standard_receive(uartcfg);
    }

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

    /* Interrupt was due to a modem service request */
    if ((uartregs->intr & UART_INTR_MI) != 0)
    {
        /* Nothing to do here - add functionality as needed. For now,
           just disable the interrupt so it won't happen again */
        uartregs->inte &= ~UART_INTR_MI;
    }
}

/***********************************************************************
 *
 * 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 *) NULL;

#if UART_1_ENABLE == 1
    if ((UART_REGS_T *) ipbase == UART1)
    {
        /* UART 1 selected */
        uartcfg = &uart1cfg;
    }
#endif

#if UART_2_ENABLE == 1
    if ((UART_REGS_T *) ipbase == UART2)
    {
        /* UART 2 selected */
        uartcfg = &uart2cfg;
    }
#endif

#if UART_3_ENABLE == 1
    if ((UART_REGS_T *) ipbase == UART3)
    {
        /* UART 3 selected */
        uartcfg = &uart3cfg;
    }
#endif

    if (uartcfg != (UART_CFG_T *) NULL)
    {
        /* 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;

            /* The UART is disabled prior to enabling so the FIFOs are
               empty when it is re-enabled */
            uartcfg->regptr->control = UART_CNTL_SIR_DIS;

            /* Enable the UART - all UART registers are reliable only
               then the UART is enabled */
            uartcfg->regptr->control =
                (UART_CNTL_EN | UART_CNTL_SIR_DIS);

            /* Disable interrupts - the interrupts remain off until
                they are enabled */
            uartcfg->regptr->inte = 0;

            /* Initialize the ring buffers */
            uartcfg->rb.tx_head = uartcfg->rb.tx_tail = 0;
            uartcfg->rb.rx_head = uartcfg->rb.rx_tail = 0;

            /* Set default UART configuration to FIFO enabled, 1 stop
               bit, no parity, and 8 data bits */
            uartcfg->regptr->lcr = (UART_LCR_WLEN8 | UART_LCR_FEN |
                UART_LCR_STP1 | UART_LCR_PNONE);

            /* Set default baud rate to 9600bps */
            uartcfg->regptr->bcr = (UNS_32) UART_BCR_9600;
        }
    }

    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)
    {
        /* Disable UART */
        uartcfgptr->regptr->control = UART_CNTL_SIR_DIS;

        status = _NO_ERROR;
        uartcfgptr->init = FALSE;
    }

    return status;
}

/***********************************************************************
 *
 * Function: uart_ioctl
 *
 * Purpose: UART configuration block
 *
 * Processing:
 *     This function is a large case block. Based on the passed function
 *     and option values, set or get the appropriate UART parameter.
 *
 * Parameters:
 *     devid: Pointer to UART config structure
 *     cmd:   ioctl command
 *     arg:   ioctl argument
 *
 * Outputs: None
 *
 * Returns: The status of the ioctl operation
 *
 * Notes: None
 *
 **********************************************************************/
STATUS uart_ioctl(INT_32 devid,
                  INT_32 cmd,
                  INT_32 arg)
{
    UNS_32 tmp1;
    UART_REGS_T *uartregs;
    UART_CFG_T *uartcfgptr = (UART_CFG_T *) devid;
    STATUS status = _ERROR;

    if (uartcfgptr->init == TRUE)
    {
        status = _NO_ERROR;
        uartregs = uartcfgptr->regptr;

        switch (cmd)
        {

⌨️ 快捷键说明

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