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

📄 au1500sio.c

📁 au1500开发的应用程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* au1500Sio.c - Au1x00 UART tty driver */

/*
 * This file has been developed or significantly modified by the
 * MIPS Center of Excellence Dedicated Engineering Staff.
 * This notice is as per the MIPS Center of Excellence Master Partner
 * Agreement, do not remove this notice without checking first with
 * WR/Platforms MIPS Center of Excellence engineering management.
 */

/* Copyright 1984-2001 Wind River Systems, Inc. */

#include "copyright_wrs.h"

/*
modification history
--------------------
01b,12mar05,fhchen  adopted from pb1500/au1000Sio.c
01a,16may02,ejd  rewritten from ns16550Sio.c.
*/

/*
DESCRIPTION

This is the driver for the AU1x00 UART. This device includes a universal
asynchronous receiver/transmitter, a baud rate generator, and a complete 
modem control capability. 

A AUSIO_CHAN structure is used to describe the serial channel. This data 
structure is defined in au1500Sio.h.

Only asynchronous serial operation is supported by this driver.
The default serial settings are 8 data bits, 1 stop bit, no parity, 9600
baud, and software flow control.  

USAGE
The BSP's sysHwInit() routine typically calls sysSerialHwInit(),
which creates the AUSIO_CHAN structure and initializes all the values in the 
structure (except the SIO_DRV_FUNCS) before calling auSioDevInit().
The BSP's sysHwInit2() routine typically calls sysSerialHwInit2(), which
connects the chips interrupts via intConnect() (either the single
interrupt `auSioInt' or the three interrupts `auSioIntWr',
auSioIntRd', and `auSioIntEx').

This driver handles setting of hardware options such as parity(odd, even) and
number of data bits(5, 6, 7, 8). Hardware flow control is provided with the
handshakes RTS/CTS. The function HUPCL(hang up on last close) is available.
When hardware flow control is enabled, the signals RTS and DTR are set TRUE 
and remain set until a HUPCL is performed. 

*/

/* includes */

#include "vxWorks.h"
#include "intLib.h"
#include "errnoLib.h"
#include "errno.h"
#include "sioLib.h"
#include "au1500Sio.h"

/* local defines */

#ifndef SIO_HUP
#   define SIO_OPEN	0x100A
#   define SIO_HUP	0x100B
#endif

/* min/max baud rate - Arbitrary limits, depends on transceivers */

#define AU_UART_MIN_RATE 50
#define AU_UART_MAX_RATE 115200

/* static forward declarations */

LOCAL 	int 	auSioCallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);
LOCAL   STATUS  auSioBaudSet (AUSIO_CHAN *, UINT);
LOCAL 	STATUS  auSioModeSet (AUSIO_CHAN *, UINT);
LOCAL 	STATUS 	auSioIoctl (AUSIO_CHAN *, int, int);
LOCAL 	void 	auSioTxStartup (AUSIO_CHAN *);
LOCAL 	int 	auSioPollOutput (AUSIO_CHAN *, char);
LOCAL 	int 	auSioPollInput (AUSIO_CHAN *, char *);
LOCAL 	STATUS 	auSioOptsSet (AUSIO_CHAN *, UINT);
LOCAL 	STATUS 	auSioOpen (AUSIO_CHAN * pChan );
LOCAL 	STATUS 	auSioHup (AUSIO_CHAN * pChan );

/* driver functions */

static SIO_DRV_FUNCS auSioDrvFuncs =
    {
    (int (*)())auSioIoctl,
    (int (*)())auSioTxStartup,
    (int (*)())auSioCallbackInstall,
    (int (*)())auSioPollInput,
    (int (*)(SIO_CHAN *,char))auSioPollOutput
    };

/******************************************************************************
*
* auSioDummyCallback - dummy callback routine.
*/

LOCAL STATUS auSioDummyCallback (void)
    {
    return (ERROR);
    }

/******************************************************************************
*
* auSioDevInit - intialize a UART channel
*
* This routine initializes some SIO_CHAN function pointers and then resets the
* chip in a quiescent state.  Before this routine is called, the BSP must
* already have initialized(typically in sysSerialHwInit) all the device
* addresses, etc. in the AUSIO_CHAN structure.
*
* RETURNS: N/A
*/

