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

📄 s3c2410sio.c

📁 s2410测试程序,源码,用来深入了解三星2410芯片
💻 C
字号:
/* primeCellSio.c - ARM AMBA UART tty driver */

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

#include "copyright_wrs.h"

/*
modification history
--------------------
*/

/*
DESCRIPTION
*/
 
#include "vxWorks.h"
#include "intLib.h"
#include "errnoLib.h"
#include "errno.h"
#include "sioLib.h"
#include "s3c2410Sio.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) \
	(result) = (AMBA_UART_REG(pChan, reg))
#endif

#ifndef AMBA_UART_REG_WRITE
#define AMBA_UART_REG_WRITE(pChan, reg, data) \
	(AMBA_UART_REG(pChan, reg)) = (data)
#endif

#ifndef AMBA_UART_REG_BIT_SET
#define AMBA_UART_REG_BIT_SET(pChan, reg, data) \
	(AMBA_UART_REG(pChan, reg)) |= (data)
#endif

#ifndef AMBA_UART_REG_BIT_CLR
#define AMBA_UART_REG_BIT_CLR(pChan, reg, data) \
	(AMBA_UART_REG(pChan, reg)) &= ~(data)
#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 = 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;

    AMBA_UART_REG_WRITE(pChan, UART_FIFO_CON, 	0x00);
    AMBA_UART_REG_WRITE(pChan, UART_MODEM_CON, 	0x00);
    
    /*Line control register : Normal,No parity,1 stop,8 bits*/
    AMBA_UART_REG_WRITE(pChan, UART_LINE_CON, 	0x03);	
  
    /*
    //    [10]       [9]     [8]        [7]        [6]      [5]         [4]           [3:2]        [1:0]
    // Clock Sel,  Tx Int,  Rx Int, Rx Time Out, Rx err, Loop-back, Send break,  Transmit Mode, Receive Mode
    //     0          1       0    ,     0          1        0           0     ,       01          01
    //   PCLK       Level    Pulse    Disable    Generate  Normal      Normal        Interrupt or Polling
    */
    AMBA_UART_REG_WRITE(pChan, UART_CON, 	0x245);	/* Control register */

    /*ambaIoctl ((SIO_CHAN *)pChan, SIO_BAUD_SET, (void *)pChan->baudRate); */
    AMBA_UART_REG_WRITE(pChan, UART_BAUD_DIV,   (pChan->xtal / (16 * pChan->baudRate) - 1) );
    /*( (int)(pclk/16./baud) -1 ));	//Baud rate divisior register 0 */
    
    AMBA_UART_REG_WRITE(pChan, UART_TX_DATA, '\r');
    AMBA_UART_REG_WRITE(pChan, UART_TX_DATA, '\n');
    AMBA_UART_REG_WRITE(pChan, UART_TX_DATA, 'H');
    AMBA_UART_REG_WRITE(pChan, UART_TX_DATA, 'E');
    AMBA_UART_REG_WRITE(pChan, UART_TX_DATA, 'L');
    AMBA_UART_REG_WRITE(pChan, UART_TX_DATA, 'L');
    AMBA_UART_REG_WRITE(pChan, UART_TX_DATA, 'O');

   /* Clear Rx FIFO */
    for(i=0;i<16;i++)
    	AMBA_UART_REG_READ(pChan, UART_RX_DATA, discard);
    	
    ambaIoctl ((SIO_CHAN *)pChan, SIO_MODE_SET, (int)pChan->channelMode);
    }

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

	    /* disable interrupts during chip access */

	    oldlevel = intLock ();

	    /* Set baud rate divisor in UART */
	    AMBA_UART_REG_WRITE(pChan, UART_BAUD_DIV,   brd );
	    
	    pChan->baudRate = arg;
 
	    intUnlock (oldlevel);

	    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 interrupts. */
		AMBA_UART_REG_WRITE(pChan, UART_FIFO_CON, 	0x00);
		
		intEnable (pChan->levelRx);
		*(volatile UINT32 *)((UINT32)(S3C2410_INTSUBMSK)) &= ~pChan->intRxSubMask;
		
		}
	    else
		{
		/* Disable all interrupts for this UART. */ 
		intDisable (pChan->levelRx);
		
		*(volatile UINT32 *)((UINT32)(S3C2410_INTSUBMSK)) |= 
				(pChan->intTxSubMask|pChan->intRxSubMask);
		}

	    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
	     * in sioLib.h). Return OK or ENOSYS if this command is not
	     * implemented.  Note: if this command is unimplemented, it
	     * will be assumed that the driver options are CREAD | CS8
	     * (e.g., eight data bits, one stop bit, no parity, ints enabled).
	     */

	default:
	    status = ENOSYS;
	}

    return status;

    }

/*******************************************************************************
*
* primeCellSioIntTx - handle a transmitter interrupt 
*
* This routine handles write interrupts from the UART.
*
* RETURNS: N/A
*/

void primeCellSioIntTx 
    (
    AMBA_CHAN *	pChan	/* ptr to AMBA_CHAN describing this channel */
    )
    {
    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.
     */

    AMBA_UART_REG_READ(pChan, UART_TXRX_STATUS, status); 
    
    if((status & UART_TX_READY) != UART_TX_READY)    
        return;
    if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
        AMBA_UART_REG_WRITE(pChan, UART_TX_DATA, outChar);
    else
        {    
        *(volatile UINT32 *)((UINT32)(S3C2410_INTSUBMSK)) |= pChan->intTxSubMask;
        }
    }

