Skip to content

Commit 6d99cd2

Browse files
committed
zephyr: Add finalizer. Allow reconfiguration. Use py/ringbuf.h.
Signed-off-by: Daniel Campora <[email protected]>
1 parent c121cf8 commit 6d99cd2

File tree

3 files changed

+102
-41
lines changed

3 files changed

+102
-41
lines changed

ports/zephyr/machine_uart.c

Lines changed: 102 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,27 @@
3131

3232
#include <zephyr/kernel.h>
3333
#include <zephyr/drivers/uart.h>
34-
#include <zephyr/sys/ring_buffer.h>
3534

3635
#include "py/mperrno.h"
36+
#include "py/obj.h"
37+
#include "py/runtime.h"
38+
#include "py/stream.h"
39+
#include "py/ringbuf.h"
3740
#include "zephyr_device.h"
41+
#include "extmod/modmachine.h"
3842

39-
// The UART class doesn't have any constants for this port.
40-
#define MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS
4143

42-
#define UART_RX_RING_BUF_DEF_SIZE 128
43-
#define UART_TX_RING_BUF_DEF_SIZE 128
44+
#define MACHINE_UART_RTS 1
45+
#define MACHINE_UART_CTS 2
46+
47+
// This class needs a finalizer, so we add it here
48+
#define MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS \
49+
{ MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(MACHINE_UART_RTS) }, \
50+
{ MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(MACHINE_UART_CTS) }, \
51+
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_uart_deinit_obj) },
52+
53+
#define UART_RX_RING_BUF_DEF_SIZE 128
54+
#define UART_TX_RING_BUF_DEF_SIZE 128
4455

4556
static void uart_interrupt_handler(const struct device *dev, void *user_data);
4657

@@ -49,12 +60,8 @@ typedef struct _machine_uart_obj_t {
4960
const struct device *dev;
5061
uint16_t timeout; // timeout waiting for first char (in ms)
5162
uint16_t timeout_char; // timeout waiting between chars (in ms)
52-
uint16_t txbuf_size;
53-
uint16_t rxbuf_size;
54-
uint8_t *rx_buffer;
55-
struct ring_buf rx_ringbuffer;
56-
uint8_t *tx_buffer;
57-
struct ring_buf tx_ringbuffer;
63+
ringbuf_t rx_ringbuffer;
64+
ringbuf_t tx_ringbuffer;
5865
} machine_uart_obj_t;
5966

6067
static const char *_parity_name[] = {"None", "Odd", "Even", "Mark", "Space"};
@@ -73,27 +80,84 @@ static void mp_machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_
7380
}
7481

7582
static 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) {
76-
enum { ARG_txbuf, ARG_rxbuf, ARG_timeout, ARG_timeout_char };
83+
enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_txbuf, ARG_rxbuf, ARG_timeout, ARG_timeout_char, ARG_flow };
7784
static const mp_arg_t allowed_args[] = {
85+
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 115200} },
86+
{ MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} },
87+
{ MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = mp_const_none} },
88+
{ MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} },
7889
{ MP_QSTR_txbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_RX_RING_BUF_DEF_SIZE} },
7990
{ MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_TX_RING_BUF_DEF_SIZE} },
8091
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
8192
{ MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
93+
{ MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
8294
};
8395

8496
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
8597
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
8698

87-
self->txbuf_size = args[ARG_txbuf].u_int;
88-
self->rxbuf_size = args[ARG_rxbuf].u_int;
8999
self->timeout = args[ARG_timeout].u_int;
90100
self->timeout_char = args[ARG_timeout_char].u_int;
91101

92-
self->tx_buffer = m_tracked_calloc(self->txbuf_size, sizeof(uint8_t));
93-
ring_buf_init(&self->tx_ringbuffer, self->txbuf_size, self->tx_buffer);
102+
uint8_t data_bits;
103+
if (args[ARG_bits].u_int == 5) {
104+
data_bits = UART_CFG_DATA_BITS_5;
105+
} else if (args[ARG_bits].u_int == 6) {
106+
data_bits = UART_CFG_DATA_BITS_6;
107+
} else if (args[ARG_bits].u_int == 7) {
108+
data_bits = UART_CFG_DATA_BITS_7;
109+
} else if (args[ARG_bits].u_int == 8) {
110+
data_bits = UART_CFG_DATA_BITS_8;
111+
} else if (args[ARG_bits].u_int == 9) {
112+
data_bits = UART_CFG_DATA_BITS_9;
113+
} else {
114+
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("invalid data bits"));
115+
}
116+
117+
uint8_t parity;
118+
if (args[ARG_parity].u_obj == mp_const_none) {
119+
parity = UART_CFG_PARITY_NONE;
120+
} else if (mp_obj_get_int(args[ARG_parity].u_obj) == 0) {
121+
parity = UART_CFG_PARITY_EVEN;
122+
} else if (mp_obj_get_int(args[ARG_parity].u_obj) == 1) {
123+
parity = UART_CFG_PARITY_ODD;
124+
} else {
125+
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("invalid parity"));
126+
}
94127

95-
self->rx_buffer = m_tracked_calloc(self->rxbuf_size, sizeof(uint8_t));
96-
ring_buf_init(&self->rx_ringbuffer, self->rxbuf_size, self->rx_buffer);
128+
uint8_t stop_bits;
129+
if (args[ARG_stop].u_int == 1) {
130+
stop_bits = UART_CFG_STOP_BITS_1;
131+
} else if (args[ARG_stop].u_int == 2) {
132+
data_bits = UART_CFG_STOP_BITS_2;
133+
} else {
134+
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("invalid stop bits"));
135+
}
136+
137+
uint8_t flow_ctrl;
138+
if (args[ARG_flow].u_obj == mp_const_none) {
139+
flow_ctrl = UART_CFG_FLOW_CTRL_NONE;
140+
} else if (mp_obj_get_int(args[ARG_flow].u_obj) == (MACHINE_UART_RTS | MACHINE_UART_RTS)) {
141+
flow_ctrl = UART_CFG_FLOW_CTRL_RTS_CTS;
142+
} else {
143+
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("invalid flow control"));
144+
}
145+
146+
const struct uart_config cfg = {
147+
.baudrate = args[ARG_baudrate].u_int,
148+
.parity = parity,
149+
.stop_bits = args[ARG_stop].u_int,
150+
.data_bits = data_bits,
151+
.flow_ctrl = flow_ctrl
152+
};
153+
154+
int ret = uart_configure(self->dev, &cfg);
155+
if (ret < 0) {
156+
mp_raise_OSError(-ret);
157+
}
158+
159+
ringbuf_alloc(&self->tx_ringbuffer, args[ARG_txbuf].u_int);
160+
ringbuf_alloc(&self->rx_ringbuffer, args[ARG_rxbuf].u_int);
97161

98162
uart_irq_callback_user_data_set(self->dev, uart_interrupt_handler, (void *)self);
99163
uart_irq_rx_enable(self->dev);
@@ -102,7 +166,7 @@ static void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args,
102166
static 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) {
103167
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
104168

105-
machine_uart_obj_t *self = mp_obj_malloc(machine_uart_obj_t, &machine_uart_type);
169+
machine_uart_obj_t *self = mp_obj_malloc_with_finaliser(machine_uart_obj_t, &machine_uart_type);
106170
self->dev = zephyr_device_find(args[0]);
107171

108172
mp_map_t kw_args;
@@ -113,19 +177,15 @@ static mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_arg
113177
}
114178

115179
static void mp_machine_uart_deinit(machine_uart_obj_t *self) {
116-
m_tracked_free(self->tx_buffer);
117-
m_tracked_free(self->rx_buffer);
180+
uart_irq_rx_disable(self->dev);
118181
}
119182

120183
static mp_int_t mp_machine_uart_any(machine_uart_obj_t *self) {
121-
return ring_buf_size_get(&self->rx_ringbuffer);
184+
return ringbuf_avail(&self->rx_ringbuffer);
122185
}
123186

124187
static bool mp_machine_uart_txdone(machine_uart_obj_t *self) {
125-
if (ring_buf_is_empty(&self->tx_ringbuffer)) {
126-
return true;
127-
}
128-
return false;
188+
return ringbuf_avail(&self->tx_ringbuffer) ? false : true;
129189
}
130190

131191
static mp_uint_t mp_machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
@@ -136,8 +196,9 @@ static mp_uint_t mp_machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t
136196
size_t time_to_wait = self->timeout;
137197

138198
do {
139-
int _rx_len = ring_buf_get(&self->rx_ringbuffer, &buffer[bytes_read], size - bytes_read);
199+
int _rx_len = MIN(ringbuf_avail(&self->rx_ringbuffer), size - bytes_read);
140200
if (_rx_len > 0) {
201+
ringbuf_get_bytes(&self->rx_ringbuffer, &buffer[bytes_read], _rx_len);
141202
bytes_read += _rx_len;
142203
elapsed_ms = 0;
143204
time_to_wait = self->timeout_char;
@@ -160,7 +221,7 @@ static mp_uint_t mp_machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_
160221
}
161222

162223
int _ex_size = 0;
163-
int _free_space = ring_buf_space_get(&self->tx_ringbuffer);
224+
int _free_space = ringbuf_free(&self->tx_ringbuffer);
164225
if (size > _free_space) {
165226
_ex_size = size - _free_space;
166227
}
@@ -170,7 +231,7 @@ static mp_uint_t mp_machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_
170231
uart_poll_out(self->dev, buffer[i]);
171232
}
172233

173-
ring_buf_put(&self->tx_ringbuffer, &buffer[_ex_size], size - _ex_size);
234+
ringbuf_put_bytes(&self->tx_ringbuffer, &buffer[_ex_size], size - _ex_size);
174235
uart_irq_tx_enable(self->dev);
175236

176237
return size;
@@ -206,7 +267,7 @@ static void uart_interrupt_handler(const struct device *dev, void *user_data) {
206267
while (uart_irq_update(dev) && uart_irq_is_pending(dev)) {
207268
if (uart_irq_rx_ready(dev)) {
208269
uint8_t _rx_buffer[32];
209-
size_t _free_space = MIN(ring_buf_space_get(&self->rx_ringbuffer), sizeof(_rx_buffer));
270+
size_t _free_space = MIN(ringbuf_free(&self->rx_ringbuffer), sizeof(_rx_buffer));
210271

211272
// empty the uart fifo even if we can't store bytes anymore
212273
// otherwise we will never exit this interrupt handler
@@ -215,17 +276,20 @@ static void uart_interrupt_handler(const struct device *dev, void *user_data) {
215276
continue;
216277
}
217278

218-
ring_buf_put(&self->rx_ringbuffer, _rx_buffer, rcv_len);
279+
ringbuf_put_bytes(&self->rx_ringbuffer, _rx_buffer, rcv_len);
219280
}
220281

221-
int _max_tx_len = uart_irq_tx_ready(dev);
222-
if (_max_tx_len > 0) {
282+
int _max_uart_tx_len = uart_irq_tx_ready(dev);
283+
if (_max_uart_tx_len > 0) {
223284
uint8_t _tx_buffer[32];
224-
size_t _tx_len = MIN(_max_tx_len, sizeof(_tx_buffer));
225-
226-
_tx_len = ring_buf_get(&self->tx_ringbuffer, _tx_buffer, _tx_len);
227-
if (_tx_len > 0) {
228-
uart_fifo_fill(dev, _tx_buffer, _tx_len);
285+
size_t _buffer_tx_len;
286+
287+
_max_uart_tx_len = MIN(_max_uart_tx_len, sizeof(_tx_buffer));
288+
_buffer_tx_len = ringbuf_avail(&self->tx_ringbuffer);
289+
if (_buffer_tx_len > 0) {
290+
_buffer_tx_len = MIN(_max_uart_tx_len, _buffer_tx_len);
291+
ringbuf_get_bytes(&self->tx_ringbuffer, _tx_buffer, _buffer_tx_len);
292+
uart_fifo_fill(dev, _tx_buffer, _buffer_tx_len);
229293
} else {
230294
uart_irq_tx_disable(dev);
231295
}

ports/zephyr/mpconfigport.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,6 @@
110110
#define MICROPY_FATFS_RPATH (2)
111111
#define MICROPY_FATFS_NORTC (1)
112112

113-
#define MICROPY_TRACKED_ALLOC (1)
114-
115113
// Saving extra crumbs to make sure binary fits in 128K
116114
#define MICROPY_COMP_CONST_FOLDING (0)
117115
#define MICROPY_COMP_CONST (0)

ports/zephyr/prj.conf

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ CONFIG_WATCHDOG=y
8383
CONFIG_WDT_DISABLE_AT_BOOT=y
8484

8585
CONFIG_SERIAL=y
86-
CONFIG_RING_BUFFER=y
8786
CONFIG_UART_INTERRUPT_DRIVEN=y
8887
CONFIG_UART_LINE_CTRL=y
8988
CONFIG_UART_USE_RUNTIME_CONFIGURE=y

0 commit comments

Comments
 (0)