📄 ppc860sccsio.c
字号:
/* ppc860SccSio.c - Motorola MPC800 SCC UART serial driver *//* Copyright 1984-1996 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01a,25may01,wmj adapted from ppc860Sio.c and updated for SCC part*//*DESCRIPTIONThis is the driver for the SCCs in the internal Communications Processor (CP)of the Motorola MPC68860/68821. This driver only supports the SCCs in asynchronous UART mode.USAGEA PPC800SCC_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 (exceptthe SIO_DRV_FUNCS) before calling ppc860SccDevInit().The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() whichconnects the chip's interrupts via intConnect().INCLUDE FILES: drv/sio/ppc860Sio.h*//* includes */#include "vxWorks.h"#include "intLib.h"#include "errno.h"#include "sioLib.h"#include "drv/multi/ppc860Siu.h"#include "drv/multi/ppc860Cpm.h"#include "drv/sio/ppc860Sio.h"/* defines */#define DEFAULT_BAUD 9600/* forward declarations */LOCAL STATUS ppc860SccIoctl (PPC860SCC_CHAN *pChan,int request,int arg);LOCAL void ppc860SccResetChannel (PPC860SCC_CHAN *pChan);LOCAL int ppc860SccPollOutput (SIO_CHAN *,char);LOCAL int ppc860SccPollInput (SIO_CHAN *,char *);LOCAL void ppc860SccStartup (PPC860SCC_CHAN *);LOCAL int ppc860SccCallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);LOCAL int ppc860SccDummy(void);/* local driver function table */LOCAL SIO_DRV_FUNCS ppc860SccSioDrvFuncs = { (int (*)()) ppc860SccIoctl, (int (*)()) ppc860SccStartup, (int (*)()) ppc860SccCallbackInstall, (int (*)()) ppc860SccPollInput, (int (*)(SIO_CHAN *,char)) ppc860SccPollOutput }; int rcvNums = 0;int sndNums = 0;/********************************************************************************* ppc860SccDevInit - initialize the SCC** This routine is called to initialize the chip to a quiescent state.* Note that the `smcNum' field of PPC860SCC_CHAN must be either 1 or 2.*/void ppc860SccDevInit ( PPC860SCC_CHAN *pChan ) { /* masks off this SCC's interrupt. */ * CIMR(pChan->regBase) &= (~(CIMR_SCC1 >> (pChan->uart.sccNum - 1))); pChan->baudRate = DEFAULT_BAUD; pChan->pDrvFuncs = &ppc860SccSioDrvFuncs; pChan->getTxChar = ppc860SccDummy; pChan->putRcvChar = ppc860SccDummy; }/********************************************************************************* ppc860SccResetChannel - initialize the SCC*/LOCAL void ppc860SccResetChannel ( PPC860SCC_CHAN *pChan ) { int scc; /* the SCC number being initialized. begin with 0. */ int baud; /* the baud rate generator being used */ int frame; SCC_UART_PROTO *pSccUart; int oldlevel = intLock (); /* lock interrupts */ scc = pChan->uart.sccNum - 1; /* get SCC number */ baud = pChan->bgrNum - 1; /* get BRG number */ pChan->uart.intMask = CIMR_SCC1 >> scc; /* set up SCC as NMSI, select Baud Rate Generator */ switch( baud ) { default: /* default to BRG1 */ case 0: * SICR(pChan->regBase) |= ((SICR_T1CS_BRG1|SICR_R1CS_BRG1) << (8 * scc)); break; case 1: * SICR(pChan->regBase) |= ((SICR_T1CS_BRG2|SICR_R1CS_BRG2) << (8 * scc)); break; case 2: * SICR(pChan->regBase) |= ((SICR_T1CS_BRG3|SICR_R1CS_BRG3) << (8 * scc)); break; case 3: * SICR(pChan->regBase) |= ((SICR_T1CS_BRG4|SICR_R1CS_BRG4) << (8 * scc)); break; } /* reset baud rate generator, wait for reset to clear... */ *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 = BD_TX_INTERRUPT_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; /* 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 = 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 SCC Rx FIFO is 8 bits width */ pChan->uart.pSccReg->gsmrh = SCC_GSMRH_RFW; /* set SCC Tx and Rx DPLL clock rate are 16x, and set UART mode.*/ pChan->uart.pSccReg->gsmrl = SCC_GSMRL_TDCR_X16 | \ SCC_GSMRL_RDCR_X16 | \ SCC_GSMRL_UART; /*| SCC_GSMRL_LOOPBACK; gtt 04.2*/ /* set SCC attributes to standard UART mode */ pChan->uart.pSccReg->psmr = PSMR_FLC | PSMR_CL_8_BITS|PSMR_UM_NORMAL; /* initialize parameter RAM area for this SCC */ 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 */ /* protocol relativity of SCC for UART */ pSccUart = (SCC_UART_PROTO *)(pChan->uart.pScc->prot); pSccUart->maxIdl = 0x0; /* no idle features */ pSccUart->brkcr = 0x1; /* xmit 1 BRK on stop */ pSccUart->parec = 0x0; /* receive parity error counter */ pSccUart->frmer = 0x0; /* receive framing error counter */ pSccUart->nosec = 0x0; /* receive noise counter */ pSccUart->brkec = 0x0; /* receive break condition counter */ pSccUart->brkln = 0x0; /* no breaks received yet */ pSccUart->uaddr1 = 0x0; /* uart address character 1 */ pSccUart->uaddr2 = 0x0; /* uart address character 2 */ pSccUart->toseq = 0x0; /* transmit out-of-sequence character */ pSccUart->character1 = 0x8000; /* control character 1 */ pSccUart->character2 = 0x8000; /* control character 2 */ pSccUart->character3 = 0x8000; /* control character 3 */ pSccUart->character4 = 0x8000; /* control character 4 */ pSccUart->character5 = 0x8000; /* control character 5 */ pSccUart->character6 = 0x8000; /* control character 6 */ pSccUart->character7 = 0x8000; /* control character 7 */ pSccUart->character8 = 0x8000; /* control character 8 */ pSccUart->rccm = 0xc0ff; /* receive control character mask */ /* clear all events */ pChan->uart.pSccReg->scce = 0xffff; /* unmask interrupt (Tx, Rx only) */ pChan->uart.pSccReg->sccm = SCC_UART_SCCX_RX | SCC_UART_SCCX_TX; *CIMR(pChan->regBase) |= pChan->uart.intMask; /* enables the transmitter and receiver */ pChan->uart.pSccReg->gsmrl |= SCC_GSMRL_ENT|SCC_GSMRL_ENR; 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 (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; 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) ppc860SccResetChannel(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; for (i=0; i < pChan->uart.txBdNum; i++) while (pChan->uart.txBdBase [(pChan->uart.txBdNext + i) % pChan->uart.txBdNum]. statusMode & BD_TX_READY_BIT); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -