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

📄 at91sio.c

📁 ARM7开发板 AT91EB01 BSP源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* at91Sio.c - Atmel AT91 USART tty driver */

/* Copyright 1999 ARM Limited */

/*
modification history
--------------------
01a,25jun99,jpd  wriiten.
*/




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

/* Make all of code in file dependent upon this symbol */

#ifdef INCLUDE_SERIAL

/* defines */


/* globals */

int at91SioIntErrs = 0;

/* function prototypes */

LOCAL STATUS at91SioDummyCallback (void);
LOCAL void at91SioInitChannel (AT91_SIO_CHAN * pChan);
LOCAL STATUS at91SioIoctl (SIO_CHAN * pSioChan, int request, int arg);
LOCAL int at91SioTxStartup (SIO_CHAN * pSioChan);
LOCAL int at91SioCallbackInstall (SIO_CHAN * pSioChan, int callbackType,
			       STATUS (*callback)(), void * callbackArg);
LOCAL int at91SioPollInput (SIO_CHAN * pSioChan, char *);
LOCAL int at91SioPollOutput (SIO_CHAN * pSioChan, char);

/* driver functions */

LOCAL SIO_DRV_FUNCS at91SioDrvFuncs =
    {
    (int (*)())at91SioIoctl,
    at91SioTxStartup,
    at91SioCallbackInstall,
    at91SioPollInput,
    at91SioPollOutput
    };

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

LOCAL STATUS at91SioDummyCallback (void)
    {
    return ERROR;
    }

/*******************************************************************************
*
* at91SioDevInit - initialise an AT91 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
* AT91_SIO_CHAN structure.
*
* RETURNS: N/A
*/

void at91SioDevInit
    (
    AT91_SIO_CHAN *	pChan	/* ptr to AT91_SIO_CHAN describing this chan */
    )
    {
    int oldlevel = intLock();

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

    pChan->sio.pDrvFuncs = &at91SioDrvFuncs;


    /* set the non BSP-specific constants */

    pChan->getTxChar = at91SioDummyCallback;
    pChan->putRcvChar = at91SioDummyCallback;

    pChan->channelMode = 0;    /* am undefined mode */


    /* initialise the chip */

    at91SioInitChannel (pChan);


    intUnlock (oldlevel);

    return;
    }

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

