extmod/machine_uart: Factor ports' UART Python bindings to common code.

This is a code factoring to have the Python bindings in one location, and
all the ports use those same bindings.  For all ports except the two listed
below there is no functional change.

The nrf port has UART.sendbreak() removed, but this method previously did
nothing.

The zephyr port has the following methods added:
- UART.init(): supports setting timeout and timeout_char.
- UART.deinit(): does nothing, just returns None.
- UART.flush(): raises OSError(EINVAL) because it's not implemented.
- UART.any() and UART.txdone(): raise NotImplementedError.

Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
Damien George
2023-10-10 23:46:07 +11:00
parent 95d8b5fd55
commit 5b4a2baff6
65 changed files with 661 additions and 996 deletions

View File

@@ -114,7 +114,6 @@ SRC_C = \
machine_bitstream.c \
machine_pin.c \
machine_rtc.c \
machine_uart.c \
machine_hspi.c \
modesp.c \
network_wlan.c \

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
* Copyright (c) 2016-2023 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,24 +24,19 @@
* THE SOFTWARE.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
// This file is never compiled standalone, it's included directly from
// extmod/machine_uart.c via MICROPY_PY_MACHINE_UART_INCLUDEFILE.
#include "py/mperrno.h"
#include "py/mphal.h"
#include "ets_sys.h"
#include "user_interface.h"
#include "uart.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mperrno.h"
#include "py/mphal.h"
#include "modmachine.h"
// UartDev is defined and initialized in rom code.
extern UartDevice UartDev;
typedef struct _pyb_uart_obj_t {
typedef struct _machine_uart_obj_t {
mp_obj_base_t base;
uint8_t uart_id;
uint8_t bits;
@@ -50,21 +45,24 @@ typedef struct _pyb_uart_obj_t {
uint32_t baudrate;
uint16_t timeout; // timeout waiting for first char (in ms)
uint16_t timeout_char; // timeout waiting between chars (in ms)
} pyb_uart_obj_t;
} machine_uart_obj_t;
STATIC const char *_parity_name[] = {"None", "1", "0"};
/******************************************************************************/
// MicroPython bindings for UART
STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
// The UART class doesn't have any constants for this port.
#define MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS
STATIC void mp_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, rxbuf=%u, timeout=%u, timeout_char=%u)",
self->uart_id, self->baudrate, self->bits, _parity_name[self->parity],
self->stop, uart0_get_rxbuf_len() - 1, self->timeout, self->timeout_char);
}
STATIC void pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
STATIC void mp_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_rxbuf, ARG_timeout, ARG_timeout_char };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 0} },
@@ -192,7 +190,7 @@ STATIC void pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const mp_o
uart_setup(self->uart_id);
}
STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
STATIC mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// get uart id
@@ -202,7 +200,7 @@ STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size
}
// create instance
pyb_uart_obj_t *self = mp_obj_malloc(pyb_uart_obj_t, &pyb_uart_type);
machine_uart_obj_t *self = mp_obj_malloc(machine_uart_obj_t, &machine_uart_type);
self->uart_id = uart_id;
self->baudrate = 115200;
self->bits = 8;
@@ -214,47 +212,25 @@ STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size
// init the peripheral
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
pyb_uart_init_helper(self, n_args - 1, args + 1, &kw_args);
mp_machine_uart_init_helper(self, n_args - 1, args + 1, &kw_args);
return MP_OBJ_FROM_PTR(self);
}
STATIC mp_obj_t pyb_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_uart_init_helper(args[0], n_args - 1, args + 1, kw_args);
return mp_const_none;
STATIC void mp_machine_uart_deinit(machine_uart_obj_t *self) {
(void)self;
}
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init);
STATIC mp_obj_t pyb_uart_any(mp_obj_t self_in) {
pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
return MP_OBJ_NEW_SMALL_INT(uart_rx_any(self->uart_id));
STATIC mp_int_t mp_machine_uart_any(machine_uart_obj_t *self) {
return uart_rx_any(self->uart_id);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_any_obj, pyb_uart_any);
STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) {
pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
return uart_txdone(self->uart_id) == true ? mp_const_true : mp_const_false;
STATIC bool mp_machine_uart_txdone(machine_uart_obj_t *self) {
return uart_txdone(self->uart_id);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone);
STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_uart_any_obj) },
{ MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) },
{ MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table);
STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
STATIC mp_uint_t mp_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);
if (self->uart_id == 1) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("UART(1) can't read"));
@@ -282,8 +258,8 @@ STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, i
}
}
STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
STATIC mp_uint_t mp_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);
const byte *buf = buf_in;
/* TODO implement non-blocking
@@ -303,8 +279,8 @@ STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t
return size;
}
STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
pyb_uart_obj_t *self = self_in;
STATIC mp_uint_t mp_machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
machine_uart_obj_t *self = self_in;
mp_uint_t ret;
if (request == MP_STREAM_POLL) {
mp_uint_t flags = arg;
@@ -321,7 +297,7 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t a
uint64_t timeout = (uint64_t)(3 + 127) * 13000000ll * 2 / self->baudrate
+ system_get_time();
do {
if (machine_uart_txdone((mp_obj_t)self) == mp_const_true) {
if (mp_machine_uart_txdone(self)) {
return 0;
}
MICROPY_EVENT_POLL_HOOK
@@ -336,21 +312,4 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t a
return ret;
}
STATIC const mp_stream_p_t uart_stream_p = {
.read = pyb_uart_read,
.write = pyb_uart_write,
.ioctl = pyb_uart_ioctl,
.is_text = false,
};
MP_DEFINE_CONST_OBJ_TYPE(
pyb_uart_type,
MP_QSTR_UART,
MP_TYPE_FLAG_ITER_IS_STREAM,
make_new, pyb_uart_make_new,
print, pyb_uart_print,
protocol, &uart_stream_p,
locals_dict, &pyb_uart_locals_dict
);
MP_REGISTER_ROOT_POINTER(byte * uart0_rxbuf);

View File

@@ -40,6 +40,7 @@
#define USE_US_TIMER 1
#include "extmod/misc.h"
#include "extmod/modmachine.h"
#include "shared/readline/readline.h"
#include "shared/runtime/pyexec.h"
#include "gccollect.h"
@@ -72,7 +73,7 @@ STATIC void mp_reset(void) {
mp_obj_t args[2];
args[0] = MP_OBJ_NEW_SMALL_INT(0);
args[1] = MP_OBJ_NEW_SMALL_INT(115200);
args[0] = MP_OBJ_TYPE_GET_SLOT(&pyb_uart_type, make_new)(&pyb_uart_type, 2, 0, args);
args[0] = MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, make_new)(&machine_uart_type, 2, 0, args);
args[1] = MP_OBJ_NEW_SMALL_INT(1);
mp_os_dupterm_obj.fun.var(2, args);
}

View File

@@ -430,7 +430,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
#if MICROPY_PY_MACHINE_ADC
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) },
#endif
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
#if MICROPY_PY_MACHINE_UART
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) },
#endif
#if MICROPY_PY_MACHINE_I2C
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) },
{ MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) },

View File

@@ -5,7 +5,6 @@
extern const mp_obj_type_t pyb_pin_type;
extern const mp_obj_type_t pyb_rtc_type;
extern const mp_obj_type_t pyb_uart_type;
extern const mp_obj_type_t pyb_i2c_type;
extern const mp_obj_type_t machine_hspi_type;

View File

@@ -30,6 +30,7 @@
#include "py/objtuple.h"
#include "py/objstr.h"
#include "extmod/misc.h"
#include "extmod/modmachine.h"
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
#include "extmod/vfs_lfs.h"
@@ -53,10 +54,10 @@ STATIC mp_obj_t mp_os_urandom(mp_obj_t num) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_os_urandom_obj, mp_os_urandom);
void mp_os_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t stream_attached) {
if (mp_obj_get_type(stream_attached) == &pyb_uart_type) {
if (mp_obj_get_type(stream_attached) == &machine_uart_type) {
++uart_attached_to_dupterm;
}
if (mp_obj_get_type(stream_detached) == &pyb_uart_type) {
if (mp_obj_get_type(stream_detached) == &machine_uart_type) {
--uart_attached_to_dupterm;
}
}

View File

@@ -74,6 +74,8 @@
#define MICROPY_PY_MACHINE_SOFTI2C (1)
#define MICROPY_PY_MACHINE_SPI (1)
#define MICROPY_PY_MACHINE_SOFTSPI (1)
#define MICROPY_PY_MACHINE_UART (1)
#define MICROPY_PY_MACHINE_UART_INCLUDEFILE "ports/esp8266/machine_uart.c"
#define MICROPY_PY_MACHINE_WDT (1)
#define MICROPY_PY_MACHINE_WDT_INCLUDEFILE "ports/esp8266/machine_wdt.c"
#define MICROPY_PY_NETWORK (1)