23
23
24
24
// Constructors ////////////////////////////////////////////////////////////////
25
25
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 )
27
27
{
28
- _rx_buffer = pRx_buffer ;
28
+ _rx_buffer = pRx_buffer;
29
+ _tx_buffer = pTx_buffer;
29
30
30
31
_pUsart=pUsart ;
31
32
_dwIrq=dwIrq ;
32
33
_dwId=dwId ;
33
34
}
34
35
36
+
35
37
// Public Methods //////////////////////////////////////////////////////////////
36
38
37
39
void USARTClass::begin ( const uint32_t dwBaudRate )
@@ -73,6 +75,8 @@ void USARTClass::end( void )
73
75
// clear any received data
74
76
_rx_buffer->_iHead = _rx_buffer->_iTail ;
75
77
78
+ while (_tx_buffer->_iHead != _tx_buffer->_iTail ); // wait for transmit data to be sent
79
+
76
80
// Disable UART interrupt in NVIC
77
81
NVIC_DisableIRQ ( _dwIrq ) ;
78
82
@@ -115,12 +119,21 @@ void USARTClass::flush( void )
115
119
116
120
size_t USARTClass::write ( const uint8_t uc_data )
117
121
{
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
121
127
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
+ }
124
137
return 1 ;
125
138
}
126
139
@@ -132,6 +145,17 @@ void USARTClass::IrqHandler( void )
132
145
if ((status & US_CSR_RXRDY) == US_CSR_RXRDY)
133
146
_rx_buffer->store_char ( _pUsart->US_RHR ) ;
134
147
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
+
135
159
// Acknowledge errors
136
160
if ((status & US_CSR_OVRE) == US_CSR_OVRE ||
137
161
(status & US_CSR_FRAME) == US_CSR_FRAME)
0 commit comments