55 *
66 * Copyright (c) 2016 Damien P. George
77 * Copyright (c) 2020 Yonatan Schachter
8+ * Copyright (c) 2025 Daniel Campora on behalf of REMOTE TECH LTD
89 *
910 * Permission is hereby granted, free of charge, to any person obtaining a copy
1011 * of this software and associated documentation files (the "Software"), to deal
3233#include <zephyr/drivers/uart.h>
3334
3435#include "py/mperrno.h"
36+ #include "py/ringbuf.h"
3537#include "zephyr_device.h"
3638
37- // The UART class doesn't have any constants for this port.
38- #define MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS
39+
40+ #define MACHINE_UART_RTS 1
41+ #define MACHINE_UART_CTS 2
42+
43+ // This class needs a finalizer, so we add it here
44+ #define MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS \
45+ { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(MACHINE_UART_RTS) }, \
46+ { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(MACHINE_UART_CTS) }, \
47+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_uart_deinit_obj) },
48+
49+ #define UART_RX_RING_BUF_DEF_SIZE 128
50+ #define UART_TX_RING_BUF_DEF_SIZE 128
51+
52+ static void uart_interrupt_handler (const struct device * dev , void * user_data );
3953
4054typedef struct _machine_uart_obj_t {
4155 mp_obj_base_t base ;
4256 const struct device * dev ;
4357 uint16_t timeout ; // timeout waiting for first char (in ms)
4458 uint16_t timeout_char ; // timeout waiting between chars (in ms)
59+ ringbuf_t rx_ringbuffer ;
60+ ringbuf_t tx_ringbuffer ;
61+ bool tx_complete ;
4562} machine_uart_obj_t ;
4663
4764static const char * _parity_name [] = {"None" , "Odd" , "Even" , "Mark" , "Space" };
@@ -60,23 +77,96 @@ static void mp_machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_
6077}
6178
6279static void mp_machine_uart_init_helper (machine_uart_obj_t * self , size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
63- enum { ARG_timeout , ARG_timeout_char };
80+ enum { ARG_baudrate , ARG_bits , ARG_parity , ARG_stop , ARG_txbuf , ARG_rxbuf , ARG_timeout , ARG_timeout_char , ARG_flow };
6481 static const mp_arg_t allowed_args [] = {
82+ { MP_QSTR_baudrate , MP_ARG_INT , {.u_int = 115200 } },
83+ { MP_QSTR_bits , MP_ARG_INT , {.u_int = 8 } },
84+ { MP_QSTR_parity , MP_ARG_OBJ , {.u_obj = mp_const_none } },
85+ { MP_QSTR_stop , MP_ARG_INT , {.u_int = 1 } },
86+ { MP_QSTR_txbuf , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = UART_RX_RING_BUF_DEF_SIZE } },
87+ { MP_QSTR_rxbuf , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = UART_TX_RING_BUF_DEF_SIZE } },
6588 { MP_QSTR_timeout , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0 } },
6689 { MP_QSTR_timeout_char , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0 } },
90+ { MP_QSTR_flow , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0 } },
6791 };
92+
6893 mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
6994 mp_arg_parse_all (n_args , pos_args , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
7095
7196 self -> timeout = args [ARG_timeout ].u_int ;
7297 self -> timeout_char = args [ARG_timeout_char ].u_int ;
98+
99+ uint8_t data_bits ;
100+ if (args [ARG_bits ].u_int == 5 ) {
101+ data_bits = UART_CFG_DATA_BITS_5 ;
102+ } else if (args [ARG_bits ].u_int == 6 ) {
103+ data_bits = UART_CFG_DATA_BITS_6 ;
104+ } else if (args [ARG_bits ].u_int == 7 ) {
105+ data_bits = UART_CFG_DATA_BITS_7 ;
106+ } else if (args [ARG_bits ].u_int == 8 ) {
107+ data_bits = UART_CFG_DATA_BITS_8 ;
108+ } else if (args [ARG_bits ].u_int == 9 ) {
109+ data_bits = UART_CFG_DATA_BITS_9 ;
110+ } else {
111+ mp_raise_msg (& mp_type_OSError , MP_ERROR_TEXT ("invalid data bits" ));
112+ }
113+
114+ uint8_t parity ;
115+ if (args [ARG_parity ].u_obj == mp_const_none ) {
116+ parity = UART_CFG_PARITY_NONE ;
117+ } else if (mp_obj_get_int (args [ARG_parity ].u_obj ) == 0 ) {
118+ parity = UART_CFG_PARITY_EVEN ;
119+ } else if (mp_obj_get_int (args [ARG_parity ].u_obj ) == 1 ) {
120+ parity = UART_CFG_PARITY_ODD ;
121+ } else {
122+ mp_raise_msg (& mp_type_OSError , MP_ERROR_TEXT ("invalid parity" ));
123+ }
124+
125+ uint8_t stop_bits ;
126+ if (args [ARG_stop ].u_int == 1 ) {
127+ stop_bits = UART_CFG_STOP_BITS_1 ;
128+ } else if (args [ARG_stop ].u_int == 2 ) {
129+ data_bits = UART_CFG_STOP_BITS_2 ;
130+ } else {
131+ mp_raise_msg (& mp_type_OSError , MP_ERROR_TEXT ("invalid stop bits" ));
132+ }
133+
134+ uint8_t flow_ctrl ;
135+ if (args [ARG_flow ].u_int == 0 ) {
136+ flow_ctrl = UART_CFG_FLOW_CTRL_NONE ;
137+ } else if (args [ARG_flow ].u_int == (MACHINE_UART_RTS | MACHINE_UART_CTS )) {
138+ flow_ctrl = UART_CFG_FLOW_CTRL_RTS_CTS ;
139+ } else {
140+ mp_raise_msg (& mp_type_OSError , MP_ERROR_TEXT ("invalid flow control" ));
141+ }
142+
143+ const struct uart_config cfg = {
144+ .baudrate = args [ARG_baudrate ].u_int ,
145+ .parity = parity ,
146+ .stop_bits = args [ARG_stop ].u_int ,
147+ .data_bits = data_bits ,
148+ .flow_ctrl = flow_ctrl
149+ };
150+
151+ int ret = uart_configure (self -> dev , & cfg );
152+ if (ret < 0 ) {
153+ mp_raise_OSError (- ret );
154+ }
155+
156+ ringbuf_alloc (& self -> tx_ringbuffer , args [ARG_txbuf ].u_int );
157+ ringbuf_alloc (& self -> rx_ringbuffer , args [ARG_rxbuf ].u_int );
158+
159+ uart_irq_callback_user_data_set (self -> dev , uart_interrupt_handler , (void * )self );
160+ uart_irq_rx_enable (self -> dev );
73161}
74162
75163static mp_obj_t mp_machine_uart_make_new (const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * args ) {
76164 mp_arg_check_num (n_args , n_kw , 1 , MP_OBJ_FUN_ARGS_MAX , true);
77165
78- machine_uart_obj_t * self = mp_obj_malloc (machine_uart_obj_t , & machine_uart_type );
79- self -> dev = zephyr_device_find (args [0 ]);
166+ const struct device * dev = zephyr_device_find (args [0 ]);
167+ machine_uart_obj_t * self = mp_obj_malloc_with_finaliser (machine_uart_obj_t , & machine_uart_type );
168+ self -> dev = dev ;
169+ self -> tx_complete = true;
80170
81171 mp_map_t kw_args ;
82172 mp_map_init_fixed_table (& kw_args , n_kw , args + n_args );
@@ -86,65 +176,125 @@ static mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_arg
86176}
87177
88178static void mp_machine_uart_deinit (machine_uart_obj_t * self ) {
89- (void )self ;
179+ uart_irq_rx_disable (self -> dev );
180+ uart_irq_tx_disable (self -> dev );
90181}
91182
92183static mp_int_t mp_machine_uart_any (machine_uart_obj_t * self ) {
93- (void )self ;
94- mp_raise_NotImplementedError (NULL ); // TODO
184+ return ringbuf_avail (& self -> rx_ringbuffer );
95185}
96186
97187static bool mp_machine_uart_txdone (machine_uart_obj_t * self ) {
98- (void )self ;
99- mp_raise_NotImplementedError (NULL ); // TODO
188+ return self -> tx_complete && !ringbuf_avail (& self -> tx_ringbuffer ) ? true : false;
100189}
101190
102191static mp_uint_t mp_machine_uart_read (mp_obj_t self_in , void * buf_in , mp_uint_t size , int * errcode ) {
103192 machine_uart_obj_t * self = MP_OBJ_TO_PTR (self_in );
104193 uint8_t * buffer = (uint8_t * )buf_in ;
105- uint8_t data ;
106194 mp_uint_t bytes_read = 0 ;
107195 size_t elapsed_ms = 0 ;
108196 size_t time_to_wait = self -> timeout ;
109197
110- while ((elapsed_ms < time_to_wait ) && (bytes_read < size )) {
111- if (!uart_poll_in (self -> dev , & data )) {
112- buffer [bytes_read ++ ] = data ;
198+ do {
199+ int _rx_len = MIN (ringbuf_avail (& self -> rx_ringbuffer ), size - bytes_read );
200+ if (_rx_len > 0 ) {
201+ ringbuf_get_bytes (& self -> rx_ringbuffer , & buffer [bytes_read ], _rx_len );
202+ bytes_read += _rx_len ;
113203 elapsed_ms = 0 ;
114204 time_to_wait = self -> timeout_char ;
115205 } else {
116206 k_msleep (1 );
117207 elapsed_ms ++ ;
118208 }
119- }
209+ } while ((elapsed_ms < time_to_wait ) && (bytes_read < size ));
210+
120211 return bytes_read ;
121212}
122213
123214static mp_uint_t mp_machine_uart_write (mp_obj_t self_in , const void * buf_in , mp_uint_t size , int * errcode ) {
124215 machine_uart_obj_t * self = MP_OBJ_TO_PTR (self_in );
125216 uint8_t * buffer = (uint8_t * )buf_in ;
126217
127- for (mp_uint_t i = 0 ; i < size ; i ++ ) {
218+ // wait for any pending transmission to complete
219+ while (!mp_machine_uart_txdone (self )) {
220+ MICROPY_EVENT_POLL_HOOK ;
221+ }
222+
223+ int _ex_size = 0 ;
224+ int _free_space = ringbuf_free (& self -> tx_ringbuffer );
225+ if (size > _free_space ) {
226+ _ex_size = size - _free_space ;
227+ }
228+
229+ // do a blocking tx of what doesn't fit into the outgoing ring buffer
230+ for (mp_uint_t i = 0 ; i < _ex_size ; i ++ ) {
128231 uart_poll_out (self -> dev , buffer [i ]);
129232 }
130233
234+ ringbuf_put_bytes (& self -> tx_ringbuffer , & buffer [_ex_size ], size - _ex_size );
235+ self -> tx_complete = false;
236+ uart_irq_tx_enable (self -> dev );
237+
131238 return size ;
132239}
133240
134241static mp_uint_t mp_machine_uart_ioctl (mp_obj_t self_in , mp_uint_t request , uintptr_t arg , int * errcode ) {
135- mp_uint_t ret ;
242+ machine_uart_obj_t * self = MP_OBJ_TO_PTR (self_in );
243+ mp_uint_t ret = 0 ;
136244
137245 if (request == MP_STREAM_POLL ) {
138- ret = 0 ;
139- // read is always blocking
140-
141- if (arg & MP_STREAM_POLL_WR ) {
246+ uintptr_t flags = arg ;
247+ if ((flags & MP_STREAM_POLL_RD ) && (mp_machine_uart_any (self ) > 0 )) {
248+ ret |= MP_STREAM_POLL_RD ;
249+ }
250+ if ((flags & MP_STREAM_POLL_WR ) && mp_machine_uart_txdone (self )) {
142251 ret |= MP_STREAM_POLL_WR ;
143252 }
144- return ret ;
253+ } else if (request == MP_STREAM_FLUSH ) {
254+ while (!mp_machine_uart_txdone (self )) {
255+ MICROPY_EVENT_POLL_HOOK ;
256+ }
145257 } else {
146258 * errcode = MP_EINVAL ;
147259 ret = MP_STREAM_ERROR ;
148260 }
261+
149262 return ret ;
150263}
264+
265+ static void uart_interrupt_handler (const struct device * dev , void * user_data ) {
266+ machine_uart_obj_t * self = (machine_uart_obj_t * )user_data ;
267+
268+ while (uart_irq_update (dev ) && uart_irq_is_pending (dev )) {
269+ if (uart_irq_rx_ready (dev )) {
270+ uint8_t _rx_buffer [32 ];
271+ size_t _free_space = MIN (ringbuf_free (& self -> rx_ringbuffer ), sizeof (_rx_buffer ));
272+
273+ // empty the uart fifo even if we can't store bytes anymore
274+ // otherwise we will never exit this interrupt handler
275+ int rcv_len = uart_fifo_read (dev , _rx_buffer , (_free_space > 0 ) ? _free_space : 1 );
276+ if ((rcv_len <= 0 ) || (_free_space == 0 )) {
277+ continue ;
278+ }
279+
280+ ringbuf_put_bytes (& self -> rx_ringbuffer , _rx_buffer , rcv_len );
281+ }
282+
283+ int _max_uart_tx_len = uart_irq_tx_ready (dev );
284+ if (_max_uart_tx_len > 0 ) {
285+ uint8_t _tx_buffer [32 ];
286+ size_t _buffer_tx_len ;
287+
288+ _max_uart_tx_len = MIN (_max_uart_tx_len , sizeof (_tx_buffer ));
289+ _buffer_tx_len = ringbuf_avail (& self -> tx_ringbuffer );
290+ if (_buffer_tx_len > 0 ) {
291+ _buffer_tx_len = MIN (_max_uart_tx_len , _buffer_tx_len );
292+ ringbuf_get_bytes (& self -> tx_ringbuffer , _tx_buffer , _buffer_tx_len );
293+ uart_fifo_fill (dev , _tx_buffer , _buffer_tx_len );
294+ } else if (uart_irq_tx_complete (dev )) {
295+ uart_irq_tx_disable (dev );
296+ self -> tx_complete = true;
297+ }
298+ }
299+ }
300+ }
0 commit comments