LOCAL void at91SioInitChannel
    (
    AT91_SIO_CHAN *	pChan	/* ptr to AT91_SIO_CHAN describing this chan */
    )
    {
    UINT32 temp;

    /* reset USART: Tx, Rx and clear error status */

    AT91_USART_REG_WRITE (pChan, AT91_US_CR, \
			    (AT91_US_RSTRX | AT91_US_RSTTX | AT91_US_RSTSTA));

#ifndef AT91_USE_PDC
    /* disable Peripheral data Controller */

    AT91_USART_REG_WRITE (pChan, AT91_US_RCR, 0);
    AT91_USART_REG_WRITE (pChan, AT91_US_RPR, 0);
    AT91_USART_REG_WRITE (pChan, AT91_US_TCR, 0);
    AT91_USART_REG_WRITE (pChan, AT91_US_TPR, 0);
#else /* AT91_USE_PDC */
    AT91_USART_REG_WRITE (pChan, AT91_US_RTOR, 8);	/* timeout ~= 4 chars */
						/* start with swing-buffer A */
    AT91_USART_REG_WRITE (pChan, AT91_US_RPR, (UINT32)(&pChan->rxBuffA[0]));
    AT91_USART_REG_WRITE (pChan, AT91_US_RCR, AT91_RXBUFF_SIZE);
    pChan->buffInUse = 0;
    AT91_USART_REG_WRITE (pChan, AT91_US_TPR, (UINT32)(&pChan->txBuff[0]));
    AT91_USART_REG_WRITE (pChan, AT91_US_TCR, 0);
#endif /* AT91_USE_PDC */


    /* Enable Rx and Tx */

    AT91_USART_REG_WRITE (pChan, AT91_US_CR, (AT91_US_RXEN | AT91_US_TXEN));

    /*
     * Set word format: set 8 bits, 1 stop bit, no parity, in
     * normal (non-loopback), asynchronous mode.
     *
     * USART clocking mode has been configured in sysSerial.c.
     */

    AT91_USART_REG_READ (pChan, AT91_US_MR, temp);
    temp &= ~0x30;	/* clear all except USCLKS field */
    AT91_USART_REG_WRITE (pChan, AT91_US_MR,(temp | AT91_US_CHRL_8 | AT91_US_NOPAR));


    /* Set baud rate divisor */

    AT91_USART_REG_WRITE (pChan, AT91_US_BRGR,(pChan->xtal / (16 * pChan->baudRate)));

    /* Disable Transmitter Time Guard function */

    AT91_USART_REG_WRITE (pChan, AT91_US_TTGR, 0);

    /*
     * Enable USART Rx and Tx interrupts: errors and data. First disable
     * unwanted interrupts, then enable the desired ones.
     */

#ifndef AT91_USE_PDC
    AT91_USART_REG_WRITE (pChan, AT91_US_IDR, AT91_US_TXRDY | AT91_US_ENDRX | \
				 	      AT91_US_ENDTX | AT91_US_TIMEOUT);

    /* Enable TxEmpty (THR and TSR empty) and RxRDY (RHR full) plus errors */

    AT91_USART_REG_WRITE (pChan, AT91_US_IER, AT91_US_RXRDY | AT91_US_RXBRK | \
					      AT91_US_OVRE  | AT91_US_FRAME | \
					      AT91_US_PARE  | AT91_US_TXEMPTY);
#else	/* AT91_USE_PDC */
    AT91_USART_REG_WRITE (pChan, AT91_US_IDR, AT91_US_RXRDY | AT91_US_TXRDY | \
					      AT91_US_TXEMPTY);

    /*
     * Enable ENDTX, and ENDRX (Tx, Rx xfer complete), and Rx timeout.
     * Also, start the timeout.
     */

    AT91_USART_REG_WRITE (pChan, AT91_US_IER, AT91_US_RXBRK | AT91_US_ENDRX | \
					      AT91_US_ENDTX | AT91_US_OVRE | \
					      AT91_US_FRAME | AT91_US_PARE | \
					      AT91_US_TIMEOUT);
    AT91_USART_REG_WRITE (pChan, AT91_US_CR, AT91_US_STTTO);
#endif	/* AT91_USE_PDC */
    }

/*******************************************************************************
*
* at91SioIoctl - 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 at91SioIoctl
    (
    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 */
    AT91_SIO_CHAN * pChan = (AT91_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 = pChan->xtal / (16 * arg);

	    if (brd & ~0xFFFF)
		{
		status = EIO;		/* baud rate out of range */
		break;
		}


	    AT91_USART_REG_WRITE (pChan, AT91_US_BRGR, brd);

	    pChan->baudRate = arg;

	    break;


	case SIO_BAUD_GET:

	    /* Get the baud rate and return OK */

	    *(int *)arg = pChan->baudRate;
	    break;


	case SIO_MODE_SET:
	    /*
	     * Set the mode (e.g., to interrupt or polled). Return OK
	     * or EIO for an unknown or unsupported mode.
	     */

	    if ((arg != SIO_MODE_POLL) && (arg != SIO_MODE_INT))
		{
		status = EIO;
		break;
		}

	    oldlevel = intLock ();

	    if (arg == SIO_MODE_INT)
		{
		/* Enable appropriate interrupt */

		intEnable (pChan->level);
		}
	    else
		{
		/* Disable the interrupt */

		intDisable (pChan->level);
		}

	    pChan->channelMode = arg;

	    intUnlock (oldlevel);
	    break;


	case SIO_MODE_GET:

	    /* Get the current mode and return OK */

	    *(int *)arg = pChan->channelMode;
	    break;


	case SIO_AVAIL_MODES_GET:

	    /* Get the available modes and return OK */

	    *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
	    break;


	case SIO_HW_OPTS_SET:

	    /*
	     * Optional command to set the hardware options (as defined
	     * in sioLib.h).
	     * Return OK, or ENOSYS if this command is not implemented.
	     * Note: several hardware options are specified at once.
	     * This routine should set as many as it can and then return
	     * OK. The SIO_HW_OPTS_GET is used to find out which options
	     * were actually set.
	     */

	case SIO_HW_OPTS_GET:

	    /*
	     * Optional command to get the hardware options (as defined

⌨️ 快捷键说明

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