📄 m68681sio.c
字号:
/* m68681Sio.c - M68681 serial communications driver *//* Copyright 1984-1996 Wind River Systems, Inc. *//*modification history--------------------01d,18dec96,db fixed bugs in m68681OptsSet() and m68681Ioctl().(SPR #7641). changed M68681_DEFAULT_OPTIONS to disable hardware handshake.01e,06nov96,dgp doc: final formatting01d,03jun96,dat added m68681Opr, m68681Opcr, m68681OpcrSetClr, m68681OprSetClr01c,21may96,dat m68681Int loops until all sources serviced.01b,29mar96,dat more comments, added m68681OptsSet(), m68681AcrSetClr()01a,14feb96,dds written.*//*DESCRIPTIONThis is the driver for the M68681 DUART. This device includes two universalasynchronous receiver/transmitters, a baud rate generator, and a counter/timerdevice. This driver module provides control of the two serial channels andthe baud-rate generator. The counter timer is controlled by a separatedriver, src/drv/timer/m68681Timer.c.A M68681_DUART structure is used to describe the chip. This data structurecontains two M68681_CHAN structures which describe the chip's two serialchannels. The M68681_DUART structure is defined in m68681Sio.h.Only asynchronous serial operation is supported by this driver.The default serial settings are 8 data bits, 1 stop bit, no parity, 9600baud, and software flow control. These default settings can be overriddenon a channel-by-channel basis by setting the M68681_CHAN options and `baudRate'fields to the desired values before calling m68681DevInit(). See sioLib.hfor option values. The defaults for the module can be changed byredefining the macros M68681_DEFAULT_OPTIONS and M68681_DEFAULT_BAUD andrecompiling this driver.This driver supports baud rates of 75, 110, 134.5, 150, 300, 600, 1200,2000, 2400, 4800, 1800, 9600, 19200, and 38400.USAGEThe BSP's sysHwInit() routine typically calls sysSerialHwInit()which initializes all the hardware addresses in the M68681_DUART structurebefore calling m68681DevInit(). This enables the chip to operate inpolled mode, but not in interrupt mode. Calling m68681DevInit2() fromthe sysSerialHwInit2() routine allows interrupts to be enabled andinterrupt-mode operation to be used.The following example shows the first part of the initialization thorughcalling m68681DevInit():.CS#include "drv/sio/m68681Sio.h"M68681_DUART myDuart; /@ my device structure @/#define MY_VEC (71) /@ use single vector, #71 @/sysSerialHwInit() { /@ initialize the register pointers for portA @/ myDuart.portA.mr = M68681_MRA; myDuart.portA.sr = M68681_SRA; myDuart.portA.csr = M68681_CSRA; myDuart.portA.cr = M68681_CRA; myDuart.portA.rb = M68681_RHRA; myDuart.portA.tb = M68681_THRA; /@ initialize the register pointers for portB @/ myDuart.portB.mr = M68681_MRB; ... /@ initialize the register pointers/data for main duart @/ myDuart.ivr = MY_VEC; myDuart.ipcr = M68681_IPCR; myDuart.acr = M68681_ACR; myDuart.isr = M68681_ISR; myDuart.imr = M68681_IMR; myDuart.ip = M68681_IP; myDuart.opcr = M68681_OPCR; myDuart.sopbc = M68681_SOPBC; myDuart.ropbc = M68681_ROPBC; myDuart.ctroff = M68681_CTROFF; myDuart.ctron = M68681_CTRON; myDuart.ctlr = M68681_CTLR; myDuart.ctur = M68681_CTUR; m68681DevInit (&myDuart); }.CEThe BSP's sysHwInit2() routine typically calls sysSerialHwInit2() whichconnects the chips interrupts via intConnect() to the singleinterrupt handler m68681Int(). After the interrupt service routines are connected, the user then calls m68681DevInit2() to allow the driver to turn on interrupt enable bits, as shown in the following example:.CSsysSerialHwInit2 () { /@ connect single vector for 68681 @/ intConnect (INUM_TO_IVEC(MY_VEC), m68681Int, (int)&myDuart); ... /@ allow interrupts to be enabled @/ m68681DevInit2 (&myDuart); }.CESPECIAL CONSIDERATIONS:The CLOCAL hardware option presumes that OP0 and OP1 output bits are wiredto the CTS outputs for channel 0 and channel 1 respectively. If not wiredcorrectly, then the user must not select the CLOCAL option. CLOCAL isnot one of the default options for this reason.This driver does not manipulate the output portor its configuration register in any way. If the userselects the CLOCAL option, then the output port bit must be wired correctlyor the hardware flow control will not function correctly.INCLUDE FILES: drv/sio/m68681Sio.h*/#include "vxWorks.h"#include "sioLib.h"#include "intLib.h"#include "errno.h"#include "drv/sio/m68681Sio.h"/* forward static declarations */LOCAL void m68681InitChannel (M68681_CHAN *, M68681_DUART *);LOCAL void m68681InitStruct (M68681_CHAN *);LOCAL STATUS m68681ModeSet (M68681_CHAN *, UINT);LOCAL STATUS m68681BaudSet (M68681_CHAN *, UINT);LOCAL STATUS m68681OptsSet (M68681_CHAN *, UINT);LOCAL int m68681Ioctl (M68681_CHAN *, int, void *);LOCAL int m68681TxStartup (M68681_CHAN *);LOCAL int m68681CallbackInstall (M68681_CHAN *, int, STATUS (*)(), void *);LOCAL int m68681PollInput (M68681_CHAN *, char *);LOCAL int m68681PollOutput (M68681_CHAN*, char);/* driver functions */LOCAL SIO_DRV_FUNCS m68681SioDrvFuncs = { (int (*)(SIO_CHAN *, int, void *))m68681Ioctl, (int (*)(SIO_CHAN *))m68681TxStartup, (int (*)())m68681CallbackInstall, (int (*)(SIO_CHAN *, char*))m68681PollInput, (int (*)(SIO_CHAN *, char))m68681PollOutput };/* typedefs */typedef struct /* M68681_BAUD */ { int rate; /* a baud rate */ UCHAR csrVal; /* rate to write to the csr reg to get that baud rate */ UCHAR baudBit; /* baud rate select bit, in ACR */ } M68681_BAUD;/* * BaudTable is a table of the available baud rates, and the values to write * to the csr reg to get those rates */#define SET1 0#define SET2 M68681_ACR_BRG_SELECTLOCAL M68681_BAUD baudTable [] = { {75, M68681_CSR_RX_75 | M68681_CSR_TX_75, SET2}, {110, M68681_CSR_RX_110 | M68681_CSR_TX_110, SET2}, {134, M68681_CSR_RX_134_5 | M68681_CSR_TX_134_5, SET2}, {150, M68681_CSR_RX_150 | M68681_CSR_TX_150, SET2}, {300, M68681_CSR_RX_300 | M68681_CSR_TX_300, SET2}, {600, M68681_CSR_RX_600 | M68681_CSR_TX_600, SET2}, {1200, M68681_CSR_RX_1200 | M68681_CSR_TX_1200, SET2}, {2000, M68681_CSR_RX_2000 | M68681_CSR_TX_2000, SET2}, {2400, M68681_CSR_RX_2400 | M68681_CSR_TX_2400, SET2}, {4800, M68681_CSR_RX_4800 | M68681_CSR_TX_4800, SET2}, {1800, M68681_CSR_RX_1800 | M68681_CSR_TX_1800, SET2}, {9600, M68681_CSR_RX_9600 | M68681_CSR_TX_9600, SET2}, {19200, M68681_CSR_RX_19200 | M68681_CSR_TX_19200, SET2}, {38400, M68681_CSR_RX_38400 | M68681_CSR_TX_38400, SET1} };#undef SET1#undef SET2/* defines */#ifndef M68681_DEFAULT_BAUD# define M68681_DEFAULT_BAUD 9600#endif#ifndef M68681_DEFAULT_OPTIONS /* no handshake, rcvr enabled, 8 data bits, 1 stop bit, no parity */# define M68681_DEFAULT_OPTIONS (CLOCAL | CREAD | CS8)#endif/* Hardware read/write routines. Can be redefined to create drivers * for boards with special i/o access procedures. The reg pointer * arguments are the register pointers from the M68681_CHAN or * M68681_DUART structure. */#ifndef M68681_READ# define M68681_READ(x) (*x) /* argument is register pointer */#endif#ifndef M68681_WRITE# define M68681_WRITE(x,y) (*x = y) /* args are reg ptr and data */#endif#define MAX_OPTIONS (0xff)#define MAX_BAUD (38400)/******************************************************************************** m68681DevInit - intialize a M68681_DUART** The BSP must already have initialized all the device addresses and* register pointers in the M68681_DUART structure as described in* `m68681Sio'. This routine initializes some transmitter and receiver status* values to be used in the interrupt mask register and then resets the chip* to a quiescent state.** RETURNS: N/A*/void m68681DevInit ( M68681_DUART * pDuart ) { int oldlevel; char resetTimer; pDuart->intEnable = FALSE; pDuart->tickRtn = NULL; pDuart->tickArg = 0; m68681ImrSetClr (pDuart, 0, -1); m68681AcrSetClr (pDuart, 0, -1); m68681OpcrSetClr(pDuart, 0, -1); m68681OprSetClr (pDuart, 0, -1); pDuart->portA.pDuart = pDuart; pDuart->portA.xmitEnb = M68681_IMR_TX_RDY_A; pDuart->portA.rcvrEnb = M68681_IMR_RX_RDY_A; pDuart->portA.channel = M68681_CHANNEL_A; pDuart->portB.pDuart = pDuart; pDuart->portB.xmitEnb = M68681_IMR_TX_RDY_B; pDuart->portB.rcvrEnb = M68681_IMR_RX_RDY_B; pDuart->portB.channel = M68681_CHANNEL_B; m68681InitStruct (&pDuart->portA); m68681InitStruct (&pDuart->portB); oldlevel = intLock (); /* Clear the interrupt mask register */ m68681ImrSetClr (pDuart, 0 , M68681_IMR_CLEAR); m68681InitChannel (&pDuart->portA, pDuart); m68681InitChannel (&pDuart->portB, pDuart); resetTimer = M68681_READ (pDuart->ctroff); intUnlock (oldlevel); }/******************************************************************************** m68681DevInit2 - intialize a M68681_DUART, part 2** This routine is called as part of sysSerialHwInit2(). It tells* the driver that interrupt vectors are connected and that it is* safe to allow interrupts to be enabled.** RETURNS: N/A*/void m68681DevInit2 ( M68681_DUART * pDuart ) { /* Allow interrupt mode */ pDuart->intEnable = TRUE; /* call ModeSet, to startup devices if needed */ m68681ModeSet (&pDuart->portA, pDuart->portA.mode); m68681ModeSet (&pDuart->portB, pDuart->portB.mode); }/********************************************************************************* m68681ImrSetClr - set and clear bits in the DUART interrupt-mask register** This routine sets and clears bits in the DUART interrupt-mask register (IMR).* It sets and clears bits in a local copy of the IMR, then* writes that local copy to the DUART. This means that all changes to* the IMR must be performed by this routine. Any direct changes* to the IMR are lost the next time this routine is called.** Set has priority over clear. Thus you can use this routine to update* multiple bit fields by specifying the field mask as the clear bits.** RETURNS: N/A*/void m68681ImrSetClr ( M68681_DUART * pDuart, UCHAR setBits, /* which bits to set in the IMR */ UCHAR clearBits /* which bits to clear in the IMR */ ) { pDuart->imrCopy = ((pDuart->imrCopy & ~clearBits) | setBits); M68681_WRITE (pDuart->imr, pDuart->imrCopy); }/********************************************************************************* m68681Imr - return the current contents of the DUART interrupt-mask register** This routine returns the contents of the interrupt-mask register (IMR). * The IMR is not directly readable; a copy of the last value written is kept* in the DUART data structure.** RETURNS: The contents of the interrupt-mask register.*/UCHAR m68681Imr ( M68681_DUART * pDuart ) { return pDuart->imrCopy; }/********************************************************************************* m68681AcrSetClr - set and clear bits in the DUART auxiliary control register** This routine sets and clears bits in the DUART auxiliary control register* (ACR). It sets and clears bits in a local copy of the ACR, then* writes that local copy to the DUART. This means that all changes to* the ACR must be performed by this routine. Any direct changes* to the ACR are lost the next time this routine is called.** Set has priority over clear. Thus you can use this routine to update* multiple bit fields by specifying the field mask as the clear bits.** RETURNS: N/A*/void m68681AcrSetClr ( M68681_DUART * pDuart, UCHAR setBits, /* which bits to set in the ACR */ UCHAR clearBits /* which bits to clear in the ACR */ ) { pDuart->acrCopy = ((pDuart->acrCopy & ~clearBits) | setBits); M68681_WRITE (pDuart->acr, pDuart->acrCopy); }/********************************************************************************* m68681Acr - return the contents of the DUART auxiliary control register** This routine returns the contents of the auxilliary control register (ACR).* The ACR is not directly readable; a copy of the last value written is kept* in the DUART data structure.** RETURNS: The contents of the auxilliary control register.*/UCHAR m68681Acr ( M68681_DUART * pDuart ) { return pDuart->acrCopy; }/********************************************************************************* m68681OprSetClr - set and clear bits in the DUART output port register** This routine sets and clears bits in the DUART output port register* (OPR). It sets and clears bits in a local copy of the OPR, then writes* that local copy to the DUART. This means that all changes to the OPR must* be performed by this routine. Any direct changes to the OPR are lost the* next time this routine is called.** Set has priority over clear. Thus you can use this routine to update* multiple bit fields by specifying the field mask as the clear bits.** RETURNS: N/A*/void m68681OprSetClr ( M68681_DUART * pDuart, UCHAR setBits, /* which bits to set in the OPR */ UCHAR clearBits /* which bits to clear in the OPR */ ) { pDuart->oprCopy = ((pDuart->oprCopy & ~clearBits) | setBits); M68681_WRITE (pDuart->ropbc, clearBits); M68681_WRITE (pDuart->sopbc, setBits); }/********************************************************************************* m68681Opr - return the current state of the DUART output port register** This routine returns the current state of the output port register (OPR) * from the saved copy in the DUART data structure. The actual OPR contents* are not directly readable.** RETURNS: The current state of the output port register.*/UCHAR m68681Opr ( M68681_DUART * pDuart ) { return pDuart->oprCopy; }/********************************************************************************* m68681OpcrSetClr - set and clear bits in the DUART output port configuration register** This routine sets and clears bits in the DUART output port configuration* register (OPCR). It sets and clears bits in a local copy of the OPCR,* then writes that local copy to the DUART. This means that all changes to* the OPCR must be performed by this routine. Any direct changes to the* OPCR are lost the next time this routine is called.** Set has priority over clear. Thus you can use this routine to update* multiple bit fields by specifying the field mask as the clear bits.** RETURNS: N/A*/void m68681OpcrSetClr ( M68681_DUART * pDuart, UCHAR setBits, /* which bits to set in the OPCR */ UCHAR clearBits /* which bits to clear in the OPCR */ ) { pDuart->opcrCopy = ((pDuart->opcrCopy & ~clearBits) | setBits); M68681_WRITE (pDuart->opcr, pDuart->opcrCopy); }/********************************************************************************* m68681Opcr - return the state of the DUART output port configuration register** This routine returns the state of the output port configuration register* (OPCR) from the saved copy in the DUART data structure. The actual OPCR* contents are not directly readable.** RETURNS: The state of the output port configuration register.*/UCHAR m68681Opcr ( M68681_DUART * pDuart ) { return pDuart->opcrCopy; }/******************************************************************************** m68681DummyCallback - dummy callback routine.** RETURNS:* Always returns ERROR*/LOCAL STATUS m68681DummyCallback (void) { return (ERROR); }/******************************************************************************** m68681TxStartup - start the interrupt transmitter.** This routine enables the transmitters for the specified DUART channel so that* the DUART channel will interrupt the CPU when TxRDY bit in the status* register is set.** RETURNS:* Returns OK on success, or EIO on hardware error.*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -