@@ -36,8 +36,8 @@ static void resume_rx(busio_uart_obj_t *self) {
3636}
3737
3838/*
39- * Read characters from UART until line end is detected. Afterwards push the
40- * data to the message queue.
39+ * Feed pending TX bytes to the driver, then move received characters into
40+ * the message queue.
4141 */
4242static void serial_cb (const struct device * dev , void * user_data ) {
4343 busio_uart_obj_t * self = (busio_uart_obj_t * )user_data ;
@@ -46,6 +46,18 @@ static void serial_cb(const struct device *dev, void *user_data) {
4646
4747 uart_irq_update (dev );
4848
49+ if (self -> tx_len > 0 && uart_irq_tx_ready (dev )) {
50+ int sent = uart_fifo_fill (dev , self -> tx_data , self -> tx_len );
51+ if (sent > 0 ) {
52+ self -> tx_data += sent ;
53+ self -> tx_len -= sent ;
54+ }
55+ if (self -> tx_len == 0 ) {
56+ uart_irq_tx_disable (dev );
57+ k_sem_give (& self -> tx_done );
58+ }
59+ }
60+
4961 if (!uart_irq_rx_ready (dev )) {
5062 return ;
5163 }
@@ -102,6 +114,8 @@ mp_obj_t common_hal_busio_uart_construct_from_device(busio_uart_obj_t *self, con
102114
103115 self -> timeout = K_FOREVER ;
104116 self -> write_timeout = K_FOREVER ;
117+ self -> tx_len = 0 ;
118+ k_sem_init (& self -> tx_done , 0 , 1 );
105119 self -> rx_paused = false;
106120 self -> flow_control = false;
107121 self -> sigint_enabled = sigint_enabled ;
@@ -233,13 +247,36 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
233247 return count ;
234248}
235249
236- // Write characters.
250+ // Write characters. serial_cb() feeds the driver from the TX interrupt, so
251+ // this thread only waits and can stop on Ctrl-C.
237252size_t common_hal_busio_uart_write (busio_uart_obj_t * self , const uint8_t * data , size_t len , int * errcode ) {
238- for ( int i = 0 ; i < len ; i ++ ) {
239- uart_poll_out ( self -> uart_device , data [ i ]) ;
253+ if ( len == 0 ) {
254+ return 0 ;
240255 }
256+ k_sem_reset (& self -> tx_done );
257+ self -> tx_data = data ;
258+ self -> tx_len = len ;
259+ uart_irq_tx_enable (self -> uart_device );
260+ while (k_sem_take (& self -> tx_done , K_MSEC (10 )) != 0 ) {
261+ RUN_BACKGROUND_TASKS ;
262+ if (mp_hal_is_interrupted ()) {
263+ break ;
264+ }
265+ }
266+ uart_irq_tx_disable (self -> uart_device );
267+
268+ unsigned int key = irq_lock ();
269+ size_t not_sent = self -> tx_len ;
270+ self -> tx_len = 0 ;
271+ irq_unlock (key );
272+
273+ return len - not_sent ;
274+ }
241275
242- return len ;
276+ void zephyr_uart_write_blocking (busio_uart_obj_t * self , const uint8_t * data , size_t len ) {
277+ for (size_t i = 0 ; i < len ; i ++ ) {
278+ uart_poll_out (self -> uart_device , data [i ]);
279+ }
243280}
244281
245282uint32_t common_hal_busio_uart_get_baudrate (busio_uart_obj_t * self ) {
0 commit comments