/*****************************************************************************
*
* primeCellSioIntRx - handle a receiver interrupt 
*
* This routine handles read interrupts from the UART.
*
* RETURNS: N/A
*/

void primeCellSioIntRx
    (
    AMBA_CHAN *	pChan	/* ptr to AMBA_CHAN describing this channel */
    )
    {
        char inchar;
        char flags;
    
	/* While RX FIFO isn't empty, we have more data to read */
	AMBA_UART_REG_READ(pChan, UART_TXRX_STATUS, flags); 
	
	if ((flags & UART_RX_READY) == UART_RX_READY)
	    {
	    /* Read from data register. */
	    AMBA_UART_REG_READ(pChan, UART_RX_DATA, inchar);
	    (*pChan->putRcvChar) (pChan->putRcvArg, inchar);
	    }
    }

/******************************************************************************
*
* primeCellSioInt - handle any UART interrupt
*
* This routine handles interrupts from the UART and determines whether
* the source is a transmit interrupt or receive/receive-timeout interrupt.
*
* The Prime Cell UART generates a receive interrupt when the RX FIFO is
* half-full, and a receive-timeout interrupt after 32 bit-clocks have
* elapsed with no incoming data.
*
* RETURNS: N/A
*/

void primeCellSioInt
    (
    AMBA_CHAN * pChan   /* ptr to AMBA_CHAN describing this channel */
    )
    {
    char intId;

    /*AMBA_UART_REG_READ(pChan, UART_TXRX_STATUS, intId);*/
    
    intId = *(volatile UINT32 *)((UINT32)(S3C2410_INTSUBPND));
    
    /*if (intId & UART_TX_READY)*/
    if (intId & pChan->intTxSubMask)
    {
	primeCellSioIntTx (pChan);
	*(volatile UINT32 *)((UINT32)(S3C2410_INTSUBPND))|=pChan->intTxSubMask;
	}

    /*if (intId & UART_RX_READY)*/
    if(intId & pChan->intRxSubMask)
	{
	primeCellSioIntRx (pChan);
	*(volatile UINT32 *)((UINT32)(S3C2410_INTSUBPND))|=pChan->intRxSubMask;
	}

    /*AMBA_UART_REG_WRITE(pChan, UARTICR, intId);*/	/* clear interrupts */

    } 


/*******************************************************************************
*
* ambaTxStartup - transmitter startup routine
*
* Enable interrupt so that interrupt-level char output routine will be called.
*
* RETURNS: OK on success, ENOSYS if the device is polled-only, or
* EIO on hardware error.
*/

LOCAL int ambaTxStartup
    (
    SIO_CHAN *	pSioChan	/* ptr to SIO_CHAN describing this channel */
    )
    {
    AMBA_CHAN * pChan = (AMBA_CHAN *)pSioChan;

    if (pChan->channelMode == SIO_MODE_INT)
	{
	/*primeCellSioIntTx(pChan);*/
	*(volatile UINT32 *)((UINT32)(S3C2410_INTSUBMSK)) &= ~pChan->intTxSubMask;
	return OK;
	}
    else
	return ENOSYS;
    }

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

LOCAL int ambaPollOutput
    (
    SIO_CHAN *	pSioChan,	/* ptr to SIO_CHAN describing this channel */
    char	outChar 	/* char to output */
    )
    {
    AMBA_CHAN * pChan = (AMBA_CHAN *)pSioChan;
    FAST UINT32 pollStatus;

    AMBA_UART_REG_READ(pChan, UART_TXRX_STATUS, pollStatus);

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

    if ((pollStatus & UART_TX_READY) != UART_TX_READY)
	return EAGAIN;


    /* write out the character */

    AMBA_UART_REG_WRITE(pChan, UART_TX_DATA, outChar);	/* transmit character */
    
    return OK;
    }

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

LOCAL int ambaPollInput
    (
    SIO_CHAN *	pSioChan,	/* ptr to SIO_CHAN describing this channel */
    char *	thisChar	/* pointer to where to return character */
    )
    {
    AMBA_CHAN * pChan = (AMBA_CHAN *)pSioChan;
    FAST UINT32 pollStatus;

    AMBA_UART_REG_READ(pChan, UART_TXRX_STATUS, pollStatus);

    if ((pollStatus & UART_RX_READY) != UART_RX_READY)
	return EAGAIN;


    /* got a character */

    AMBA_UART_REG_READ(pChan, UART_RX_DATA, *thisChar);
    
    return OK;
    }

/******************************************************************************
*
* ambaCallbackInstall - install ISR callbacks to get/put chars.
*
* This routine installs interrupt callbacks for transmitting characters
* and receiving characters.
*
* RETURNS: OK on success, or ENOSYS for an unsupported callback type.
*
*/

LOCAL int ambaCallbackInstall
    (
    SIO_CHAN *	pSioChan,	/* ptr to SIO_CHAN describing this channel */
    int		callbackType,	/* type of callback */
    STATUS	(*callback)(),	/* callback */
    void *	callbackArg	/* parameter to callback */
		 
    )
    {
    AMBA_CHAN * pChan = (AMBA_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;
	}

    }

⌨️ 快捷键说明

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