📄 at91uart.c
字号:
pChan->errorArg = callbackArg; return (OK); default: return (ENOSYS); } }/********************************************************************************* templatePollOutput - output a character in polled mode** Polled mode operation takes place without any kernel or other OS* services available. Use extreme care to insure that this code does not* call any kernel services. Polled mode is only for WDB system mode use.* Kernel services, semaphores, tasks, etc, are not available during WDB* system 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 at91PollOutput ( SIO_CHAN * pSioChan, char outChar ) { AT91_UART_CHAN * pChan = (AT91_UART_CHAN *)pSioChan; AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */ UINT32 status; /* is the transmitter ready to accept a character? */ /* Read TX device status */ status = pUsart->US_CSR; /* determine if transmitter is ready */ if (0x00 == (status & (AT91RM9200_US_SR_TXRDY))) /* device is busy, try again later */ return (EAGAIN); /* transmit the character */ pUsart->US_THR = (AT91_REG)outChar; return (OK); }/******************************************************************************** at91PollInput - poll the device for input** Polled mode operation takes place without any kernel or other OS* services available. Use extreme care to insure that this code does not* call any kernel services. Polled mode is only for WDB system mode use.* Kernel services, semaphores, tasks, etc, are not available during WDB* system mode.** 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 at91PollInput ( SIO_CHAN * pSioChan, char * thisChar ) { AT91_UART_CHAN * pChan = (AT91_UART_CHAN *)pSioChan; AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */ UINT32 status; /* Read RX device status */ status = pUsart->US_CSR; /* Check if receive data is available */ if (0x00 == (status & (AT91RM9200_US_SR_RXRDY))) { return EAGAIN; /* no input available at this time */ } /* Check for receive error conditions */ if (0x00 != (status & (AT91RM9200_US_SR_PARE | AT91RM9200_US_SR_FRAME | AT91RM9200_US_SR_OVRE))) { /* Decode and handle the specific error condition */ pUsart->US_CR = AT91RM9200_US_CR_RSTSTA; /* reset receive of USART to clear error */ /* Do NOT call the error callback routine, just return EIO */ return EIO; } /* read character, store it, and return OK */ *thisChar = (char)(pUsart->US_RHR); return (OK); }/******************************************************************************** at91ModeSet - toggle between interrupt and polled mode** RETURNS: OK on success, EIO on unsupported mode.*/LOCAL int at91ModeSet ( AT91_UART_CHAN * pChan, /* channel */ uint_t newMode /* new mode */ ) { AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */ AT91_UART_PARAS *pParas = (AT91_UART_PARAS *)(pChan->pUart); int oldIntLvl; if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT)) return (EIO); oldIntLvl = intLock(); /* * use this function will made all the action done in * at91IosDevInit be cancelled, so we can't do it now pUsart->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX; */ if (pChan->mode == SIO_MODE_INT) { /* switch device to interrupt mode */ if (pChan->intConnect == FALSE) { /* interconnect ISR to intvector */; intConnect (INUM_TO_IVEC(pParas->vector), at91UARTInt, (int)pChan); pChan->intConnect = TRUE; } /* enable interrupt of device */ pUsart->US_IER = AT91RM9200_US_INT_RXRDY | AT91RM9200_US_INT_PARE |AT91RM9200_US_INT_FRAME | AT91RM9200_US_INT_OVRE; pUsart->US_IDR = AT91RM9200_US_INT_TXRDY; /* we only enable receive and error interrupt pUsart->US_IER = AT91RM9200_US_INT_RXRDY | AT91RM9200_US_INT_RXRDY |AT91RM9200_US_INT_PARE | AT91RM9200_US_INT_FRAME |AT91RM9200_US_INT_OVRE; */ intEnable (pParas->intLevel); } else { /* switch device to polled mode */ /* disable interrupt of device */ pUsart->US_IDR = -1; /* disable all interrupt */ intDisable (pParas->intLevel); } /* activate the new mode */ pChan->mode = newMode; intUnlock(oldIntLvl); return (OK); }#if 0/********************************************************************************* templateHup - hang up the modem control lines ** Resets the RTS and DTR signals.** RETURNS: OK always.*/LOCAL STATUS at91Hup ( AT91_UART_CHAN * pChan /* pointer to channel */ ) { /* * TODO - Use global intLock if lockout time will be very short. If not, * use a device specific lockout that will not damage overall system * latency. */ at91MstatSetClr (pChan,(SIO_MODEM_RTS|SIO_MODEM_DTR), FALSE); return (OK); } /********************************************************************************* at91Open - Set the modem control lines ** Set the modem control lines(RTS, DTR) TRUE if not already set. ** RETURNS: OK*/LOCAL STATUS at91Open ( AT91_UART_CHAN * pChan /* pointer to channel */ ) { /* * TODO - Use global intLock if lockout time will be very short. If not, * use a device specific lockout that will not damage overall system * latency. */ at91MstatSetClr (pChan, (SIO_MODEM_RTS|SIO_MODEM_DTR), TRUE); return (OK); }#endif/******************************************************************************** at91OptSet - set hardware options** This routine sets up the hardware according to the specified option* argument. If the hardware cannot support a particular option value, then* it should ignore that portion of the request.** RETURNS: OK upon success, or EIO for invalid arguments.*/LOCAL int at91OptSet ( AT91_UART_CHAN * pChan, /* channel */ uint_t newOpts /* new options */ ) { AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */ AT91_UART_PARAS *pParas = (AT91_UART_PARAS *)(pChan->pUart); int uartHwOptions = pParas->uartOption;/* BOOL hdweFlowCtrl=TRUE; BOOL rcvrEnable = TRUE;*/ int oldIntLvl; if (pChan == NULL || newOpts & 0xffffff00) return EIO; /* do nothing if options already set */ if (pParas->uartOption== newOpts) return OK; /* ignore requests for unsupported options */ /* decode individual request elements */ uartHwOptions &= ~(AT91RM9200_US_MR_CHRL); switch (newOpts & CSIZE) { case CS5: uartHwOptions |= AT91RM9200_US_MR_CHRL_5_BITS; break; case CS6: uartHwOptions |= AT91RM9200_US_MR_CHRL_6_BITS; break; case CS7: uartHwOptions |= AT91RM9200_US_MR_CHRL_7_BITS; break; default: case CS8: uartHwOptions |= AT91RM9200_US_MR_CHRL_8_BITS; break; } uartHwOptions &= ~(AT91RM9200_US_MR_NBSTOP); if (newOpts & STOPB) /* 2 bits stop bit */ uartHwOptions |= AT91RM9200_US_MR_NBSTOP_2_BIT; else /* 1 bit stop bit */ uartHwOptions |= AT91RM9200_US_MR_NBSTOP_1_BIT; uartHwOptions &= ~(AT91RM9200_US_MR_PAR); switch (newOpts & (PARENB|PARODD)) { case PARENB|PARODD: /* enable odd parity */ uartHwOptions |= AT91RM9200_US_MR_PAR_ODD; break; case PARENB: /* enable even parity */ uartHwOptions |= AT91RM9200_US_MR_PAR_EVEN; break; case PARODD: /* invalid mode, not normally used. */ uartHwOptions |= AT91RM9200_US_MR_PAR_MULTI_DROP; break; default: case 0: /* no parity */; uartHwOptions |= AT91RM9200_US_MR_PAR_NONE; break; } if (newOpts & CLOCAL) { /* clocal disables hardware flow control */ uartHwOptions &= ~(AT91RM9200_US_MR_USMODE); uartHwOptions |= AT91RM9200_US_MR_USMODE_NORMAL; } else { /* enable hardware flow control */ uartHwOptions &= ~(AT91RM9200_US_MR_USMODE); uartHwOptions |= AT91RM9200_US_MR_USMODE_HWHSH; uartHwOptions |= AT91RM9200_US_MR_USMODE_MODEM; } if ((newOpts & CREAD) == 0) pUsart->US_CR = AT91RM9200_US_CR_RXDIS; else pUsart->US_CR = AT91RM9200_US_CR_RXEN; oldIntLvl = intLock (); /* * Reset the device according to uartHwOptions */ pUsart->US_MR = uartHwOptions; intUnlock (oldIntLvl); /* * Be sure that pChan->options reflects the actual * hardware settings. If 5 data bits were requested, but unsupported, * then be sure pChan->options reflects the actual number of data bits * currently selected. */ /* * we store register setting in pParas->uartOption * and software setting in pChan->options */ pParas->uartOption = uartHwOptions; pChan->options = newOpts; return (OK); }/********************************************************************************* at91Ioctl - 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 at91Ioctl ( SIO_CHAN * pSioChan, /* device to control */ int request, /* request code */ void * someArg /* some argument */ ) { AT91_UART_CHAN *pChan = (AT91_UART_CHAN *) pSioChan; AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */ AT91_UART_PARAS *pParas = (AT91_UART_PARAS *)(pChan->pUart); int oldLevel; /* current interrupt level mask */ int baudConstant; int arg = (int)someArg; /* TEMPLATE_PIPE_FLUSH(pChan); */ switch (request) { case SIO_BAUD_SET: /* * like unix, a baud request for 0 is really a request to hangup. */ if (arg == 0) return (EIO);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -