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

📄 serial.c

📁 AT91所有开发板的资料 AT91所有开发板的资料
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*-C-*- * * $Revision:  $ *   $Author:  $ *     $Date:  $ * * Copyright (c) 1996 Advanced RISC Machines Limited. * All Rights Reserved. * *   Project: ANGEL * *     Title: Serial device driver for Integrator board *//* * Provide a single serial device.  Since we're only providing a single * device we don't need to worry about device id's and idents.  But these * could be used to provide for two or more devices via the one driver. */#include "angel.h"#include "devconf.h"#include "serial.h"#include "evaluator.h"		/* header for this file */#include "devdriv.h"            /* device driver support */#include "params.h"             /* parameter structures and utilities */#include "rxtx.h"               /* rx/tx packet engines */#include "logging.h"#include "serlock.h"            /* serialisation, etc. */#include "serring.h"            /* interface to high-level driver */#include "c501uart.h"           /* chip definition struct & register bit values *//* General purpose constants, macros, enums, typedefs */#define DEFBAUD               9600  /* default baud rate *//* * forward declarations of necessary functions */static void c501uart_ControlTx(const DeviceID devid);static void c501uart_ControlRx(const unsigned int devid);static DevError c501uart_Control(DeviceID devid,                                  DeviceControl op,                                 void *arg);static void c501uart_KickStartFn(DeviceID devid);extern void delayloop(int ms);static unsigned int baud_options[] ={    1200,    2400,    4800,    9600,    19200,    38400,    57600,    115200,    230400};static ParameterList param_list[] = {    {        AP_BAUD_RATE,        sizeof(baud_options) / sizeof(baud_options[0]),        baud_options    }};/*  * The default parameter config for the device */static Parameter param_default[] = {    { AP_BAUD_RATE, 9600 }};/* the state shared between the Int. handler and the deferred processor */static RingBuffer c501uart_rx_ring[C501UART_NUM_PORTS];static RingBuffer c501uart_tx_ring[C501UART_NUM_PORTS];#if (HAVE_ANGEL_C501UART)/* * the configuration needed by the TX and RX engines */#define SERIAL_FC_SET  ((1 << serial_XON) | (1 << serial_XOFF))#define SERIAL_CTL_SET ((1 << serial_STX) | (1 << serial_ETX) |\                        (1 << serial_ESC))#define SERIAL_ESC_SET (SERIAL_FC_SET | SERIAL_CTL_SET)static const struct re_config engine_config[C501UART_NUM_PORTS] ={    {         serial_STX, serial_ETX, serial_ESC, /* self-explanatory?               */        SERIAL_FC_SET,                      /* set of flow-control characters  */        SERIAL_ESC_SET,                     /* set of characters to be escaped */        serpkt_flow_control, (void *)DI_C501UART_B,/* what to do with FC chars */        angel_DD_RxEng_BufferAlloc, (void *)DI_C501UART_B /* how to get a buffer */    }#if (C501UART_NUM_PORTS > 1)    ,{         serial_STX, serial_ETX, serial_ESC, /* self-explanatory?               */        SERIAL_FC_SET,                      /* set of flow-control characters  */        SERIAL_ESC_SET,                     /* set of characters to be escaped */        serpkt_flow_control, (void *)DI_C501UART_A,/* what to do with FC chars */        angel_DD_RxEng_BufferAlloc, (void *)DI_C501UART_A /* how to get a buffer */    }#endif};/* the state of the rx engine */static struct re_state rx_engine_state[C501UART_NUM_PORTS];/* the state of the tx engine */static struct te_state tx_engine_state[C501UART_NUM_PORTS];/* packet for actual rx in progress */static struct data_packet rx_packet[C501UART_NUM_PORTS];/* the current write packet */static struct data_packet tx_packet[C501UART_NUM_PORTS];/* the above, collected */static RxTxState c501uart_rx_tx_state[C501UART_NUM_PORTS] ={    {        &engine_config[C501UART_IDENT_B],        &rx_engine_state[C501UART_IDENT_B],        &tx_engine_state[C501UART_IDENT_B],        &rx_packet[C501UART_IDENT_B],        &tx_packet[C501UART_IDENT_B],        1 /* rx_flow */    }#if (C501UART_NUM_PORTS > 1)    ,{         &engine_config[C501UART_IDENT_A],        &rx_engine_state[C501UART_IDENT_A],        &tx_engine_state[C501UART_IDENT_A],        &rx_packet[C501UART_IDENT_A],        &tx_packet[C501UART_IDENT_A],        1 /* rx_flow */    }#endif};#endif /* HAVE_ANGEL_C501UART */#if (HAVE_RAW_C501UART)static RawState c501uart_raw_state[C501UART_NUM_PORTS];#endif/* * The control functions and interface */static const SerialControl c501uart_Ctrl[C501UART_NUM_PORTS] ={    {#if (RAW_C501UART_B == 0)        &c501uart_rx_tx_state[C501UART_IDENT_B],        NULL,        serpkt_int_tx_processing,        serpkt_int_rx_processing,#else        NULL,        &c501uart_raw_state[C501UART_IDENT_B],        serraw_int_tx_processing,        serraw_int_rx_processing,#endif        C501UART_IDENT_B,        &c501uart_tx_ring[C501UART_IDENT_B],        &c501uart_rx_ring[C501UART_IDENT_B],        c501uart_ControlTx,        c501uart_ControlRx,        c501uart_Control,        c501uart_KickStartFn    }#if C501UART_NUM_PORTS > 1    ,{#if (RAW_C501UART_A == 0)        &c501uart_rx_tx_state[C501UART_IDENT_A],        NULL,        &packet_state[C501UART_IDENT_A],        serpkt_int_tx_processing,        serpkt_int_rx_processing,#else        NULL,        &c501uart_raw_state[C501UART_IDENT_A],        NULL,        serraw_int_tx_processing,        serraw_int_rx_processing,#endif        C501UART_IDENT_A,        &c501uart_tx_ring[C501UART_IDENT_A],        &c501uart_rx_ring[C501UART_IDENT_A],        c501uart_ControlTx,        c501uart_ControlRx,        c501uart_Control,        c501uart_KickStartFn    }#endif};/* Publically-accessible globals *//* * The device table entry for this device */const struct angel_DeviceEntry angel_C501UARTSerial[C501UART_NUM_PORTS] ={    {#if (RAW_C501UART_B == 0)        DT_ANGEL,        {            serpkt_AsyncWrite,            serpkt_RegisterRead        },        serpkt_Control,#else        DT_RAW,        {            /* nasty but necessary casts, as can only statically initialise             * the first member of a union             */            (angel_DeviceWriteFn)       serraw_Write,            (angel_DeviceRegisterReadFn)serraw_Read        },        serraw_Control,#endif        &c501uart_Ctrl[C501UART_IDENT_B],        {            sizeof(param_list) / sizeof(param_list[0]), param_list        },        {            sizeof(param_default) / sizeof(param_default[0]), param_default        }    }#if C501UART_NUM_PORTS > 1    ,{#if (RAW_C501UART_A == 0)        DT_ANGEL,        {            serpkt_AsyncWrite,            serpkt_RegisterRead        },        serpkt_Control,#else        DT_RAW,        {            /* nasty but necessary casts, as can only statically initialise             * the first member of a union             */            (angel_DeviceWriteFn)       serraw_Write,            (angel_DeviceRegisterReadFn)serraw_Read        },        serraw_Control,#endif        &c501uart_Ctrl[C501UART_IDENT_A],        {            sizeof(param_list) / sizeof(param_list[0]), param_list        },        {            sizeof(param_default) / sizeof(param_default[0]), param_default        }    }#endif};/* what address? */#define c501uart_Address(port)     ((port == C501UART_IDENT_B) ? \                                    (C501UARTReg *)EVALUATOR_UART1_BASE : (C501UARTReg *)EVALUATOR_UART0_BASE)/* which ring buffer? */#define c501uart_TxRingBuf(port)   (&c501uart_tx_ring[port])#define c501uart_RxRingBuf(port)   (&c501uart_rx_ring[port])/* *  Function: c501uart_KickStartFn *   Purpose: Kick-start tx by sending first character * *    Params: *       Input: devid   device ID of the driver * *   Returns: Nothing */static void c501uart_KickStartFn(DeviceID devid){   char c;   const unsigned int port = SerCtrl(devid)->port;   C501UARTReg *const serchip = c501uart_Address(port);   IGNORE(devid);   c = ringBufGetChar( c501uart_TxRingBuf(port) );   while ( !TX_READY(c501uart_GetStatus(serchip)) )   {      ;   } /* Yes, you may have been told to kickstart while already transmiting */   c501uart_SerPutChar(serchip, c);}/* * enable async transmission if not already enabled * NB caller should ensure protection against interrupt */static void c501uart_ControlTx(DeviceID devid){   unsigned tx_status = angel_DeviceStatus[devid] & SER_TX_MASK;    /*     * We enable tx whenever we want to send a flow control char,     * OR when we are sending a packet and we have not been XOFF'ed     */   if ((tx_status & SER_TX_FLOW_CONTROL) || (tx_status == SER_TX_DATA))   {      /* tx interrupt should be enabled */      if ((angel_DeviceStatus[devid] & SER_TX_IRQ_EN) == 0)      {	 /* LogInfo(LOG_SERIAL, ("Enable TX Interrupt\n")); */	 angel_DeviceStatus[devid] |= SER_TX_IRQ_EN;	 EnableInterruptNum( DEBUG_COMPORT_TX_INT );      }   }   else   {      /* tx interrupt should be disabled */      if (angel_DeviceStatus[devid] & SER_TX_IRQ_EN)      {	 /* LogInfo(LOG_SERIAL, ("Disable TX Interrupt\n")); */	 DisableInterruptNum( DEBUG_COMPORT_TX_INT );	 angel_DeviceStatus[devid] &= ~SER_TX_IRQ_EN;      }   }}/* * control rx interrupt mask according to flow control and read interest * NB caller should ensure protection against interrupt */static void c501uart_ControlRx(DeviceID devid){   if ( ((angel_DeviceStatus[devid] & SER_RX_DISABLED) == 0)        && ((angel_DeviceStatus[devid] & DEV_READ_BUSY_MASK) != 0) )   {      /* rx interrupt should be enabled */      if ((angel_DeviceStatus[devid] & SER_RX_IRQ_EN) == 0 )      {	 angel_DeviceStatus[devid] |= SER_RX_IRQ_EN;	 EnableInterruptNum( DEBUG_COMPORT_RX_INT );      }   }   else   {      if ( (angel_DeviceStatus[devid] & SER_RX_DISABLED) != 0 )      {	 DisableInterruptNum( DEBUG_COMPORT_RX_INT );	 if ( (angel_DeviceStatus[devid] & SER_RX_IRQ_EN) != 0 )	 {	    angel_DeviceStatus[devid] &= ~SER_RX_IRQ_EN;	 }      }   }}/* * wait for tx to drain completely */static void serial_tx_drain(DeviceID devid){   const unsigned int port = SerCtrl(devid)->port;   C501UARTReg *const serchip = c501uart_Address(port);   RingBuffer *ring = c501uart_TxRingBuf(port);   int c = 0;   if (ringBufNotEmpty(ring))   {      /* Wait for message to move over to UART */      while ( (angel_DeviceStatus[devid] & SER_TX_EOD) != 0 )	 continue;   }       /* Now wait for UART to drain */   while ((c501uart_GetStatus(serchip) & USRTxEmpty) == 0)      c++;       if (c > 0)      LogInfo(LOG_SERIAL, ("serial_tx_drain: waited %d\n", c));    }/* * Initialisation control operation */static DevError c501uart_init(DeviceID devid){   DevError err;    /*     * do one-time start-up initialisation     * (for this device, just a device reset)     */   Angel_ExitToUSR();          /* because DeviceControl requires it */   err = angel_DeviceControl(devid, DC_RESET, NULL);   Angel_EnterSVC();   return err;}/* * Receive Mode control operation */static DevError c501uart_recv_mode(DeviceID devid, DevRecvMode mode){   DevError ret_code = DE_OKAY;   if (mode == DR_DISABLE)   {      if (!(angel_DeviceStatus[devid] & SER_RX_DISABLED))      {	 /* disable reception and schedule send of XOFF */	 angel_DeviceStatus[devid] |= (SER_RX_DISABLED | SER_TX_FLOW_CONTROL);	 c501uart_ControlRx(devid);	 c501uart_ControlTx(devid);      }   }   else if (mode == DR_ENABLE)   {      if (angel_DeviceStatus[devid] & SER_RX_DISABLED)      {	 /* enable reception and schedule send of XON */	 angel_DeviceStatus[devid] &= ~SER_RX_DISABLED;	 angel_DeviceStatus[devid] |= SER_TX_FLOW_CONTROL;	 c501uart_ControlRx(devid);	 c501uart_ControlTx(devid);

⌨️ 快捷键说明

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