8000 esp32/machine_uart: Add flow kw-arg to enable hardware flow control. · micropython/micropython@a367529 · GitHub
[go: up one dir, main page]

Skip to content

Commit a367529

Browse files
willsowerbuttsdpgeorge
authored andcommitted
esp32/machine_uart: Add flow kw-arg to enable hardware flow control.
This enables optional support for the hardware UART to use the RTS and/or CTS pins for flow control. The new "flow" constructor keyword specifies a bitmask of RTS and/or CTS. This matches the interface used by machine.UART on stm32 and rp2. Previously on ESP32 it was possible to specify which pins to use for the RTS and CTS signals, but hardware flow control was never functional: CTS was not checked before transmitting bytes, and RTS was always driven high (signalling no buffer space available). With this patch, CTS and RTS both operate as expected. This also includes an update to the machine.UART documentation. Signed-off-by: Will Sowerbutts <will@sowerbutts.com>
1 parent 71722c8 commit a367529

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

docs/library/machine.UART.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,22 @@ Methods
5656

5757
- *tx* specifies the TX pin to use.
5858
- *rx* specifies the RX pin to use.
59+
- *rts* specifies the RTS (output) pin to use for hardware receive flow control.
60+
- *cts* specifies the CTS (input) pin to use for hardware transmit flow control.
5961
- *txbuf* specifies the length in characters of the TX buffer.
6062
- *rxbuf* specifies the length in characters of the RX buffer.
6163
- *timeout* specifies the time to wait for the first character (in ms).
6264
- *timeout_char* specifies the time to wait between characters (in ms).
6365
- *invert* specifies which lines to invert.
66+
- *flow* specifies which hardware flow control signals to use. The value
67+
is a bitmask.
68+
69+
- ``0`` will ignore hardware flow control signals.
70+
- ``UART.RTS`` will enable receive flow control by using the RTS output pin to
71+
signal if the receive FIFO has sufficient space to accept more data.
72+
- ``UART.CTS`` will enable transmit flow control by pausing transmission when the
73+
CTS input pin signals that the receiver is running low on buffer space.
74+
- ``UART.RTS | UART.CTS`` will enable both, for full hardware flow control.
6475

6576
On the WiPy only the following keyword-only parameter is supported:
6677

ports/esp32/machine_uart.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
typedef struct _machine_uart_obj_t {
5454
mp_obj_base_t base;
5555
uart_port_t uart_num;
56+
uart_hw_flowcontrol_t flowcontrol;
5657
uint8_t bits;
5758
uint8_t parity;
5859
uint8_t stop;
@@ -107,11 +108,25 @@ STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_pri
107108
mp_printf(print, "INV_CTS");
108109
}
109110
}
111+
if (self->flowcontrol) {
112+
mp_printf(print, ", flow=");
113+
uint32_t flow_mask = self->flowcontrol;
114+
if (flow_mask & UART_HW_FLOWCTRL_RTS) {
115+
mp_printf(print, "RTS");
116+
flow_mask &= ~UART_HW_FLOWCTRL_RTS;
117+
if (flow_mask) {
118+
mp_printf(print, "|");
119+
}
120+
}
121+
if (flow_mask & UART_HW_FLOWCTRL_CTS) {
122+
mp_printf(print, "CTS");
123+
}
124+
}
110125
mp_printf(print, ")");
111126
}
112127

113128
STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
114-
enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx, ARG_rts, ARG_cts, ARG_txbuf, ARG_rxbuf, ARG_timeout, ARG_timeout_char, ARG_invert };
129+
enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx, ARG_rts, ARG_cts, ARG_txbuf, ARG_rxbuf, ARG_timeout, ARG_timeout_char, ARG_invert, ARG_flow };
115130
static const mp_arg_t allowed_args[] = {
116131
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 0} },
117132
{ MP_QSTR_bits, MP_ARG_INT, {.u_int = 0} },
@@ -126,6 +141,7 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co
126141
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
127142
{ MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
128143
{ MP_QSTR_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
144+
{ MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
129145
};
130146
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
131147
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
@@ -257,6 +273,13 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co
257273
}
258274
self->invert = args[ARG_invert].u_int;
259275
uart_set_line_inverse(self->uart_num, self->invert);
276+
277+
// set hardware flow control
278+
if (args[ARG_flow].u_int & ~UART_HW_FLOWCTRL_CTS_RTS) {
279+
mp_raise_ValueError(MP_ERROR_TEXT("invalid flow control mask"));
280+
}
281+
self->flowcontrol = args[ARG_flow].u_int;
282+
uart_set_hw_flow_ctrl(self->uart_num, self->flowcontrol, UART_FIFO_LEN - UART_FIFO_LEN / 4);
260283
}
261284

262285
STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
@@ -400,6 +423,9 @@ STATIC const mp_rom_map_elem_t machine_ua 68F0 rt_locals_dict_table[] = {
400423
{ MP_ROM_QSTR(MP_QSTR_INV_RX), MP_ROM_INT(UART_INV_RX) },
401424
{ MP_ROM_QSTR(MP_QSTR_INV_RTS), MP_ROM_INT(UART_INV_RTS) },
402425
{ MP_ROM_QSTR(MP_QSTR_INV_CTS), MP_ROM_INT(UART_INV_CTS) },
426+
427+
{ MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HW_FLOWCTRL_RTS) },
428+
{ MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HW_FLOWCTRL_CTS) },
403429
};
404430

405431
STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table);

0 commit comments

Comments
 (0)
0