📄 sngks32csio-old.c
字号:
/* sngks32cSio.c - Samsung KS32C 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 SNGKS32C_REG_READ and SNGKS32C_REG_WRITE read and write32-bit integers from and to the given addresses. SNGKS32C_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 sngks32cDevInit(), sngks32cDevInit2(), sngks32cIntRcv(), sngks32cIntTx(), and sngks32cIntErr().The BSP calls sngks32cDevInit() to initialize or reset the device.It connects the driver's interrupt handlers (sngks32cIntRcv(), sngks32cIntTx(),and sngks32cIntErr()), using intConnect().After connecting the interrupt handlers, the BSP calls sngks32cDevInit2()to inform the driver that interrupt mode operation is now possible.INCLUDES:sngks32cSio.h sioLib.hSEE ALSO:<Samsung KS32C50100 User's Manual>*/#include "vxWorks.h"#include "sioLib.h"#include "intLib.h"#include "errno.h"#include "sngks32cSio.h"#include "ioLib.h"void myDelay();#define AT91C_BAUD_MIN 1200#define AT91C_BAUD_MAX 230400#define AT91C_SIO_DEFAULT_BAUD 38400/* Hardware abstraction macros *//* local defines */#ifndef AT91C_SIO_REG_READ#define AT91C_SIO_REG_READ(pChan, reg, result) \ ((result) = (*(volatile UINT32 *)((UINT32)(pChan)->regs + (reg))))#endif /*AT91C_SIO_REG_READ*/#ifndef AT91C_SIO_REG_WRITE#define AT91C_SIO_REG_WRITE(pChan, reg, data) \ ((*(volatile UINT32 *)((UINT32)(pChan)->regs + (reg))) = (data))#endif /*AT91C_SIO_REG_WRITE*//* 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 at91cTxStartup (SIO_CHAN * pSioChan);LOCAL int at91cCallbackInstall (SIO_CHAN *pSioChan, int callbackType, STATUS (*callback)(), void *callbackArg);LOCAL int at91cPollOutput (SIO_CHAN *pSioChan, char outChar);LOCAL int at91cPollInput (SIO_CHAN *pSioChan, char *thisChar);LOCAL int at91cIoctl (SIO_CHAN *pSioChan, int request, void *arg);LOCAL STATUS dummyCallback (void);LOCAL void at91cIntRcv(AT91C_CHAN * pChan);LOCAL void at91cIntTx(AT91C_CHAN * pChan);/* local variables */LOCAL SIO_DRV_FUNCS at91cSioDrvFuncs = { at91cIoctl, at91cTxStartup, at91cCallbackInstall, at91cPollInput, at91cPollOutput };LOCAL BOOL at91cIntrMode = FALSE; /* interrupt mode allowed flag *//******************************************************************************** at91cDevInit - initialize a AT91C_DUSART** 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 AT91C_DUSART structure before passing it to* this routine.** RETURNS: N/A*/void at91cDevInit ( AT91C_CHAN * pChan ) { /* initialize each channel's driver function pointers */ pChan->sio.pDrvFuncs = &at91cSioDrvFuncs; /* install dummy driver callbacks */ pChan->getTxChar = dummyCallback; pChan->putRcvChar = dummyCallback; /* reset the chip */ AT91C_SIO_REG_WRITE(pChan,AT91C_US_CR,(AT91C_US_RSTRX | AT91C_US_RSTTX));/*RESET*/ AT91C_SIO_REG_WRITE(pChan,AT91C_US_CR,(AT91C_US_RXEN | AT91C_US_TXEN)); /*TX&RX ENABLE*/ AT91C_SIO_REG_WRITE(pChan,AT91C_US_MR,(AT91C_US_CLKS_CLOCK | AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE | AT91C_US_NBSTOP_1_BIT));/*MODE*/ /* setting polled mode is one way to make the device quiet */ at91cIoctl ((SIO_CHAN *)pChan, SIO_MODE_SET, (void *)SIO_MODE_POLL); at91cIoctl ((SIO_CHAN *)pChan, SIO_BAUD_SET, (void *)AT91C_SIO_DEFAULT_BAUD); }/******************************************************************************** at91cDevInit2 - initialize a AT91C_DUSART, 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 at91cDevInit2 ( AT91C_CHAN * pChan /* device to initialize */ ) { char outchar = '\0'; UINT32 status;#if 0 int i; /* Interrupt mode is allowed */ AT91C_SIO_REG_WRITE(pChan,AT91C_US_CR,(AT91C_US_RSTRX | AT91C_US_RSTTX));/*RESET*/ AT91C_SIO_REG_WRITE(pChan,AT91C_US_CR,(AT91C_US_RXEN | AT91C_US_TXEN)); /*TX&RX ENABLE*/ AT91C_SIO_REG_WRITE(pChan,AT91C_US_MR,(AT91C_US_CLKS_CLOCK | AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE | AT91C_US_NBSTOP_1_BIT));/*MODE*/ AT91C_SIO_REG_WRITE(pChan,AT91C_US_IER,(AT91C_US_RXRDY |AT91C_US_TXRDY));/*INT ENABLE*/ intEnable(pChan->intLevel); /* * Dummy write to TXBUF to start TX empty interrupt */ AT91C_SIO_REG_WRITE(pChan,AT91C_US_THR,outchar); AT91C_SIO_REG_READ(pChan,AT91C_US_CSR, status); /* AT91C_SIO_REG_WRITE(pChan,AT91C_AIC_ICCR,(1<<pChan->intLevel));/*clear pend */ *(volatile UINT32 *)0xfffff800 = 0x35; *(volatile UINT32 *)0xfffff810 = 0x35; while(1) { *(volatile UINT32 *)0xfffff834 = 0x35;/*lit*/ for(i=0;i<1000000;i++); *(volatile UINT32 *)0xfffff830 = 0x35; for(i=0;i<1000000;i++); } while ((status & AT91C_US_TXREADY) != AT91C_US_TXREADY) ;#endif AT91C_SIO_REG_WRITE(pChan,AT91C_US_IER,AT91C_US_RXRDY |AT91C_US_TXRDY); at91cIntrMode = TRUE; }/******************************************************************************** at91cInt - handle a system interrupt:DBGU or ST_PIT** RETURNS: N/A*/ void sysIntHandler ( AT91C_CHAN * pChan /* channel generating the interrupt */ ){ UINT32 status; UINT32 mask; status = *(volatile UINT32 *)AT91C_ST_SR; mask = *(volatile UINT32 *)AT91C_ST_IMR; if((status & mask) == 1) { sysClkInt(); } else { at91cInt(pChan); }}/******************************************************************************** at91cInt - handle a channel's Tramsmit or receive-character interrupt** RETURNS: N/A*/ void at91cInt ( AT91C_CHAN * pChan /* channel generating the interrupt */ ){ UINT32 status; AT91C_SIO_REG_READ(pChan,AT91C_US_CSR, status); if((status & AT91C_US_RXREADY ) == AT91C_US_RXREADY ) at91cIntRcv(pChan); else if((status & AT91C_US_TXREADY) != AT91C_US_TXREADY) return; at91cIntTx(pChan);}/******************************************************************************** at91cIntRcv - handle a channel's receive-character interrupt** RETURNS: N/A*/ LOCAL void at91cIntRcv ( AT91C_CHAN * pChan /* channel generating the interrupt */ ) { char inChar; /* * 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. */ AT91C_SIO_REG_READ(pChan,AT91C_US_RHR, inChar); (*pChan->putRcvChar) (pChan->putRcvArg, inChar); }/******************************************************************************** at91cIntTx - handle a channels transmitter-ready interrupt** RETURNS: N/A*/ LOCAL void at91cIntTx ( AT91C_CHAN * pChan /* channel generating the interrupt */ ) { char outChar; /* * 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. */ if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR) AT91C_SIO_REG_WRITE(pChan, AT91C_US_THR, outChar); else { AT91C_SIO_REG_WRITE(pChan, AT91C_US_IDR, AT91C_US_TXRDY);/*disable Tx interrupt*/#if 0 *(volatile UINT32 *) AT91C_AIC_CISR= (1 << pChan->intLevel); /*INT pend clear*/#endif *(volatile UINT32 *) AT91C_AIC_ICCR= (1 << pChan->intLevel); /*INT pend clear*/ } }/******************************************************************************** at91cTxStartup - start the interrupt transmitter** RETURNS: OK on success, ENOSYS if the device is polled-only, or* EIO on hardware error.*/LOCAL int at91cTxStartup ( SIO_CHAN * pSioChan /* channel to start */ ) { AT91C_CHAN * pChan = (AT91C_CHAN *)pSioChan;/* *(volatile UINT32 *)AT91C_AIC_CISR = (1 << pChan->intLevel);*/ *(volatile UINT32 *) AT91C_AIC_ICCR= (1 << pChan->intLevel); /*INT pend clear*/ AT91C_SIO_REG_WRITE(pChan, AT91C_US_IER,AT91C_US_TXRDY); intEnable (pChan->intLevel); return (OK); }/******************************************************************************** at91cCallbackInstall - 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 at91cCallbackInstall ( SIO_CHAN * pSioChan, /* channel */ int callbackType, /* type of callback */ STATUS (*callback)(), /* callback */ void * callbackArg /* parameter to callback */ ) { AT91C_CHAN * pChan = (AT91C_CHAN *)pSioChan; switch (callbackType) { case SIO_CALLBACK_GET_TX_CHAR: pChan->getTxChar = callback; pChan->getTxArg = callbackArg; return (OK); case SIO_CALLBACK_PUT_RCV_CHAR: pChan->putRcvChar = callback; pChan->putRcvArg = callbackArg; return (OK); default: return (ENOSYS); } }/********************************************************************************* at91cPollOutput - 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 at91cPollOutput ( SIO_CHAN *pSioChan, char outChar ) { AT91C_CHAN * pChan = (AT91C_CHAN *)pSioChan; UINT32 status; /* is the transmitter ready to accept a character? */ AT91C_SIO_REG_READ (pChan, AT91C_US_CSR, status); if ((status & AT91C_US_TXREADY) == 0x00) return (EAGAIN); /* write out the character */ AT91C_SIO_REG_WRITE(pChan, AT91C_US_THR, outChar); return (OK); }/******************************************************************************** at91cPollInput - 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 at91cPollInput ( SIO_CHAN * pSioChan, char * thisChar ) { AT91C_CHAN * pChan = (AT91C_CHAN *)pSioChan; UINT32 status; AT91C_SIO_REG_READ (pChan,AT91C_US_CSR, status); if ((status & AT91C_US_RXREADY) == 0x00) return (EAGAIN); /* no input available at this time */ /* got a character */ AT91C_SIO_REG_READ(pChan, AT91C_US_RHR, *thisChar); return (OK); }/******************************************************************************** at91cModeSet - toggle between interrupt and polled mode** RETURNS: OK on success, EIO on unsupported mode.*/LOCAL int at91cModeSet ( AT91C_CHAN * pChan, /* channel */ uint_t newMode /* new mode */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -