@@ -50,6 +50,7 @@ struct {
5050 volatile uint32_t tx_size ;
5151
5252 uint8_t rx ;
53+ uint8_t tx ;
5354} cb_buf ;
5455
5556void uart_handler (uint32_t event );
@@ -192,41 +193,23 @@ int32_t uart_write_free(void)
192193 return circ_buf_count_free (& write_buffer );
193194}
194195
195- // Start a new TX transfer if there are bytes pending to be transferred on the
196- // write_buffer buffer. The transferred bytes are not removed from the circular
197- // by this function, only the event handler will remove them once the transfer
198- // is done.
199- static void uart_start_tx_transfer () {
200- uint32_t tx_size = 0 ;
201- const uint8_t * buf = circ_buf_peek (& write_buffer , & tx_size );
202- if (tx_size > BUFFER_SIZE / 4 ) {
203- // The bytes being transferred remain on the circular buffer memory
204- // until the transfer is done. Limiting the UART transfer size
205- // allows the uart_handler to clear those bytes earlier.
206- tx_size = BUFFER_SIZE / 4 ;
207- }
208- cb_buf .tx_size = tx_size ;
209- if (tx_size ) {
210- USART_INSTANCE .Send (buf , tx_size );
211- }
212- }
213-
214196int32_t uart_write_data (uint8_t * data , uint16_t size )
215197{
216198 if (size == 0 ) {
217199 return 0 ;
218200 }
219201
202+ // Disable interrupts to prevent the uart_handler from modifying the
203+ // circular buffer at the same time.
204+ NVIC_DisableIRQ (USART_IRQ );
220205 uint32_t cnt = circ_buf_write (& write_buffer , data , size );
221- if (cb_buf .tx_size == 0 ) {
222- // There's no pending transfer and the value of cb_buf.tx_size will not
223- // change to non-zero by the event handler once it is zero. Note that it
224- // is entirely possible that we transferred all the bytes we added to
225- // the circular buffer in this function by the time we are in this
226- // branch, in that case uart_start_tx_transfer() would not schedule any
227- // transfer.
228- uart_start_tx_transfer ();
206+ if (cb_buf .tx_size == 0 && circ_buf_count_used (& write_buffer ) > 0 ) {
207+ // There's no pending transfer, so we need to start the process.
208+ cb_buf .tx = circ_buf_pop (& write_buffer );
209+ USART_INSTANCE .Send (& (cb_buf .tx ), 1 );
210+ cb_buf .tx_size = 1 ;
229211 }
212+ NVIC_EnableIRQ (USART_IRQ );
230213
231214 return cnt ;
232215}
@@ -250,7 +233,13 @@ void uart_handler(uint32_t event) {
250233 }
251234
252235 if (event & ARM_USART_EVENT_SEND_COMPLETE ) {
253- circ_buf_pop_n (& write_buffer , cb_buf .tx_size );
254- uart_start_tx_transfer ();
236+ if (circ_buf_count_used (& write_buffer ) > 0 ) {
237+ cb_buf .tx = circ_buf_pop (& write_buffer );
238+ USART_INSTANCE .Send (& (cb_buf .tx ), 1 );
239+ } else {
240+ // Signals that next call to uart_write_data() should start a
241+ // transfer.
242+ cb_buf .tx_size = 0 ;
243+ }
255244 }
256245}
0 commit comments