📄 at91sio.c
字号:
/* s3c2510Sio.c - at91rm9200 UART controller driver */#include "vxWorks.h"#include "intLib.h"#include "errno.h"#include "config.h"#include "drv/intrCtl/at91Intr.h"#include "drv/sio/at91Sio.h"#include "lib_AT91RM9200.h"#define UART_PUT_CR(port,v) port->US_CR = v#define UART_GET_MR(port) port->US_MR#define UART_PUT_MR(port,v) port->US_MR = v#define UART_PUT_IER(port,v) port->US_IER = v#define UART_PUT_IDR(port,v) port->US_IDR = v#define UART_GET_IMR(port) port->US_IMR#define UART_GET_CSR(port) port->US_CSR#define UART_GET_CHAR(port) port->US_RHR#define UART_PUT_CHAR(port,v) port->US_THR = v#define UART_GET_BRGR(port) port->US_BRGR#define UART_PUT_BRGR(port,v) port->US_BRGR = v#define UART_PUT_RTOR(port,v) port->US_RTOR = v/* #define UART_GET_CR(port) port->US_CR // is write-only*/ /* PDC registers */#define UART_PUT_PTCR(port,v) port->US_PTCR = v#define UART_PUT_RPR(port,v) port->US_RPR = v#define UART_PUT_RCR(port,v) port->US_RCR = v#define UART_GET_RCR(port) port->US_RCR#define UART_PUT_RNPR(port,v) port->US_RNPR = v#define UART_PUT_RNCR(port,v) port->US_RNCR = v#define DEFAULT_BAUD 115200/* Local Forward Declarations */LOCAL STATUS s3c2510SioDummyCallback(void);LOCAL int at91SioBaudSet(AT91_SIO_CHAN *pChan, int baudRate);LOCAL int at91SioOptsSet(AT91_SIO_CHAN *pChan, int options);LOCAL int at91SioModeSet(AT91_SIO_CHAN *pChan, int sioMode);LOCAL int at91SioOpen(AT91_SIO_CHAN *pChan);LOCAL int at91SioHup(AT91_SIO_CHAN *pChan);LOCAL int at91SioIoctl(SIO_CHAN *pSioChan, int cmd, void* arg);LOCAL int at91SioTxStartup(SIO_CHAN *pSioChan);LOCAL int at91SioCallbackInstall(SIO_CHAN *pSioChan, int callbackType, STATUS(*callback)(), void *callbackArg);LOCAL int at91SioPollInput(SIO_CHAN *pSioChan, char *inChar);LOCAL int at91SioPollOutput(SIO_CHAN *pSioChan, char outChar);/* Driver Function Table */LOCAL AT91_SIO_CHAN *pDbgUChan = 0;LOCAL SIO_DRV_FUNCS at91SioDrvFuncs = { at91SioIoctl, at91SioTxStartup, at91SioCallbackInstall, at91SioPollInput, at91SioPollOutput};/********************************************************************************* at91SioDummyCallback - dummy callback routine.** RETURNS: ERROR, always.*/LOCAL STATUS at91SioDummyCallback(void){ return ERROR;}/******************************************************************************** at91SioDevInit - initialize a UART** This routine is called to initialize the chip to a quiescent state. Note that* the `ch' field of at91_CHAN must be less than or equal to the maximum* number of UART channels to configure as SIOs, as defined in at91.h** RETURNS: N/A*/void at91SioDevInit( AT91_SIO_CHAN *pChan /* device to initialize */ ){char * buffer = "first string from vxwork\n";AT91PS_USART port=(AT91PS_USART) pChan->base;if(pChan->base==(void*)AT91C_BASE_DBGU){ AT91F_DBGU_CfgPIO(); AT91F_US_Configure ( (AT91PS_USART) AT91C_BASE_DBGU, /* DBGU base address*/ AT91C_MASTER_CLOCK, /* MCK*/ AT91C_US_ASYNC_MODE, /* mode Register to be programmed*/ DEFAULT_BAUD , /* baudrate to be programmed*/ 0); /* timeguard to be programmed*/ /* Enable peripheral clock if required AT91_SYS->PMC_PCER = 1 << AT91C_ID_US0; * Finally, clear and enable interrupts */ pDbgUChan = pChan; pChan->read_status_mask = AT91C_US_RXRDY | AT91C_US_TXRDY | AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE | AT91C_US_RXBRK|AT91C_US_TXEMPTY; UART_PUT_IDR(port, -1); UART_PUT_CR(port, AT91C_US_TXEN | AT91C_US_RXEN); /* enable xmit & rcvr */ UART_PUT_IER(port, AT91C_US_RXRDY); }else{ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOB,AT91C_PB21_RXD1 | AT91C_PB20_TXD1,0); /* First, enable the clock of the PIOB*/ AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1<<AT91C_ID_US1 ) ; /* Usart Configure*/ AT91F_US_Configure (port, AT91C_MASTER_CLOCK,AT91C_US_ASYNC_MODE, DEFAULT_BAUD, 0); /* Enable usart */ UART_PUT_CR(port, AT91C_US_TXEN | AT91C_US_RXEN); /* enable xmit & rcvr */ pChan->read_status_mask = AT91C_US_RXRDY | AT91C_US_TXRDY | AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE | AT91C_US_RXBRK|AT91C_US_TXEMPTY; /* Enable USART IT error and AT91C_US_ENDRX*/ AT91F_US_EnableIt(port,AT91C_US_TIMEOUT | AT91C_US_FRAME | AT91C_US_OVRE |AT91C_US_ENDRX|AT91C_US_TXEMPTY); /* open Usart 1 interrupt*/ /*AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_US1, USART_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, usart_asm_irq_handler); AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_US1); */ /* set time out US_RTOR * Arm time out after 255 * 4 bits time * for 115200 bit time = 1/115200 = 8.6 micro sec time out unuti= 4* 8.6 = 34 micro */ port->US_RTOR = 0xFFFF; /*Enable usart SSTO*/ port->US_CR = AT91C_US_STTTO;} /* Initialize each channel's structure. */ pChan->pDrvFuncs = &at91SioDrvFuncs; pChan->getTxChar = at91SioDummyCallback; pChan->putRcvChar = at91SioDummyCallback; at91SioBaudSet(pChan, DEFAULT_BAUD); at91SioOptsSet(pChan, CREAD | CS8); at91SioModeSet(pChan, SIO_MODE_POLL); /* while(*buffer != '\0') { while (!AT91F_US_TxReady((AT91PS_USART)AT91C_BASE_DBGU)); AT91F_US_PutChar((AT91PS_USART)AT91C_BASE_DBGU, *buffer++); }*/}/******************************************************************************** at91SioDevInit2 - initialize a 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*/void at91SioDevInit2( AT91_SIO_CHAN *pChan /* device to initialize */ ){}/********************************************************************************* at91SioIoctl - special device control** This routine handles the IOCTL messages from the user. It supports commands* to get/set baud rate, mode(INT,POLL), hardware options(parity, number of data* bits) and modem control(RTS/CTS and DTR/DSR handshakes). The ioctl commands* SIO_HUP and SIO_OPEN are used to implement the HUPCL(hang up on last close)* function.** As on a UNIX system, requesting a baud rate of zero is translated into a* hangup request. The DTR and RTS lines are dropped. This should cause a* connected modem to drop the connection. The SIO_HUP command will only hangup* if the HUPCL option is active. The SIO_OPEN function will raise DTR and RTS* lines whenever it is called. Use the BAUD_RATE=0 function to hangup when HUPCL* is not active.** The CLOCAL option will disable hardware flow control. When selected, hardware* flow control is not used. When not selected hardware flow control is based on* the RTS/CTS signals. CTS is the clear to send input from the other end. It* must be true for this end to begin sending new characters. In most drivers,* the RTS signal will be assumed to be connected to the opposite end's CTS* signal and can be used to control output from the other end. Raising RTS* asserts CTS at the other end and the other end can send data. Lowering RTS* de-asserts CTS and the other end will stop sending data. (This is non-EIA* defined use of RTS).** RETURNS: OK on success, ENOSYS on unsupported request, EIO on failed request.*/LOCAL int at91SioIoctl( SIO_CHAN *pSioChan, /* device to control */ int cmd, /* request code */ void *arg /* some argument */ ){ AT91_SIO_CHAN *pChan = (AT91_SIO_CHAN *)pSioChan; int status = OK; int lockKey; switch (cmd) { /* Set the baud rate. */ case SIO_BAUD_SET: /* Disable interrupts during chip access. */ lockKey = intLock(); status = at91SioBaudSet(pChan, (int)arg); /* Enable interrupts after chip access. */ intUnlock(lockKey); break; /* Get the baud rate. */ case SIO_BAUD_GET: *(int *)arg = pChan->baudRate; break; /* Set the hardware options (as defined in sioLib.h). */ case SIO_HW_OPTS_SET: /* Disable interrupts during chip access. */ lockKey = intLock(); status = at91SioOptsSet(pChan, (int)arg); /* Enable interrupts after chip access. */ intUnlock(lockKey); break; /* Get the hardware options (as defined in sioLib.h). */ case SIO_HW_OPTS_GET: *(int *)arg = pChan->options; break; /* Set the mode (e.g., to interrupt or polled). */ case SIO_MODE_SET: /* Disable interrupts during chip access. */ lockKey = intLock(); status = at91SioModeSet(pChan, (int)arg); /* Enable interrupts after chip access. */ intUnlock(lockKey); break; /* Get the current mode. */ case SIO_MODE_GET: *(int *)arg = pChan->sioMode; break; /* Get the available modes. */ case SIO_AVAIL_MODES_GET: *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL; break; case SIO_OPEN: status = at91SioOpen(pChan); break; case SIO_HUP: status = at91SioHup(pChan); break; default: status = ENOSYS; } return (status);}/******************************************************************************** at91SioTxStartup - start the interrupt transmitter** RETURNS: OK on success, ENOSYS if the device is polled-only, or EIO on* hardware error.*/LOCAL int at91SioTxStartup( SIO_CHAN *pSioChan /* device to start */ ){ AT91_SIO_CHAN *pChan = (AT91_SIO_CHAN *)pSioChan; AT91PS_USART port =(AT91PS_USART) (pChan->base); if (pChan->sioMode != SIO_MODE_INT) /* polling mode */ { return ENOSYS; } /* Enable Transmit Holding Register Empty Interrupt. */ /**at91_UINT(pChan->ch) |= at91_UINT_THEIE;*/ UART_PUT_IER(port, AT91C_US_TXEMPTY); return OK;}/******************************************************************************** at91SioCallbackInstall - 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 at91SioCallbackInstall( SIO_CHAN *pSioChan, /* device */ int callbackType, /* type of callback */ STATUS (*callback)(), /* callback */ void* callbackArg /* parameter to callback */ ){ AT91_SIO_CHAN *pChan = (AT91_SIO_CHAN *)pSioChan; switch (callbackType) { case SIO_CALLBACK_GET_TX_CHAR: pChan->getTxChar = callback; pChan->getTxArg = callbackArg; break; case SIO_CALLBACK_PUT_RCV_CHAR: pChan->putRcvChar = callback; pChan->putRcvArg = callbackArg; break; default: return ENOSYS; } return OK;}/******************************************************************************** at91SioPollInput - 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 at91SioPollInput( SIO_CHAN *pSioChan, /* device to poll */ char *inChar /* buffer to receive char */ ){ AT91_SIO_CHAN *pChan = (AT91_SIO_CHAN *)pSioChan; UINT32 stat; AT91PS_USART port =(AT91PS_USART) (pChan->base); /*stat = *at91_USTAT(pChan->ch);*/ stat = UART_GET_CSR(port); /*stat = *at91_USTAT(pChan->ch);*/ /* If no valid data present, retry later. */ if (!(stat & AT91C_US_RXRDY)) /* Receive Data Valid */ { return EAGAIN; } /* Read character from Receive Data Register. */ *inChar = UART_GET_CHAR(port); /**inChar = (char)*at91_URXBUF(pChan->ch);*/ return OK;}/********************************************************************************* at91SioPollOutput - 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 at91SioPollOutput( SIO_CHAN *pSioChan, /* device to poll */ char outChar /* char to transmit */ ){ AT91_SIO_CHAN *pChan = (AT91_SIO_CHAN *)pSioChan; UINT32 stat; AT91PS_USART port =(AT91PS_USART) (pChan->base); /*stat = *at91_USTAT(pChan->ch);*/ stat = UART_GET_CSR(port); if (!(stat & AT91C_US_TXEMPTY)) /* Transmit Holding Register Empty */ { return EAGAIN; } /* Write char to Transmit Data Register. */ UART_PUT_CHAR(port, outChar);/**at91_UTXBUF(pChan->ch) = (VUINT8)outChar;*/ return OK;}/* * Interrupt handler */void at91SioInt(AT91_SIO_CHAN *pChan ){ /*struct uart_port *port = dev_id;*/ char ch = 0; unsigned int status, pending, pass_counter = 0; AT91PS_USART port = 0; if(pChan==0) { pChan = pDbgUChan; if(pChan==0) return; } port =(AT91PS_USART) (pChan->base);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -