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

📄 sndssio.c

📁 4510b的vxworks的BSP
💻 C
📖 第 1 页 / 共 2 页
字号:
/* sndsSio.c - Samsung SNDS100 serial driver */

/*
modification history
--------------------
01c,25nov99,ak  changed sndsTxStartup as per Samsung note
01b,08Oct99,ak	Added polled mode support
01a,22aug99,ak  adapated from WRS sio template
*/

/*
DESCRIPTION

This is an sio driver for Samsung's SNDS100 evaluation board for their
KS32C50100 microprocessor.  This is an ARM based processor with several 
integrated peripherals.  It has an interrupt controller, two 32-bit timers,
one Ethernet controller,two HDLC controllers, one IIC controller, general 
purpose I/O ports, and a 2 channel DMA controller.

The 2 UART channels integrated with the processor are controlled by this
driver.  Both the UARTs can work in interrupt mode as well as DMA mode.
This driver supports only the interrupt mode for the UARTs.

All the UART registers are accessible as 32-bit integers from the internal
system registers.  The macros SNDS_REG_READ and SNDS_REG_WRITE read and write
32-bit integers from and to the given addresses.  SNDS_SIO_DEFAULT_BAUD is
defined to 38400 in this file.  This is the default baud rate with which 
the UART channels will be initialized.  The channels are also initialized 
with one start bit, one stop bit, 8 bit data and no parity bits.

The driver is typically only called only by the BSP. The directly callable
routines in this module are sndsDevInit(), sndsDevInit2(), sndsIntRcv(), 
sndsIntTx(), and sndsIntErr().

The BSP calls sndsDevInit() to initialize or reset the device.
It connects the driver's interrupt handlers (sndsIntRcv, sndsIntTx,
and sndsIntErr), using intConnect().
After connecting the interrupt handlers, the BSP calls sndsDevInit2()
to inform the driver that interrupt mode operation is now possible.

INCLUDES:
sndsSio.h sioLib.h
*/

#include "vxWorks.h"
#include "sioLib.h"
#include "intLib.h"
#include "errno.h"
#include "sndsSio.h"
#include "ioLib.h"


#define SNDS_BAUD_MIN	1200
#define SNDS_BAUD_MAX	460860
#define SNDS_SIO_DEFAULT_BAUD 38400

/* Hardware abstraction macros */

/* local defines  */

#ifndef SNDS_REG_READ
#define SNDS_REG_READ(pChan, reg, result) \
	((result) = (*(volatile UINT32 *)((UINT32)(pChan)->regs + (reg))))
#endif	/*SNDS_REG_READ*/

#ifndef SNDS_REG_WRITE
#define SNDS_REG_WRITE(pChan, reg, data) \
	((*(volatile UINT32 *)((UINT32)(pChan)->regs + (reg))) = (data))
#endif	/*SNDS_REG_WRITE*/


/* for backward compatibility */

#ifndef	SIO_HUP
#   define SIO_OPEN	0x100A	/* open channel, raise DTR, RTS */
#   define SIO_HUP	0x100B	/* hang-up, lower DTR, RTS */
#endif

/* forward static declarations */

LOCAL int	sndsTxStartup (SIO_CHAN * pSioChan);
LOCAL int	sndsCallbackInstall (SIO_CHAN *pSioChan, int callbackType,
				    STATUS (*callback)(), void *callbackArg);
LOCAL int	sndsPollOutput (SIO_CHAN *pSioChan, char	outChar);
LOCAL int	sndsPollInput (SIO_CHAN *pSioChan, char *thisChar);
LOCAL int	sndsIoctl (SIO_CHAN *pSioChan, int request, void *arg);
LOCAL STATUS	dummyCallback (void);

/* local variables */

LOCAL	SIO_DRV_FUNCS sndsSioDrvFuncs =
    {
    sndsIoctl,
    sndsTxStartup,
    sndsCallbackInstall,
    sndsPollInput,
    sndsPollOutput
    };

LOCAL BOOL sndsIntrMode = FALSE;	/* interrupt mode allowed flag */

/******************************************************************************
*
* sndsDevInit - initialize a SNDS_DUSART
*
* This routine initializes the driver
* function pointers and then resets the chip in a quiescent state.
* The BSP must have already initialized all the device addresses and the
* baudFreq fields in the SNDS_DUSART structure before passing it to
* this routine.
*
* RETURNS: N/A
*/

void sndsDevInit
    (
    SNDS_CHAN * pChan
    )
    {
    /* initialize each channel's driver function pointers */

    pChan->sio.pDrvFuncs	= &sndsSioDrvFuncs;

    /* install dummy driver callbacks */

    pChan->getTxChar    = dummyCallback;
    pChan->putRcvChar	= dummyCallback;
    
    /* reset the chip */

    SNDS_REG_WRITE(pChan,SNDS_ULCON,(EXT_CLK | PARITY_NONE | ONE_STOP |WORD_LEN));


    /* setting polled mode is one way to make the device quiet */

    sndsIoctl ((SIO_CHAN *)pChan,SIO_MODE_SET,(void *)SIO_MODE_POLL);
	sndsIoctl ((SIO_CHAN *)pChan, SIO_BAUD_SET, (void *)SNDS_SIO_DEFAULT_BAUD);

    }

/******************************************************************************
*
* sndsDevInit2 - initialize a SNDS_DUSART, part 2
*
* This routine is called by the BSP after interrupts have been connected.
* The driver can now operate in interrupt mode.  Before this routine is
* called only polled mode operations should be allowed.
*
* RETURNS: N/A
* ARGSUSED
*/

void sndsDevInit2
    (
    SNDS_CHAN * pChan		/* device to initialize */
    )
    {
	char outchar = NULL;
    /* Interrupt mode is allowed */

    SNDS_REG_WRITE(pChan,SNDS_UCON,UCON_RX|UCON_TX);

	/* 
	 * Dummy write to TXBUF to start TX empty interrupt
	 */

	SNDS_REG_WRITE(pChan,SNDS_UTXBUF,outchar);
    sndsIntrMode = TRUE;
    }

/******************************************************************************
*
* sndsIntRcv - handle a channel's receive-character interrupt
*
* RETURNS: N/A
*/ 

void sndsIntRcv
    (
    SNDS_CHAN *	pChan		/* channel generating the interrupt */
    )
    {
    char            inChar;
    UINT32	    status;

    /*
     * Grab the input character from the chip and hand it off via a
     * callback. For chips with input FIFO's it is more efficient
     * to empty the entire FIFO here.
     */
    SNDS_REG_READ(pChan,SNDS_USTAT, status);

    if((status & USTAT_RX_READY) == USTAT_RX_READY)
    {
    SNDS_REG_READ(pChan,SNDS_URXBUF, inChar);
	(*pChan->putRcvChar) (pChan->putRcvArg, inChar);
    }
    }

/******************************************************************************
*
* sndsIntTx - handle a channels transmitter-ready interrupt
*
* RETURNS: N/A
*/ 

void sndsIntTx
    (
    SNDS_CHAN *	pChan		/* channel generating the interrupt */
    )
    {
    char            outChar;
	UINT32	status;
    /*
     * If there's a character to transmit then write it out, else reset
     * the transmitter. For chips with output FIFO's it is more efficient
     * to fill the entire FIFO here.
     */

    SNDS_REG_READ(pChan,SNDS_USTAT, status);	

    if((status & USTAT_TX_READY) != USTAT_TX_READY)	
		return;
	if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
		SNDS_REG_WRITE(pChan, SNDS_UTXBUF, outChar);
	else
	{	
	    if (pChan == &sndsChan[0])
		{
	        intDisable (INT_LVL_UARTTX0);
		    /* *(UINT32 *) SNDS_INT_CSR_PEND = (1 << INT_LVL_UARTTX0); */
		}
	    else
		{
	        intDisable (INT_LVL_UARTTX1);
		    /* *(UINT32 *) SNDS_INT_CSR_PEND = (1 << INT_LVL_UARTTX1); */
		}
	}
    }

/******************************************************************************
*
* sndsTxStartup - start the interrupt transmitter
*
* RETURNS: OK on success, ENOSYS if the device is polled-only, or
* EIO on hardware error.
*/

