rp2/machine_uart: Add hardware flow control support.
This commit is contained in:
parent
9f71a11d3f
commit
8599f7a68d
|
@ -40,8 +40,12 @@
|
||||||
#define DEFAULT_UART_STOP (1)
|
#define DEFAULT_UART_STOP (1)
|
||||||
#define DEFAULT_UART0_TX (0)
|
#define DEFAULT_UART0_TX (0)
|
||||||
#define DEFAULT_UART0_RX (1)
|
#define DEFAULT_UART0_RX (1)
|
||||||
|
#define DEFAULT_UART0_CTS (2)
|
||||||
|
#define DEFAULT_UART0_RTS (3)
|
||||||
#define DEFAULT_UART1_TX (4)
|
#define DEFAULT_UART1_TX (4)
|
||||||
#define DEFAULT_UART1_RX (5)
|
#define DEFAULT_UART1_RX (5)
|
||||||
|
#define DEFAULT_UART1_CTS (6)
|
||||||
|
#define DEFAULT_UART1_RTS (7)
|
||||||
#define DEFAULT_BUFFER_SIZE (256)
|
#define DEFAULT_BUFFER_SIZE (256)
|
||||||
#define MIN_BUFFER_SIZE (32)
|
#define MIN_BUFFER_SIZE (32)
|
||||||
#define MAX_BUFFER_SIZE (32766)
|
#define MAX_BUFFER_SIZE (32766)
|
||||||
|
@ -49,11 +53,16 @@
|
||||||
#define IS_VALID_PERIPH(uart, pin) (((((pin) + 4) & 8) >> 3) == (uart))
|
#define IS_VALID_PERIPH(uart, pin) (((((pin) + 4) & 8) >> 3) == (uart))
|
||||||
#define IS_VALID_TX(uart, pin) (((pin) & 3) == 0 && IS_VALID_PERIPH(uart, pin))
|
#define IS_VALID_TX(uart, pin) (((pin) & 3) == 0 && IS_VALID_PERIPH(uart, pin))
|
||||||
#define IS_VALID_RX(uart, pin) (((pin) & 3) == 1 && IS_VALID_PERIPH(uart, pin))
|
#define IS_VALID_RX(uart, pin) (((pin) & 3) == 1 && IS_VALID_PERIPH(uart, pin))
|
||||||
|
#define IS_VALID_CTS(uart, pin) (((pin) & 3) == 2 && IS_VALID_PERIPH(uart, pin))
|
||||||
|
#define IS_VALID_RTS(uart, pin) (((pin) & 3) == 3 && IS_VALID_PERIPH(uart, pin))
|
||||||
|
|
||||||
#define UART_INVERT_TX (1)
|
#define UART_INVERT_TX (1)
|
||||||
#define UART_INVERT_RX (2)
|
#define UART_INVERT_RX (2)
|
||||||
#define UART_INVERT_MASK (UART_INVERT_TX | UART_INVERT_RX)
|
#define UART_INVERT_MASK (UART_INVERT_TX | UART_INVERT_RX)
|
||||||
|
|
||||||
|
#define UART_HWCONTROL_CTS (1)
|
||||||
|
#define UART_HWCONTROL_RTS (2)
|
||||||
|
|
||||||
typedef struct _machine_uart_obj_t {
|
typedef struct _machine_uart_obj_t {
|
||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
uart_inst_t *const uart;
|
uart_inst_t *const uart;
|
||||||
|
@ -64,9 +73,12 @@ typedef struct _machine_uart_obj_t {
|
||||||
uint8_t stop;
|
uint8_t stop;
|
||||||
uint8_t tx;
|
uint8_t tx;
|
||||||
uint8_t rx;
|
uint8_t rx;
|
||||||
|
uint8_t cts;
|
||||||
|
uint8_t rts;
|
||||||
uint16_t timeout; // timeout waiting for first char (in ms)
|
uint16_t timeout; // timeout waiting for first char (in ms)
|
||||||
uint16_t timeout_char; // timeout waiting between chars (in ms)
|
uint16_t timeout_char; // timeout waiting between chars (in ms)
|
||||||
uint8_t invert;
|
uint8_t invert;
|
||||||
|
uint8_t flow;
|
||||||
ringbuf_t read_buffer;
|
ringbuf_t read_buffer;
|
||||||
bool read_lock;
|
bool read_lock;
|
||||||
ringbuf_t write_buffer;
|
ringbuf_t write_buffer;
|
||||||
|
@ -75,9 +87,9 @@ typedef struct _machine_uart_obj_t {
|
||||||
|
|
||||||
STATIC machine_uart_obj_t machine_uart_obj[] = {
|
STATIC machine_uart_obj_t machine_uart_obj[] = {
|
||||||
{{&machine_uart_type}, uart0, 0, 0, DEFAULT_UART_BITS, UART_PARITY_NONE, DEFAULT_UART_STOP,
|
{{&machine_uart_type}, uart0, 0, 0, DEFAULT_UART_BITS, UART_PARITY_NONE, DEFAULT_UART_STOP,
|
||||||
DEFAULT_UART0_TX, DEFAULT_UART0_RX, 0, 0, 0, {NULL, 1, 0, 0}, 0, {NULL, 1, 0, 0}, 0},
|
DEFAULT_UART0_TX, DEFAULT_UART0_RX, DEFAULT_UART0_CTS, DEFAULT_UART0_RTS, 0, 0, 0, 0, {NULL, 1, 0, 0}, 0, {NULL, 1, 0, 0}, 0},
|
||||||
{{&machine_uart_type}, uart1, 1, 0, DEFAULT_UART_BITS, UART_PARITY_NONE, DEFAULT_UART_STOP,
|
{{&machine_uart_type}, uart1, 1, 0, DEFAULT_UART_BITS, UART_PARITY_NONE, DEFAULT_UART_STOP,
|
||||||
DEFAULT_UART1_TX, DEFAULT_UART1_RX, 0, 0, 0, {NULL, 1, 0, 0}, 0, {NULL, 1, 0, 0}, 0,},
|
DEFAULT_UART1_TX, DEFAULT_UART1_RX, DEFAULT_UART1_CTS, DEFAULT_UART1_RTS, 0, 0, 0, 0, {NULL, 1, 0, 0}, 0, {NULL, 1, 0, 0}, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
STATIC const char *_parity_name[] = {"None", "0", "1"};
|
STATIC const char *_parity_name[] = {"None", "0", "1"};
|
||||||
|
@ -140,8 +152,8 @@ STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_pri
|
||||||
}
|
}
|
||||||
|
|
||||||
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 *all_args) {
|
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 *all_args) {
|
||||||
enum { ARG_id, ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx,
|
enum { ARG_id, ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx, ARG_cts, ARG_rts,
|
||||||
ARG_timeout, ARG_timeout_char, ARG_invert, ARG_txbuf, ARG_rxbuf};
|
ARG_timeout, ARG_timeout_char, ARG_invert, ARG_flow, ARG_txbuf, ARG_rxbuf};
|
||||||
static const mp_arg_t allowed_args[] = {
|
static const mp_arg_t allowed_args[] = {
|
||||||
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||||
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
|
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
|
||||||
|
@ -150,9 +162,12 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args,
|
||||||
{ MP_QSTR_stop, MP_ARG_INT, {.u_int = -1} },
|
{ MP_QSTR_stop, MP_ARG_INT, {.u_int = -1} },
|
||||||
{ MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
{ MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||||
{ MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
{ MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||||
|
{ MP_QSTR_cts, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||||
|
{ MP_QSTR_rts, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||||
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||||
{ MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
{ MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||||
{ MP_QSTR_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
{ MP_QSTR_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||||
|
{ MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||||
{ MP_QSTR_txbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
{ MP_QSTR_txbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||||
{ MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
{ MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||||
};
|
};
|
||||||
|
@ -212,6 +227,22 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args,
|
||||||
self->rx = rx;
|
self->rx = rx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set CTS/RTS pins if configured.
|
||||||
|
if (args[ARG_cts].u_obj != mp_const_none) {
|
||||||
|
int cts = mp_hal_get_pin_obj(args[ARG_cts].u_obj);
|
||||||
|
if (!IS_VALID_CTS(self->uart_id, cts)) {
|
||||||
|
mp_raise_ValueError(MP_ERROR_TEXT("bad CTS pin"));
|
||||||
|
}
|
||||||
|
self->cts = cts;
|
||||||
|
}
|
||||||
|
if (args[ARG_rts].u_obj != mp_const_none) {
|
||||||
|
int rts = mp_hal_get_pin_obj(args[ARG_rts].u_obj);
|
||||||
|
if (!IS_VALID_RTS(self->uart_id, rts)) {
|
||||||
|
mp_raise_ValueError(MP_ERROR_TEXT("bad RTS pin"));
|
||||||
|
}
|
||||||
|
self->rts = rts;
|
||||||
|
}
|
||||||
|
|
||||||
// Set timeout if configured.
|
// Set timeout if configured.
|
||||||
if (args[ARG_timeout].u_int >= 0) {
|
if (args[ARG_timeout].u_int >= 0) {
|
||||||
self->timeout = args[ARG_timeout].u_int;
|
self->timeout = args[ARG_timeout].u_int;
|
||||||
|
@ -230,6 +261,14 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args,
|
||||||
self->invert = args[ARG_invert].u_int;
|
self->invert = args[ARG_invert].u_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set hardware flow control if configured.
|
||||||
|
if (args[ARG_flow].u_int >= 0) {
|
||||||
|
if (args[ARG_flow].u_int & ~(UART_HWCONTROL_CTS | UART_HWCONTROL_RTS)) {
|
||||||
|
mp_raise_ValueError(MP_ERROR_TEXT("bad hardware flow control mask"));
|
||||||
|
}
|
||||||
|
self->flow = args[ARG_flow].u_int;
|
||||||
|
}
|
||||||
|
|
||||||
self->read_lock = false;
|
self->read_lock = false;
|
||||||
|
|
||||||
// Set the RX buffer size if configured.
|
// Set the RX buffer size if configured.
|
||||||
|
@ -278,6 +317,15 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args,
|
||||||
gpio_set_outover(self->tx, GPIO_OVERRIDE_INVERT);
|
gpio_set_outover(self->tx, GPIO_OVERRIDE_INVERT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set hardware flow control if configured.
|
||||||
|
if (self->flow & UART_HWCONTROL_CTS) {
|
||||||
|
gpio_set_function(self->cts, GPIO_FUNC_UART);
|
||||||
|
}
|
||||||
|
if (self->flow & UART_HWCONTROL_RTS) {
|
||||||
|
gpio_set_function(self->rts, GPIO_FUNC_UART);
|
||||||
|
}
|
||||||
|
uart_set_hw_flow(self->uart, self->flow & UART_HWCONTROL_CTS, self->flow & UART_HWCONTROL_RTS);
|
||||||
|
|
||||||
// Allocate the RX/TX buffers.
|
// Allocate the RX/TX buffers.
|
||||||
ringbuf_alloc(&(self->read_buffer), rxbuf_len + 1);
|
ringbuf_alloc(&(self->read_buffer), rxbuf_len + 1);
|
||||||
MP_STATE_PORT(rp2_uart_rx_buffer[uart_id]) = self->read_buffer.buf;
|
MP_STATE_PORT(rp2_uart_rx_buffer[uart_id]) = self->read_buffer.buf;
|
||||||
|
@ -333,6 +381,9 @@ STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = {
|
||||||
{ MP_ROM_QSTR(MP_QSTR_INV_TX), MP_ROM_INT(UART_INVERT_TX) },
|
{ MP_ROM_QSTR(MP_QSTR_INV_TX), MP_ROM_INT(UART_INVERT_TX) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_INV_RX), MP_ROM_INT(UART_INVERT_RX) },
|
{ MP_ROM_QSTR(MP_QSTR_INV_RX), MP_ROM_INT(UART_INVERT_RX) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HWCONTROL_CTS) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) },
|
||||||
|
|
||||||
};
|
};
|
||||||
STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table);
|
STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue