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

📄 lh79524_uart_driver.c

📁 SHARP_ARM720T_LH79524/5软件开发包_支持TFT_LCD_NAND_FLASH_ETH_USB
💻 C
📖 第 1 页 / 共 2 页
字号:
/***********************************************************************
 * $Workfile:   lh79524_uart_driver.c  $
 * $Revision:   1.0  $
 * $Author:   ZhangJ  $
 * $Date:   Oct 20 2004 09:48:58  $
 * 
 * Project: LH79524 CSP library
 * 
 * Description: 
 *      This file contains the implementation of the LH79524 UART driver
 *      for UARTS 0, 1 and 2.
 * 
 * 
 * Revision History: 
 * $Log::   //smaicnt2/pvcs/VM/sharpmcu/archives/sharpmcu/software/csps$ 
 * 
 *    Rev 1.0   Oct 20 2004 09:48:58   ZhangJ
 * Initial revision.
 * 
 *    Rev 1.1   Jul 20 2004 16:50:32   PattamattaD
 * Updated comments.
 * 
 *    Rev 1.0   Jun 15 2004 14:01:58   PattamattaD
 * Initial revision.
 * 
 * 
 * 
 *********************************************************************** 
 * 
 *  Copyright (c) 2004 Sharp Microelectronics of the Americas 
 * 
 *  All rights reserved 
 * 
 *  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. 
 * 
 **********************************************************************/
#include "lh79524_iocon.h"
#include "lh79524_rcpc.h"
#include "lh79524_uart_driver.h"
 
/* Serial driver interrupt priorities */
typedef enum
{
  UART_TX_POS = 0,
  UART_RX_POS,
  UART_RT_POS,
  UART_FE_POS,
  UART_PE_POS,
  UART_BE_POS,
  UART_OE_POS
} UART_INT_PRIO_T;

/* Defines for the ip block base address and driver control object */
#define REGS_T   UART_REGS_T
#define DRIVER_T SERIAL_T

/* Forward declarations of private methods */
static void uart0_enable (BOOL_32 enable); 
static void uart1_enable (BOOL_32 enable); 
static void uart2_enable (BOOL_32 enable); 
static void uart0_isr (void); 
static void uart1_isr (void); 
static void uart2_isr (void); 
static void uart_isr (void*);
static void uart_rx_isr (void*);
static void uart_tx_isr (void*);
static void uart_err_isr (void*, INT_32);

/* Table of device base addresses */
static UNS_32 driverid[N_UARTS] = 
{
  UART0_BASE, /* uart0 base address */ 
  UART1_BASE, /* uart1 base address */
  UART2_BASE  /* uart2 base address */
};

/* Instansiations of the driver control object */
static DRIVER_T driver[N_UARTS];

/* Address of the driver control objects */
static DRIVER_T* pdriver[N_UARTS] = 
{
  (DRIVER_T*)&driver[0],
  (DRIVER_T*)&driver[1],
  (DRIVER_T*)&driver[2]
};

/* Address of the driver interrupt handlers  */
static void* driver_isr[N_UARTS] =
{
  (void*)uart0_isr,
  (void*)uart1_isr,
  (void*)uart2_isr
};

/***********************************************************************
* 
* Function: uart_open
* 
* Purpose: 
*  Initialize the specified 16C550 UART with the paramters specified.
* 
* Processing: 
*  Sets up the device control structure for the UART.
*
* Parameters: 
*  uart  - uart to open
*  arg   - XTAL System clock
* 
* Outputs: 
*  None
* 
* Returns: 
*  device id or 0
* 
* Notes: 
*  None
* 
**********************************************************************/

INT_32 uart_open (INT_32 ipbase, INT_32 arg)
{
  DRIVER_T* pdev       = NULL;      
  INT_32    dev_exists = FALSE;
  INT_32    devid      = 0;
  CHAR*     dst        = NULL;
  INT_32    idx        = 0;
  REGS_T*   pregs      = NULL;
  
  /* Find the device in the device table */
  for (devid = 0; devid < NELEMENTS(driver); devid++)
  {
    /* Do we have a match */
    if (ipbase == driverid[devid])
    {
      /* Found the device */
      dev_exists = TRUE;
      break;
    }
  }
  /* Check to make sure that the device exists */
  if (dev_exists == FALSE)
  {
    return (0);
  }
  
  /* Attach to the base address of the serial device */
  pdev = (DRIVER_T*)pdriver[devid];
  
  /* Make sure the device is not already opened */
  if (pdev->init == TRUE)
  {
    /* Device has already been opened */
    return (0);
  }
  
  /* Clear the serial driver control structure */
  dst = (CHAR*)pdev;
  for (idx = 0; idx < sizeof (DRIVER_T); idx++)
  {
    *dst++ = 0;
  }
  
  /* Attach to the base address of the selected uart */
  pdev->regs = (void*)driverid[devid];
  pregs      = (REGS_T*)pdev->regs;
  
  /*set the XTAL system clock */
  pdev->cfg.sys_clk = (UNS_32)arg;
  
  /* Init the uart clock and pin muxing (RX/TX lines) */
  switch(devid)
  {
  case 0:
    uart0_enable(TRUE);
    break;
  case 1:
    uart1_enable(TRUE);
    break;
  case 2:
    uart2_enable(TRUE);
    break;
  }
  
  /* Init the dma buffers */
  pdev->rx_dma = NULL; 
  pdev->tx_dma = NULL;
  
  /* Bind to the tx and rx ring buffers data sections */
  pdev->rx_id.data = (CHAR*)&pdev->rx_data[0];
  pdev->tx_id.data = (CHAR*)&pdev->tx_data[0];
  
  /* Init the ring buffers that are to be used for buffer IO */
  RING_INIT (&pdev->rx_id, NELEMENTS(pdev->rx_data));
  RING_INIT (&pdev->tx_id, NELEMENTS(pdev->tx_data));
  
  /* Mask all uart interrupts at the source */
  pregs->imsc = UART_IMASK_ALL;
  
  /* Clear any pending errors */
  pregs->rsr_ecr = UART_ECR_CLEAR;
  
  /* clear any pending interrupts  */
  pregs->icr = UART_CLR_ALL;
  
  /* Install the interrupt handlers */
  pdev->isr[UART_TX_POS] = (PFV)uart_tx_isr;
  pdev->isr[UART_RX_POS] = (PFV)uart_rx_isr;
  pdev->isr[UART_RT_POS] = (PFV)uart_rx_isr;
  pdev->isr[UART_FE_POS] = (PFV)uart_err_isr;
  pdev->isr[UART_PE_POS] = (PFV)uart_err_isr;
  pdev->isr[UART_BE_POS] = (PFV)uart_err_isr;
  pdev->isr[UART_OE_POS] = (PFV)uart_err_isr;
  
  /* Save the default handler isr */
  pdev->irq_hdlr = driver_isr[devid];
  
  /* set the device in default config state 115200-8-N-1*/
  pregs->ibrd = UART_BRINT(pdev->cfg.sys_clk, 115200);
  pregs->fbrd = UART_BRFRAC(pdev->cfg.sys_clk, 115200);
  pdev->cfg.baud_rate = 115200;
  pregs->lcr_h = UART_LCR_WLEN8;
  
  /* Mark the device as open */
  pdev->init = TRUE;
  
  /* return device id */
  return ((INT_32)pdev);
}

/***********************************************************************
* 
* Function: uart_close
* 
* Purpose: 
*  Turn the driver off
* 
* Processing: 
*  This routine flushes the device, disables interrupts, disables the
*  device, and marks it as closed.
*
* Parameters: 
*  devid - device id (UART0 or UART1)
* 
* Outputs: 
*  None
* 
* Returns: 
*  _NO_ERROR if device is closed successfully.
*  _ERROR otherwise.
* 
* Notes: None
* 
**********************************************************************/

STATUS uart_close (INT_32 devid)
{
  STATUS    status = _NO_ERROR;
  INT_32    arg    = 0;
  INT_32    idx    = 0;
  CHAR*     dst    = NULL;
  DRIVER_T* pdev   = NULL;
  
  /* Sanity check */
  if (devid == 0)
  {
    /* device not opened or non-valid file handle */
    return (_ERROR);
  }
  
  /* Bind to the device control structure */
  pdev = (DRIVER_T*)devid;
  
  /* Make sure the device is already opened */
  if (pdev->init == FALSE)
  {
    return (_ERROR);
  }
  
  /* Flush the device */
  (void) uart_ioctl (devid, UART_FLUSH, 0);
  
  /* Disable the rx and tx sections */
  (void) uart_ioctl (devid, UART_DISABLE_TX, 0);
  (void) uart_ioctl (devid, UART_DISABLE_RX, 0);
  
  /* Mask (Disable) off the interrupts */
  arg = UART_INT_TX | UART_INT_RX | 
    UART_INT_RT | UART_INT_FE | 
    UART_INT_PE | UART_INT_BE | 
    UART_INT_OE;
  uart_ioctl (devid, UART_DISABLE_INT, arg);
  
  /* Un-install the interrupts */
  pdev->isr[UART_TX_POS] = NULL;
  pdev->isr[UART_RX_POS] = NULL;
  pdev->isr[UART_RT_POS] = NULL;
  pdev->isr[UART_FE_POS] = NULL;
  pdev->isr[UART_PE_POS] = NULL;
  pdev->isr[UART_BE_POS] = NULL;
  pdev->isr[UART_OE_POS] = NULL;
  
  /* Turn the device off */
  (void) uart_ioctl (devid, UART_STOP, 0);
  
  /* Disable the uart clock and pin muxing (RX/TX lines) */
  switch(devid)
  {
  case 0:
    uart0_enable(FALSE);
    break;
  case 1:
    uart1_enable(FALSE);
    break;
  case 2:
    uart2_enable(FALSE);
    break;
  }
  
  /* Invalidate the device */
  pdev->init = FALSE;
  
  /* Clear the serial driver control structure */
  dst = (CHAR*)pdev;
  for (idx = 0; idx < sizeof (DRIVER_T); idx++)
  {
    *dst++ = 0;
  }
  
  /* Done */
  return (status);
}

/***********************************************************************
* 
* Function: uart_read
* 
* Purpose: 
*  Read the specified UART data.
* 
* Processing: 
*  Checks to see if the device is running in polled or interrupt mode.
*  In polled mode data is read directly from the uart rx fifo, while
*  in interrupt mode data is read from a ring buffer. Data is read 
*  until ring buffer is empty, the rx fifo is empty, or the max
*  number of bytes has been read. 
*
* Parameters: 
*  devid      - device id (UART0 or UART1)
*  buffer     - data buffer
*  max_bytes  - maximum number of bytes to read
* 
* Outputs: 
*  None
* 
* Returns: 
*  n_bytes - the actual number of bytes read 
*  
* Notes: 
*  None
* 
**********************************************************************/

INT_32 uart_read (INT_32 devid, 
                  CHAR*  buffer, 
                  INT_32 max_bytes)
{
  INT_32    n_bytes = 0;   
  DRIVER_T* pdev    = NULL;
  REGS_T*   pregs   = NULL;
  
  /* Sanity check */
  if ((buffer == NULL) || (devid == 0))
  {
    /* Null pointer */
    return (0);
  }
  
  /* Bind to the device control structure */
  pdev = (DRIVER_T*)devid;
  
  /* Make sure the device is already opened */
  if (pdev->init == FALSE)
  {
    return (0);
  }
  
  /* Attach to the base address of the selected uart (0 or 1) */
  pregs = (REGS_T*)pdev->regs;
  
  /* Check to see if we are in polled or interrupt mode */
  if (pdev->cfg.poll_mode == TRUE)
  {
    /* Read data from the receive buffer */
    for (n_bytes = 0; n_bytes < max_bytes; n_bytes++)
    {
      /* Make sure there is data in the receive fifo */
      if ((pregs->fr & UART_FR_RXFE) == 
        UART_FR_RXFE)
      {
        /* No more data */
        break;
      }
      /* Read data from the device */
      *buffer++ = pregs->dr;
    }  
  }
  else
  {
    /* get the data from the device */
    for (n_bytes = 0; n_bytes < max_bytes; n_bytes++)
    {
      /* Is there data in the ring buffer */
      if (RING_COUNT (&pdev->rx_id) != 0)
      {
        /* Add the data to the ring buffer */
        RING_GETC (&pdev->rx_id, *buffer++);
      }
      else
      {
        /* break out and return the number of bytes written */ 
        break;
      }
    }
  }
  
  /* return */
  return (n_bytes);
}

/***********************************************************************
* 
* Function: uart_write
* 
* Purpose: 
*  Write data to the UART.
* 
* Processing: 
*
* Parameters: 
*  devid   - device id (UART0 or UART1)
*  buffer  - data buffer 
*  n_bytes - number of bytes to write.
* 
* Outputs: 
*  None
* 
* Returns: 
*  actual_bytes - number of bytes written.
* 
* Notes: 
*  None
* 
**********************************************************************/

INT_32 uart_write (INT_32 devid, 
                   CHAR*  buffer, 
                   INT_32 n_bytes)
{
  UNS_32    actual_bytes = 0;   
  DRIVER_T* pdev         = NULL;
  REGS_T*   pregs        = NULL;
  
  /* Sanity check */
  if ((buffer == NULL) || (devid == 0))
  {
    /* Null pointer */
    return (0);
  }
  
  /* Bind to the device control structure */
  pdev = (DRIVER_T*)devid;
  
  /* Make sure the device is already opened */
  if (pdev->init == FALSE)
  {
    return (0);
  }
  
  /* Attach to the base address of the selected uart (0 or 1) */
  pregs = (REGS_T*)pdev->regs;
  
  /* Check to see if we are in polled or interrupt mode */
  if (pdev->cfg.poll_mode == TRUE)
  {
    /* Write the data into the transmit buffer */
    for (actual_bytes = 0; actual_bytes < n_bytes; actual_bytes++)
    {
      /* Wait for the transmit fifo to drain */
      while ((pregs->fr & UART_FR_TXFF) 
        == UART_FR_TXFF); 
      /* Write the data to the device */
      pregs->dr = *buffer++;
    }  
  }
  else
  {
    /* Lock the system irq */
    /*INT_LOCK();*/
    
    /* Clear pending interrupts */
    pregs->icr = UART_INT_TX;
    
    /* Write data into the transmit ring buffer */
    for (actual_bytes = 0; actual_bytes < n_bytes; actual_bytes++)
    {
      /* Load the ring buffer */
      RING_PUTC (&pdev->tx_id, *buffer++);
    }
    
    /* Kick start the tranasmitter */
    while ( (RING_COUNT(&pdev->tx_id) != 0) &&
      !(pregs->fr & UART_FR_TXFF) )      
    {
      /* Write the data to the Tx fifo */
      RING_GETC (&pdev->tx_id, pregs->dr);
    }
    
    /* UnMask (Enable) the tx interrupt */
    (void) uart_ioctl 
      (devid, UART_ENABLE_INT, UART_INT_TX);
    
    /* Enable the uart transmitter */
    (void) uart_ioctl (devid, UART_ENABLE_TX, 0);
    
    /* Unlock the system irq */
    /*INT_UNLOCK();*/
  }
  
  /* Return number of bytes written */
  return (actual_bytes);
}

/***********************************************************************
* 
* Function: uart_ioctl
* 
* Purpose: 
*  handle uart control requests.
* 
* Processing: Set/resets designated state in the device.
*  
*
* Parameters:
*  devid - device id
*  cmd   - request to process
*  arg   - generic argument 
* 
* Outputs: None
* 
* Returns: 
*  _NO_ERROR if device controlled successfully.
*  _ERROR otherwise.
* 
* Notes: None
* 
**********************************************************************/
                   
STATUS uart_ioctl (INT_32 devid, 
                   INT_32 cmd, 
                   INT_32 arg)
{
  UNS_32    temp   = 0; 
  INT_32    status = _NO_ERROR; 
  REGS_T*   pregs  = NULL;
  DRIVER_T* pdev   = NULL;
  
  /* Sanity check */
  if (devid == 0)
  {
    /* Null pointer */
    return (0);
  }
  
  /* Attach to the base address of the serial device */
  pdev = (DRIVER_T*)devid;
  
  /* Make sure the device is already opened */
  if (pdev->init == FALSE)
  {
    return (_ERROR);
  }
  
  /* Attach to the base address of the selected uart (0 or 1) */
  pregs = (REGS_T*)pdev->regs;
  
  /* Service the users request */
  switch (cmd)
  {
    /* Get and set requests for the baud rate */
  case UART_SET_BAUD_RATE:
    /* Save the new baud rate */
    pregs->ibrd = UART_BRINT(pdev->cfg.sys_clk,arg);
    pregs->fbrd = UART_BRFRAC(pdev->cfg.sys_clk,arg);
    /* 
    * read and write lcr_h to ensure baud 
    * divisors are set 
    */
    temp = pregs->lcr_h;
    pregs->lcr_h = temp;
    /* Save the config data */
    pdev->cfg.baud_rate = arg;
    break;
    
    /* Get the baud rate */
  case UART_GET_BAUD_RATE:
    if ((void*)arg == NULL)
    {
      status = _ERROR;
      break;
    }
    *(INT_32*)arg = pdev->cfg.baud_rate;
    break;
    
    /* Set tx fifo level */
  case UART_SET_TX_FIFO_LVL:
    temp = pregs->ifls;
    temp &= UART_TX_FIFO_MASK;
    temp |= ((UNS_32)arg<<0);
    pregs->ifls = temp; 
    /* Save the config data */
    pdev->cfg.tx_fifo_depth = arg;

⌨️ 快捷键说明

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