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

📄 serial.c

📁 ARM入门的好帮手.包含了从简单到相对较复杂的程序.
💻 C
📖 第 1 页 / 共 2 页
字号:
    /* -*-C-*-
 *
 * $Revision: 1.27.2.6 $
 *   $Author: rivimey $
 *     $Date: 1998/01/23 18:41:02 $
 *
 * Copyright (c) 1996 Advanced RISC Machines Limited.
 * All Rights Reserved.
 *
 *   Project: ANGEL
 *
 *     Title: Serial device driver for PIE 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 "serial.h"             /* header for this file */

#include "devconf.h"
#include "devdriv.h"            /* device driver support */
#include "hw.h"                 /* description of serial hardware */
#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 "prof.h"

#include "usart.h"
#include "aic.h"

/* General purpose constants, macros, enums, typedefs */

#define DEFBAUD               9600           /* default baud rate */

unsigned int In_Int = 0; /* Interrupt flag in suppasm */

/* Forward declarations */

extern unsigned Get_Mode(void);
extern void angel_DeviceInterruptHandler(void) ;

void clear_led( char state);
void set_led  ( char state);
void ser_View(void);

static void serial_ControlTx(DeviceID devid);
static void serial_ControlRx(DeviceID devid);
static DevError serial_Control(DeviceID devid,
                               DeviceControl op, void *arg);
static void serial_KickStartFn(DeviceID devid);

static DevError serial_set_params(DeviceID devid, const ParameterConfig *conf);

/*
 * The set of parameter options supported by the device
 */
static unsigned int baud_options[] =
{
    1200,
    2400,
    4800,
    9600,
    19200,
    38400,
    57600,
    115200
};

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 interrupt handler and the deferred processor */
static struct RingBuffer serial_rx_ring;
static struct RingBuffer serial_tx_ring;

/* Is global in order to save Tx processing serialization request */
static  bool    queue_tx_deferred ;




#if !defined(RAW_PIE_SERIAL) || (RAW_PIE_SERIAL == 0) /* Angel/shared */

/* 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 = {
    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_SERIAL,    /* what to do with FC chars */
    angel_DD_RxEng_BufferAlloc, (void *)DI_SERIAL   /* how to get a buffer */
};

/* the state of the rx engine */
static struct re_state rx_engine_state;

/* the state of the tx engine */
static struct te_state tx_engine_state;

/* packet for actual rx in progress */
static struct data_packet  rx_packet;

/* the current write packet */
static struct data_packet  tx_packet;

/* collected TX and RX engine state */
static RxTxState serial_rx_tx_state =
{
    &engine_config,
    &rx_engine_state,
    &tx_engine_state,
    &rx_packet,
    &tx_packet,
    1
};

#else  /* raw */

static RawState serial_raw_state;

#endif /* ... else raw ... */


/*
 * The control functions and interface
 */
static const SerialControl serial_ctrl =
{
#if !defined(RAW_PIE_SERIAL) || (RAW_PIE_SERIAL == 0)
    &serial_rx_tx_state,
    NULL,
    serpkt_int_tx_processing,
    serpkt_int_rx_processing,
#else
    NULL,
    &serial_raw_state,
    serraw_int_tx_processing,
    serraw_int_rx_processing,
#endif
    SER_DEV_IDENT_0,
    &serial_tx_ring,
    &serial_rx_ring,
    serial_ControlTx,
    serial_ControlRx,
    serial_Control,
    serial_KickStartFn
};

/* Publically-accessible globals */

/*
 * This is the device table entry for this device
 */
const struct angel_DeviceEntry angel_SerialDevice = {
#if !defined(RAW_PIE_SERIAL) || (RAW_PIE_SERIAL == 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
    &serial_ctrl,
    { sizeof(param_list) / sizeof(param_list[0]), param_list },
    { sizeof(param_default) / sizeof(param_default[0]), param_default }
};

/* Private globals */



/* macros to manipulate and keep track of Interrupt Mask Register */
#define IMR_set(f) ( AT91Serial->ier =  (f) )
#define IMR_clr(f) ( AT91Serial->idr = (f) )




#define USART_ANGEL         0

#if (USART_ANGEL == 0)
#define USART_ANGEL_BASE    USART0_BASE
#define IRQ_ANGEL           2
#define PIO_USART_ANGEL     PIO_US0
#endif

#if (USART_ANGEL == 1)
#define USART_ANGEL_BASE    USART1_BASE
#define IRQ_ANGEL           3
#define PIO_USART_ANGEL     PIO_US1
#endif



#pragma no_check_stack
/*
 *  Function: serial_KickStartFn
 *   Purpose: Kick-start tx by sending first character
 *
 *    Params:
 *       Input: devid   device ID of the driver
 *
 *   Returns: Nothing
 */
static void serial_KickStartFn(DeviceID devid)
{
    StructUSART *usart_pt = USART_ANGEL_BASE ;

    IGNORE(devid);

    /* If transmit interrupt is disabled */
    if (( usart_pt->US_IMR & TXRDY ) == 0 )
    {
        /* Wait transmission of the last character */
        while (( usart_pt->US_CSR & TXRDY ) == 0 ) ;
        /* Next character from the Ring buffer to the transmitter */
        usart_pt->US_THR = ringBufGetChar( &serial_tx_ring ) ;
        /* Enable the Transmit Interrupt */
        usart_pt->US_IER = TXRDY ;

        angel_DeviceStatus[DI_SERIAL] |= SER_TX_IRQ_EN;
    }
}
#pragma check_stack

/*
 * enable async transmission if not already enabled
 * NB caller should ensure protection against interrupt
 */
#pragma no_check_stack

static void serial_ControlTx(DeviceID devid)
{
    unsigned tx_status = angel_DeviceStatus[DI_SERIAL] & SER_TX_MASK;
 

    IGNORE(devid);
    /*
    * 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 ))
    {
        angel_DeviceStatus[DI_SERIAL] |= SER_TX_IRQ_EN;
        /*usart_pt->US_IER = TXRDY ;*/
    }
    else
    {
        angel_DeviceStatus[DI_SERIAL] &= ~SER_TX_IRQ_EN;
        /*usart_pt->US_IDR = TXRDY ;*/
    }
}

#pragma check_stack


/*
 * control rx interrupt mask according to flow control and read interest
 * NB caller should ensure protection against interrupt
 */
static void serial_ControlRx(DeviceID devid)
{
    StructUSART *usart_pt = USART_ANGEL_BASE ;

    IGNORE(devid);

    if (! (angel_DeviceStatus[DI_SERIAL] & SER_RX_DISABLED) &&
        ( angel_DeviceStatus[DI_SERIAL] & DEV_READ_BUSY_MASK ))
    {
        /* rx interrupt should be enabled */
        /*usart_pt->US_IER = RXRDY ;*/
        angel_DeviceStatus[DI_SERIAL] |= SER_RX_IRQ_EN;
    }
    else
    {
        /* rx interrupt should be disabled */
        /*usart_pt->US_IDR = RXRDY ;*/
        angel_DeviceStatus[DI_SERIAL] &= ~SER_RX_IRQ_EN;
    }
}




/*
 * Harware reset of UART
 */
static DevError serdriv_ResetDriver( DeviceID devid )
{

    return ( serial_set_params( devid, &angel_SerialDevice.default_config ) );
}


/*
 * Initialisation control operation
 */
static DevError serial_init(DeviceID devid)
{
   DevError err;

   /*
    * do one-time start-up initialisation
    * (for this device, just a device reset)
    */
   Angel_ExitToUSR();           /* because DeviceControl requires it */

#if defined(MINIMAL_ANGEL) && MINIMAL_ANGEL != 0
   err=Angel_RawDeviceControl(devid, DC_RESET, NULL);
#else
   err=angel_DeviceControl(devid, DC_RESET, NULL);
#endif

   Angel_EnterSVC();

   return err;
}


/*
 * Reset control operation
 */
static DevError serial_reset(DeviceID devid)
{
   (void)serdriv_ResetDriver(devid);            /* low_level reset */

   /* reset private flags (LEAVE lowest 8 bits alone) */
   angel_DeviceStatus[devid] &= 0xFF;

   serial_ControlRx(devid);

   return DE_OKAY;
}


/*
 * Receive Mode control operation
 */
static DevError serial_recv_mode(DeviceID devid, DevRecvMode mode)
{
    DevError ret_code = DE_OKAY;

    if ( mode == DR_DISABLE )
    {
        if ( ! (angel_DeviceStatus[DI_SERIAL] & SER_RX_DISABLED) )
        {
            /* disable reception and schedule send of XOFF */
            angel_DeviceStatus[DI_SERIAL] |= (SER_RX_DISABLED | SER_TX_FLOW_CONTROL);
            serial_ControlRx(devid);
            serial_ControlTx(devid);
        }
    }
    else if ( mode == DR_ENABLE )
    {
        if ( angel_DeviceStatus[DI_SERIAL] & SER_RX_DISABLED )
        {
            /* enable reception and schedule send of XON */
            angel_DeviceStatus[DI_SERIAL] &= ~SER_RX_DISABLED;
            angel_DeviceStatus[DI_SERIAL] |= SER_TX_FLOW_CONTROL;
            serial_ControlRx(devid);
            serial_ControlTx(devid);
        }
    }
    else
    {
        ret_code = DE_INVAL;
    }

    return ret_code;
}


/*
 * Set Speed control operation
 */
static DevError serial_set_params(DeviceID devid, const ParameterConfig *conf)
{

    word speed;
    word baud_word;
    StructUSART *usart_pt = USART_ANGEL_BASE ;
    StructAIC       *aic_pt = AIC_BASE ;
    int i ;

    IGNORE(devid);

⌨️ 快捷键说明

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