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

📄 ppc860sioscc.c

📁 powerPC866 系列平台BSP移植开发的参考代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ppc860SioScc.c - Motorola MPC860 SCC UART serial driver */

/* Copyright 1984-1996 Wind River Systems, Inc. */
/* Copyright 1997 Motorola, Inc., All Rights Reserved */
#include "copyright_wrs.h"

/*
modification history
--------------------
01h,04feb98,kla  hooks for SCC Serial devices com2,3 & 4.
01g,04apr97,srr  setup to run on MPC860.
01f,28may96,dat  fixed SPR #5526, baud rate divisor calculation
01e,10oct95,ms   made poll input routine work if len(RX FIFO)>1 (SPR #5130).
01d,08sep95,myz  fixed the SPR #4678
01c,20jun95,ms   fixed comments for mangen
01b,15jun95,ms   updated for new driver structure
01a,22may95,myz  written (using m68360Serial.c).
*/

/*
DESCRIPTION
This is the driver for the SCC's in the internal Communications Processor (CP)
of the Motorola MPC860/821.  This driver only supports the SCC's in asynchronous
UART mode.

USAGE
A PPC860SCC_CHAN structure is used to describe the chip.
The BSP's sysHwInit() routine typically calls sysSerialHwInit()
which initializes all the values in the PPC860SCC_CHAN structure (except
the SIO_DRV_FUNCS) before calling ppc860SccDevInit().
The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() which
connects the chips interrupt (ppc860SccInt) via intConnect().

INCLUDE FILES: drv/sio/ppc860Sio.h
               drv/multi/ppc860Siu.h
               drv/multi/ppc860Cpm.h
*/

/* includes */

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

#if 1
  #include "drv/multi/ppc860Siu.h"
  #include "drv/multi/ppc860Cpm.h"
  #include "drv/sio/ppc860Sio.h"
#else
  #include "ppc860Siu.h"
  #include "ppc860Cpm.h"
  #include "ppc860Sio.h"
#endif

/* defines */

#define DEFAULT_BAUD 9600

/* forward declarations */

static  STATUS ppc860SccIoctl (PPC860SCC_CHAN *pChan,int request,int arg);
static  void   ppc860SccResetChannel (PPC860SCC_CHAN *pChan);
static  int    ppc860SccPollOutput (SIO_CHAN *,char);
static  int    ppc860SccPollInput (SIO_CHAN *,char *);
static  void   ppc860SccStartup (PPC860SCC_CHAN *);
static  int    ppc860SccCallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);

/* local driver function table */

static SIO_DRV_FUNCS ppc860SccSioDrvFuncs =
    {
    (int (*)())ppc860SccIoctl,
    (int (*)())ppc860SccStartup,
    (int (*)())ppc860SccCallbackInstall,
    (int (*)())ppc860SccPollInput,
    (int (*)(SIO_CHAN *,char))ppc860SccPollOutput
    };

/*******************************************************************************
*
* ppc860SccDevInit - initialize the SCC
*
* This routine is called to initialize the chip to a quiescent state.
*/

void ppc860SccDevInit
    (
    PPC860SCC_CHAN *pChan
    )
    {
    /* masks off this SCC's interrupt. */

    *CIMR(pChan->regBase) &=
         (~(CIPR_SCC4 << (3 - (pChan->uart.sccNum - 1) )));

    pChan->baudRate = DEFAULT_BAUD;
    pChan->pDrvFuncs = &ppc860SccSioDrvFuncs;
    }


/*******************************************************************************
*
* ppc860SccResetChannel - initialize the SCC
*/

