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

📄 m8260smcsio.c

📁 au1500开发的应用程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* m8260SmcSio.c - Motorola MPC8260 SMC UART serial driver */

/* Copyright 1984-2001 Wind River Systems, Inc. */
#include "copyright_wrs.h"

/*
modification history
--------------------
01a,17feb05,fhchen  adopted from wrSbc8260Atm/smc8260Sio.c (ver 01e) 
*/

/*
DESCRIPTION

This is the driver for the SMCs in the internal Communications Processor (CP)
of the Motorola MPC8260.  This driver only supports the SMCs in 
asynchronous UART mode.

USAGE
A PPC8260SMC_CHAN structure is used to describe the chip.
The BSP's sysHwInit() routine typically calls sysSerialHwInit(),
which initializes some values in the PPC8260SMC_CHAN structure (except
the SIO_DRV_FUNCS) before calling smc8260DevInit().

The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() which
connects the chip's interrupts via intConnect().

INCLUDE FILES: m8260SmcSio.h
*/

/* includes */

#include "vxWorks.h"
#include "intLib.h"
#include "errno.h"
#include "sioLib.h"
#include "cacheLib.h"

#include "drv/mem/m8260Siu.h"
#include "drv/sio/m8260Brg.h"
#include "drv/sio/m8260Cp.h"
#include "drv/sio/m8260CpmMux.h"

#include "m8260SmcSio.h"
#include "m8260IntrCtl.h"

/* defines */

#define SMC_DEFAULT_BAUD	9600
#define M8260_SMC_POLL_OUT_TIMEOUT	10000

/* forward declarations */

LOCAL STATUS smc8260Ioctl (PPC8260SMC_CHAN *pChan,int request,int arg);
LOCAL void   smc8260ResetChannel (PPC8260SMC_CHAN *pChan);
LOCAL int    smc8260PollOutput (SIO_CHAN *,char);
LOCAL int    smc8260PollInput (SIO_CHAN *,char *);
LOCAL void   smc8260Startup (PPC8260SMC_CHAN *);
LOCAL int    smc8260CallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);

/* local driver function table */

LOCAL SIO_DRV_FUNCS smc8260SioDrvFuncs =
    {
    (int (*)())                smc8260Ioctl,
    (int (*)())                smc8260Startup,
    (int (*)())                smc8260CallbackInstall,
    (int (*)())                smc8260PollInput,
    (int (*)(SIO_CHAN *,char)) smc8260PollOutput
    };

/*******************************************************************************
*
* smc8260DevInit - initialize the SMC
*
* This routine is called to initialize the chip to a quiescent state.
* Note that the `smcNum' field of PPC8260SMC_CHAN must be either 1 or 2.
*
* RETURNS: N/A.
*/

void smc8260DevInit
    (
    PPC8260SMC_CHAN *pChan
    )
    {
    /* masks off this SMC's interrupt. SIMR_L[SMC1] is bit 19, SMC2 is bit 20 */
	
    *M8260_SIMR_L(pChan->regBase) &= (~(0x00001000 >> (pChan->uart.smcNum - 1)));

    pChan->baudRate  = SMC_DEFAULT_BAUD;
    pChan->pDrvFuncs = &smc8260SioDrvFuncs;
    }

/*******************************************************************************
*
* smc8260ResetChannel - reset the SMC channel
*
* This routine reset the SMC channel. It select and reset baud rate generator,
* set baud rate, initialize Tx/Rx buffer descriptors, initialize parameter RAM
* area, clear all events and enable Tx/Rx interrupt.
*
* RETURNS: N/A.
*/

LOCAL void smc8260ResetChannel 
    (
    PPC8260SMC_CHAN *pChan
    )
    {
    int smc;			/* the SMC number being initialized */
    int baud;			/* the baud rate generator being used */
    int frame;

    int oldlevel = intLock ();	/* lock interrupts */ 

    smc  = pChan->uart.smcNum - 1;		/* get SMC number */
    baud = pChan->bgrNum - 1;			/* get BRG number */

    pChan->uart.intMask = 0x00001000 >> smc;

    /* set up SMC as NMSI, select Baud Rate Generator,see table 15-7 in manual */

    switch( baud ) 
	{
	default:        /* default to BRG1 */
	case 0:         /* Select BRG1 */ 
	    * CMXSMR(pChan->regBase) |= (0x00 >> (4 * smc));
	    break;
	case 1:         /* Select BRG2 */ 
	    * CMXSMR(pChan->regBase) |= (0x00 >> (4 * smc));
	    break;
	case 6:         /* select BRG7 */
	    * CMXSMR(pChan->regBase) |= (0x10 >> (4 * smc));
	    break;
	case 7:         /* select BRG8 */
	    * CMXSMR(pChan->regBase) |= (0x10 >> (4 * smc));
	    break;
        }
 
    /* reset baud rate generator, wait for reset to clear... */
 
    *pChan->pBaud |= M8260_BRGC_RST;
    while (*pChan->pBaud & M8260_BRGC_RST);

    smc8260Ioctl (pChan, SIO_BAUD_SET, pChan->baudRate);

    /*
     * set up transmit buffer descriptors
     * txBdBase was initialized in sysSerialHwInit as relative address.
     * Problem: if IMMR was changed after call to m82xxDpramLibInit?
     */

    pChan->uart.txBdBase = (SMC_BUF *) (pChan->regBase +
			 ((UINT32) pChan->uart.txBdBase )); 
    pChan->uart.pSmc->param.tbase = (UINT16) ((UINT32) pChan->uart.txBdBase);
    pChan->uart.pSmc->param.tbptr = (UINT16) ((UINT32) pChan->uart.txBdBase);
    pChan->uart.txBdNext = 0;

    /* initialize each transmit buffer descriptor */

    for (frame = 0; frame < pChan->uart.txBdNum; frame++)
        {
        pChan->uart.txBdBase[frame].statusMode = BD_TX_INTERRUPT_BIT; /* I bit */

        pChan->uart.txBdBase[frame].dataPointer = pChan->uart.txBufBase +
                                                (frame * pChan->uart.txBufSize);
        }

    /* set the last BD to wrap to the first */

    pChan->uart.txBdBase[(frame - 1)].statusMode |= BD_TX_WRAP_BIT; /* W bit */

    /*
     * set up receive buffer descriptors
     * rxBdBase was initialized in sysSerialHwInit as relative address.
     */

    pChan->uart.rxBdBase = (SMC_BUF *) (pChan->regBase +
		         ((UINT32) pChan->uart.rxBdBase ));

    pChan->uart.pSmc->param.rbase = (UINT16) ((UINT32) pChan->uart.rxBdBase);
    pChan->uart.pSmc->param.rbptr = (UINT16) ((UINT32) pChan->uart.rxBdBase);
    pChan->uart.rxBdNext = 0;

    /* initialize each receive buffer descriptor */
	
    for (frame = 0; frame < pChan->uart.rxBdNum; frame++)
        {
        pChan->uart.rxBdBase[frame].statusMode = BD_RX_EMPTY_BIT |
						 BD_RX_INTERRUPT_BIT;
        pChan->uart.rxBdBase[frame].dataLength = 1; /* char oriented */
        pChan->uart.rxBdBase[frame].dataPointer = pChan->uart.rxBufBase + frame;
        }

    /* set the last BD to wrap to the first */

    pChan->uart.rxBdBase[(frame - 1)].statusMode |= BD_RX_WRAP_BIT;

    /* set SMC attributes to standard UART mode */

    pChan->uart.pSmcReg->smcmr = SMCMR_STD_MODE;

    /* initialize parameter RAM area for this SMC */

    pChan->uart.pSmc->param.rfcr   = 0x18;	/* supervisor data access */
    pChan->uart.pSmc->param.tfcr   = 0x18;	/* supervisor data access */
    pChan->uart.pSmc->param.mrblr  = 0x1;	/* one character rx buffers */
    pChan->uart.pSmc->param.maxidl = 0x0;	/* no idle features */
    pChan->uart.pSmc->param.brkln  = 0x0;	/* no breaks received yet */
    pChan->uart.pSmc->param.brkec  = 0x0;	/* zero break condition ctr */
    pChan->uart.pSmc->param.brkcr  = 0x1;	/* transmit 1 BRK on stop */

    /* clear all events: set bit in smce to clear event */

    pChan->uart.pSmcReg->smce = SMCE_ALL_EVENTS;

    /* enables the transmitter and receiver  */

    pChan->uart.pSmcReg->smcmr |= SMCMR_TEN | SMCMR_REN;

    /* unmask interrupt (Tx, Rx only) */

    pChan->uart.pSmcReg->smcm  = SMCM_TX_MSK | SMCM_RX_MSK;
    *M8260_SIMR_L(pChan->regBase) |= pChan->uart.intMask;

                     
    intUnlock (oldlevel);			/* UNLOCK INTERRUPTS */
    }

