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

📄 c5471_serial.c

📁 這是一個實時嵌入式作業系統 實作了MCS51 ARM等MCU
💻 C
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************** * c5471/c5471_serial.c * *   Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. *   Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. * 3. Neither the name NuttX nor the names of its contributors may be *    used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************//**************************************************************************** * Included Files ****************************************************************************/#include <nuttx/config.h>#include <sys/types.h>#include <unistd.h>#include <semaphore.h>#include <string.h>#include <errno.h>#include <debug.h>#include <nuttx/irq.h>#include <nuttx/arch.h>#include <nuttx/serial.h>#include <arch/serial.h>#include "up_arch.h"#include "os_internal.h"#include "up_internal.h"/**************************************************************************** * Definitions ****************************************************************************/#define BASE_BAUD     115200#if defined(CONFIG_UART_IRDA_HWFLOWCONTROL) || defined(CONFIG_UART_MODEM_HWFLOWCONTROL)# define CONFIG_UART_HWFLOWCONTROL#endif/**************************************************************************** * Private Types ****************************************************************************/struct uart_regs_s{  uint32  ier;  uint32  lcr;  uint32  fcr;#ifdef CONFIG_UART_HWFLOWCONTROL  uint32  efr;  uint32  tcr;#endif};struct up_dev_s{  unsigned int         uartbase;	/* Base address of UART registers */  unsigned int         baud_base;	/* Base baud for conversions */  unsigned int         baud;		/* Configured baud */  ubyte                xmit_fifo_size;	/* Size of transmit FIFO */  ubyte                irq;		/* IRQ associated with this UART */  ubyte                parity;		/* 0=none, 1=odd, 2=even */  ubyte                bits;		/* Number of bits (7 or 8) */#ifdef CONFIG_UART_HWFLOWCONTROL  boolean              flowcontrol;	/* TRUE: Hardware flow control					 * is enabled. */#endif  boolean              stopbits2;	/* TRUE: Configure with 2					 * stop bits instead of 1 */  struct uart_regs_s   regs;		/* Shadow copy of readonly regs */};/**************************************************************************** * Private Function Prototypes ****************************************************************************/static int     up_setup(struct uart_dev_s *dev);static void    up_shutdown(struct uart_dev_s *dev);static int     up_attach(struct uart_dev_s *dev);static void    up_detach(struct uart_dev_s *dev);static int     up_interrupt(int irq, void *context);static int     up_ioctl(struct file *filep, int cmd, unsigned long arg);static int     up_receive(struct uart_dev_s *dev, unsigned int *status);static void    up_rxint(struct uart_dev_s *dev, boolean enable);static boolean up_rxavailable(struct uart_dev_s *dev);static void    up_send(struct uart_dev_s *dev, int ch);static void    up_txint(struct uart_dev_s *dev, boolean enable);static boolean up_txready(struct uart_dev_s *dev);static boolean up_txempty(struct uart_dev_s *dev);/**************************************************************************** * Private Variables ****************************************************************************/struct uart_ops_s g_uart_ops ={  .setup          = up_setup,  .shutdown       = up_shutdown,  .attach         = up_attach,  .detach         = up_detach,  .ioctl          = up_ioctl,  .receive        = up_receive,  .rxint          = up_rxint,  .rxavailable    = up_rxavailable,  .send           = up_send,  .txint          = up_txint,  .txready        = up_txready,  .txempty        = up_txempty,};/* I/O buffers */static char g_irdarxbuffer[CONFIG_UART_IRDA_RXBUFSIZE];static char g_irdatxbuffer[CONFIG_UART_IRDA_TXBUFSIZE];static char g_modemrxbuffer[CONFIG_UART_MODEM_RXBUFSIZE];static char g_modemtxbuffer[CONFIG_UART_MODEM_TXBUFSIZE];/* This describes the state of the C5471 serial IRDA port. */static struct up_dev_s g_irdapriv ={  .xmit_fifo_size = UART_IRDA_XMIT_FIFO_SIZE,  .baud_base      = BASE_BAUD,  .uartbase       = UART_IRDA_BASE,  .baud           = CONFIG_UART_IRDA_BAUD,  .irq            = C5471_IRQ_UART_IRDA,  .parity         = CONFIG_UART_IRDA_PARITY,  .bits           = CONFIG_UART_IRDA_BITS,#ifdef CONFIG_UART_IRDA_HWFLOWCONTROL  .flowcontrol    = TRUE,#endif  .stopbits2      = CONFIG_UART_IRDA_2STOP,};static uart_dev_t g_irdaport ={  .recv     =  {    .size   = CONFIG_UART_IRDA_RXBUFSIZE,    .buffer = g_irdarxbuffer,  },  .xmit     =  {    .size   = CONFIG_UART_IRDA_TXBUFSIZE,    .buffer = g_irdatxbuffer,   },  .ops      = &g_uart_ops,  .priv     = &g_irdapriv,};/* This describes the state of the C5471 serial Modem port. */static struct up_dev_s g_modempriv ={  .xmit_fifo_size = UART_XMIT_FIFO_SIZE,  .baud_base      = BASE_BAUD,  .uartbase       = UART_MODEM_BASE,  .baud           = CONFIG_UART_MODEM_BAUD,  .irq            = C5471_IRQ_UART,  .parity         = CONFIG_UART_MODEM_PARITY,  .bits           = CONFIG_UART_MODEM_BITS,#ifdef CONFIG_UART_MODEM_HWFLOWCONTROL  .flowcontrol    = TRUE,#endif  .stopbits2      = CONFIG_UART_MODEM_2STOP,};static uart_dev_t g_modemport ={  .recv     =  {    .size   = CONFIG_UART_MODEM_RXBUFSIZE,    .buffer = g_modemrxbuffer,  },  .xmit     =  {    .size   = CONFIG_UART_MODEM_TXBUFSIZE,    .buffer = g_modemtxbuffer,  },  .ops      = &g_uart_ops,  .priv     = &g_modempriv,};/* Now, which one with be tty0/console and which tty1? */#ifdef CONFIG_SERIAL_IRDA_CONSOLE# define CONSOLE_DEV     g_irdaport# define TTYS0_DEV       g_irdaport# define TTYS1_DEV       g_modemport#else# define CONSOLE_DEV     g_modemport# define TTYS0_DEV       g_modemport# define TTYS1_DEV       g_irdaport#endif/**************************************************************************** * Private Functions ****************************************************************************//**************************************************************************** * Name: up_inserial ****************************************************************************/static inline uint32 up_inserial(struct up_dev_s *priv, uint32 offset){  return getreg32(priv->uartbase + offset);}/**************************************************************************** * Name: up_serialout ****************************************************************************/static inline void up_serialout(struct up_dev_s *priv, uint32 offset, uint32 value){  putreg32(value, priv->uartbase + offset);}/**************************************************************************** * Name: up_disableuartint ****************************************************************************/static inline void up_disableuartint(struct up_dev_s *priv, uint16 *ier){  if (ier)    {      *ier = priv->regs.ier & UART_IER_INTMASK;    }  priv->regs.ier &= ~UART_IER_INTMASK;  up_serialout(priv, UART_IER_OFFS, priv->regs.ier);}/**************************************************************************** * Name: up_restoreuartint ****************************************************************************/static inline void up_restoreuartint(struct up_dev_s *priv, uint16 ier){  priv->regs.ier |= ier & (UART_IER_RECVINT|UART_IER_XMITINT);  up_serialout(priv, UART_IER_OFFS, priv->regs.ier);}/**************************************************************************** * Name: up_waittxready ****************************************************************************/static inline void up_waittxready(struct up_dev_s *priv){  int tmp;  for (tmp = 1000 ; tmp > 0 ; tmp--)    {      if ((up_inserial(priv, UART_SSR_OFFS) & UART_SSR_TXFULL) == 0)        {          break;        }    }}/**************************************************************************** * Name: up_disablebreaks ****************************************************************************/static inline void up_disablebreaks(struct up_dev_s *priv){  priv->regs.lcr &= ~UART_LCR_BOC;  up_serialout(priv, UART_LCR_OFFS, priv->regs.lcr);}/**************************************************************************** * Name: up_enablebreaks ****************************************************************************/static inline void up_enablebreaks(struct up_dev_s *priv){  priv->regs.lcr |= UART_LCR_BOC;  up_serialout(priv, UART_LCR_OFFS, priv->regs.lcr);}/**************************************************************************** * Name: up_setrate ****************************************************************************/static inline void up_setrate(struct up_dev_s *priv, unsigned int rate){  uint32 div_bit_rate;  switch (rate)    {    case 115200:      div_bit_rate = BAUD_115200;      break;    case 57600:      div_bit_rate = BAUD_57600;      break;    case 38400:      div_bit_rate = BAUD_38400;      break;    case 19200:      div_bit_rate = BAUD_19200;      break;    case 4800:      div_bit_rate = BAUD_4800;      break;    case 2400:      div_bit_rate = BAUD_2400;      break;    case 1200:      div_bit_rate = BAUD_1200;      break;    case 9600:    default:      div_bit_rate = BAUD_9600;      break;    }  up_serialout(priv, UART_DIV_BIT_RATE_OFFS, div_bit_rate);}/**************************************************************************** * Name: up_setup * * Description: *   Configure the UART baud, bits, parity, fifos, etc. This *   method is called the first time that the serial port is *   opened. * ****************************************************************************/static int up_setup(struct uart_dev_s *dev){#ifndef CONFIG_SUPPRESS_UART_CONFIG  struct up_dev_s *priv = dev->priv;  unsigned int cval;  if (priv->bits == 7)    {      cval = UART_LCR_7BITS;    }  else    {      cval = UART_LCR_8BITS;    }  if (priv->stopbits2)    {      cval |= UART_LCR_2STOP;    }  if (priv->parity == 1)   /* Odd parity */    {      cval |= (UART_LCR_PAREN|UART_LCR_PARODD);    }  else if (priv->parity == 2)  /* Even parity */    {      cval |= (UART_LCR_PAREN|UART_LCR_PAREVEN);    }  /* Both the IrDA and MODEM UARTs support RESET and UART mode. */  up_serialout(priv, UART_MDR_OFFS, MDR_RESET_MODE);  up_mdelay(5);  up_serialout(priv, UART_MDR_OFFS, MDR_UART_MODE);  up_mdelay(5);  priv->regs.ier = up_inserial(priv, UART_IER_OFFS);  priv->regs.lcr = up_inserial(priv, UART_LCR_OFFS);#ifdef CONFIG_UART_HWFLOWCONTROL  if (priv->flowcontrol)    {      priv->regs.efr = up_inserial(priv, UART_EFR_OFFS);      priv->regs.tcr = up_inserial(priv, UART_TCR_OFFS);    }#endif  up_disableuartint(priv, NULL);  up_serialout(priv, UART_EFR_OFFS,  0x0010);           /* Enable fifo control */  up_serialout(priv, UART_TFCR_OFFS, 0);                /* Reset to 0 */  up_serialout(priv, UART_RFCR_OFFS, UART_FCR_RX_CLR);  /* Clear RX fifo */  up_serialout(priv, UART_TFCR_OFFS, UART_FCR_TX_CLR);  /* Clear TX fifo */  up_serialout(priv, UART_TFCR_OFFS, UART_FCR_FIFO_EN); /* Enable RX/TX fifos */  up_disablebreaks(priv);  /* Set the RX and TX trigger levels to the minimum */  priv->regs.fcr = (priv->regs.fcr & 0xffffffcf) | UART_FCR_FTL;  up_serialout(priv, UART_RFCR_OFFS, priv->regs.fcr);  priv->regs.fcr = (priv->regs.fcr & 0xffffff3f) | UART_FCR_FTL;  up_serialout(priv, UART_RFCR_OFFS, priv->regs.fcr);  up_setrate(priv, priv->baud);  priv->regs.lcr &= 0xffffffe0;      /* clear original field, and... */  priv->regs.lcr |= (uint32)cval;    /* Set new bits in that field. */  up_serialout(priv, UART_LCR_OFFS, priv->regs.lcr);#ifdef CONFIG_UART_HWFLOWCONTROL  if (priv->flowcontrol)    {      /* Set the FIFO level triggers for flow control       * Halt = 48 bytes, resume = 12 bytes       */      priv->regs.tcr = (priv->regs.tcr & 0xffffff00) | 0x0000003c;      up_serialout(priv, UART_TCR_OFFS, priv->regs.tcr);

⌨️ 快捷键说明

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