2323
2424// Constructors ////////////////////////////////////////////////////////////////
2525
26- USARTClass::USARTClass ( Usart* pUsart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer )
26+ USARTClass::USARTClass ( Usart* pUsart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer, volatile RingBuffer* pTx_buffer )
2727{
28- _rx_buffer = pRx_buffer ;
28+ _rx_buffer = pRx_buffer;
29+ _tx_buffer = pTx_buffer;
2930
3031 _pUsart=pUsart ;
3132 _dwIrq=dwIrq ;
3233 _dwId=dwId ;
3334}
3435
36+
3537// Public Methods //////////////////////////////////////////////////////////////
3638
3739void USARTClass::begin ( const uint32_t dwBaudRate )
@@ -73,6 +75,8 @@ void USARTClass::end( void )
7375 // clear any received data
7476 _rx_buffer->_iHead = _rx_buffer->_iTail ;
7577
78+ while (_tx_buffer->_iHead != _tx_buffer->_iTail ); // wait for transmit data to be sent
79+
7680 // Disable UART interrupt in NVIC
7781 NVIC_DisableIRQ ( _dwIrq ) ;
7882
@@ -115,12 +119,21 @@ void USARTClass::flush( void )
115119
116120size_t USARTClass::write ( const uint8_t uc_data )
117121{
118- // Check if the transmitter is ready
119- while ((_pUsart->US_CSR & US_CSR_TXRDY) != US_CSR_TXRDY)
120- ;
122+ if ((_pUsart->US_CSR & US_CSR_TXRDY) != US_CSR_TXRDY) // is the hardware currently busy?
123+ {
124+ // if busy we buffer
125+ unsigned int l = (_tx_buffer->_iHead + 1 ) % SERIAL_BUFFER_SIZE;
126+ while (_tx_buffer->_iTail == l); // spin locks if we're about to overwrite the buffer. This continues once the data is sent
121127
122- // Send character
123- _pUsart->US_THR = uc_data ;
128+ _tx_buffer->_aucBuffer [_tx_buffer->_iHead ] = uc_data;
129+ _tx_buffer->_iHead = l;
130+ _pUsart->US_IER = US_IER_TXRDY; // make sure TX interrupt is enabled
131+ }
132+ else
133+ {
134+ // Send character
135+ _pUsart->US_THR = uc_data ;
136+ }
124137 return 1 ;
125138}
126139
@@ -132,6 +145,17 @@ void USARTClass::IrqHandler( void )
132145 if ((status & US_CSR_RXRDY) == US_CSR_RXRDY)
133146 _rx_buffer->store_char ( _pUsart->US_RHR ) ;
134147
148+ // Do we need to keep sending data?
149+ if ((status & US_CSR_TXRDY) == US_CSR_TXRDY)
150+ {
151+ _pUsart->US_THR = _tx_buffer->_aucBuffer [_tx_buffer->_iTail ];
152+ _tx_buffer->_iTail = (unsigned int )(_tx_buffer->_iTail + 1 ) % SERIAL_BUFFER_SIZE;
153+ if (_tx_buffer->_iTail == _tx_buffer->_iHead ) // if this is true we have no more data to transmit
154+ {
155+ _pUsart->US_IDR = US_IDR_TXRDY; // mask off transmit interrupt so we don't get it anymore
156+ }
157+ }
158+
135159 // Acknowledge errors
136160 if ((status & US_CSR_OVRE) == US_CSR_OVRE ||
137161 (status & US_CSR_FRAME) == US_CSR_FRAME)
0 commit comments