void auSioDevInit
    (
    AUSIO_CHAN * pChan	/* pointer to channel */
    )
    {
    int oldlevel = intLock ();

    AU1000_UART *regs = (AU1000_UART *)pChan->regs;

    /* Enable UART module */
    
    regs->uart_enable = UART_ENABLE_CE;                 /* enable clocks */
    regs->uart_enable = UART_ENABLE_CE | UART_ENABLE_E; /* take away reset */

    /* initialize the driver function pointers in the SIO_CHAN's */
    
    pChan->pDrvFuncs    = &auSioDrvFuncs;

    /* set the non BSP-specific constants */

    pChan->getTxChar    = auSioDummyCallback;
    pChan->putRcvChar   = auSioDummyCallback;
    pChan->channelMode  = 0;                 /* initialized to undefined mode */
    pChan->options      = (CLOCAL | CREAD | CS8);
    pChan->mcr		= UART_MDMCTRL_I1;
    pChan->ier		= UART_INTEN_LIE;    /* necessary for servicing Break */

    /* set the requested baud rate */

    auSioBaudSet(pChan, pChan->baudRate);

    /* set the options */

    auSioOptsSet(pChan, pChan->options);

    intUnlock (oldlevel);
    }

/*******************************************************************************
*
* auSioOptsSet - set the serial options
*
* Set the channel operating mode to that specified.  All sioLib options
* are supported: CLOCAL, HUPCL, CREAD, CSIZE, PARENB, and PARODD.
* When the HUPCL option is enabled, a connection is closed on the last
* close() call and opened on each open() call.
*
* Note, this routine disables the transmitter.  The calling routine
* may have to re-enable it.
*
* RETURNS:
* Returns OK to indicate success, other wise ERROR is returned
*/

LOCAL STATUS auSioOptsSet
    (
    AUSIO_CHAN * pChan,	/* pointer to channel */
    UINT options	/* new hardware options */
    )
    {
    FAST int     oldlevel;		/* current interrupt level mask */
    AU1000_UART *regs = (AU1000_UART *)pChan->regs;

    if (options & 0xffffff00)
	return ERROR;

    pChan->lcr = 0; 
    pChan->mcr &= ~(UART_MDMCTRL_RT | UART_MDMCTRL_DT); /* clear RTS and DTR bits */
    
    /* word length */

    switch (options & CSIZE)
	{
	case CS5:
	    pChan->lcr = UART_LINECTRL_WLS_5; break;
	case CS6:
	    pChan->lcr = UART_LINECTRL_WLS_6; break;
	case CS7:
	    pChan->lcr = UART_LINECTRL_WLS_7; break;
	default:
	case CS8:
	    pChan->lcr = UART_LINECTRL_WLS_8; break;
	}

    /* stop bit */

    if (options & STOPB)
	pChan->lcr |= UART_LINECTRL_ST;
    else
	pChan->lcr &= ~UART_LINECTRL_ST;

    /* parity */

    pChan->lcr &= ~(UART_LINECTRL_PAR | UART_LINECTRL_PE); /* no parity */
    switch (options & (PARENB | PARODD))
	{
	case PARENB|PARODD:
            pChan->lcr |= (UART_LINECTRL_PE | UART_LINECTRL_PAR_O);
	    break;
	case PARENB:
            pChan->lcr |= (UART_LINECTRL_PE | UART_LINECTRL_PAR_E);
	    break;
	default:
	    break;
	}

    /* ensure interrupt disabled */

    regs->uart_inten = 0;

    /* modem status lines */

    if (!(options & CLOCAL))
	{
	/* !clocal enables hardware flow control(DTR/DSR) */
	pChan->mcr |= (UART_MDMCTRL_RT | UART_MDMCTRL_DT);
        pChan->ier &= ~UART_INTEN_TIE; /* disable transmit interrupt */
	pChan->ier |= UART_INTEN_MIE; /* enable modem status interrupt */
	}
    else
        pChan->ier &= ~UART_INTEN_MIE; /* disable modem status interrupt */ 

    oldlevel = intLock ();

    regs->uart_linectrl = pChan->lcr;
    regs->uart_mdmctrl = pChan->mcr;

    /* reset tx/rx, enable 16 bytes tx/rx FIFO */

    regs->uart_fifoctrl = UART_FIFOCTRL_RR | UART_FIFOCTRL_TR | UART_FIFOCTRL_FE;

    /* receiver enabled? */

    if (options & CREAD)  
        pChan->ier |= UART_INTEN_RIE;

    /* SIO in interrupt mode? */

    if (pChan->channelMode == SIO_MODE_INT)
	{
        regs->uart_inten = pChan->ier;
        }

    intUnlock (oldlevel);

    pChan->options = options;

    return OK;
    }

/*******************************************************************************
*
* auSioHup - hang up the modem control lines 
*
* Resets the RTS and DTR signals and clears both the receiver and
* transmitter sections.
*
* RETURNS: OK
*/

LOCAL STATUS auSioHup
    (
    AUSIO_CHAN * pChan 	/* pointer to channel */
    )
    {
    FAST int     oldlevel;	/* current interrupt level mask */
    AU1000_UART *regs = (AU1000_UART *)pChan->regs;

    oldlevel = intLock ();

    pChan->mcr &= ~(UART_MDMCTRL_RT | UART_MDMCTRL_DT);
    regs->uart_mdmctrl = pChan->mcr;
    regs->uart_fifoctrl = UART_FIFOCTRL_TR | UART_FIFOCTRL_RR;

    intUnlock (oldlevel);

    return (OK);
    }    

/*******************************************************************************
*
* auSioOpen - Set the modem control lines 
*
* Set the modem control lines(RTS, DTR) TRUE if not already set.  
* It also clears the receiver, transmitter and enables the fifo. 
*
* RETURNS: OK
*/

LOCAL STATUS auSioOpen
    (
    AUSIO_CHAN * pChan 	/* pointer to channel */
    )
    {
    FAST int     oldlevel;	/* current interrupt level mask */
    char mask;
    AU1000_UART *regs = (AU1000_UART *)pChan->regs;

    mask = regs->uart_mdmctrl & (UART_MDMCTRL_RT | UART_MDMCTRL_DT);

    if (mask != (UART_MDMCTRL_RT | UART_MDMCTRL_DT)) 
    	{
    	/* RTS and DTR not set yet */

    	oldlevel = intLock ();

        /* set RTS and DTR TRUE */

        pChan->mcr |= (UART_MDMCTRL_RT | UART_MDMCTRL_DT);
        regs->uart_mdmctrl = pChan->mcr;

    	/* clear Tx and receive and enable FIFO */

        regs->uart_fifoctrl = UART_FIFOCTRL_RR | UART_FIFOCTRL_TR | UART_FIFOCTRL_FE;

    	intUnlock (oldlevel);
        }

    return (OK);
    }

/******************************************************************************
*
* auSioBaudSet - change baud rate for channel
*
* This routine sets the baud rate for the UART. The interrupts are disabled
* during chip access.
*
* NOTE:
* - Baudrate = CPU / (SD * 2 * CLKDIV * 16)
*
* RETURNS: OK
*/

LOCAL STATUS auSioBaudSet
    (
    AUSIO_CHAN * pChan,	/* pointer to channel */
    UINT	   baud	/* requested baud rate */
    )
    {
    int   oldlevel;
    int   divisor = ((pChan->xtal + (8 * baud)) / (16 * baud));
    AU1000_UART *regs = (AU1000_UART *)pChan->regs;

    /* disable interrupts during chip access */

    oldlevel = intLock ();

    /* set clkdiv to use new baud rate */

    regs->uart_clkdiv = divisor;
    pChan->baudRate = baud;
 
    intUnlock (oldlevel);

    return (OK);
    }

/*******************************************************************************
*
* auSioModeSet - change channel mode setting
*
* This driver supports both polled and interrupt modes and is capable of
* switching between modes dynamically. 
*
* If interrupt mode is desired this routine enables the channels receiver and 
* transmitter interrupts. If the modem control option is TRUE, the Tx interrupt
* is disabled if the CTS signal is FALSE. It is enabled otherwise. 
*
* If polled mode is desired the device interrupts are disabled. 
*
* RETURNS:
* Returns a status of OK if the mode was set else ERROR.
*/

LOCAL STATUS auSioModeSet
    (
    AUSIO_CHAN * pChan,	/* pointer to channel */
    UINT	newMode	/* mode requested */
    )
    {
    FAST int     oldlevel;	/* current interrupt level mask */
    char mask;
    AU1000_UART *regs = pChan->regs;

    if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT))
        return (ERROR);
           

⌨️ 快捷键说明

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