/*******************************************************************************
*
* smc8260Ioctl - special device control
*
* This routine support device specific ioctl commands, including buad set,
* baud get, mode set, mode get, available mode get.
*
* RETURNS: OK on success, EIO on device error, ENOSYS on unsupported
*          request.
*/

LOCAL STATUS smc8260Ioctl
    (
    PPC8260SMC_CHAN *	pChan,		/* device to control */
    int			request,	/* request code */
    int			arg		/* some argument */
    )
    {
    int		baudRate;
    int 	oldlevel;
    STATUS 	status = OK;

    switch (request)
	{
	case SIO_BAUD_SET:
            if (arg >=  SMC_MIN_BAUD && arg <= SMC_MAX_BAUD)
		{
		/* calculate proper counter value, then enable BRG */

		baudRate = (pChan->clockRate + (8 * arg)) / (16 * arg);

		if (--baudRate > 0xfff)
		    *pChan->pBaud = (BRGC_CD_MSK &
		    (((baudRate + 8) / 16) << M8260_BRGC_CD_SHIFT)) | M8260_BRGC_EN |
		    M8260_BRGC_DIV16;
                else
                    *pChan->pBaud = (BRGC_CD_MSK & 
			(baudRate << 1)) | M8260_BRGC_EN;

                pChan->baudRate = arg;
		}
            else
	        status = EIO;
	    break;
    
	case SIO_BAUD_GET:
	    * (int *) arg = pChan->baudRate;
	    break;

	case SIO_MODE_SET:
            if (!((int) arg == SIO_MODE_POLL || (int) arg == SIO_MODE_INT))
                {
                status = EIO;
                break;
                }

            /* lock interrupt  */

            oldlevel = intLock();

            /* initialize channel on first MODE_SET */

            if (!pChan->channelMode)
                smc8260ResetChannel(pChan);

            /*
             * if switching from POLL to INT mode, wait for all characters to
             * clear the output pins
             */

            if ((pChan->channelMode == SIO_MODE_POLL) && (arg == SIO_MODE_INT))
                {
		int i;

                /* if R bit is set, the buffer has not been completely sent */

                for (i=0; i < pChan->uart.txBdNum; i++)
                    while (pChan->uart.txBdBase
                           [(pChan->uart.txBdNext + i) % pChan->uart.txBdNum].
                           statusMode & BD_TX_READY_BIT);

                }

            if (arg == SIO_MODE_INT)
		{
                * M8260_SIPNR_L(pChan->regBase) = pChan->uart.intMask;
				/* reset the SMC's interrupt status bit */

		* M8260_SIMR_L(pChan->regBase) |= pChan->uart.intMask;
				/* enable this SMC's interrupt  */

		pChan->uart.pSmcReg->smce = SMCE_RX;	
				/* reset the receiver status bit */ 

                pChan->uart.pSmcReg->smcm = SMCM_RX_MSK | SMCM_TX_MSK;
				/* enables receive and transmit interrupts */
		}

⌨️ 快捷键说明

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