📄 usartavr.c
字号:
* 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; }#ifdef __AVR_ENHANCED__ if (flags & UART_RXADDRFRAME) { sbi(UCSRnA, MPCM); } if (flags & UART_RXNORMFRAME) { cbi(UCSRnA, MPCM); }#endif /* * Clear UART receive errors. */ if (flags & UART_FRAMINGERROR) { rx_errors &= ~_BV(FE); } if (flags & UART_OVERRUNERROR) { rx_errors &= ~_BV(DOR); }#ifdef __AVR_ENHANCED__ if (flags & UART_PARITYERROR) { rx_errors &= ~_BV(UPE); }#endif /* * Verify the result. */ if ((AvrUsartGetStatus() & ~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 AvrUsartGetClockMode(void){ u_char rc = 0;#ifdef __AVR_ENHANCED__ if (bit_is_set(UCSRnC, UMSEL)) { rc |= UART_SYNC; if (bit_is_set(DDRE, 2)) { rc |= UART_MASTER; } if (bit_is_set(UCSRnC, UCPOL)) { rc |= UART_NCLOCK; } } else if (bit_is_set(UCSRnA, U2X)) { rc |= UART_HIGHSPEED; }#endif 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 AvrUsartSetClockMode(u_char mode){#ifdef __AVR_ENHANCED__ AvrUsartDisable(); /* * Handle synchronous mode. */ if (mode & UART_SYNC) { if (mode & UART_MASTER) { /* Enable master mode. */ sbi(DDRE, 2); } else { /* Disable master mode. */ cbi(DDRE, 2); } if (mode & UART_NCLOCK) { /* Enable negated clock. */ sbi(UCSRnC, UCPOL); } else { /* Disable negated clock. */ cbi(UCSRnC, UCPOL); } /* Disable high speed. */ cbi(UCSRnA, U2X); /* Enable synchronous mode. */ sbi(UCSRnA, UMSEL); } /* * Handle asynchronous mode. */ else { if (mode & UART_HIGHSPEED) { /* Enable high speed. */ sbi(UCSRnA, U2X); } else { /* Disable high speed. */ cbi(UCSRnA, U2X); } /* Disable negated clock. */ cbi(UCSRnC, UCPOL); /* Disable synchronous mode. */ cbi(UCSRnC, UMSEL); } AvrUsartEnable();#endif /* * Verify the result. */ if (AvrUsartGetClockMode() != 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 AvrUsartGetFlowControl(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 AvrUsartSetFlowControl(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, AvrUsartCts, 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, AvrUsartTxComplete, &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 (AvrUsartGetFlowControl() != 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 AvrUsartTxStart(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. */ sbi(UCSRnB, UDRIE);}/*! * \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 AvrUsartRxStart(void){ /* * Do any required software flow control. */ if (flow_control && (flow_control & XOFF_SENT) != 0) { NutEnterCritical(); if (inb(UCSRnA) & _BV(UDRE)) { outb(UDRn, 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 AvrUsartInit(void){#ifndef USE_USART /* * Register receive and transmit interrupts. */ if (NutRegisterIrqHandler(&sig_UART_RECV, AvrUsartRxComplete, &dcb_usart.dcb_rx_rbf)) return -1; if (NutRegisterIrqHandler(&sig_UART_DATA, AvrUsartTxEmpty, &dcb_usart.dcb_tx_rbf)) { NutRegisterIrqHandler(&sig_UART_RECV, 0, 0); return -1; }#endif 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 AvrUsartDeinit(void){#ifndef USE_USART /* Deregister receive and transmit interrupts. */ NutRegisterIrqHandler(&sig_UART_RECV, 0, 0); NutRegisterIrqHandler(&sig_UART_DATA, 0, 0);#endif /* * 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 + -