Skip to content

Commit

Permalink
rp2/machine_uart: Add timeout/timeout_char to read and write.
Browse files Browse the repository at this point in the history
  • Loading branch information
robert-hh authored and dpgeorge committed Mar 11, 2021
1 parent 8610bab commit 8ade163
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 7 deletions.
59 changes: 52 additions & 7 deletions ports/rp2/machine_uart.c
Expand Up @@ -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[] = {
Expand All @@ -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} },
Expand All @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions ports/rp2/mpconfigport.h
Expand Up @@ -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)
Expand Down

0 comments on commit 8ade163

Please sign in to comment.