📄 usartat91.c
字号:
* * \param mode 0 (disabled), 1 (odd) or 2 (even) * * \return 0 on success, -1 otherwise. */static int At91UsartSetParity(u_char mode){ ureg_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_PAR; switch (mode) { case 0: val |= US_PAR_NO; break; case 1: val |= US_PAR_ODD; break; case 2: val |= US_PAR_EVEN; break; } At91UsartDisable(); outr(USARTn_BASE + US_MR_OFF, val); At91UsartEnable(); /* * Verify the result. */ if (At91UsartGetParity() != mode) { return -1; } return 0;}/*! * \brief Query the USART hardware for the number of stop bits. * * This routine is called by ioctl function of the upper level USART * driver through the USARTDCB jump table. * * \return The number of stop bits set, either 1, 2 or 3 (1.5 bits). */static u_char At91UsartGetStopBits(void){ ureg_t val = inr(USARTn_BASE + US_MR_OFF) & US_NBSTOP; if (val == US_NBSTOP_1) { val = 1; } else if (val == US_NBSTOP_2) { val = 2; } else { val = 3; } return (u_char)val;}/*! * \brief Set the USART hardware to the number of stop bits. * * This routine is called by ioctl function of the upper level USART * driver through the USARTDCB jump table. * * \return 0 on success, -1 otherwise. */static int At91UsartSetStopBits(u_char bits){ ureg_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_NBSTOP; switch(bits) { case 1: val |= US_NBSTOP_1; break; case 2: val |= US_NBSTOP_2; break; case 3: val |= US_NBSTOP_1_5; break; } At91UsartDisable(); outr(USARTn_BASE + US_MR_OFF, val); At91UsartEnable(); /* * Verify the result. */ if (At91UsartGetStopBits() != bits) { return -1; } return 0;}/*! * \brief Query the USART hardware status. * * \return Status flags. */static u_long At91UsartGetStatus(void){ u_long rc = 0; /* * Set receiver error flags. */ if ((rx_errors & US_FRAME) != 0) { rc |= UART_FRAMINGERROR; } if ((rx_errors & US_OVRE) != 0) { rc |= UART_OVERRUNERROR; } if ((rx_errors & US_PARE) != 0) { rc |= UART_PARITYERROR; } /* * Determine software handshake status. The flow control status may * change during interrupt, but this doesn't really hurt us. */ if (flow_control) { if (flow_control & XOFF_SENT) { rc |= UART_RXDISABLED; } if (flow_control & XOFF_RCVD) { rc |= UART_TXDISABLED; } }#ifdef UART_RTS_BIT /* * Determine hardware handshake control status. */ if (bit_is_set(UART_RTS_PORT, UART_RTS_BIT)) { rc |= UART_RTSDISABLED; if (rts_control) { rc |= UART_RXDISABLED; } } else { rc |= UART_RTSENABLED; }#endif#ifdef UART_CTS_BIT /* * Determine hardware handshake sense status. */ if (bit_is_set(UART_CTS_PIN, UART_CTS_BIT)) { rc |= UART_CTSDISABLED; if (cts_sense) { rc |= UART_RXDISABLED; } } else { rc |= UART_CTSENABLED; }#endif /* * If transmitter and receiver haven't been detected disabled by any * of the checks above, then they are probably enabled. */ if ((rc & UART_RXDISABLED) == 0) { rc |= UART_RXENABLED; } if ((rc & UART_TXDISABLED) == 0) { rc |= UART_TXENABLED; } /* * Process multidrop setting. */ if (tx_aframe) { rc |= UART_TXADDRFRAME; } else { rc |= UART_TXNORMFRAME; } return rc;}/*! * \brief Set the USART hardware status. * * \param flags Status flags. * * \return 0 on success, -1 otherwise. */static int At91UsartSetStatus(u_long flags){ /* * Process software handshake control. */ if (flow_control) { /* Access to the flow control status must be atomic. */ NutEnterCritical(); /* * Enabling or disabling the receiver means to behave like * having sent a XON or XOFF character resp. */ if (flags & UART_RXENABLED) { flow_control &= ~XOFF_SENT; } else if (flags & UART_RXDISABLED) { flow_control |= XOFF_SENT; } /* * Enabling or disabling the transmitter means to behave like * having received a XON or XOFF character resp. */ if (flags & UART_TXENABLED) { flow_control &= ~XOFF_RCVD; } else if (flags & UART_TXDISABLED) { flow_control |= XOFF_RCVD; } NutExitCritical(); }#ifdef UART_RTS_BIT /* * Process hardware handshake control. */ if (rts_control) { if (flags & UART_RXDISABLED) { sbi(UART_RTS_PORT, UART_RTS_BIT); } if (flags & UART_RXENABLED) { cbi(UART_RTS_PORT, UART_RTS_BIT); } } if (flags & UART_RTSDISABLED) { sbi(UART_RTS_PORT, UART_RTS_BIT); } if (flags & UART_RTSENABLED) { cbi(UART_RTS_PORT, UART_RTS_BIT); }#endif /* * Process multidrop setting. */ if (flags & UART_TXADDRFRAME) { tx_aframe = 1; } if (flags & UART_TXNORMFRAME) { tx_aframe = 0; } /* * Clear UART receive errors. */ if (flags & UART_ERRORS) { outr(USARTn_BASE + US_CR_OFF, US_RSTSTA); } /* * Verify the result. */ if ((At91UsartGetStatus() & ~UART_ERRORS) != flags) { return -1; } return 0;}/*! * \brief Query the USART hardware for synchronous mode. * * This function is called by ioctl function of the upper level USART * driver through the USARTDCB jump table. * * \return Or-ed combination of \ref UART_SYNC, \ref UART_MASTER, * \ref UART_NCLOCK and \ref UART_HIGHSPEED. */static u_char At91UsartGetClockMode(void){ u_char rc = 0; return rc;}/*! * \brief Set asynchronous or synchronous mode. * * This function is called by ioctl function of the upper level USART * driver through the USARTDCB jump table. * * \param mode Must be an or-ed combination of USART_SYNC, USART_MASTER, * USART_NCLOCK and USART_HIGHSPEED. * * \return 0 on success, -1 otherwise. */static int At91UsartSetClockMode(u_char mode){ /* * Verify the result. */ if (At91UsartGetClockMode() != mode) { return -1; } return 0;}/*! * \brief Query flow control mode. * * This routine is called by ioctl function of the upper level USART * driver through the USARTDCB jump table. * * \return See UsartIOCtl(). */static u_long At91UsartGetFlowControl(void){ u_long rc = 0; if (flow_control) { rc |= USART_MF_XONXOFF; } else { rc &= ~USART_MF_XONXOFF; }#ifdef UART_RTS_BIT if (rts_control) { rc |= USART_MF_RTSCONTROL; } else { rc &= ~USART_MF_RTSCONTROL; }#endif#ifdef UART_CTS_BIT if (cts_sense) { rc |= USART_MF_CTSSENSE; } else { rc &= ~USART_MF_CTSSENSE; }#endif#ifdef UART_HDX_BIT if (hdx_control) { rc |= USART_MF_HALFDUPLEX; } else { rc &= ~USART_MF_HALFDUPLEX; }#endif return rc;}/*! * \brief Set flow control mode. * * This function is called by ioctl function of the upper level USART * driver through the USARTDCB jump table. * * \param flags See UsartIOCtl(). * * \return 0 on success, -1 otherwise. */static int At91UsartSetFlowControl(u_long flags){ /* * Set software handshake mode. */ if (flags & USART_MF_XONXOFF) { if(flow_control == 0) { NutEnterCritical(); flow_control = 1 | XOFF_SENT; /* force XON to be sent on next read */ NutExitCritical(); } } else { NutEnterCritical(); flow_control = 0; NutExitCritical(); }#ifdef UART_RTS_BIT /* * Set RTS control mode. */ if (flags & USART_MF_RTSCONTROL) { sbi(UART_RTS_PORT, UART_RTS_BIT); sbi(UART_RTS_DDR, UART_RTS_BIT); rts_control = 1; } else if (rts_control) { rts_control = 0; cbi(UART_RTS_DDR, UART_RTS_BIT); }#endif#ifdef UART_CTS_BIT /* * Set CTS sense mode. */ if (flags & USART_MF_CTSSENSE) { /* Register CTS sense interrupt. */ if (NutRegisterIrqHandler(&UART_CTS_SIGNAL, At91UsartCts, 0)) { return -1; } sbi(UART_CTS_PORT, UART_CTS_BIT); cbi(UART_CTS_DDR, UART_CTS_BIT); cts_sense = 1; } else if (cts_sense) { cts_sense = 0; /* Deregister CTS sense interrupt. */ NutRegisterIrqHandler(&UART_CTS_SIGNAL, 0, 0); cbi(UART_CTS_DDR, UART_CTS_BIT); }#endif#ifdef UART_HDX_BIT /* * Set half duplex mode. */ if (flags & USART_MF_HALFDUPLEX) { /* Register transmit complete interrupt. */ if (NutRegisterIrqHandler(&sig_UART_TRANS, At91UsartTxComplete, &dcb_usart.dcb_rx_rbf)) { return -1; } /* Initially enable the receiver. */ UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT); sbi(UART_HDX_DDR, UART_HDX_BIT); hdx_control = 1; /* Enable transmit complete interrupt. */ sbi(UCSRnB, TXCIE); } else if (hdx_control) { hdx_control = 0; /* disable transmit complete interrupt */ cbi(UCSRnB, TXCIE); /* Deregister transmit complete interrupt. */ NutRegisterIrqHandler(&sig_UART_TRANS, 0, 0); cbi(UART_HDX_DDR, UART_HDX_BIT); }#endif /* * Verify the result. */ if (At91UsartGetFlowControl() != flags) { return -1; } return 0;}/*! * \brief Start the USART transmitter hardware. * * The upper level USART driver will call this function through the * USARTDCB jump table each time it added one or more bytes to the * transmit buffer. */static void At91UsartTxStart(void){#ifdef UART_HDX_BIT if (hdx_control) { /* Enable half duplex transmitter. */ UART_HDX_TX(UART_HDX_PORT, UART_HDX_BIT); }#endif /* Enable transmit interrupts. */ outr(USARTn_BASE + US_IER_OFF, US_TXRDY);}/*! * \brief Start the USART receiver hardware. * * The upper level USART driver will call this function through the * USARTDCB jump table each time it removed enough bytes from the * receive buffer. Enough means, that the number of bytes left in * the buffer is below the low watermark. */static void At91UsartRxStart(void){ /* * Do any required software flow control. */ if (flow_control && (flow_control & XOFF_SENT) != 0) { NutEnterCritical(); if ((inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY)) { outr(USARTn_BASE + US_THR_OFF, ASCII_XON); flow_control &= ~XON_PENDING; } else { flow_control |= XON_PENDING; } flow_control &= ~(XOFF_SENT | XOFF_PENDING); NutExitCritical(); }#ifdef UART_RTS_BIT if (rts_control) { /* Enable RTS. */ cbi(UART_RTS_PORT, UART_RTS_BIT); }#endif}/* * \brief Initialize the USART hardware driver. * * This function is called during device registration by the upper level * USART driver through the USARTDCB jump table. * * \return 0 on success, -1 otherwise. */static int At91UsartInit(void){ /* * Register receive and transmit interrupts. */ if (NutRegisterIrqHandler(&SIG_UART, At91UsartInterrupt, &dcb_usart)) { return -1; } /* Enable UART clock. */ outr(PS_PCER, _BV(US_ID)); /* Disable GPIO on UART tx/rx pins. */ outr(PIO_PDR, US_GPIO_PINS); /* Reset UART. */ outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS); /* Disable all UART interrupts. */ outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF); /* Clear UART counter registers. */ outr(USARTn_BASE + US_RCR_OFF, 0); outr(USARTn_BASE + US_TCR_OFF, 0); /* Set UART baud rate generator register. */ outr(USARTn_BASE + US_BRGR_OFF, AT91_US_BAUD(115200)); /* Set UART mode to 8 data bits, no parity and 1 stop bit. */ outr(USARTn_BASE + US_MR_OFF, US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1); return 0;}/* * \brief Deinitialize the USART hardware driver. * * This function is called during device deregistration by the upper * level USART driver through the USARTDCB jump table. * * \return 0 on success, -1 otherwise. */static int At91UsartDeinit(void){ /* Deregister receive and transmit interrupts. */ NutRegisterIrqHandler(&SIG_UART, 0, 0); /* Reset UART. */ outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS); /* Disable all UART interrupts. */ outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF); /* Disable UART clock. */ outr(PS_PCDR, _BV(US_ID)); /* Enable GPIO on UART tx/rx pins. */ outr(PIO_PER, US_GPIO_PINS); /* * Disabling flow control shouldn't be required here, because it's up * to the upper level to do this on the last close or during * deregistration. */#ifdef UART_HDX_BIT /* Deregister transmit complete interrupt. */ if (hdx_control) { hdx_control = 0; NutRegisterIrqHandler(&sig_UART_TRANS, 0, 0); }#endif#ifdef UART_CTS_BIT if (cts_sense) { cts_sense = 0; cbi(UART_CTS_DDR, UART_CTS_BIT); /* Deregister CTS sense interrupt. */ NutRegisterIrqHandler(&UART_CTS_SIGNAL, 0, 0); }#endif#ifdef UART_RTS_BIT if (rts_control) { rts_control = 0; cbi(UART_RTS_DDR, UART_RTS_BIT); }#endif return 0;}/*@}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -