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>
pull/7613/head
Will Sowerbutts 2021-02-14 16:34:26 +00:00 zatwierdzone przez Damien George
rodzic 71722c84ca
commit a3675294ae
2 zmienionych plików z 38 dodań i 1 usunięć

Wyświetl plik

@ -56,11 +56,22 @@ Methods
- *tx* specifies the TX pin to use.
- *rx* specifies the RX pin to use.
- *rts* specifies the RTS (output) pin to use for hardware receive flow control.
- *cts* specifies the CTS (input) pin to use for hardware transmit flow control.
- *txbuf* specifies the length in characters of the TX buffer.
- *rxbuf* specifies the length in characters of the RX buffer.
- *timeout* specifies the time to wait for the first character (in ms).
- *timeout_char* specifies the time to wait between characters (in ms).
- *invert* specifies which lines to invert.
- *flow* specifies which hardware flow control signals to use. The value
is a bitmask.
- ``0`` will ignore hardware flow control signals.
- ``UART.RTS`` will enable receive flow control by using the RTS output pin to
signal if the receive FIFO has sufficient space to accept more data.
- ``UART.CTS`` will enable transmit flow control by pausing transmission when the
CTS input pin signals that the receiver is running low on buffer space.
- ``UART.RTS | UART.CTS`` will enable both, for full hardware flow control.
On the WiPy only the following keyword-only parameter is supported:

Wyświetl plik

@ -53,6 +53,7 @@
typedef struct _machine_uart_obj_t {
mp_obj_base_t base;
uart_port_t uart_num;
uart_hw_flowcontrol_t flowcontrol;
uint8_t bits;
uint8_t parity;
uint8_t stop;
@ -107,11 +108,25 @@ STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_pri
mp_printf(print, "INV_CTS");
}
}
if (self->flowcontrol) {
mp_printf(print, ", flow=");
uint32_t flow_mask = self->flowcontrol;
if (flow_mask & UART_HW_FLOWCTRL_RTS) {
mp_printf(print, "RTS");
flow_mask &= ~UART_HW_FLOWCTRL_RTS;
if (flow_mask) {
mp_printf(print, "|");
}
}
if (flow_mask & UART_HW_FLOWCTRL_CTS) {
mp_printf(print, "CTS");
}
}
mp_printf(print, ")");
}
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) {
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 };
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 };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 0} },
{ 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
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
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
}
self->invert = args[ARG_invert].u_int;
uart_set_line_inverse(self->uart_num, self->invert);
// set hardware flow control
if (args[ARG_flow].u_int & ~UART_HW_FLOWCTRL_CTS_RTS) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid flow control mask"));
}
self->flowcontrol = args[ARG_flow].u_int;
uart_set_hw_flow_ctrl(self->uart_num, self->flowcontrol, UART_FIFO_LEN - UART_FIFO_LEN / 4);
}
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_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_INV_RX), MP_ROM_INT(UART_INV_RX) },
{ MP_ROM_QSTR(MP_QSTR_INV_RTS), MP_ROM_INT(UART_INV_RTS) },
{ MP_ROM_QSTR(MP_QSTR_INV_CTS), MP_ROM_INT(UART_INV_CTS) },
{ MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HW_FLOWCTRL_RTS) },
{ MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HW_FLOWCTRL_CTS) },
};
STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table);