📄 ppc555scisio.c
字号:
/* ppc555SciSio.c - MPC555 SCI serial driver *//* Copyright 1984-1999 Wind River Systems, Inc. *//*modification history--------------------01c,27apr99,zl fixed mode set to allow switch between polled and intr mode01b,19apr99,zl added support for queued mode, set default baud rate01a,22mar99,zl written based on m68332Sio.c*//*DESCRIPTIONThis is the driver for SCIs of the QSMC the the Motorola PPC555. The SMC has two SCI channels. Both channels are compatible with earlier SCI devices fromMotorola (eg. MC68332), with enhancements to allow external baud clock sourceand queued operation fro the first SCI channel. .SH DATA STRUCTURESAn PPC555SCI_CHAN data structure is used to describe each channel, thisstructure is described in h/drv/sio/ppc555SciSio.h. Based on the "options" field of this structure, the driver can work in queued or non-queued mode.Only the first SCI of the QSMC on the PowerPC 555 provides queued modeoperation..SH CALLBACKSServicing a "transmitter ready" interrupt involves making a callback toa higher level library in order to get a character to transmit. Bydefault, this driver installs dummy callback routines which do nothing.A higher layer library that wants to use this driver (e.g. ttyDrv)will install its own callback routine using the SIO_INSTALL_CALLBACKioctl command. Likewise, a receiver interrupt handler makes a callbackto pass the character to the higher layer library. .SH MODESThis driver supports both polled and interrupt modes..SH USAGEThe BSP's sysHwInit() routine typically calls sysSerialHwInit(),which initializes all the values in the PPC555SCI_CHAN structure (exceptthe SIO_DRV_FUNCS) before calling m68332DevInit().The BSP's sysHwInit2() routine typically calls sysSerialHwInit2(), whichconnects the chips interrupt (m68332Int) via intConnect()..SH INCLUDE FILES:drv/sio/ppc555SciSio.h sioLib.h.SH SEE ALSO:.I "Section 14 QUEUED SERIAL MULTI-CHANNEL MODULE, MPC555 User抯 Manual"*/#include "vxWorks.h"#include "sioLib.h"#include "intLib.h"#include "errno.h"#include "drv/sio/ppc555SciSio.h"#define PPC555SCI_BAUD_MIN 75#define PPC555SCI_BAUD_MAX 115200#ifndef PPC555SCI_DEFAULT_BAUD# define PPC555SCI_DEFAULT_BAUD 9600#endif/* Hardware abstraction macros */#ifndef PPC555SCI_REG_READ# define PPC555SCI_REG_READ(pChan, reg, result) \ ((result) = *(pChan->reg))#endif /*PPC555SCI_REG_READ*/#ifndef PPC555SCI_REG_WRITE# define PPC555SCI_REG_WRITE(pChan, reg, data) \ (*(pChan->reg) = data)#endif /*PPC555SCI_REG_WRITE*/#ifndef PPC555SCI_SCTQ# define PPC555SCI_SCTQ(pChan) \ (pChan->sctq)#endif /*PPC555SCI_SCTQ*/#ifndef PPC555SCI_SCRQ# define PPC555SCI_SCRQ(pChan) \ (pChan->scrq)#endif /*PPC555SCI_SCRQ*//* forward declarations */LOCAL STATUS dummyCallback (void);LOCAL int ppc555SciIoctl (SIO_CHAN *pSioChan, int request, void *arg);LOCAL int ppc555SciTxStartup (SIO_CHAN * pSioChan);LOCAL int ppc555SciCallbackInstall (SIO_CHAN *pSioChan, int callbackType, STATUS (*callback)(), void *callbackArg);LOCAL int ppc555SciPollOutput (SIO_CHAN *pSioChan, char outChar);LOCAL int ppc555SciPollInput (SIO_CHAN *pSioChan, char *thisChar);LOCAL void ppc555SciIntQueued (PPC555SCI_CHAN * pChan);LOCAL void ppc555SciIntNotQueued (PPC555SCI_CHAN * pChan);/* local variables */LOCAL SIO_DRV_FUNCS ppc555SciSioDrvFuncs = { ppc555SciIoctl, ppc555SciTxStartup, ppc555SciCallbackInstall, ppc555SciPollInput, ppc555SciPollOutput };LOCAL BOOL ppc555SciIntrMode = FALSE; /* interrupt mode allowed flag *//******************************************************************************** ppc555SciDevInit - initialize a PPC555SCI channel** 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 PPC555SCI_CHAN structure before passing it to* this routine.** RETURNS: N/A*/void ppc555SciDevInit ( PPC555SCI_CHAN * pChan ) { /* initialize the channel's driver function pointers */ pChan->sio.pDrvFuncs = &ppc555SciSioDrvFuncs; /* install dummy driver callbacks */ pChan->getTxChar = dummyCallback; pChan->putRcvChar = dummyCallback; ppc555SciIoctl ((SIO_CHAN *) pChan, SIO_BAUD_SET, (void *) PPC555SCI_DEFAULT_BAUD); /* set interrupt level */ PPC555SCI_REG_WRITE (pChan, scilr, (pChan->intLevel) << QSM_QILR_SCI_SHIFT); /* clear control registers 0 and 1 */ PPC555SCI_REG_WRITE(pChan, sccr0, 0); PPC555SCI_REG_WRITE(pChan, sccr1, 0); }/******************************************************************************** ppc555SciDevInit2 - initialize a PPC555SCI, 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*/void ppc555SciDevInit2 ( PPC555SCI_CHAN * pChan /* device to initialize */ ) { /* Interrupt mode is allowed */ ppc555SciIntrMode = TRUE; }/******************************************************************************** ppc555SciInt - handle a channel's interrupt** RETURNS: N/A*/ void ppc555SciInt ( PPC555SCI_CHAN * pChan /* channel generating the interrupt */ ) { if (pChan->options & QUEUED) ppc555SciIntQueued(pChan); else ppc555SciIntNotQueued(pChan); }/******************************************************************************** ppc555SciIntNotQueued - handle a channel's interrupt in not queued mode** RETURNS: N/A*/ LOCAL void ppc555SciIntNotQueued ( PPC555SCI_CHAN * pChan /* channel generating the interrupt */ ) { char ioChar; FAST UINT16 status; FAST UINT16 temp; /* Check for receive */ PPC555SCI_REG_READ(pChan, scsr, status); if (status & QSM_SCSR_RDRF) { PPC555SCI_REG_READ(pChan, scdr, ioChar); (*pChan->putRcvChar) (pChan->putRcvArg, ioChar); } /* Check for error conditions and clear them with dummy read */ if (status & (QSM_SCSR_OR | QSM_SCSR_NF | QSM_SCSR_FE | QSM_SCSR_PF)) { PPC555SCI_REG_READ(pChan, scdr, ioChar); } /* Check for transmit */ if (status & QSM_SCSR_TDRE) { /* check if there is more to send */ if ((*pChan->getTxChar) (pChan->getTxArg, &ioChar) == OK) { PPC555SCI_REG_WRITE(pChan, scdr, ioChar); } else { /* disable transmit interrupts */ PPC555SCI_REG_READ(pChan, sccr1, temp); temp &= ~QSM_SCCR1_TIE; PPC555SCI_REG_WRITE(pChan, sccr1, temp); } } }/******************************************************************************** ppc555SciIntQueued - handle a channel's interrupt in queued mode** RETURNS: N/A*/ LOCAL void ppc555SciIntQueued ( PPC555SCI_CHAN * pChan /* channel generating the interrupt */ ) { char ioChar; FAST UINT16 scsrVal; FAST UINT16 qscsrVal; FAST UINT16 temp; FAST UINT16 byteCount; /* read SCI status registers */ PPC555SCI_REG_READ(pChan, qscsr, qscsrVal); PPC555SCI_REG_READ(pChan, scsr, scsrVal); /* check for receive top half */ if (qscsrVal & QSM_QSCSR_QTHF) { /* read data from queue */ for (byteCount=0; byteCount < 8; byteCount++) { ioChar = PPC555SCI_SCRQ(pChan)[byteCount]; (*pChan->putRcvChar) (pChan->putRcvArg, ioChar); } /* clear "top half full" */ qscsrVal &= ~QSM_QSCSR_QTHF; } /* check for receive bottom half */ else if (qscsrVal & QSM_QSCSR_QBHF) { /* read data from queue */ for (byteCount=0; byteCount < 8; byteCount++) { ioChar = PPC555SCI_SCRQ(pChan)[byteCount + 8]; (*pChan->putRcvChar) (pChan->putRcvArg, ioChar); } /* clear "bottom half full" */ qscsrVal &= ~QSM_QSCSR_QBHF; } /* Check for idle */ if (scsrVal & QSM_SCSR_IDLE) { /* read data from queue */ temp = (qscsrVal & QSM_QSCSR_QRPNT_MSK) >> 4; if ((temp == 0) || (temp == 8)) { /* need a dummy read to clear IDLE */ ioChar = PPC555SCI_SCRQ(pChan)[0]; } else if (temp < 8) { /* read top half only */ for (byteCount=0; byteCount < temp; byteCount++) { ioChar = PPC555SCI_SCRQ(pChan)[byteCount]; (*pChan->putRcvChar) (pChan->putRcvArg, ioChar); } } else { /* read bottom half only */ for (byteCount=8; byteCount < temp; byteCount++) { ioChar = PPC555SCI_SCRQ(pChan)[byteCount]; (*pChan->putRcvChar) (pChan->putRcvArg, ioChar); } } /* temporarily disable receive */ PPC555SCI_REG_READ(pChan, sccr1, temp); temp &= ~QSM_SCCR1_RE; PPC555SCI_REG_WRITE(pChan, sccr1, temp); } /* check for transmit complete */ if ((scsrVal & QSM_SCSR_TC) && (qscsrVal & QSM_QSCSR_QTHE) && (qscsrVal & QSM_QSCSR_QBHE)) { /* check if there is more to send */ for (byteCount=0; byteCount < 16; byteCount++) { if ((*pChan->getTxChar) (pChan->getTxArg, &ioChar) == OK) PPC555SCI_SCTQ(pChan)[byteCount] = ioChar; else break; } if (byteCount > 0) { /* Temporarily disable transmission */ PPC555SCI_REG_READ(pChan, sccr1, temp); temp &= ~QSM_SCCR1_TE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -