📄 c5471_serial.c
字号:
/**************************************************************************** * 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 + -