📄 s3c44bsio.c
字号:
/* s3c44bSio.c - Samsung S3C44B0X serial driver *//* Copyright 1984-2001 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01c,30nov01,m_h Save pChan->baudRate when setting baud01b,26apr01,m_h convert tabs to spaces for readability01a,12apr01,m_h created from snds100 template.*//*DESCRIPTIONThis is the serial I/O driver for Samsung's KS32C50100 microprocessor which is anARM based processor with several integrated peripherals. It has an interruptcontroller, two 32-bit timers, one Ethernet controller,two HDLC controllers,one IIC controller, general purpose I/O ports, and a 2 channel DMA controller.The 2 UART channels integrated with the processor are controlled by thisdriver. Both the UARTs can work in interrupt mode as well as DMA mode.This driver supports only the interrupt mode for the UARTs.All the UART registers are accessible as 32-bit integers from the internalsystem registers. The macros S3C44B_REG_READ and S3C44B_REG_WRITE read and write32-bit integers from and to the given addresses. S3C44B_SIO_DEFAULT_BAUD isdefined to 38400 in this file. This is the default baud rate with which the UART channels will be initialized. The channels are also initialized with one start bit, one stop bit, 8 bit data and no parity bits.The driver is typically only called only by the BSP. The directly callableroutines in this module are s3c44bDevInit(), s3c44bDevInit2(), s3c44bIntRcv(), s3c44bIntTx(), and s3c44bIntErr().The BSP calls s3c44bDevInit() to initialize or reset the device.It connects the driver's interrupt handlers (s3c44bIntRcv(), s3c44bIntTx(),and s3c44bIntErr()), using intConnect().After connecting the interrupt handlers, the BSP calls s3c44bDevInit2()to inform the driver that interrupt mode operation is now possible.INCLUDES:s3c44bSio.h sioLib.hSEE ALSO:<Samsung KS32C50100 User's Manual>*/#include "vxWorks.h"#include "sioLib.h"#include "intLib.h"#include "errno.h"#include "s3c44bSio.h"#include "ioLib.h"#define S3C44B_BAUD_MIN 1200#define S3C44B_BAUD_MAX 115200#define S3C44B_SIO_DEFAULT_BAUD 115200 /* 115200 *//* Hardware abstraction macros *//* local defines */#ifndef S3C44B_SIO_REG_READ#define S3C44B_SIO_REG_READ(pChan, reg, result) \ ((result) = (*(volatile UINT32 *)((UINT32)(pChan)->regs + (reg))))#endif /* S3C44B_SIO_REG_READ */#ifndef S3C44B_SIO_REG_WRITE#define S3C44B_SIO_REG_WRITE(pChan, reg, data) \ ((*(volatile UINT32 *)((UINT32)(pChan)->regs + (reg))) = (data))#endif /* S3C44B_SIO_REG_WRITE */#ifndef S3C44B_SIO_REG_WR_CHAR#define S3C44B_SIO_REG_WR_CHAR(pChan, reg, data) \ ((*(volatile char *)((UINT32)(pChan)->regs + (reg))) = (char)(data))#endif /* S3C44B_SIO_REG_WR_CHAR */#ifndef S3C44B_SIO_REG_RD_CHAR#define S3C44B_SIO_REG_RD_CHAR(pChan, reg, result) \ ((result) = (*(volatile char *)((UINT32)(pChan)->regs + (reg))))#endif /* S3C44B_SIO_REG_RD_CHAR *//* for backward compatibility */#ifndef SIO_HUP# define SIO_OPEN 0x100A /* open channel, raise DTR, RTS */# define SIO_HUP 0x100B /* hang-up, lower DTR, RTS */#endif/* forward static declarations */LOCAL int s3c44bTxStartup (SIO_CHAN * pSioChan);LOCAL int s3c44bCallbackInstall (SIO_CHAN *pSioChan, int callbackType, STATUS (*callback)(void *,...), void *callbackArg);LOCAL int s3c44bPollOutput (SIO_CHAN *pSioChan, char outChar);LOCAL int s3c44bPollInput (SIO_CHAN *pSioChan, char *thisChar);LOCAL int s3c44bIoctl (SIO_CHAN *pSioChan, int request, void *arg);LOCAL STATUS dummyTxCallback (void *, char *);LOCAL void dummyRxCallback (void *, char);/* local variables */LOCAL SIO_DRV_FUNCS s3c44bSioDrvFuncs = { s3c44bIoctl, s3c44bTxStartup, s3c44bCallbackInstall, s3c44bPollInput, s3c44bPollOutput };LOCAL BOOL s3c44bIntrMode = FALSE; /* interrupt mode allowed flag */IMPORT SIO_CHAN * sysSioChans [];/******************************************************************************** s3c44bDevInit - initialize a S3C44B0x UART** 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 S3C44B_UART structure before passing it to* this routine.** RETURNS: N/A*/void s3c44bDevInit ( S3C44B_CHAN * pChan ) { /* initialize each channel's driver function pointers */ pChan->sio.pDrvFuncs = &s3c44bSioDrvFuncs; /* install dummy driver callbacks */ pChan->getTxChar = (STATUS (*)(void *, char *))dummyTxCallback; pChan->putRcvChar = dummyRxCallback; /* reset the chip */ S3C44B_SIO_REG_WRITE(pChan,S3C44B_ULCON,( PARITY_NONE | ONE_STOP | WORD_LEN)); /* 03-17 */ S3C44B_SIO_REG_WRITE(pChan,S3C44B_UCON,( UCON_TX | UCON_RX )); S3C44B_SIO_REG_WRITE(pChan,S3C44B_FCON,0x01); /* disable fifo*/ /* setting polled mode is one way to make the device quiet */ s3c44bIoctl ((SIO_CHAN *)pChan, SIO_MODE_SET, (void *)SIO_MODE_POLL); s3c44bIoctl ((SIO_CHAN *)pChan, SIO_BAUD_SET, (void *)S3C44B_SIO_DEFAULT_BAUD); }/******************************************************************************** s3c44bDevInit2 - initialize a S3C44B_UART, 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* ARGSUSED*/void s3c44bDevInit2 ( S3C44B_CHAN * pChan /* device to initialize */ ) { /* Interrupt mode is allowed */ S3C44B_SIO_REG_WRITE(pChan,S3C44B_UCON,UCON_RX|UCON_TX|UCON_RXTIMOUT_EN); /* UCON_BREAK|UCON_TXINT_TYPE|UCON_RXSTAT_EN);*/ s3c44bIntrMode = TRUE; }/******************************************************************************** s3c44bIntRcv - handle a channel's receive-character interrupt** RETURNS: N/A*/ void s3c44bIntRcv ( S3C44B_CHAN * pChan /* channel generating the interrupt */ ) { char inChar; UINT32 status; /* * Grab the input character from the chip and hand it off via a * callback. For chips with input FIFO's it is more efficient * to empty the entire FIFO here. */while (1) { S3C44B_SIO_REG_READ(pChan,S3C44B_UFSTAT, status); if((status & 0xf) != 0) { S3C44B_SIO_REG_RD_CHAR(pChan,S3C44B_URXBUF, inChar); (*pChan->putRcvChar) (pChan->putRcvArg, inChar); } else break; } return; }/******************************************************************************** s3c44bIntTx - handle a channels transmitter-ready interrupt** RETURNS: N/A*/ void s3c44bIntTx ( S3C44B_CHAN * pChan /* channel generating the interrupt */ ) { char outChar; UINT8 status; /* * If there's a character to transmit then write it out, else reset * the transmitter. For chips with output FIFO's it is more efficient * to fill the entire FIFO here. */while (1) { S3C44B_SIO_REG_READ(pChan,S3C44B_UFSTAT, status); status &= 0xf0; status = status >>4; if (status <4) { if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR) { S3C44B_SIO_REG_WR_CHAR(pChan, S3C44B_UTXBUF, outChar); } else { intDisable(pChan->intLevelTx); break; } } else { return; } } return; }/******************************************************************************** s3c44bTxStartup - start the interrupt transmitter** RETURNS: OK on success, ENOSYS if the device is polled-only, or* EIO on hardware error.*/LOCAL int s3c44bTxStartup ( SIO_CHAN * pSioChan /* channel to start */ ) { char outChar; S3C44B_CHAN * pChan = (S3C44B_CHAN *)pSioChan; if (pChan->mode == SIO_MODE_POLL) { return ENOSYS; } if (SIO_MODE_INT == pChan->mode) { intEnable (pChan->intLevelTx); if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR) { S3C44B_SIO_REG_WR_CHAR(pChan, S3C44B_UTXBUF, outChar); } return OK; } return ERROR; }/******************************************************************************** s3c44bCallbackInstall - install ISR callbacks to get/put chars** This driver allows interrupt callbacks for transmitting characters* and receiving characters. In general, drivers may support other* types of callbacks too.** RETURNS: OK on success, or ENOSYS for an unsupported callback type.*/ LOCAL int s3c44bCallbackInstall ( SIO_CHAN * pSioChan, /* channel */ int callbackType, /* type of callback */ STATUS (*callback)(void *,...), /* callback */ void * callbackArg /* parameter to callback */ ) { S3C44B_CHAN * pChan = (S3C44B_CHAN *)pSioChan; switch (callbackType) { case SIO_CALLBACK_GET_TX_CHAR: pChan->getTxChar = (STATUS (*)(void *, char *))callback; pChan->getTxArg = callbackArg; return (OK); case SIO_CALLBACK_PUT_RCV_CHAR: pChan->putRcvChar = (void (*)(void *, char))callback; pChan->putRcvArg = callbackArg; return (OK); default: return (ENOSYS); } }/********************************************************************************* s3c44bPollOutput - output a character in polled mode** RETURNS: OK if a character arrived, EIO on device error, EAGAIN* if the output buffer if full. ENOSYS if the device is* interrupt-only.*/LOCAL int s3c44bPollOutput ( SIO_CHAN *pSioChan, char outChar ) { UINT8 status; S3C44B_CHAN * pChan = (S3C44B_CHAN *)pSioChan; /* is the transmitter ready to accept a character? */ S3C44B_SIO_REG_READ (pChan, S3C44B_UTRSTAT, status); if ((status & USTAT_TX_READY) != USTAT_TX_READY) { return (EAGAIN); } /* write out the character */ S3C44B_SIO_REG_WR_CHAR(pChan, S3C44B_UTXBUF, outChar); return (OK); }/******************************************************************************** s3c44bPollInput - poll the device for input** RETURNS: OK if a character arrived, EIO on device error, EAGAIN* if the input buffer if empty, ENOSYS if the device is* interrupt-only.*/LOCAL int s3c44bPollInput ( SIO_CHAN * pSioChan, char * thisChar ) { UINT8 status; S3C44B_CHAN * pChan = (S3C44B_CHAN *)pSioChan; S3C44B_SIO_REG_READ (pChan,S3C44B_UTRSTAT, status); if ((status & USTAT_RX_READY) != USTAT_RX_READY) { return (EAGAIN); /* no input available at this time */ } /* got a character */ S3C44B_SIO_REG_RD_CHAR(pChan, S3C44B_URXBUF, *thisChar); return (OK); }/******************************************************************************** s3c44bModeSet - toggle between interrupt and polled mode** RETURNS: OK on success, EIO on unsupported mode.*/LOCAL int s3c44bModeSet ( S3C44B_CHAN * pChan, /* channel */ uint_t newMode /* new mode */ ) { UINT8 temp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -