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

📄 primecellsio.c

📁 ATMEL920T的BSP及ETH等已经设备驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* primeCellSio.c - ARM AMBA UART tty driver */

/* Copyright 1997-2000 Wind River Systems, Inc. */

#include "copyright_wrs.h"

/*
modification history
--------------------
01c,21feb00,jpd  renamed primecell... symbols to primeCell...
01b,25jan00,jpd  renamed primeCellSio.c.
01a,10nov99,ajb  copied from ambaSio.c, adding support for 1 interrupt per UART.
*/

/*
DESCRIPTION
This is the device driver for the Advanced RISC Machines (ARM) AMBA
UART. This is a generic design of UART used within a number of chips
containing (or for use with) ARM CPUs such as in the Digital Semiconductor
21285 chip as used in the EBSA-285 BSP.
 
This design contains a universal asynchronous receiver/transmitter, a
baud-rate generator, and an InfraRed Data Association (IrDa) Serial
InfraRed (SiR) protocol encoder. The Sir encoder is not supported by
this driver. The UART contains two 16-entry deep FIFOs for receive and
transmit: if a framing, overrun or parity error occurs during
reception, the appropriate error bits are stored in the receive FIFO
along with the received data. The FIFOs can be programmed to be one
byte deep only, like a conventional UART with double buffering, but the
only mode of operation supported is with the FIFOs enabled.
 
The UART design does not support the modem control output signals: DTR,
RI and RTS. Moreover, the implementation in the 21285 chip does not
support the modem control inputs: DCD, CTS and DSR.
 
The UART design can generate four interrupts: Rx, Tx, modem status
change and a UART disabled interrupt (which is asserted when a start
bit is detected on the receive line when the UART is disabled). The
implementation in the 21285 chip has only two interrupts: Rx and Tx,
but the Rx interrupt is a combination of the normal Rx interrupt status
and the UART disabled interrupt status.
 
Only asynchronous serial operation is supported by the UART which
supports 5 to 8 bit 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 AMBA_CHAN structure before
calling ambaDevInit().
 
The exact baud rates supported by this driver will depend on the
crystal fitted (and consequently the input clock to the baud-rate
generator), but in general, baud rates from about 300 to about 115200
are possible.
 
In theory, any number of UART channels could be implemented within a
chip. This driver has been designed to cope with an arbitrary number of
channels, but at the time of writing, has only ever been tested with
one channel.
 
.SH DATA STRUCTURES
An AMBA_CHAN data structure is used to describe each channel, this
structure is described in h/drv/sio/ambaSio.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 USAGE
The driver is typically only called by the BSP. The directly callable
routines in this modules are ambaDevInit(), ambaIntTx() and
ambaIntRx().
 
The BSP's sysHwInit() routine typically calls sysSerialHwInit(), which
initialises the hardware-specific fields in the AMBA_CHAN structure
(e.g. register I/O addresses etc) before calling ambaDevInit() which
resets the device and installs the driver function pointers.  After
this the UART 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 "primeCellSio.h"
 
LOCAL AMBA_CHAN ambaChan[N_AMBA_UART_CHANS];
 
void sysSerialHwInit (void)
    {
    int i;
 
    for (i = 0; i < N_AMBA_UART_CHANS; i++)
	{
	ambaChan[i].regs = devParas[i].baseAdrs;
	ambaChan[i].baudRate = CONSOLE_BAUD_RATE;
	ambaChan[i].xtal = UART_XTAL_FREQ; 
 
	ambaChan[i].levelRx = devParas[i].intLevelRx;
	ambaChan[i].levelTx = devParas[i].intLevelTx;
 
	/@
	 * Initialise driver functions, getTxChar, putRcvChar and
	 * channelMode, then initialise UART
	 @/
 
	ambaDevInit(&ambaChan[i]);
	}
    }
.CE
 
The BSP's sysHwInit2() routine typically calls sysSerialHwInit2(),
which connects the chips interrupts via intConnect() (the two
interrupts `ambaIntTx' and `ambaIntRx') and enables those interrupts,
as shown in the following example:
 
.CS
 
void sysSerialHwInit2 (void)
    {
    /@ connect and enable Rx interrupt @/
 
    (void) intConnect (INUM_TO_IVEC(devParas[0].vectorRx),
		       ambaIntRx, (int) &ambaChan[0]);
    intEnable (devParas[0].intLevelRx);
 
 
    /@ connect Tx interrupt @/
 
    (void) intConnect (INUM_TO_IVEC(devParas[0].vectorTx),
		       ambaIntTx, (int) &ambaChan[0]);
    /@
     * There is no point in enabling the Tx interrupt, as it will
     * interrupt immediately and then be disabled.
     @/
 
    }
.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 AMBA_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:
drv/sio/ambaSio.h sioLib.h
 
.SH SEE ALSO:
.I "Advanced RISC Machines AMBA UART (AP13) Data Sheet,"
.I "Digital Semiconductor 21285 Core Logic for SA-110 Microprocessor Data
Sheet,"
.I "Digital Semiconductor EBSA-285 Evaluation Board Reference Manual."
*/

#include "vxWorks.h"
#include "intLib.h"
#include "errnoLib.h"
#include "errno.h"
#include "sioLib.h"
#include "primeCellSio.h"
/* local defines  */

#ifndef AMBA_UART_REG
#define AMBA_UART_REG(pChan, reg) \
	(*(volatile UINT32 *)((UINT32)(pChan)->regs + (reg)))
#endif

#ifndef AMBA_UART_REG_READ
#define AMBA_UART_REG_READ(pChan, reg, result) \
{ \
	int s = intLock(); \
	(result) = (AMBA_UART_REG(pChan, reg)); \
	intUnlock(s); \
}
#endif

#ifndef AMBA_UART_REG_WRITE
#define AMBA_UART_REG_WRITE(pChan, reg, data)  \
{ \
	int s = intLock(); \
	(AMBA_UART_REG(pChan, reg)) = (data); \
	intUnlock(s); \
}
#endif

#ifndef AMBA_UART_REG_BIT_SET
#define AMBA_UART_REG_BIT_SET(pChan, reg, data) \
{ \
	int s = intLock(); \
	(AMBA_UART_REG(pChan, reg)) |= (data); \
	intUnlock(s); \
}
#endif

#ifndef AMBA_UART_REG_BIT_CLR
#define AMBA_UART_REG_BIT_CLR(pChan, reg, data) \
{ \
	int s = intLock(); \
	(AMBA_UART_REG(pChan, reg)) &= ~(data); \
	intUnlock(s); \
}
#endif

/* locals */

/* function prototypes */

LOCAL STATUS ambaDummyCallback (void);
LOCAL void ambaInitChannel (AMBA_CHAN * pChan);
LOCAL STATUS ambaIoctl (SIO_CHAN * pSioChan, int request, int arg);
LOCAL int ambaTxStartup (SIO_CHAN * pSioChan);
LOCAL int ambaCallbackInstall (SIO_CHAN * pSioChan, int callbackType,
                               STATUS (*callback)(), void * callbackArg);
LOCAL int ambaPollInput (SIO_CHAN * pSioChan, char *);
LOCAL int ambaPollOutput (SIO_CHAN * pSioChan, char);

/* driver functions */

LOCAL SIO_DRV_FUNCS ambaSioDrvFuncs =
    {
        (int (*)())ambaIoctl,
        ambaTxStartup,
        ambaCallbackInstall,
        ambaPollInput,
        ambaPollOutput
    };

/*******************************************************************************
*
* ambaDummyCallback - dummy callback routine.
*
* RETURNS: ERROR, always.
*/

LOCAL STATUS ambaDummyCallback (void)
{

    return ERROR;
}

/*******************************************************************************
*
* primeCellSioDevInit - initialise an AMBA 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
* AMBA_CHAN structure.
*
* RETURNS: N/A
*/

void primeCellSioDevInit
(
    AMBA_CHAN *	pChan	/* ptr to AMBA_CHAN describing this channel */
)
{
    int oldlevel = intLock();


    /* initialise the driver function pointers in the SIO_CHAN */

    pChan->sio.pDrvFuncs = &ambaSioDrvFuncs;


    /* set the non BSP-specific constants */

    pChan->getTxChar = ambaDummyCallback;
    pChan->putRcvChar = ambaDummyCallback;

    /*  pChan->channelMode = 0;   */ /* undefined */
    pChan->channelMode = SIO_MODE_POLL;


    /* initialise the chip */

    ambaInitChannel (pChan);


    intUnlock (oldlevel);

}

/*******************************************************************************
*
* ambaInitChannel - initialise UART
*
* This routine performs hardware initialisation of the UART channel.
*
* RETURNS: N/A
*/

LOCAL void ambaInitChannel
(
    AMBA_CHAN *	pChan	/* ptr to AMBA_CHAN describing this channel */
)
{
    int		i;
    /*    UINT32	discard;*/
    int		baud_value; /*huxianpeng 20051230*/

    /* Disable interrupts */
    AMBA_UART_REG_WRITE(pChan, DBGU_IDR, 0xffffffff);
    /* Reset receiver and transmitter */
    AMBA_UART_REG_WRITE(pChan, UARTCON, 0x1ac);

    /* Fill Tx FIFO with nulls (data sheet specifies this) */

    for (i = 0; i < 16; i++)
        AMBA_UART_REG_WRITE(pChan, UARTDR, 0);


    /* Program UART control register */

    /*    AMBA_UART_REG_WRITE(pChan, UARTCON, 0);*/
    /*    AMBA_UART_REG_WRITE(pChan, UARTCON, UART_ENABLE);*/


    /* Ensure that only Receive ints are generated. */
    /*    AMBA_UART_REG_BIT_CLR(pChan,
    			  UARTCON, 
    			  UART_RTIE | UART_TIE | 
    			  UART_RIE | UART_MSIE );
    */
    /*    AMBA_UART_REG_BIT_SET(pChan, UARTCON, UART_RIE | UART_RTIE);*/

    AMBA_UART_REG_WRITE(pChan, DBGU_IER,
                        DBGU_IER_RXRDY);

    /* Set baud rate divisor */
    baud_value=(pChan->xtal*10) /(pChan->baudRate*16);/*huxianpeng 20051230*/
    if ((baud_value % 10) >= 5)
        baud_value = (baud_value / 10) + 1;
    else
        baud_value /= 10;
    AMBA_UART_REG_WRITE(pChan, DBGU_BRGR, baud_value);

    /*
        AMBA_UART_REG_WRITE(pChan, L_UBRLCR,
    		    (pChan->xtal / (16 * pChan->baudRate) - 1) & 0xFF);
        AMBA_UART_REG_WRITE(pChan, M_UBRLCR,
    		    ((pChan->xtal / (16 * pChan->baudRate) - 1) >> 8) & 0xF);
    */


    /* Write the Timeguard Register*/
    AMBA_UART_REG_WRITE(pChan, DBGU_TTGR, 0x0);

    /* Disable the RX PDC transfer requests*/
    AMBA_UART_REG_WRITE(pChan, DBGU_PDC_PTCR, (0x1<<1));

    /* Disable the TX PDC transfer requests*/
    AMBA_UART_REG_WRITE(pChan, DBGU_PDC_PTCR, (0x1<<9));

    /* Set the next transmit transfer descriptor*/
    AMBA_UART_REG_WRITE(pChan, DBGU_PDC_TNPR, 0x0);
    AMBA_UART_REG_WRITE(pChan, DBGU_PDC_TNCR, 0x0);

    /* Set the next receive transfer descriptor */
    AMBA_UART_REG_WRITE(pChan, DBGU_PDC_RNPR, 0x0);
    AMBA_UART_REG_WRITE(pChan, DBGU_PDC_RNCR, 0x0);

    /*  Set the transmit transfer descriptor*/
    AMBA_UART_REG_WRITE(pChan, DBGU_PDC_TPR, 0x0);
    AMBA_UART_REG_WRITE(pChan, DBGU_PDC_TCR, 0x0);

    /*  Set the receive transfer descriptor */
    AMBA_UART_REG_WRITE(pChan, DBGU_PDC_RPR, 0x0);
    AMBA_UART_REG_WRITE(pChan, DBGU_PDC_RCR, 0x0);

    /* Enable the RX PDC transfer requests*/
    AMBA_UART_REG_WRITE(pChan, DBGU_PDC_PTCR, (0x1<<0));

    /* Enable the TX PDC transfer requests*/
    AMBA_UART_REG_WRITE(pChan, DBGU_PDC_PTCR, (0x1<<8));

    /* Define the USART mode   Normal Mode/No parity */
    AMBA_UART_REG_WRITE(pChan, DBGU_MR,
                        AT91C_US_CHMODE_NORMAL | AT91C_US_PAR_NONE );


    AMBA_UART_REG_WRITE(pChan, UARTCON,
                        DBGU_CR_TXEN | DBGU_CR_RXEN );

    /*
     * Set word format, enable FIFOs: set 8 bits, 1 stop bit, no parity.
     * This also latches the writes to the two (sub)registers above.
     */
    /*
        AMBA_UART_REG_WRITE(pChan, H_UBRLCR,
    	(UINT8)(WORD_LEN_8 | ONE_STOP | PARITY_NONE | FIFO_ENABLE));
    */

    /* Clear Rx FIFO (data sheet specifies this) */

    /*
        for (i = 0; i < 16; i++)
    	AMBA_UART_REG_READ(pChan, RXSTAT, discard);
    */

    /*	ambaPollOutput((SIO_CHAN *)pChan,'O'); 	*//* transmit character */

    /*	comOutputTest('A');*/
}

/*******************************************************************************
*
* ambaIoctl - 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 ambaIoctl
(
    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 */

    AMBA_CHAN * pChan = (AMBA_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.
         */

        /*
         * baudrate divisor must be non-zero and must fit in a 12-bit
         * register.
         */

        brd = (pChan->xtal/(16*arg)) - 1;	/* calculate baudrate divisor */

⌨️ 快捷键说明

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