LOCAL int sndsTxStartup
    (
    SIO_CHAN * pSioChan                 /* channel to start */
    )
    {
    SNDS_CHAN * pChan = (SNDS_CHAN *)pSioChan;
	*(UINT32 *)SNDS_IOPMOD = 0xff ;

	if (pChan == &sndsChan[0])
	{
		SNDS_REG_WRITE(pChan, SNDS_UTXBUF, NULL);
		*(UINT32 *)SNDS_IOPDATA = 0x0f ;
	    /* *(UINT32 *) SNDS_INTPENDTST |= (1 << INT_LVL_UARTTX0); */
        intEnable (INT_LVL_UARTTX0);
	}
    else if (pChan == &sndsChan[1])
	{
		SNDS_REG_WRITE(pChan, SNDS_UTXBUF, NULL);
	    /* *(UINT32 *) SNDS_INTPENDTST |= (1 << INT_LVL_UARTTX1); */
        intEnable (INT_LVL_UARTTX1);
	}
    return (OK);
    }

/******************************************************************************
*
* sndsCallbackInstall - install ISR callbacks to get/put chars
*
* This driver allows interrupt callbacks for transmitting characters
* and receiving characters. In general, drivers may support other
* types of callbacks too.
*
* RETURNS: OK on success, or ENOSYS for an unsupported callback type.
*/ 

LOCAL int sndsCallbackInstall
    (
    SIO_CHAN *	pSioChan,               /* channel */
    int		callbackType,           /* type of callback */
    STATUS	(*callback)(),          /* callback */
    void *      callbackArg             /* parameter to callback */
    )
    {
    SNDS_CHAN * pChan = (SNDS_CHAN *)pSioChan;
    switch (callbackType)
	{
	case SIO_CALLBACK_GET_TX_CHAR:
	    pChan->getTxChar	= callback;
	    pChan->getTxArg	= callbackArg;
	    return (OK);

	case SIO_CALLBACK_PUT_RCV_CHAR:
	    pChan->putRcvChar	= callback;
	    pChan->putRcvArg	= callbackArg;
	    return (OK);

	default:
	    return (ENOSYS);
	}
    }

/*******************************************************************************
*
* sndsPollOutput - output a character in polled mode
*
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN
* if the output buffer if full. ENOSYS if the device is
* interrupt-only.
*/

LOCAL int sndsPollOutput
    (
    SIO_CHAN *	pSioChan,
    char	outChar
    )
    {
    SNDS_CHAN * pChan = (SNDS_CHAN *)pSioChan;
    UINT32	status;

    /* is the transmitter ready to accept a character? */

    SNDS_REG_READ (pChan, SNDS_USTAT, status);
    if ((status & USTAT_TX_READY) == 0x00)
		return (EAGAIN);

    /* write out the character */

    SNDS_REG_WRITE(pChan, SNDS_UTXBUF, outChar);
	return (OK);
    }

/******************************************************************************
*
* sndsPollInput - poll the device for input
*
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN
* if the input buffer if empty, ENOSYS if the device is
* interrupt-only.
*/

LOCAL int sndsPollInput
    (
    SIO_CHAN *	pSioChan,
    char *	thisChar
    )
    {
    SNDS_CHAN * pChan = (SNDS_CHAN *)pSioChan;
    UINT32	status;

    SNDS_REG_READ (pChan,SNDS_USTAT, status);

    if ((status & USTAT_RX_AVAIL) == 0x00)
		return (EAGAIN);	/* no input available at this time */

    /* got a character */

    SNDS_REG_READ(pChan, SNDS_URXBUF, *thisChar);

    return (OK);
    }

/******************************************************************************
*
* sndsModeSet - toggle between interrupt and polled mode
*
* RETURNS: OK on success, EIO on unsupported mode.
*/

LOCAL int sndsModeSet
    (
    SNDS_CHAN * pChan,		/* channel */
    uint_t	newMode        	/* new mode */
    )
    {
    UINT32	temp;


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


    /* Don't enter interrupt mode unless it is allowed. */

    if ((newMode == SIO_MODE_INT) && (!sndsIntrMode))
	return (EIO);

    /* set the new mode */

    pChan->mode = newMode;

    if (pChan->mode == SIO_MODE_INT)
		{
  
 	   	SNDS_REG_READ(pChan, SNDS_UCON, temp);
		temp &=UCON_RX_TX_RESET;	/**Reset RX and TX mode bits*/
    	temp |= (UCON_RX|UCON_TX);
    	SNDS_REG_WRITE(pChan,SNDS_UCON, temp);
		if (pChan == &sndsChan[0])
			{
        	intEnable(INT_LVL_UARTRX0);
			}
    	else if (pChan == &sndsChan[1])
			{
         	intEnable(INT_LVL_UARTRX1);

⌨️ 快捷键说明

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