📄 s3c2410sio.c
字号:
/* s2410Sio.c - S2410 USART tty driver */
/* Copyright 1999 ARM Limited */
/*
modification history
--------------------
01a,25jun99,jpd wriiten.
*/
/*
DESCRIPTION
This is the device driver for the USARTs in the Atmel Corporation
S2410M40400 microcontroller. The chip contains 2 USARTs, usable in
synchronous or asynchronous mode.
The USARTs are identical in design. They contain a universal
synchronous/asynchronous receiver/transmitter, and a baud-rate
generator, The USARTs contain no FIFOs, but are supported by a
Peripheral Data Controller (PDC) which can be programmed to perform
data transfers to and from the USART without CPU intervention. The
driver is conditionally compilable to support use of the PDC, or simple
character-at-a time operation.
The USART design does not support modem control input or output signals
e.g. DTR, RI, RTS, DCD, CTS and DSR.
Interrupts are programmed to occur when framing, parity receive break
or receiver overrun errors occur, when the Receive or Transmitter
Holding Registers are full/empty, when PDC transfers have occurred, or
when receiver timeout has occurred.
Only asynchronous serial operation is supported by the USARTs which
support 5, 6, 7 or 8 bit word lengths with or without parity and with one or
two stop bits. The only serial word format supported by the driver is 8
data bits, 1 stop bit, no parity, The default baud rate is determined
by the BSP by filling in the S2410_SIO_CHAN structure before calling
s2410DevInit().
The USART supports baud rates depending on the frequency of the clocks
applied to it, but typically these will range from about 31 bps to
about 2 Mbps.
.SH DATA STRUCTURES
An S2410_SIO_CHAN data structure is used to describe each channel, this
structure is described in s2410Sio.h.
.SH CALLBACKS
Servicing a "transmitter ready" interrupt involves making a callback to
a higher level library in order to get a character to transmit. By
default, this driver installs dummy callback routines which do nothing.
A higher layer library that wants to use this driver (e.g. ttyDrv)
will install its own callback routine using the SIO_INSTALL_CALLBACK
ioctl command. Likewise, a receiver interrupt handler makes a callback
to pass the character to the higher layer library.
.SH MODES
This driver supports both polled and interrupt modes.
.SH PERIPHERAL DATA CONTROLLER
If the symbol S2410_USE_PDC is defined, then code is conditionally
compiled to use the peripheral data controller associated with the
USARTs. If the symbol is not defined, then the USART is used in
character-at-a-time mode and the maximum serial speeds that the
hardware can support will be lower. When used with the PDC, the driver
buffers both receive and transmit. The size of the buffers is dictated
by the symbols S2410_RXBUFF_SIZE and S2410_TXBUFF_SIZE, which are
defaulted within s2410Sio.h. On the receive side, there are two
swing-buffers used alternately, of the same size.
.SH USAGE
The driver is typically only called by the BSP. The directly callable
routines in this modules are s2410SioDevInit(), and s2410SioInt().
The BSP's sysHwInit() routine typically calls sysSerialHwInit(), which
initialises the hardware-specific fields in the S2410_SIO_CHAN structure
(e.g. register I/O addresses etc) before calling s2410SioDevInit() which
resets the device and installs the driver function pointers. After
this the USART will be enabled and ready to generate interrupts, but
those interrupts will be disabled in the interrupt controller.
The following example shows the first parts of the initialisation:
.CS
#include "s2410Sio.h"
LOCAL S2410_SIO_CHAN s2410SioChan[N_S2410_USART_CHANNELS];
void sysSerialHwInit (void)
{
int i;
for (i = 0; i < N_S2410_USART_CHANNELS; i++)
{
s2410SioChan[i].regs = devParas[i].baseAdrs;
s2410SioChan[i].baudRate = CONSOLE_BAUD_RATE;
s2410SioChan[i].xtal = S2410_USART_FREQ;
s2410SioChan[i].level = devParas[i].intLevel;
/@ Set USART to be clocked from MCKI (for example) @/
S2410_USART_REG_WRITE (&s2410SioChan[i], S2410_US_MR, 0);
/@
* Initialise driver functions, getTxChar, putRcvChar and
* channelMode and otherwise initialise USART.
@/
s2410SioDevInit(&s2410SioChan[i]);
}
.CE
The BSP's sysHwInit2() routine typically calls sysSerialHwInit2(),
which connects the chips interrupts via intConnect() and enables those
interrupts, as shown in the following example:
.CS
void sysSerialHwInit2 (void)
{
int i;
for (i = 0; i < N_S2410_USART_CHANNELS; i++)
{
/@ connect and enable interrupts @/
(void)intConnect (INUM_TO_IVEC(devParas[i].vector),
s2410SioInt, (int) &s2410SioChan[i]);
intEnable (devParas[i].intLevel);
}
}
.CE
.SH BSP
By convention all the BSP-specific serial initialisation is performed
in a file called sysSerial.c, which is #include'ed by sysLib.c.
sysSerial.c implements at least four functions, sysSerialHwInit()
sysSerialHwInit2(), sysSerialChanGet(), and sysSerialReset(). The first
two have been described above, the others work as follows:
sysSerialChanGet is called by usrRoot to get the serial channel
descriptor associated with a serial channel number. The routine takes a
single parameter which is a channel number ranging between zero and
NUM_TTY. It returns a pointer to the corresponding channel descriptor,
(SIO_CHAN), which is just the address of the S2410_SIO_CHAN structure.
sysSerialReset is called from sysToMonitor() and should reset the
serial devices to an inactive state (prevent them from generating any
interrupts).
.SH INCLUDE FILES:
s2410Sio.h sioLib.h
.SH SEE ALSO:
.I "Atmel S2410M40400 16/32-Bit Microcontroller, Data Sheet."
*/
#include "vxWorks.h"
#include "intLib.h"
#include "errnoLib.h"
#include "errno.h"
#include "sioLib.h"
#include "s3c2410Sio.h"
/* Make all of code in file dependent upon this symbol */
#ifdef INCLUDE_SERIAL
/* defines */
/* globals */
extern S2410_SIO_CHAN s2410SioChan[N_2410BP_UART_CHANNELS];
int s2410SioIntErrs = 0;
/* function prototypes */
LOCAL STATUS s2410SioDummyCallback (void);
LOCAL void s2410SioInitChannel (S2410_SIO_CHAN * pChan);
LOCAL STATUS s2410SioIoctl (SIO_CHAN * pSioChan, int request, int arg);
LOCAL int s2410SioTxStartup (SIO_CHAN * pSioChan);
LOCAL int s2410SioCallbackInstall (SIO_CHAN * pSioChan, int callbackType,
STATUS (*callback)(), void * callbackArg);
LOCAL int s2410SioPollInput (SIO_CHAN * pSioChan, char *);
LOCAL int s2410SioPollOutput (SIO_CHAN * pSioChan, char);
/* driver functions */
LOCAL SIO_DRV_FUNCS s2410SioDrvFuncs =
{
(int (*)()) s2410SioIoctl,
(int (*)()) s2410SioTxStartup,
(int (*)()) s2410SioCallbackInstall,
(int (*)()) s2410SioPollInput,
(int (*)(SIO_CHAN *,char)) s2410SioPollOutput
};
/*******************************************************************************
*
* s2410SioDummyCallback - dummy callback routine.
*
* RETURNS: ERROR, always.
*/
LOCAL STATUS s2410SioDummyCallback (void)
{
return ERROR;
}
/*******************************************************************************
*
* s2410SioDevInit - initialise an s3c2410 SIO channel
*
* This routine initialises some SIO_CHAN function pointers and then resets
* the chip to a quiescent state. Before this routine is called, the BSP
* must already have initialised all the device addresses, etc. in the
* S2410_SIO_CHAN structure.
*
* RETURNS: N/A
*/
void s2410SioDevInit
(
S2410_SIO_CHAN * pChan /* ptr to s2410_SIO_CHAN describing this chan */
)
{
int oldlevel = intLock();
/* initialise the driver function pointers in the SIO_CHAN */
pChan->sio.pDrvFuncs = &s2410SioDrvFuncs;
/* set the non BSP-specific constants */
pChan->getTxChar = s2410SioDummyCallback;
pChan->putRcvChar = s2410SioDummyCallback;
pChan->channelMode = SIO_MODE_POLL;
/* initialise the chip */
s2410SioInitChannel (pChan);
intUnlock (oldlevel);
return;
}
/*******************************************************************************
*
* s2410SioInitChannel - initialise USART
*
* This routine performs hardware initialisation of the USART channel.
*
* RETURNS: N/A
*/
LOCAL void s2410SioInitChannel
(
S2410_SIO_CHAN* pChan /* ptr to S2410_SIO_CHAN describing this chan */
)
{
UINT32 temp,i;
/* reset UART: disable rx tx and clear error status*/
S2410_UART_REG_WRITE(pChan,S2410_UCON,0);
S2410_UART_REG_READ(pChan, S2410_UERSTAT, temp);
/*8bits ;1 stop bit;No parity;Normal mode*/
S2410_UART_REG_WRITE(pChan,S2410_ULCON, \
(ULCON_PARITY_NONE| ULCON_STOP_BIT_1| ULCON_WORD_LGTH_8));
/*PCLK; Rx PULSE interrupt; Tx Level interrupt; Rx Error inerrupt Enable;
Normal operation; Disable Tx and Rx*/
S2410_UART_REG_WRITE(pChan,S2410_UCON,\
(UCON_TXINT_LVL|UCON_RXERRINT_EN|UCON_RXMD_DIS|UCON_TXMD_DIS));
/*Disable FIFO*/
S2410_UART_REG_WRITE(pChan,S2410_UFCON,0);
/*Disable Modem control*/
S2410_UART_REG_WRITE(pChan,S2410_UMCON,0);
/*set baud rate divisor*/
S2410_UART_REG_WRITE(pChan, S2410_UBRDIV, \
((int)(pChan->xtal / (16 * pChan->baudRate)+0.5)-1));
/*Enable UART*/
S2410_UART_REG_READ(pChan, S2410_UCON, temp);
temp|=(UCON_RXMD_INT_POLL|UCON_TXMD_INT_POLL);
S2410_UART_REG_WRITE(pChan,S2410_UCON,temp);
for(i=0;i<100;i++);
}
/*******************************************************************************
*
* s2410SioIoctl - special device control
*
* This routine handles the IOCTL messages from the user.
*
* RETURNS: OK on success, ENOSYS on unsupported request, EIO on failed
* request.
*/
LOCAL STATUS s2410SioIoctl
(
SIO_CHAN * pSioChan, /* ptr to SIO_CHAN describing this channel */
int request, /* request code */
int arg /* some argument */
)
{
int oldlevel; /* current interrupt level mask */
STATUS status; /* status to return */
UINT32 brd; /* baud rate divisor */
S2410_SIO_CHAN * pChan = (S2410_SIO_CHAN *)pSioChan;
status = OK; /* preset to return OK */
switch (request)
{
case SIO_BAUD_SET:
/*
* Set the baud rate. Return EIO for an invalid baud rate, or
* OK on success.
*
* Calculate the baud rate divisor: it must be non-zero and must
* fit in a 16-bit register.
*/
brd =(int) (pChan->xtal/16./arg +0.5)-1;
if (brd & ~0xFFFF)
{
status = EIO; /* baud rate out of range */
break;
}
/*set baud rate divisor*/
S2410_UART_REG_WRITE(pChan, S2410_UBRDIV, brd);
pChan->baudRate = arg;
break;
case SIO_BAUD_GET:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -