diff --git a/hardware/arduino/sam/cores/arduino/USARTClass.cpp b/hardware/arduino/sam/cores/arduino/USARTClass.cpp index d950c50c9..44f92be5a 100644 --- a/hardware/arduino/sam/cores/arduino/USARTClass.cpp +++ b/hardware/arduino/sam/cores/arduino/USARTClass.cpp @@ -23,15 +23,17 @@ // Constructors //////////////////////////////////////////////////////////////// -USARTClass::USARTClass( Usart* pUsart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer ) +USARTClass::USARTClass( Usart* pUsart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer, volatile RingBuffer* pTx_buffer ) { - _rx_buffer = pRx_buffer ; + _rx_buffer = pRx_buffer; + _tx_buffer = pTx_buffer; _pUsart=pUsart ; _dwIrq=dwIrq ; _dwId=dwId ; } + // Public Methods ////////////////////////////////////////////////////////////// void USARTClass::begin( const uint32_t dwBaudRate ) @@ -73,6 +75,8 @@ void USARTClass::end( void ) // clear any received data _rx_buffer->_iHead = _rx_buffer->_iTail ; + while (_tx_buffer->_iHead != _tx_buffer->_iTail); //wait for transmit data to be sent + // Disable UART interrupt in NVIC NVIC_DisableIRQ( _dwIrq ) ; @@ -115,12 +119,21 @@ void USARTClass::flush( void ) size_t USARTClass::write( const uint8_t uc_data ) { - // Check if the transmitter is ready - while ((_pUsart->US_CSR & US_CSR_TXRDY) != US_CSR_TXRDY) - ; + if ((_pUsart->US_CSR & US_CSR_TXRDY) != US_CSR_TXRDY) //is the hardware currently busy? + { + //if busy we buffer + unsigned int l = (_tx_buffer->_iHead + 1) % SERIAL_BUFFER_SIZE; + while (_tx_buffer->_iTail == l); //spin locks if we're about to overwrite the buffer. This continues once the data is sent - // Send character - _pUsart->US_THR = uc_data ; + _tx_buffer->_aucBuffer[_tx_buffer->_iHead] = uc_data; + _tx_buffer->_iHead = l; + _pUsart->US_IER = US_IER_TXRDY; //make sure TX interrupt is enabled + } + else + { + // Send character + _pUsart->US_THR = uc_data ; + } return 1; } @@ -132,6 +145,17 @@ void USARTClass::IrqHandler( void ) if ((status & US_CSR_RXRDY) == US_CSR_RXRDY) _rx_buffer->store_char( _pUsart->US_RHR ) ; + //Do we need to keep sending data? + if ((status & US_CSR_TXRDY) == US_CSR_TXRDY) + { + _pUsart->US_THR = _tx_buffer->_aucBuffer[_tx_buffer->_iTail]; + _tx_buffer->_iTail = (unsigned int)(_tx_buffer->_iTail + 1) % SERIAL_BUFFER_SIZE; + if (_tx_buffer->_iTail == _tx_buffer->_iHead) //if this is true we have no more data to transmit + { + _pUsart->US_IDR = US_IDR_TXRDY; //mask off transmit interrupt so we don't get it anymore + } + } + // Acknowledge errors if ((status & US_CSR_OVRE) == US_CSR_OVRE || (status & US_CSR_FRAME) == US_CSR_FRAME) diff --git a/hardware/arduino/sam/cores/arduino/USARTClass.h b/hardware/arduino/sam/cores/arduino/USARTClass.h index 9082cc6c2..9d820c982 100644 --- a/hardware/arduino/sam/cores/arduino/USARTClass.h +++ b/hardware/arduino/sam/cores/arduino/USARTClass.h @@ -60,6 +60,7 @@ class USARTClass : public HardwareSerial { protected: RingBuffer *_rx_buffer ; + volatile RingBuffer *_tx_buffer; protected: Usart* _pUsart ; @@ -67,7 +68,7 @@ class USARTClass : public HardwareSerial uint32_t _dwId ; public: - USARTClass( Usart* pUsart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer ) ; + USARTClass( Usart* pUsart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer, volatile RingBuffer* pTx_buffer ) ; void begin( const uint32_t dwBaudRate ) ; void begin( const uint32_t dwBaudRate , const uint32_t config ) ; diff --git a/hardware/arduino/sam/variants/arduino_due_x/variant.cpp b/hardware/arduino/sam/variants/arduino_due_x/variant.cpp index ac066898d..f4ccc0c12 100644 --- a/hardware/arduino/sam/variants/arduino_due_x/variant.cpp +++ b/hardware/arduino/sam/variants/arduino_due_x/variant.cpp @@ -317,14 +317,17 @@ void UART_Handler(void) RingBuffer rx_buffer2; RingBuffer rx_buffer3; RingBuffer rx_buffer4; +volatile RingBuffer tx_buffer2; +volatile RingBuffer tx_buffer3; +volatile RingBuffer tx_buffer4; -USARTClass Serial1(USART0, USART0_IRQn, ID_USART0, &rx_buffer2); +USARTClass Serial1(USART0, USART0_IRQn, ID_USART0, &rx_buffer2, &tx_buffer2); void serialEvent1() __attribute__((weak)); void serialEvent1() { } -USARTClass Serial2(USART1, USART1_IRQn, ID_USART1, &rx_buffer3); +USARTClass Serial2(USART1, USART1_IRQn, ID_USART1, &rx_buffer3, &tx_buffer3); void serialEvent2() __attribute__((weak)); void serialEvent2() { } -USARTClass Serial3(USART3, USART3_IRQn, ID_USART3, &rx_buffer4); +USARTClass Serial3(USART3, USART3_IRQn, ID_USART3, &rx_buffer4, &tx_buffer4); void serialEvent3() __attribute__((weak)); void serialEvent3() { }