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