static  void ppc860SccResetChannel
    (
    PPC860SCC_CHAN *pChan
    )
    {
    int scc;			/* the SCC number being initialized */
    int baud;			/* the baud rate generator being used */
    int frame;

    int oldlevel = intLock ();			/* LOCK INTERRUPTS */

    scc = pChan->uart.sccNum - 1;		/* get SCC number */
    baud = pChan->bgrNum - 1;			/* get BRG number */

    pChan->uart.intMask = CIPR_SCC4 << (3 - scc);

    /* set up SCC as NMSI */

    *SICR(pChan->regBase) |= (UINT32) (baud << (scc << 3));

    *SICR(pChan->regBase) |= (UINT32) ((baud << 3) << (scc << 3));

    /* setup SCC as NMSI and clear SCC clock sources */

    *SICR(pChan->regBase) &= ~( (1 << ((scc << 3) + 6)) |   /* SICR_SCx_MUX */
                                ((7 << 3) << (scc << 3)) |  /* SICR_RxCS_MSK */
                                (7 << (scc << 3)) );        /* SICR_TxCS_MUX */

    /* setup SCC clock sources */

    *SICR(pChan->regBase) |= (((baud << 3) << (scc << 3)) | /* SICR_RxCS_BRGx */
                              (baud << (scc << 3)));        /* SICR_TxCS_BRGx */

    /* reset baud rate generator */

    *pChan->pBaud |= BRGC_RST;
    while (*pChan->pBaud & BRGC_RST);

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

    /* set up transmit buffer descriptors */

    pChan->uart.txBdBase = (SCC_BUF *) (pChan->regBase + ((UINT32) pChan->uart.txBdBase));

    pChan->uart.pScc->param.tbase = (UINT16) ((UINT32) pChan->uart.txBdBase);
    pChan->uart.pScc->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 = SCC_UART_TX_BD_INT;

        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 |= SCC_UART_TX_BD_WRAP;

    /* set up receive buffer descriptors */

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

    pChan->uart.pScc->param.rbase = (UINT16) ((UINT32) pChan->uart.rxBdBase);
    pChan->uart.pScc->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 = SCC_UART_RX_BD_EMPTY | SCC_UART_RX_BD_INT;
        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 |= SCC_UART_TX_BD_WRAP;

    /* set SCC attributes to UART mode */

    pChan->uart.pSccReg->gsmrl = SCC_GSMRL_RDCR_X16 | SCC_GSMRL_TDCR_X16 | SCC_GSMRL_UART;

    pChan->uart.pSccReg->gsmrh = SCC_GSMRH_RFW | SCC_GSMRH_TFL;
    pChan->uart.pSccReg->psmr  =  SCC_UART_PSMR_FLC | SCC_UART_PSMR_CL_8BIT;
    pChan->uart.pSccReg->dsr	 = 0x7e7e;	/* no fractional stop bits */

    pChan->uart.pScc->param.rfcr  = 0x18;	/* supervisor data access */
    pChan->uart.pScc->param.tfcr  = 0x18;	/* supervisor data access */
    pChan->uart.pScc->param.mrblr = 0x1;	/* one character rx buffers */

    /* initialize parameter the SCC RAM */

    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->maxIdl      = 0x0;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->brkcr       = 0x1;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->parec       = 0x0;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->frmer       = 0x0;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->nosec       = 0x0;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->brkec       = 0x0;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->uaddr1      = 0x0;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->uaddr2      = 0x0;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->toseq       = 0x0;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character1  = 0x8000;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character2  = 0x8000;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character3  = 0x8000;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character4  = 0x8000;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character5  = 0x8000;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character6  = 0x8000;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character7  = 0x8000;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character8  = 0x8000;
    ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->rccm        = 0x8000;

    pChan->uart.pSccReg->scce = 0xffff;	/* clr events */

    /* enables the transmitter and receiver  */

    pChan->uart.pSccReg->gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;

    /* unmask interrupt */

    pChan->uart.pSccReg->sccm = SCC_UART_SCCX_RX | SCC_UART_SCCX_TX;
    *CIMR(pChan->regBase) |= pChan->uart.intMask;

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

/*******************************************************************************
*
* ppc860SccIoctl - special device control
*
* RETURNS: OK on success, EIO on device error, ENOSYS on unsupported
*          request.
*
*/

LOCAL STATUS ppc860SccIoctl
    (
    PPC860SCC_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 XXX
            if (arg >=  50 && arg <= 38400)	/* could go higher... */
		{
		/* 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) << BRGC_CD_SHIFT)) | BRGC_EN | BRGC_DIV16;
                else
                    *pChan->pBaud = (BRGC_CD_MSK & (baudRate << 1)) | BRGC_EN;
		}
#endif
#if 1
            if (arg > 300)
		{
		baudRate = pChan->clockRate / (16 * arg);
		*pChan->pBaud = (BRGC_CD_MSK & (baudRate << 1)) | BRGC_EN;
		}
	    else			/* set bit DIV16 for 300 & less */
		{
		baudRate = pChan->clockRate / (16 * 16 * arg);
		*pChan->pBaud = (BRGC_CD_MSK & (baudRate << 1)) | BRGC_EN | BRGC_DIV16;
		}
#endif
            pChan->baudRate = arg;
	    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)
                ppc860SccResetChannel(pChan);

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

⌨️ 快捷键说明

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