📄 sc28l198serial.c
字号:
{ 150, B150},
{ 200, B200},
{ 300, B300},
{ 450, B450},
{ 600, B600},
{ 900, B900},
{ 1200, B1200},
{ 1800, B1800},
{ 2400, B2400},
{ 3600, B3600},
{ 4800, B4800},
{ 7200, B7200},
{ 9600, B9600},
{ 14400, B14400},
{ 19200, B19200},
{ 28800, B28800},
{ 38400, B38400},
{ 57600, B57600},
{115200, B115200},
{230400, B230400}
};
/* This is the value of the IMMR register.
* It is initialized in sc28l198Drv().
* It is used in sc28l198Interrupt().
*/
static int immrVal;
LOCAL SC28L198_DEV_CHAN* sc28l198Open(SC28L198_DEV_CHAN *pChannel,
char *extension, int mode);
LOCAL int sc28l198Close(SC28L198_DEV_CHAN *pChannel);
LOCAL int sc28l198Read (SC28L198_DEV_CHAN *pChannel, char *buffer,
int maxBytes);
LOCAL int sc28l198Write(SC28L198_DEV_CHAN *pChannel, char *buffer, int nBytes);
LOCAL int sc28l198Ioctl(SC28L198_DEV_CHAN *pChannel, int ioctlCode, int *arg);
LOCAL int sc28l198BufRead(FAST SC28L198_DEV_CHAN *pChannel, char *buffer,
int maxBytes);
LOCAL int sc28l198BufWrite (FAST SC28L198_DEV_CHAN *pChannel, char *buffer,
int nBytes);
LOCAL void sc28l198Flush (FAST SC28L198_DEV_CHAN *pChannel);
LOCAL void sc28l198FlushWrt(FAST SC28L198_DEV_CHAN *pChannel);
LOCAL void sc28l198FlushRd (FAST SC28L198_DEV_CHAN *pChannel);
LOCAL STATUS sc28l198HrdInit(int uart);
LOCAL void sc28l198ResetChan(int uart, int chan);
LOCAL void sc28l198Error(int errorNum, char *errorMsg);
LOCAL int sc28l198BaudRate(int baudRate);
LOCAL int sc28l198Parity(char *parity);
LOCAL int sc28l198StopBits(int stopBits);
LOCAL int sc28l198DataBits(int dataBits);
void sc28l198SetBaudRate(int uart, int chan, int baudRate);
void sc28l198ConfigChan(int uart, int chan, int dataBits, int stopBits,
int parity);
void sc28l198InitInterrupts(int uart);
/* Driver debug control */
#define SC28L198_DEBUG
#ifdef SC28L198_DEBUG
#define DRV_DEBUG_OFF 0x0000
#define DRV_DEBUG_INIT 0x0001
#define DRV_DEBUG_OPEN 0x0002
#define DRV_DEBUG_READ 0x0004
#define DRV_DEBUG_WRITE 0x0008
#define DRV_DEBUG_IOCTRL 0x0010
#define DRV_DEBUG_INTR 0x0020
#define DRV_DEBUG_CMDS 0x0040
#define DRV_DEBUG_ALL 0xffff
/* Sets driver diagnostic output level */
int sc28l198Debug=DRV_DEBUG_OFF;
#define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) \
do { \
if (sc28l198Debug & FLG) \
logMsg (X0, (int)X1, (int)X2, (int)X3, (int)X4, \
(int)X5, (int)X6); \
} while (0)
#define DRV_PRINT(FLG, X) \
do { \
if (sc28l198Debug & FLG) \
printf X; \
} while (0)
#else
#define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)
#define DRV_PRINT(FLG, X)
#endif
/******************************************************************************
* Error message handler for the SC28L198.
*
* Note that the current implementation does not use the error number.
******************************************************************************/
LOCAL void
sc28l198Error(int errorNum, char *errorMsg)
{
logMsg("SC28L198: %s\n",(int)errorMsg,0,0,0,0,0);
/* errnoSet(errorNum); */
} /* sc28l198Error() */
/******************************************************************************
* Note that we need some way to disable the transmitter interrupts when the
* TxFIFO is empty. One way would be to use the "Enable TX" bit in the
* Command Register (CR). This is the method used by most of the other
* serial drivers. However, if you look at the design of this chip we can
* only write to it which means it get very messy to preserve the state of
* "Enable RX" bit.
*
* To get around this "feature" we will use the mask bit in the Interrupt
* Mask Register (IMR) to function in this role. We will enable and disable
* TxRDY in the IMR just prior to and then end of a block transmission.
******************************************************************************/
/******************************************************************************
* Enable the generation of interrupts for TxFIFO.
******************************************************************************/
void
sc28l198EnableTxInt(SC28L198_DEV_CHAN *pChannel)
{
DRV_LOG(DRV_DEBUG_CMDS, "enabling tx int, uart=%d, chan=%d.\n",
pChannel->uart,pChannel->chan,0,0,0,0);
pChannel->lastIMR |= TXRDY_INT;
*SC28L198_IMR(pChannel->uart,pChannel->chan) = pChannel->lastIMR;
} /* sc28l198EnableTxInt() */
/******************************************************************************
* Disable the generation of interrupts for TxFIFO.
******************************************************************************/
void
sc28l198DisableTxInt(SC28L198_DEV_CHAN *pChannel)
{
DRV_LOG(DRV_DEBUG_CMDS, "disabling tx int, uart=%d, chan=%d.\n",
pChannel->uart,pChannel->chan,0,0,0,0);
pChannel->lastIMR &= ~TXRDY_INT;
*SC28L198_IMR(pChannel->uart,pChannel->chan) = pChannel->lastIMR;
} /* sc28l198DisableTxInt() */
/******************************************************************************
* Enable the generation of interrupts for RxFIFO.
******************************************************************************/
void
sc28l198EnableRxInt(SC28L198_DEV_CHAN *pChannel)
{
SC28L198_DEV_CHAN *pRxChan = SAME_PCHANNEL_IN_OTHER_OCTART(pChannel);
DRV_LOG(DRV_DEBUG_CMDS, "enabling rx int, uart=%d, chan=%d.\n",
pRxChan->uart,pRxChan->chan,0,0,0,0);
pRxChan->lastIMR |= RXRDY_INT;
*SC28L198_IMR(pRxChan->uart,pRxChan->chan) = pRxChan->lastIMR;
} /* sc28l198EnableRxInt() */
/******************************************************************************
* Disable the generation of interrupts for RxFIFO.
******************************************************************************/
void
sc28l198DisableRxInt(SC28L198_DEV_CHAN *pChannel)
{
SC28L198_DEV_CHAN *pRxChan = SAME_PCHANNEL_IN_OTHER_OCTART(pChannel);
DRV_LOG(DRV_DEBUG_CMDS, "disabling rx int, uart=%d, chan=%d.\n",
pRxChan->uart,pRxChan->chan,0,0,0,0);
pRxChan->lastIMR &= ~RXRDY_INT;
*SC28L198_IMR(pRxChan->uart,pRxChan->chan) = pRxChan->lastIMR;
} /* sc28l198DisableRxInt() */
/******************************************************************************
* Enable transmitter and receiver.
******************************************************************************/
void
sc28l198EnableRxTx(SC28L198_DEV_CHAN *pChannel)
{
SC28L198_DEV_CHAN *pRxChan = SAME_PCHANNEL_IN_OTHER_OCTART(pChannel);
DRV_LOG(DRV_DEBUG_CMDS,
"enabling rx (uart=%d, chan=%d) and tx (uart=%d, chan=%d)...\n",
pRxChan->uart,pRxChan->chan, pChannel->uart,pChannel->chan,0,0);
pRxChan->lastCR |= RX_ENABLE;
*pRxChan->uartCommandReg = pRxChan->lastCR;
pChannel->lastCR |= TX_ENABLE;
*pChannel->uartCommandReg = pChannel->lastCR;
DRV_LOG(DRV_DEBUG_CMDS,
"...sent 0x%02x to rx cmd reg, 0x%02x to tx cmd reg.\n",
pRxChan->lastCR, pChannel->lastCR,0,0,0,0);
} /* sc28l198EnableRxTx() */
/******************************************************************************
* Disable transmitter and receiver.
******************************************************************************/
void
sc28l198DisableRxTx(SC28L198_DEV_CHAN *pChannel)
{
SC28L198_DEV_CHAN *pRxChan = SAME_PCHANNEL_IN_OTHER_OCTART(pChannel);
DRV_LOG(DRV_DEBUG_CMDS,
"disabling rx (uart=%d, chan=%d) and tx (uart=%d, chan=%d)...\n",
pRxChan->uart,pRxChan->chan, pChannel->uart,pChannel->chan,0,0);
pRxChan->lastCR &= ~(RX_ENABLE);
*pRxChan->uartCommandReg = pRxChan->lastCR;
pChannel->lastCR &= ~(TX_ENABLE);
*pChannel->uartCommandReg = pChannel->lastCR;
DRV_LOG(DRV_DEBUG_CMDS,
"...sent 0x%02x to rx cmd reg, 0x%02x to tx cmd reg.\n",
pRxChan->lastCR, pChannel->lastCR,0,0,0,0);
} /* sc28l198DisableRxTx() */
/******************************************************************************
* Open a channel.
******************************************************************************/
LOCAL SC28L198_DEV_CHAN*
sc28l198Open(SC28L198_DEV_CHAN *pChannel, char *extension, int mode)
{
DRV_LOG(DRV_DEBUG_OPEN,
"Open request uart=%d channel=%d extension='%s' mode=%d\n",
pChannel->uart, pChannel->chan, extension,mode,0,0);
if( pChannel->chanOpen==TRUE )
{
sc28l198Error(0, "Requested device already open\n");
return((SC28L198_DEV_CHAN*) ERROR);
}
/* Indicate that the channel is now open */
pChannel->chanOpen=TRUE;
/* Flush input and output buffers */
sc28l198Flush(pChannel);
/* Reset the channel to a known good state */
sc28l198ResetChan(pChannel->uart, pChannel->chan);
/* Set baud rate and line format options */
sc28l198SetBaudRate(pChannel->uart, pChannel->chan, pChannel->baudRate);
sc28l198ConfigChan(pChannel->uart, pChannel->chan, pChannel->dataBits,
pChannel->stopBits, pChannel->parity);
/* Enable the transmitter and receiver */
sc28l198EnableRxTx(pChannel);
/* Enable the RxFIFO interrupt only */
sc28l198EnableRxInt(pChannel);
return(pChannel);
} /* sc28l198Open() */
/******************************************************************************
*******************************************************************************/
LOCAL int
sc28l198Close(SC28L198_DEV_CHAN *pChannel)
{
/* Disable Receiver and Transmitter */
sc28l198DisableRxTx(pChannel);
/* Clear the channel open flag so we can reopen this channel later */
pChannel->chanOpen = FALSE;
return(OK);
} /* sc28l198Close() */
/******************************************************************************
*******************************************************************************/
LOCAL int
sc28l198Read (SC28L198_DEV_CHAN *pChannel, char *buffer, int maxBytes)
{
DRV_LOG(DRV_DEBUG_READ, "Read request uart=%d channel=%d size=%d\n",
pChannel->uart, pChannel->chan, maxBytes,0,0,0);
return(sc28l198BufRead (pChannel, buffer, maxBytes));
} /* sc28l198Read() */
/******************************************************************************
*******************************************************************************/
LOCAL int
sc28l198Write(SC28L198_DEV_CHAN *pChannel, char *buffer, int nBytes)
{
DRV_LOG(DRV_DEBUG_WRITE, "Write request uart=%d channel=%d size=%d\n",
pChannel->uart, pChannel->chan, nBytes,0,0,0);
return(sc28l198BufWrite(pChannel, buffer, nBytes));
} /* sc28l198Write() */
/******************************************************************************
*******************************************************************************/
LOCAL int
sc28l198Ioctl(SC28L198_DEV_CHAN *pChannel, int ioctlCode, int *arg)
{
SC28L198_DEV_CHAN *pRxChan;
DRV_LOG(DRV_DEBUG_IOCTRL, "IOCTL request uart=%d channel=%d code=%d\n",
pChannel->uart, pChannel->chan, ioctlCode,0,0,0);
/* Decide which request is being made */
switch(ioctlCode)
{
case FIONREAD:
pRxChan = SAME_PCHANNEL_IN_OTHER_OCTART(pChannel);
*arg = rngNBytes(pRxChan->rdBuf);
break;
case FIONWRITE:
*arg = rngNBytes(pChannel->wrtBuf);
break;
case FIOFLUSH:
sc28l198Flush(pChannel);
break;
case FIORFLUSH:
sc28l198FlushRd(pChannel);
break;
case FIOWFLUSH:
sc28l198FlushWrt(pChannel);
break;
case FIOISATTY:
return(TRUE);
break;
case FIOBAUDRATE:
/* Set a channel's baud rate */
pChannel->baudRate = sc28l198BaudRate((int) *arg);
/* Set baud rate to user specified value */
sc28l198SetBaudRate(pChannel->uart, pChannel->chan,
pChannel->baudRate);
break;
default:
errnoSet (S_ioLib_UNKNOWN_REQUEST);
return(ERROR);
break;
} /* switch */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -