rp2/machine_uart: Add timeout/timeout_char to read and write.

This commit is contained in:
robert-hh 2021-02-09 15:50:21 +01:00 committed by Damien George
parent 8610bababe
commit 8ade163fff
2 changed files with 53 additions and 7 deletions

View File

@ -54,6 +54,8 @@ typedef struct _machine_uart_obj_t {
uint8_t stop;
uint8_t tx;
uint8_t rx;
uint16_t timeout; // timeout waiting for first char (in ms)
uint16_t timeout_char; // timeout waiting between chars (in ms)
} machine_uart_obj_t;
STATIC machine_uart_obj_t machine_uart_obj[] = {
@ -68,13 +70,13 @@ STATIC const char *_parity_name[] = {"None", "0", "1"};
STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, tx=%d, rx=%d)",
mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, tx=%d, rx=%d, timeout=%u, timeout_char=%u)",
self->uart_id, self->baudrate, self->bits, _parity_name[self->parity],
self->stop, self->tx, self->rx);
self->stop, self->tx, self->rx, self->timeout, self->timeout_char);
}
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_timeout, ARG_timeout_char };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
@ -83,6 +85,8 @@ 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_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_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} },
};
// Parse args.
@ -140,11 +144,28 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args,
self->rx = rx;
}
// Set timeout if configured.
if (args[ARG_timeout].u_int >= 0) {
self->timeout = args[ARG_timeout].u_int;
}
// Set timeout_char if configured.
if (args[ARG_timeout_char].u_int >= 0) {
self->timeout_char = args[ARG_timeout_char].u_int;
}
// Initialise the UART peripheral if any arguments given, or it was not initialised previously.
if (n_args > 1 || n_kw > 0 || self->baudrate == 0) {
if (self->baudrate == 0) {
self->baudrate = DEFAULT_UART_BAUDRATE;
}
// Make sure timeout_char is at least as long as a whole character (13 bits to be safe).
uint32_t min_timeout_char = 13000 / self->baudrate + 1;
if (self->timeout_char < min_timeout_char) {
self->timeout_char = min_timeout_char;
}
uart_init(self->uart, self->baudrate);
uart_set_format(self->uart, self->bits, self->stop, self->parity);
uart_set_fifo_enabled(self->uart, true);
@ -184,26 +205,50 @@ STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_t
STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
// TODO support timeout
uint64_t t = time_us_64() + (uint64_t)self->timeout * 1000;
uint64_t timeout_char_us = (uint64_t)self->timeout_char * 1000;
uint8_t *dest = buf_in;
for (size_t i = 0; i < size; ++i) {
for (size_t i = 0; i < size; i++) {
// Wait for the first/next character
while (!uart_is_readable(self->uart)) {
if (time_us_64() > t) { // timed out
if (i <= 0) {
*errcode = MP_EAGAIN;
return MP_STREAM_ERROR;
} else {
return i;
}
}
MICROPY_EVENT_POLL_HOOK
}
*dest++ = uart_get_hw(self->uart)->dr;
t = time_us_64() + timeout_char_us;
}
return size;
}
STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
// TODO support timeout
uint64_t t = time_us_64() + (uint64_t)self->timeout * 1000;
uint64_t timeout_char_us = (uint64_t)self->timeout_char * 1000;
const uint8_t *src = buf_in;
for (size_t i = 0; i < size; ++i) {
for (size_t i = 0; i < size; i++) {
// wait for the first/next character
while (!uart_is_writable(self->uart)) {
if (time_us_64() > t) { // timed out
if (i <= 0) {
*errcode = MP_EAGAIN;
return MP_STREAM_ERROR;
} else {
return i;
}
}
MICROPY_EVENT_POLL_HOOK
}
uart_get_hw(self->uart)->dr = *src++;
t = time_us_64() + timeout_char_us;
}
return size;
}

View File

@ -62,6 +62,7 @@
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
#define MICROPY_ENABLE_SOURCE_LINE (1)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
#define MICROPY_STREAMS_NON_BLOCK (1)
#define MICROPY_MODULE_BUILTIN_INIT (1)
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)