diff --git a/drivers/cyw43/cywbt.c b/drivers/cyw43/cywbt.c index bc6674ea2e..d1b19382c5 100644 --- a/drivers/cyw43/cywbt.c +++ b/drivers/cyw43/cywbt.c @@ -49,7 +49,7 @@ extern uint8_t mp_bluetooth_hci_cmd_buf[4 + 256]; #include "uart.h" // Provided by the port. -extern pyb_uart_obj_t mp_bluetooth_hci_uart_obj; +extern machine_uart_obj_t mp_bluetooth_hci_uart_obj; STATIC void cywbt_wait_cts_low(void) { mp_hal_pin_config(CYW43_PIN_BT_CTS, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); diff --git a/extmod/extmod.cmake b/extmod/extmod.cmake index 6f01bafe46..a1a0a9f736 100644 --- a/extmod/extmod.cmake +++ b/extmod/extmod.cmake @@ -16,6 +16,7 @@ set(MICROPY_SOURCE_EXTMOD ${MICROPY_EXTMOD_DIR}/machine_pwm.c ${MICROPY_EXTMOD_DIR}/machine_signal.c ${MICROPY_EXTMOD_DIR}/machine_spi.c + ${MICROPY_EXTMOD_DIR}/machine_uart.c ${MICROPY_EXTMOD_DIR}/machine_wdt.c ${MICROPY_EXTMOD_DIR}/modbluetooth.c ${MICROPY_EXTMOD_DIR}/modframebuf.c diff --git a/extmod/extmod.mk b/extmod/extmod.mk index 76dfbf0a45..8a48a42936 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -13,6 +13,7 @@ SRC_EXTMOD_C += \ extmod/machine_signal.c \ extmod/machine_spi.c \ extmod/machine_timer.c \ + extmod/machine_uart.c \ extmod/machine_wdt.c \ extmod/modasyncio.c \ extmod/modbinascii.c \ diff --git a/extmod/machine_uart.c b/extmod/machine_uart.c new file mode 100644 index 0000000000..dd556bbbbf --- /dev/null +++ b/extmod/machine_uart.c @@ -0,0 +1,187 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 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 + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/stream.h" + +#if MICROPY_PY_MACHINE_UART + +#include "extmod/modmachine.h" +#include "shared/runtime/mpirq.h" + +// The port must provide implementations of these low-level UART functions. + +STATIC void mp_machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); +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); +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); +STATIC void mp_machine_uart_deinit(machine_uart_obj_t *self); +STATIC mp_int_t mp_machine_uart_any(machine_uart_obj_t *self); +STATIC bool mp_machine_uart_txdone(machine_uart_obj_t *self); + +#if MICROPY_PY_MACHINE_UART_SENDBREAK +STATIC void mp_machine_uart_sendbreak(machine_uart_obj_t *self); +#endif + +#if MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR +STATIC mp_int_t mp_machine_uart_readchar(machine_uart_obj_t *self); +STATIC void mp_machine_uart_writechar(machine_uart_obj_t *self, uint16_t data); +#endif + +#if MICROPY_PY_MACHINE_UART_IRQ +STATIC mp_irq_obj_t *mp_machine_uart_irq(machine_uart_obj_t *self, bool any_args, mp_arg_val_t *args); +#endif + +STATIC mp_uint_t mp_machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode); +STATIC mp_uint_t mp_machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode); +STATIC mp_uint_t mp_machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode); + +// The port provides implementations of the above in this file. +#include MICROPY_PY_MACHINE_UART_INCLUDEFILE + +// UART.init(...) +STATIC mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + mp_machine_uart_init_helper(MP_OBJ_TO_PTR(args[0]), n_args - 1, args + 1, kw_args); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init); + +// UART.deinit() +STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_machine_uart_deinit(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit); + +// UART.any() +STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(mp_machine_uart_any(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any); + +// UART.txdone() +STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_bool(mp_machine_uart_txdone(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone); + +#if MICROPY_PY_MACHINE_UART_SENDBREAK + +// UART.sendbreak() +STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_machine_uart_sendbreak(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak); + +#endif + +#if MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR + +// UART.readchar() +STATIC mp_obj_t machine_uart_readchar(mp_obj_t self_in) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(mp_machine_uart_readchar(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_readchar_obj, machine_uart_readchar); + +// UART.writechar(char) +STATIC mp_obj_t machine_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_machine_uart_writechar(self, mp_obj_get_int(char_in)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_uart_writechar_obj, machine_uart_writechar); + +#endif + +#if MICROPY_PY_MACHINE_UART_IRQ + +// UART.irq(handler, trigger, hard) +STATIC mp_obj_t machine_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + mp_arg_val_t args[MP_IRQ_ARG_INIT_NUM_ARGS]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_IRQ_ARG_INIT_NUM_ARGS, mp_irq_init_args, args); + machine_uart_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + bool any_args = n_args > 1 || kw_args->used != 0; + return MP_OBJ_FROM_PTR(mp_machine_uart_irq(self, any_args, args)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_irq_obj, 1, machine_uart_irq); + +#endif + +STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_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) }, + + { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) }, + { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) }, + + #if MICROPY_PY_MACHINE_UART_SENDBREAK + { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) }, + #endif + + #if MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR + { MP_ROM_QSTR(MP_QSTR_readchar), MP_ROM_PTR(&machine_uart_readchar_obj) }, + { MP_ROM_QSTR(MP_QSTR_writechar), MP_ROM_PTR(&machine_uart_writechar_obj) }, + #endif + + #if MICROPY_PY_MACHINE_UART_IRQ + { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_uart_irq_obj) }, + #endif + + // A port must add UART class constants defining the following macro. + // It can be defined to nothing if there are no constants. + MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS +}; +STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table); + +STATIC const mp_stream_p_t uart_stream_p = { + .read = mp_machine_uart_read, + .write = mp_machine_uart_write, + .ioctl = mp_machine_uart_ioctl, + .is_text = false, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + machine_uart_type, + MP_QSTR_UART, + MP_TYPE_FLAG_ITER_IS_STREAM, + make_new, mp_machine_uart_make_new, + print, mp_machine_uart_print, + protocol, &uart_stream_p, + locals_dict, &machine_uart_locals_dict + ); + +#endif // MICROPY_PY_MACHINE_UART diff --git a/extmod/modmachine.h b/extmod/modmachine.h index e635eedaae..c18c55553b 100644 --- a/extmod/modmachine.h +++ b/extmod/modmachine.h @@ -65,10 +65,29 @@ #define MICROPY_PY_MACHINE_ADC_READ (0) #endif +// Whether to enable the UART.sendbreak() method. +// Requires a port to implement mp_machine_uart_sendbreak(). +#ifndef MICROPY_PY_MACHINE_UART_SENDBREAK +#define MICROPY_PY_MACHINE_UART_SENDBREAK (0) +#endif + +// Whether to enable the UART.readchar() and UART.writechar() methods. +// Requires a port to implement mp_machine_uart_readchar() and mp_machine_uart_writechar(). +#ifndef MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR +#define MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR (0) +#endif + +// Whether to enable the UART.irq() method. +// Requires a port to implement mp_machine_uart_irq(). +#ifndef MICROPY_PY_MACHINE_UART_IRQ +#define MICROPY_PY_MACHINE_UART_IRQ (0) +#endif + // A port must provide these types, but they are otherwise opaque. typedef struct _machine_adc_obj_t machine_adc_obj_t; typedef struct _machine_i2s_obj_t machine_i2s_obj_t; typedef struct _machine_pwm_obj_t machine_pwm_obj_t; +typedef struct _machine_uart_obj_t machine_uart_obj_t; typedef struct _machine_wdt_obj_t machine_wdt_obj_t; // These classes correspond to machine.Type entries in the machine module. @@ -80,6 +99,7 @@ extern const mp_obj_type_t machine_i2s_type; extern const mp_obj_type_t machine_pwm_type; extern const mp_obj_type_t machine_spi_type; extern const mp_obj_type_t machine_timer_type; +extern const mp_obj_type_t machine_uart_type; extern const mp_obj_type_t machine_wdt_type; #endif // MICROPY_INCLUDED_EXTMOD_MODMACHINE_H diff --git a/ports/esp32/esp32_common.cmake b/ports/esp32/esp32_common.cmake index 4c90282c9f..8b3dac532a 100644 --- a/ports/esp32/esp32_common.cmake +++ b/ports/esp32/esp32_common.cmake @@ -69,7 +69,6 @@ list(APPEND MICROPY_SOURCE_PORT machine_adcblock.c machine_dac.c machine_i2c.c - machine_uart.c modmachine.c network_common.c network_lan.c diff --git a/ports/esp32/machine_uart.c b/ports/esp32/machine_uart.c index 0b4f5890ba..f498ab5b32 100644 --- a/ports/esp32/machine_uart.c +++ b/ports/esp32/machine_uart.c @@ -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,9 +24,8 @@ * THE SOFTWARE. */ -#include -#include -#include +// This file is never compiled standalone, it's included directly from +// extmod/machine_uart.c via MICROPY_PY_MACHINE_UART_INCLUDEFILE. #include "driver/uart.h" #include "freertos/FreeRTOS.h" @@ -35,7 +34,6 @@ #include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" -#include "modmachine.h" #include "uart.h" #if SOC_UART_SUPPORT_XTAL_CLK @@ -75,7 +73,15 @@ STATIC const char *_parity_name[] = {"None", "1", "0"}; /******************************************************************************/ // MicroPython bindings for UART -STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +#define MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS \ + { MP_ROM_QSTR(MP_QSTR_INV_TX), MP_ROM_INT(UART_INV_TX) }, \ + { 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 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); uint32_t baudrate; uart_get_baudrate(self->uart_num, &baudrate); @@ -127,7 +133,7 @@ STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_pri 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) { +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_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} }, @@ -303,7 +309,7 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co 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) { +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 @@ -372,7 +378,7 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - machine_uart_init_helper(self, n_args - 1, args + 1, &kw_args); + mp_machine_uart_init_helper(self, n_args - 1, args + 1, &kw_args); // Make sure pins are connected. uart_set_pin(self->uart_num, self->tx, self->rx, self->rts, self->cts); @@ -380,30 +386,21 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, return MP_OBJ_FROM_PTR(self); } -STATIC mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - machine_uart_init_helper(args[0], n_args - 1, args + 1, kw_args); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init); - -STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +STATIC void mp_machine_uart_deinit(machine_uart_obj_t *self) { uart_driver_delete(self->uart_num); - return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit); -STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +STATIC mp_int_t mp_machine_uart_any(machine_uart_obj_t *self) { size_t rxbufsize; uart_get_buffered_data_len(self->uart_num, &rxbufsize); - return MP_OBJ_NEW_SMALL_INT(rxbufsize); + return rxbufsize; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any); -STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +STATIC bool mp_machine_uart_txdone(machine_uart_obj_t *self) { + return uart_wait_tx_done(self->uart_num, 0) == ESP_OK; +} +STATIC void mp_machine_uart_sendbreak(machine_uart_obj_t *self) { // Save settings uint32_t baudrate; uart_get_baudrate(self->uart_num, &baudrate); @@ -418,46 +415,9 @@ STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { // Restore original setting uart_set_baudrate(self->uart_num, baudrate); - - return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak); -STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - - if (uart_wait_tx_done(self->uart_num, 0) == ESP_OK) { - return mp_const_true; - } else { - return mp_const_false; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone); - -STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_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) }, - { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) }, - { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) }, - - { MP_ROM_QSTR(MP_QSTR_INV_TX), MP_ROM_INT(UART_INV_TX) }, - { 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); - -STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { +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); // make sure we want at least 1 char @@ -491,7 +451,7 @@ STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t siz return bytes_read; } -STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { +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); int bytes_written = uart_write_bytes(self->uart_num, buf_in, size); @@ -505,7 +465,7 @@ STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uin return bytes_written; } -STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { +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) { @@ -537,20 +497,3 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr } return ret; } - -STATIC const mp_stream_p_t uart_stream_p = { - .read = machine_uart_read, - .write = machine_uart_write, - .ioctl = machine_uart_ioctl, - .is_text = false, -}; - -MP_DEFINE_CONST_OBJ_TYPE( - machine_uart_type, - MP_QSTR_UART, - MP_TYPE_FLAG_ITER_IS_STREAM, - make_new, machine_uart_make_new, - print, machine_uart_print, - protocol, &uart_stream_p, - locals_dict, &machine_uart_locals_dict - ); diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index b1c9011cb6..96df32d435 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -328,7 +328,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, + #if MICROPY_PY_MACHINE_UART { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, + #endif // Reset reasons { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) }, diff --git a/ports/esp32/modmachine.h b/ports/esp32/modmachine.h index 68b7d4ffd5..f60715f77a 100644 --- a/ports/esp32/modmachine.h +++ b/ports/esp32/modmachine.h @@ -16,7 +16,6 @@ extern const mp_obj_type_t machine_adcblock_type; extern const mp_obj_type_t machine_dac_type; extern const mp_obj_type_t machine_i2c_type; extern const mp_obj_type_t machine_spi_type; -extern const mp_obj_type_t machine_uart_type; extern const mp_obj_type_t machine_rtc_type; extern const mp_obj_type_t machine_sdcard_type; diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 1718f31f6c..39f91ab831 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -126,6 +126,9 @@ #define MICROPY_PY_MACHINE_I2S_FINALISER (1) #define MICROPY_PY_MACHINE_I2S_CONSTANT_RX (I2S_MODE_MASTER | I2S_MODE_RX) #define MICROPY_PY_MACHINE_I2S_CONSTANT_TX (I2S_MODE_MASTER | I2S_MODE_TX) +#define MICROPY_PY_MACHINE_UART (1) +#define MICROPY_PY_MACHINE_UART_INCLUDEFILE "ports/esp32/machine_uart.c" +#define MICROPY_PY_MACHINE_UART_SENDBREAK (1) #define MICROPY_PY_MACHINE_WDT (1) #define MICROPY_PY_MACHINE_WDT_INCLUDEFILE "ports/esp32/machine_wdt.c" #define MICROPY_PY_NETWORK (1) diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index 0485f9bc05..b29df9fd22 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -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 \ diff --git a/ports/esp8266/machine_uart.c b/ports/esp8266/machine_uart.c index 873b12b2fa..f38858b0c2 100644 --- a/ports/esp8266/machine_uart.c +++ b/ports/esp8266/machine_uart.c @@ -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 -#include -#include +// 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); diff --git a/ports/esp8266/main.c b/ports/esp8266/main.c index 87e72bace9..33e0272f80 100644 --- a/ports/esp8266/main.c +++ b/ports/esp8266/main.c @@ -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); } diff --git a/ports/esp8266/modmachine.c b/ports/esp8266/modmachine.c index 43e94e0c8a..d7e8ed0333 100644 --- a/ports/esp8266/modmachine.c +++ b/ports/esp8266/modmachine.c @@ -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) }, diff --git a/ports/esp8266/modmachine.h b/ports/esp8266/modmachine.h index 469d25e81d..0c6a6afbba 100644 --- a/ports/esp8266/modmachine.h +++ b/ports/esp8266/modmachine.h @@ -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; diff --git a/ports/esp8266/modos.c b/ports/esp8266/modos.c index 78072d4f44..0194bf25f0 100644 --- a/ports/esp8266/modos.c +++ b/ports/esp8266/modos.c @@ -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; } } diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 4e3248513e..8493814b41 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -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) diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index b631c829bf..6131a509d8 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -202,7 +202,6 @@ SRC_C += \ machine_rtc.c \ machine_sdcard.c \ machine_spi.c \ - machine_uart.c \ main.c \ mbedtls/mbedtls_port.c \ mimxrt_flash.c \ diff --git a/ports/mimxrt/machine_uart.c b/ports/mimxrt/machine_uart.c index 8e1505349a..7d228d9159 100644 --- a/ports/mimxrt/machine_uart.c +++ b/ports/mimxrt/machine_uart.c @@ -25,8 +25,9 @@ * THE SOFTWARE. */ -#include "py/runtime.h" -#include "py/stream.h" +// This file is never compiled standalone, it's included directly from +// extmod/machine_uart.c via MICROPY_PY_MACHINE_UART_INCLUDEFILE. + #include "py/mphal.h" #include "ticks.h" #include "fsl_common.h" @@ -163,7 +164,16 @@ void machine_uart_set_baudrate(mp_obj_t uart_in, uint32_t baudrate) { #endif } -STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +/******************************************************************************/ +// MicroPython bindings for UART + +#define MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS \ + { 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_CTS), MP_ROM_INT(UART_HWCONTROL_CTS) }, \ + { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) }, \ + +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, flow=%s, " "rxbuf=%d, txbuf=%d, timeout=%u, timeout_char=%u, invert=%s)", @@ -174,7 +184,7 @@ STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_pri _invert_name[self->invert]); } -STATIC mp_obj_t machine_uart_init_helper(machine_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_flow, ARG_timeout, ARG_timeout_char, ARG_invert, ARG_rxbuf, ARG_txbuf}; static const mp_arg_t allowed_args[] = { @@ -328,11 +338,9 @@ STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args self->lpuart->STAT |= 1 << LPUART_STAT_BRK13_SHIFT; LPUART_EnableTx(self->lpuart, true); } - - return MP_OBJ_FROM_PTR(self); } -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) { +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 bus. @@ -358,53 +366,33 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, if (uart_present) { mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - return machine_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); } else { return mp_const_none; } } -// uart.init(baud, [kwargs]) -STATIC mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - return machine_uart_init_helper(args[0], n_args - 1, args + 1, kw_args); -} -MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init); - // uart.deinit() -STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +STATIC void mp_machine_uart_deinit(machine_uart_obj_t *self) { LPUART_SoftwareReset(self->lpuart); - return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit); -STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +STATIC mp_int_t mp_machine_uart_any(machine_uart_obj_t *self) { machine_uart_ensure_active(self); size_t count = LPUART_TransferGetRxRingBufferLength(self->lpuart, &self->handle); - return MP_OBJ_NEW_SMALL_INT(count); + return count; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any); -STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +STATIC bool mp_machine_uart_txdone(machine_uart_obj_t *self) { + return self->tx_status == kStatus_LPUART_TxIdle; +} + +STATIC void mp_machine_uart_sendbreak(machine_uart_obj_t *self) { machine_uart_ensure_active(self); self->lpuart->CTRL |= 1 << LPUART_CTRL_SBK_SHIFT; // Set SBK bit self->lpuart->CTRL &= ~LPUART_CTRL_SBK_MASK; // Clear SBK bit - return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak); - -STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - - if (self->tx_status == kStatus_LPUART_TxIdle) { - return mp_const_true; - } else { - return mp_const_false; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone); // Reset all defined UARTs void machine_uart_deinit_all(void) { @@ -415,31 +403,7 @@ void machine_uart_deinit_all(void) { } } -STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) }, - - { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_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) }, - - { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) }, - { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) }, - - { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) }, - { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HWCONTROL_CTS) }, - - { 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) }, - -}; -STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table); - -STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { +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); uint64_t t = ticks_us64() + (uint64_t)self->timeout * 1000; uint64_t timeout_char_us = (uint64_t)self->timeout_char * 1000; @@ -474,7 +438,7 @@ STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t siz return size; } -STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { +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); lpuart_transfer_t xfer; uint64_t t; @@ -534,7 +498,7 @@ STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uin return size; } -STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { +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) { @@ -558,7 +522,7 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint self->config.baudRate_Bps + ticks_us64(); do { - if (machine_uart_txdone((mp_obj_t)self) == mp_const_true) { + if (mp_machine_uart_txdone(self)) { return 0; } MICROPY_EVENT_POLL_HOOK @@ -572,20 +536,3 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint } return ret; } - -STATIC const mp_stream_p_t uart_stream_p = { - .read = machine_uart_read, - .write = machine_uart_write, - .ioctl = machine_uart_ioctl, - .is_text = false, -}; - -MP_DEFINE_CONST_OBJ_TYPE( - machine_uart_type, - MP_QSTR_UART, - MP_TYPE_FLAG_ITER_IS_STREAM, - make_new, machine_uart_make_new, - print, machine_uart_print, - protocol, &uart_stream_p, - locals_dict, &machine_uart_locals_dict - ); diff --git a/ports/mimxrt/modmachine.c b/ports/mimxrt/modmachine.c index 33394e62dd..ab7f1de485 100644 --- a/ports/mimxrt/modmachine.c +++ b/ports/mimxrt/modmachine.c @@ -206,7 +206,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_I2S), MP_ROM_PTR(&machine_i2s_type) }, #endif { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, + #if MICROPY_PY_MACHINE_UART { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, + #endif #if MICROPY_PY_MACHINE_WDT { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) }, #endif diff --git a/ports/mimxrt/modmachine.h b/ports/mimxrt/modmachine.h index ff8ac0f085..c6ac4eb390 100644 --- a/ports/mimxrt/modmachine.h +++ b/ports/mimxrt/modmachine.h @@ -34,7 +34,6 @@ extern const mp_obj_type_t machine_rtc_type; extern const mp_obj_type_t machine_sdcard_type; extern const mp_obj_type_t machine_spi_type; extern const mp_obj_type_t machine_timer_type; -extern const mp_obj_type_t machine_uart_type; void machine_adc_init(void); void machine_pin_irq_deinit(void); diff --git a/ports/mimxrt/mpconfigport.h b/ports/mimxrt/mpconfigport.h index 9df6397a87..01502d5472 100644 --- a/ports/mimxrt/mpconfigport.h +++ b/ports/mimxrt/mpconfigport.h @@ -105,6 +105,9 @@ uint32_t trng_random_u32(void); #define MICROPY_PY_MACHINE_WDT_INCLUDEFILE "ports/mimxrt/machine_wdt.c" #define MICROPY_PY_MACHINE_WDT_TIMEOUT_MS (1) #define MICROPY_SOFT_TIMER_TICKS_MS systick_ms +#define MICROPY_PY_MACHINE_UART (1) +#define MICROPY_PY_MACHINE_UART_INCLUDEFILE "ports/mimxrt/machine_uart.c" +#define MICROPY_PY_MACHINE_UART_SENDBREAK (1) #define MICROPY_PY_ONEWIRE (1) // fatfs configuration used in ffconf.h diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index b5d8325773..ac86ad2b15 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -321,7 +321,6 @@ endif DRIVERS_SRC_C += $(addprefix modules/,\ machine/modmachine.c \ - machine/uart.c \ machine/spi.c \ machine/i2c.c \ machine/pin.c \ diff --git a/ports/nrf/main.c b/ports/nrf/main.c index cd22521f4a..959c31e2e7 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -38,6 +38,7 @@ #include "py/stackctrl.h" #include "py/gc.h" #include "py/compile.h" +#include "extmod/modmachine.h" #include "shared/runtime/pyexec.h" #include "readline.h" #include "gccollect.h" diff --git a/ports/nrf/modules/machine/modmachine.c b/ports/nrf/modules/machine/modmachine.c index f8a6e424af..4d39a29b03 100644 --- a/ports/nrf/modules/machine/modmachine.c +++ b/ports/nrf/modules/machine/modmachine.c @@ -39,7 +39,6 @@ #include "lib/oofatfs/diskio.h" #include "gccollect.h" #include "pin.h" -#include "uart.h" #include "spi.h" #include "i2c.h" #include "timer.h" diff --git a/ports/nrf/modules/machine/uart.c b/ports/nrf/modules/machine/uart.c index fd176549d0..e0b56e8310 100644 --- a/ports/nrf/modules/machine/uart.c +++ b/ports/nrf/modules/machine/uart.c @@ -26,13 +26,9 @@ * THE SOFTWARE. */ -#include -#include -#include +// This file is never compiled standalone, it's included directly from +// extmod/machine_uart.c via MICROPY_PY_MACHINE_UART_INCLUDEFILE. -#include "py/nlr.h" -#include "py/runtime.h" -#include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" #include "py/ringbuf.h" @@ -41,9 +37,7 @@ #include "shared/runtime/interrupt_char.h" #include "uart.h" -#include "mpconfigboard.h" #include "nrf.h" -#include "mphalport.h" #if NRFX_UART_ENABLED #include "nrfx_uart.h" @@ -51,15 +45,12 @@ #include "nrfx_uarte.h" #endif - -#if MICROPY_PY_MACHINE_UART - -typedef struct _machine_hard_uart_buf_t { +typedef struct _machine_uart_buf_t { uint8_t tx_buf[1]; uint8_t rx_buf[1]; uint8_t rx_ringbuf_array[64]; volatile ringbuf_t rx_ringbuf; -} machine_hard_uart_buf_t; +} machine_uart_buf_t; #if NRFX_UARTE_ENABLED @@ -96,17 +87,17 @@ typedef struct _machine_hard_uart_buf_t { #endif -typedef struct _machine_hard_uart_obj_t { +typedef struct _machine_uart_obj_t { mp_obj_base_t base; const nrfx_uart_t * p_uart; // Driver instance - machine_hard_uart_buf_t buf; + machine_uart_buf_t buf; uint16_t timeout; // timeout waiting for first char (in ms) uint16_t timeout_char; // timeout waiting between chars (in ms) -} machine_hard_uart_obj_t; +} machine_uart_obj_t; static const nrfx_uart_t instance0 = NRFX_UART_INSTANCE(0); -STATIC machine_hard_uart_obj_t machine_hard_uart_obj[] = { +STATIC machine_uart_obj_t machine_uart_obj[] = { {{&machine_uart_type}, .p_uart = &instance0} }; @@ -116,14 +107,14 @@ void uart_init0(void) { STATIC int uart_find(mp_obj_t id) { // given an integer id int uart_id = mp_obj_get_int(id); - if (uart_id >= 0 && uart_id < MP_ARRAY_SIZE(machine_hard_uart_obj)) { + if (uart_id >= 0 && uart_id < MP_ARRAY_SIZE(machine_uart_obj)) { return uart_id; } mp_raise_ValueError(MP_ERROR_TEXT("UART doesn't exist")); } STATIC void uart_event_handler(nrfx_uart_event_t const *p_event, void *p_context) { - machine_hard_uart_obj_t *self = p_context; + machine_uart_obj_t *self = p_context; if (p_event->type == NRFX_UART_EVT_RX_DONE) { nrfx_uart_rx(self->p_uart, &self->buf.rx_buf[0], 1); int chr = self->buf.rx_buf[0]; @@ -143,15 +134,15 @@ STATIC void uart_event_handler(nrfx_uart_event_t const *p_event, void *p_context } } -bool uart_rx_any(machine_hard_uart_obj_t *self) { +bool uart_rx_any(machine_uart_obj_t *self) { return self->buf.rx_ringbuf.iput != self->buf.rx_ringbuf.iget; } -int uart_rx_char(machine_hard_uart_obj_t *self) { +int uart_rx_char(machine_uart_obj_t *self) { return ringbuf_get((ringbuf_t *)&self->buf.rx_ringbuf); } -STATIC nrfx_err_t uart_tx_char(machine_hard_uart_obj_t *self, int c) { +STATIC nrfx_err_t uart_tx_char(machine_uart_obj_t *self, int c) { while (nrfx_uart_tx_in_progress(self->p_uart)) { ; } @@ -160,13 +151,13 @@ STATIC nrfx_err_t uart_tx_char(machine_hard_uart_obj_t *self, int c) { } -void uart_tx_strn(machine_hard_uart_obj_t *uart_obj, const char *str, uint len) { +void uart_tx_strn(machine_uart_obj_t *uart_obj, const char *str, uint len) { for (const char *top = str + len; str < top; str++) { uart_tx_char(uart_obj, *str); } } -void uart_tx_strn_cooked(machine_hard_uart_obj_t *uart_obj, const char *str, uint len) { +void uart_tx_strn_cooked(machine_uart_obj_t *uart_obj, const char *str, uint len) { for (const char *top = str + len; str < top; str++) { if (*str == '\n') { uart_tx_char(uart_obj, '\r'); @@ -178,16 +169,24 @@ void uart_tx_strn_cooked(machine_hard_uart_obj_t *uart_obj, const char *str, uin /******************************************************************************/ /* MicroPython bindings */ -STATIC void machine_hard_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +// 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) { mp_printf(print, "UART(0)"); } -/// \method init(id, baudrate) -/// -/// Initialise the UART bus with the given parameters: -/// - `id`is bus id. -/// - `baudrate` is the clock rate. -STATIC mp_obj_t machine_hard_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_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) { + // Parse args (none supported at this stage). + mp_arg_parse_all(n_args, pos_args, kw_args, 0, NULL, NULL); +} + +// UART(id, baudrate) +// +// Initialise the UART bus with the given parameters: +// - `id`is bus id. +// - `baudrate` is the clock rate. +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 *all_args) { enum { ARG_id, ARG_baudrate, ARG_timeout, ARG_timeout_char }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -202,7 +201,7 @@ STATIC mp_obj_t machine_hard_uart_make_new(const mp_obj_type_t *type, size_t n_a // get static peripheral object int uart_id = uart_find(args[ARG_id].u_obj); - machine_hard_uart_obj_t *self = &machine_hard_uart_obj[uart_id]; + machine_uart_obj_t *self = &machine_uart_obj[uart_id]; nrfx_uart_config_t config; @@ -267,78 +266,36 @@ STATIC mp_obj_t machine_hard_uart_make_new(const mp_obj_type_t *type, size_t n_a return MP_OBJ_FROM_PTR(self); } -/// \method writechar(char) -/// Write a single character on the bus. `char` is an integer to write. -/// Return value: `None`. -STATIC mp_obj_t machine_hard_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) { - machine_hard_uart_obj_t *self = self_in; - - // get the character to write (might be 9 bits) - int data = mp_obj_get_int(char_in); +STATIC void mp_machine_uart_deinit(machine_uart_obj_t *self) { + (void)self; +} +// Write a single character on the bus. `data` is an integer to write. +STATIC void mp_machine_uart_writechar(machine_uart_obj_t *self, uint16_t data) { nrfx_err_t err = uart_tx_char(self, data); if (err != NRFX_SUCCESS) { mp_hal_raise(err); } - - return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hard_uart_writechar_obj, machine_hard_uart_writechar); -/// \method readchar() -/// Receive a single character on the bus. -/// Return value: The character read, as an integer. Returns -1 on timeout. -STATIC mp_obj_t machine_hard_uart_readchar(mp_obj_t self_in) { - machine_hard_uart_obj_t *self = self_in; - return MP_OBJ_NEW_SMALL_INT(uart_rx_char(self)); +// Receive a single character on the bus. +// Return value: The character read, as an integer. Returns -1 on timeout. +STATIC mp_int_t mp_machine_uart_readchar(machine_uart_obj_t *self) { + return uart_rx_char(self); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hard_uart_readchar_obj, machine_hard_uart_readchar); // uart.any() -STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) { - machine_hard_uart_obj_t *self = self_in; - return MP_OBJ_NEW_SMALL_INT(ringbuf_avail((ringbuf_t *)&self->buf.rx_ringbuf)); +STATIC mp_int_t mp_machine_uart_any(machine_uart_obj_t *self) { + return ringbuf_avail((ringbuf_t *)&self->buf.rx_ringbuf); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any); - -// uart.sendbreak() -STATIC mp_obj_t machine_hard_uart_sendbreak(mp_obj_t self_in) { - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hard_uart_sendbreak_obj, machine_hard_uart_sendbreak); // uart.txdone() -STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) { - machine_hard_uart_obj_t *self = self_in; - return mp_obj_new_bool(!nrfx_uart_tx_in_progress(self->p_uart)); +STATIC bool mp_machine_uart_txdone(machine_uart_obj_t *self) { + return !nrfx_uart_tx_in_progress(self->p_uart); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone); -STATIC const mp_rom_map_elem_t machine_hard_uart_locals_dict_table[] = { - // instance methods - { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_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) }, - - { MP_ROM_QSTR(MP_QSTR_writechar), MP_ROM_PTR(&machine_hard_uart_writechar_obj) }, - { MP_ROM_QSTR(MP_QSTR_readchar), MP_ROM_PTR(&machine_hard_uart_readchar_obj) }, - { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_hard_uart_sendbreak_obj) }, - { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, - { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) }, - - // class constants -/* - { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) }, - { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HWCONTROL_CTS) }, -*/ -}; - -STATIC MP_DEFINE_CONST_DICT(machine_hard_uart_locals_dict, machine_hard_uart_locals_dict_table); - -STATIC mp_uint_t machine_hard_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { - machine_hard_uart_obj_t *self = 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 = self_in; byte *buf = buf_in; uint32_t t = self->timeout + mp_hal_ticks_ms(); @@ -362,8 +319,8 @@ STATIC mp_uint_t machine_hard_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_ return size; } -STATIC mp_uint_t machine_hard_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { - machine_hard_uart_obj_t *self = 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 = self_in; nrfx_err_t err = nrfx_uart_tx(self->p_uart, buf_in, size); if (err == NRFX_SUCCESS) { @@ -378,8 +335,8 @@ STATIC mp_uint_t machine_hard_uart_write(mp_obj_t self_in, const void *buf_in, m } } -STATIC mp_uint_t machine_hard_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { - machine_hard_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; (void)self; mp_uint_t ret = 0; @@ -399,22 +356,3 @@ STATIC mp_uint_t machine_hard_uart_ioctl(mp_obj_t self_in, mp_uint_t request, ui } return MP_STREAM_ERROR; } - -STATIC const mp_stream_p_t uart_stream_p = { - .read = machine_hard_uart_read, - .write = machine_hard_uart_write, - .ioctl = machine_hard_uart_ioctl, - .is_text = false, -}; - -MP_DEFINE_CONST_OBJ_TYPE( - machine_uart_type, - MP_QSTR_UART, - MP_TYPE_FLAG_ITER_IS_STREAM, - make_new, machine_hard_uart_make_new, - print, machine_hard_uart_print, - protocol, &uart_stream_p, - locals_dict, &machine_hard_uart_locals_dict - ); - -#endif // MICROPY_PY_MACHINE_UART diff --git a/ports/nrf/modules/machine/uart.h b/ports/nrf/modules/machine/uart.h index eee0738fe1..741473ab7a 100644 --- a/ports/nrf/modules/machine/uart.h +++ b/ports/nrf/modules/machine/uart.h @@ -31,16 +31,15 @@ #include "pin.h" #include "genhdr/pins.h" -typedef struct _machine_hard_uart_obj_t machine_hard_uart_obj_t; -extern const mp_obj_type_t machine_uart_type; +typedef struct _machine_uart_obj_t machine_uart_obj_t; void uart_init0(void); void uart_deinit(void); void uart_irq_handler(mp_uint_t uart_id); -bool uart_rx_any(machine_hard_uart_obj_t *uart_obj); -int uart_rx_char(machine_hard_uart_obj_t *uart_obj); -void uart_tx_strn(machine_hard_uart_obj_t *uart_obj, const char *str, uint len); -void uart_tx_strn_cooked(machine_hard_uart_obj_t *uart_obj, const char *str, uint len); +bool uart_rx_any(machine_uart_obj_t *uart_obj); +int uart_rx_char(machine_uart_obj_t *uart_obj); +void uart_tx_strn(machine_uart_obj_t *uart_obj, const char *str, uint len); +void uart_tx_strn_cooked(machine_uart_obj_t *uart_obj, const char *str, uint len); #endif diff --git a/ports/nrf/modules/os/modos.c b/ports/nrf/modules/os/modos.c index 7654ac119b..ebe5045515 100644 --- a/ports/nrf/modules/os/modos.c +++ b/ports/nrf/modules/os/modos.c @@ -34,11 +34,11 @@ #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "modules/os/microbitfs.h" +#include "extmod/modmachine.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" #include "extmod/vfs_lfs.h" #include "genhdr/mpversion.h" -#include "uart.h" #if MICROPY_HW_ENABLE_RNG #include "drivers/rng.h" diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 79a74e8566..929065b49a 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -206,6 +206,9 @@ #define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/nrf/modules/machine/soft_pwm.c" #endif +#define MICROPY_PY_MACHINE_UART_INCLUDEFILE "ports/nrf/modules/machine/uart.c" +#define MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR (1) + #ifndef MICROPY_PY_MACHINE_TIMER_NRF #define MICROPY_PY_MACHINE_TIMER_NRF (1) #endif diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index a2eec7fceb..7a51e187b7 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -378,4 +378,4 @@ const char *nrfx_error_code_lookup(uint32_t err_code) { #endif // NRFX_LOG_ENABLED -MP_REGISTER_ROOT_POINTER(struct _machine_hard_uart_obj_t *board_stdio_uart); +MP_REGISTER_ROOT_POINTER(struct _machine_uart_obj_t *board_stdio_uart); diff --git a/ports/renesas-ra/Makefile b/ports/renesas-ra/Makefile index 4630c30fc0..fb7bb67e48 100644 --- a/ports/renesas-ra/Makefile +++ b/ports/renesas-ra/Makefile @@ -322,7 +322,6 @@ SRC_C += \ machine_dac.c \ machine_i2c.c \ machine_spi.c \ - machine_uart.c \ machine_pin.c \ machine_rtc.c \ machine_sdcard.c \ diff --git a/ports/renesas-ra/machine_uart.c b/ports/renesas-ra/machine_uart.c index f365223afa..6c520f941f 100644 --- a/ports/renesas-ra/machine_uart.c +++ b/ports/renesas-ra/machine_uart.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013-2018 Damien P. George + * Copyright (c) 2013-2023 Damien P. George * Copyright (c) 2021,2022 Renesas Electronics Corporation * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -25,12 +25,9 @@ * THE SOFTWARE. */ -#include -#include -#include +// This file is never compiled standalone, it's included directly from +// extmod/machine_uart.c via MICROPY_PY_MACHINE_UART_INCLUDEFILE. -#include "py/runtime.h" -#include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" #include "shared/runtime/interrupt_char.h" @@ -41,44 +38,13 @@ #define DEFAULT_UART_BAUDRATE (115200) +#define MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS \ + { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) }, \ + { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HWCONTROL_CTS) }, \ + STATIC const char *_parity_name[] = {"None", "ODD", "EVEN"}; -/// \moduleref pyb -/// \class UART - duplex serial communication bus -/// -/// UART implements the standard UART/USART duplex serial communications protocol. At -/// the physical level it consists of 2 lines: RX and TX. The unit of communication -/// is a character (not to be confused with a string character) which can be 8 or 9 -/// bits wide. -/// -/// UART objects can be created and initialised using: -/// -/// from pyb import UART -/// -/// uart = UART(1, 9600) # init with given baudrate -/// uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters -/// -/// Bits can be 8 or 9. Parity can be None, 0 (even) or 1 (odd). Stop can be 1 or 2. -/// -/// A UART object acts like a stream object and reading and writing is done -/// using the standard stream methods: -/// -/// uart.read(10) # read 10 characters, returns a bytes object -/// uart.read() # read all available characters -/// uart.readline() # read a line -/// uart.readinto(buf) # read and store into the given buffer -/// uart.write('abc') # write the 3 characters -/// -/// Individual characters can be read/written using: -/// -/// uart.readchar() # read 1 character and returns it as an integer -/// uart.writechar(42) # write 1 character -/// -/// To check if there is anything to be read, use: -/// -/// uart.any() # returns True if any characters waiting - -STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +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); if (!self->is_enabled) { mp_printf(print, "UART(%u)", self->uart_id); @@ -116,7 +82,7 @@ STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_pri /// - `timeout_char` is the timeout in milliseconds to wait between characters. /// - `flow` is RTS | CTS where RTS == 256, CTS == 512 /// - `read_buf_len` is the character length of the read buffer (0 to disable). -STATIC mp_obj_t machine_uart_init_helper(machine_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) { static const mp_arg_t allowed_args[] = { { MP_QSTR_baudrate, MP_ARG_INT | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} }, @@ -238,7 +204,6 @@ STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args #endif // enable_irq(irq_state); - return mp_const_none; } /// \classmethod \constructor(bus, ...) @@ -256,7 +221,7 @@ STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args /// - `UART(6)` is on `YA`: `(TX, RX) = (Y1, Y2) = (PC6, PC7)` /// - `UART(3)` is on `YB`: `(TX, RX) = (Y9, Y10) = (PB10, PB11)` /// - `UART(2)` is on: `(TX, RX) = (X3, X4) = (PA2, PA3)` -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) { +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) { // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); @@ -335,43 +300,33 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, // start the peripheral mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - machine_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 machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - return machine_uart_init_helper(MP_OBJ_TO_PTR(args[0]), n_args - 1, args + 1, kw_args); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init); - -/// \method deinit() -/// Turn off the UART bus. -STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +// Turn off the UART bus. +STATIC void mp_machine_uart_deinit(machine_uart_obj_t *self) { uart_deinit(self); - return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit); -/// \method any() -/// Return `True` if any characters waiting, else `False`. -STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - return MP_OBJ_NEW_SMALL_INT(uart_rx_any(self)); +// Return number of characters waiting. +STATIC mp_int_t mp_machine_uart_any(machine_uart_obj_t *self) { + return uart_rx_any(self); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any); -/// \method writechar(char) -/// Write a single character on the bus. `char` is an integer to write. -/// Return value: `None`. -STATIC mp_obj_t machine_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +// Return `true` if all characters have been sent. +STATIC bool mp_machine_uart_txdone(machine_uart_obj_t *self) { + return !uart_tx_busy(self); +} - // get the character to write (might be 9 bits) - uint16_t data = mp_obj_get_int(char_in); +// Send a break condition. +STATIC void mp_machine_uart_sendbreak(machine_uart_obj_t *self) { + ra_sci_tx_break((uint32_t)self->uart_id); +} - // write the character +// Write a single character on the bus. `data` is an integer to write. +STATIC void mp_machine_uart_writechar(machine_uart_obj_t *self, uint16_t data) { int errcode; if (uart_tx_wait(self, self->timeout)) { uart_tx_data(self, &data, 1, &errcode); @@ -382,53 +337,26 @@ STATIC mp_obj_t machine_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) { if (errcode != 0) { mp_raise_OSError(errcode); } - - return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_uart_writechar_obj, machine_uart_writechar); -/// \method readchar() -/// Receive a single character on the bus. -/// Return value: The character read, as an integer. Returns -1 on timeout. -STATIC mp_obj_t machine_uart_readchar(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +// Receive a single character on the bus. +// Return value: The character read, as an integer. Returns -1 on timeout. +STATIC mp_int_t mp_machine_uart_readchar(machine_uart_obj_t *self) { if (uart_rx_wait(self, self->timeout)) { - return MP_OBJ_NEW_SMALL_INT(uart_rx_char(self)); + return uart_rx_char(self); } else { // return -1 on timeout - return MP_OBJ_NEW_SMALL_INT(-1); + return -1; } } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_readchar_obj, machine_uart_readchar); - -// uart.sendbreak() -STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - ra_sci_tx_break((uint32_t)self->uart_id); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak); - -// \method uart.txdone() -// Return `True` if all characters have been sent. -STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - return uart_tx_busy(self) ? mp_const_false : mp_const_true; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone); - -// irq(handler, trigger, hard) -STATIC mp_obj_t machine_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - mp_arg_val_t args[MP_IRQ_ARG_INIT_NUM_ARGS]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_IRQ_ARG_INIT_NUM_ARGS, mp_irq_init_args, args); - machine_uart_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); +STATIC mp_irq_obj_t *mp_machine_uart_irq(machine_uart_obj_t *self, bool any_args, mp_arg_val_t *args) { if (self->mp_irq_obj == NULL) { self->mp_irq_trigger = 0; self->mp_irq_obj = mp_irq_new(&uart_irq_methods, MP_OBJ_FROM_PTR(self)); } - if (n_args > 1 || kw_args->used != 0) { + if (any_args) { // Check the handler mp_obj_t handler = args[MP_IRQ_ARG_INIT_handler].u_obj; if (handler != mp_const_none && !mp_obj_is_callable(handler)) { @@ -450,41 +378,10 @@ STATIC mp_obj_t machine_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map uart_irq_config(self, true); } - return MP_OBJ_FROM_PTR(self->mp_irq_obj); + return self->mp_irq_obj; } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_irq_obj, 1, machine_uart_irq); -STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { - // instance methods - - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_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) }, - - /// \method read([nbytes]) - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, - /// \method readline() - { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)}, - /// \method readinto(buf[, nbytes]) - { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, - /// \method write(buf) - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, - { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_uart_irq_obj) }, - - { MP_ROM_QSTR(MP_QSTR_writechar), MP_ROM_PTR(&machine_uart_writechar_obj) }, - { MP_ROM_QSTR(MP_QSTR_readchar), MP_ROM_PTR(&machine_uart_readchar_obj) }, - { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) }, - - // class constants - { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) }, - { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HWCONTROL_CTS) }, -}; - -STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table); - -STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { +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); byte *buf = buf_in; @@ -526,7 +423,7 @@ STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t siz } } -STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { +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; @@ -555,7 +452,7 @@ STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uin } } -STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { +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 = MP_OBJ_TO_PTR(self_in); mp_uint_t ret; if (request == MP_STREAM_POLL) { @@ -587,21 +484,4 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr return ret; } -STATIC const mp_stream_p_t uart_stream_p = { - .read = machine_uart_read, - .write = machine_uart_write, - .ioctl = machine_uart_ioctl, - .is_text = false, -}; - -MP_DEFINE_CONST_OBJ_TYPE( - machine_uart_type, - MP_QSTR_UART, - MP_TYPE_FLAG_ITER_IS_STREAM, - make_new, machine_uart_make_new, - locals_dict, &machine_uart_locals_dict, - print, machine_uart_print, - protocol, &uart_stream_p - ); - MP_REGISTER_ROOT_POINTER(struct _machine_uart_obj_t *machine_uart_obj_all[MICROPY_HW_MAX_UART + MICROPY_HW_MAX_LPUART]); diff --git a/ports/renesas-ra/modmachine.c b/ports/renesas-ra/modmachine.c index 9b93b69480..62c9a392c0 100644 --- a/ports/renesas-ra/modmachine.c +++ b/ports/renesas-ra/modmachine.c @@ -296,7 +296,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, #endif + #if MICROPY_PY_MACHINE_UART { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, + #endif { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, #if MICROPY_PY_MACHINE_PWM #if MICROPY_HW_ENABLE_HW_PWM diff --git a/ports/renesas-ra/modmachine.h b/ports/renesas-ra/modmachine.h index 1dd0eec758..ddf212221d 100644 --- a/ports/renesas-ra/modmachine.h +++ b/ports/renesas-ra/modmachine.h @@ -37,7 +37,6 @@ extern const mp_obj_type_t machine_dac_type; extern const mp_obj_type_t machine_i2c_type; extern const mp_obj_type_t machine_spi_type; extern const mp_obj_type_t machine_i2s_type; -extern const mp_obj_type_t machine_uart_type; extern const mp_obj_type_t machine_rtc_type; extern const mp_obj_type_t machine_sdcard_type; diff --git a/ports/renesas-ra/mpconfigport.h b/ports/renesas-ra/mpconfigport.h index 71d5cab820..d3bc3235fd 100644 --- a/ports/renesas-ra/mpconfigport.h +++ b/ports/renesas-ra/mpconfigport.h @@ -151,6 +151,11 @@ #define MICROPY_PY_MACHINE_PWM_DUTY (1) #define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/renesas-ra/machine_pwm.c" #endif +#define MICROPY_PY_MACHINE_UART (1) +#define MICROPY_PY_MACHINE_UART_INCLUDEFILE "ports/renesas-ra/machine_uart.c" +#define MICROPY_PY_MACHINE_UART_IRQ (1) +#define MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR (1) +#define MICROPY_PY_MACHINE_UART_SENDBREAK (1) #if MICROPY_HW_ENABLE_HW_DAC #define MICROPY_PY_MACHINE_DAC (1) #endif diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index c93a8a55d8..16f2d8a247 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -123,7 +123,6 @@ set(MICROPY_SOURCE_PORT machine_rtc.c machine_spi.c machine_timer.c - machine_uart.c main.c modmachine.c modrp2.c diff --git a/ports/rp2/machine_uart.c b/ports/rp2/machine_uart.c index 09870e78f0..044c905ff2 100644 --- a/ports/rp2/machine_uart.c +++ b/ports/rp2/machine_uart.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2020-2021 Damien P. George + * Copyright (c) 2020-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,12 +24,12 @@ * THE SOFTWARE. */ -#include "py/runtime.h" -#include "py/stream.h" +// This file is never compiled standalone, it's included directly from +// extmod/machine_uart.c via MICROPY_PY_MACHINE_UART_INCLUDEFILE. + #include "py/mphal.h" #include "py/mperrno.h" #include "py/ringbuf.h" -#include "modmachine.h" #include "hardware/irq.h" #include "hardware/uart.h" @@ -183,7 +183,13 @@ STATIC void uart1_irq_handler(void) { /******************************************************************************/ // MicroPython bindings for UART -STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +#define MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS \ + { 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_CTS), MP_ROM_INT(UART_HWCONTROL_CTS) }, \ + { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) }, \ + +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, tx=%d, rx=%d, " "txbuf=%d, rxbuf=%d, timeout=%u, timeout_char=%u, invert=%s)", @@ -192,7 +198,7 @@ STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_pri self->timeout, self->timeout_char, _invert_name[self->invert]); } -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) { +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_cts, ARG_rts, ARG_timeout, ARG_timeout_char, ARG_invert, ARG_flow, ARG_txbuf, ARG_rxbuf}; static const mp_arg_t allowed_args[] = { @@ -378,7 +384,7 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co } } -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) { +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 bus. @@ -393,20 +399,12 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, // Initialise the UART peripheral. mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - machine_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 machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - // Initialise the UART peripheral. - machine_uart_init_helper(args[0], n_args - 1, args + 1, kw_args); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init); - -STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +STATIC void mp_machine_uart_deinit(machine_uart_obj_t *self) { uart_deinit(self->uart); if (self->uart_id == 0) { irq_set_enabled(UART0_IRQ, false); @@ -416,63 +414,26 @@ STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) { self->baudrate = 0; MP_STATE_PORT(rp2_uart_rx_buffer[self->uart_id]) = NULL; MP_STATE_PORT(rp2_uart_tx_buffer[self->uart_id]) = NULL; - return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit); -STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +STATIC mp_int_t mp_machine_uart_any(machine_uart_obj_t *self) { // get all bytes from the fifo first uart_drain_rx_fifo(self); - return MP_OBJ_NEW_SMALL_INT(ringbuf_avail(&self->read_buffer)); + return ringbuf_avail(&self->read_buffer); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any); -STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +STATIC bool mp_machine_uart_txdone(machine_uart_obj_t *self) { + return ringbuf_avail(&self->write_buffer) == 0 + && (uart_get_hw(self->uart)->fr & UART_UARTFR_TXFE_BITS); +} + +STATIC void mp_machine_uart_sendbreak(machine_uart_obj_t *self) { uart_set_break(self->uart, true); mp_hal_delay_us(13000000 / self->baudrate + 1); uart_set_break(self->uart, false); - return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak); -STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - - if (ringbuf_avail(&self->write_buffer) == 0 && - uart_get_hw(self->uart)->fr & UART_UARTFR_TXFE_BITS) { - return mp_const_true; - } else { - return mp_const_false; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone); - -STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) }, - - { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_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) }, - - { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) }, - { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) }, - - { 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_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_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { +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); uint64_t t = time_us_64() + (uint64_t)self->timeout * 1000; uint64_t timeout_char_us = (uint64_t)self->timeout_char * 1000; @@ -502,7 +463,7 @@ STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t siz return size; } -STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { +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); uint64_t t = time_us_64() + (uint64_t)self->timeout * 1000; uint64_t timeout_char_us = (uint64_t)self->timeout_char * 1000; @@ -542,7 +503,7 @@ STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uin return size; } -STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { +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) { @@ -560,7 +521,7 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint uint64_t timeout = time_us_64() + (uint64_t)(33 + self->write_buffer.size) * 13000000ll * 2 / self->baudrate; do { - if (machine_uart_txdone((mp_obj_t)self) == mp_const_true) { + if (mp_machine_uart_txdone(self)) { return 0; } MICROPY_EVENT_POLL_HOOK @@ -574,22 +535,5 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint return ret; } -STATIC const mp_stream_p_t uart_stream_p = { - .read = machine_uart_read, - .write = machine_uart_write, - .ioctl = machine_uart_ioctl, - .is_text = false, -}; - -MP_DEFINE_CONST_OBJ_TYPE( - machine_uart_type, - MP_QSTR_UART, - MP_TYPE_FLAG_ITER_IS_STREAM, - make_new, machine_uart_make_new, - print, machine_uart_print, - protocol, &uart_stream_p, - locals_dict, &machine_uart_locals_dict - ); - MP_REGISTER_ROOT_POINTER(void *rp2_uart_rx_buffer[2]); MP_REGISTER_ROOT_POINTER(void *rp2_uart_tx_buffer[2]); diff --git a/ports/rp2/modmachine.c b/ports/rp2/modmachine.c index b47af1aba0..94d87cf314 100644 --- a/ports/rp2/modmachine.c +++ b/ports/rp2/modmachine.c @@ -267,7 +267,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, + #if MICROPY_PY_MACHINE_UART { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, + #endif #if MICROPY_PY_MACHINE_WDT { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) }, #endif diff --git a/ports/rp2/modmachine.h b/ports/rp2/modmachine.h index 5feafdcea8..4e4245ed38 100644 --- a/ports/rp2/modmachine.h +++ b/ports/rp2/modmachine.h @@ -8,7 +8,6 @@ extern const mp_obj_type_t machine_pin_type; extern const mp_obj_type_t machine_rtc_type; extern const mp_obj_type_t machine_spi_type; extern const mp_obj_type_t machine_timer_type; -extern const mp_obj_type_t machine_uart_type; void machine_pin_init(void); void machine_pin_deinit(void); diff --git a/ports/rp2/mpbthciport.c b/ports/rp2/mpbthciport.c index 7722360920..16d50ddacc 100644 --- a/ports/rp2/mpbthciport.c +++ b/ports/rp2/mpbthciport.c @@ -28,6 +28,7 @@ #include "py/stream.h" #include "py/mphal.h" #include "extmod/modbluetooth.h" +#include "extmod/modmachine.h" #include "extmod/mpbthci.h" #include "modmachine.h" #include "mpbthciport.h" diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index b69a06387e..0a63312734 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -129,6 +129,9 @@ #define MICROPY_PY_MACHINE_SPI_MSB (SPI_MSB_FIRST) #define MICROPY_PY_MACHINE_SPI_LSB (SPI_LSB_FIRST) #define MICROPY_PY_MACHINE_SOFTSPI (1) +#define MICROPY_PY_MACHINE_UART (1) +#define MICROPY_PY_MACHINE_UART_INCLUDEFILE "ports/rp2/machine_uart.c" +#define MICROPY_PY_MACHINE_UART_SENDBREAK (1) #define MICROPY_PY_MACHINE_WDT (1) #define MICROPY_PY_MACHINE_WDT_INCLUDEFILE "ports/rp2/machine_wdt.c" #define MICROPY_PY_ONEWIRE (1) diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 841e6a9928..7d27367b6b 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -102,7 +102,6 @@ SRC_C += \ machine_pin.c \ machine_rtc.c \ machine_spi.c \ - machine_uart.c \ main.c \ modmachine.c \ modsamd.c \ diff --git a/ports/samd/machine_i2c.c b/ports/samd/machine_i2c.c index f3364950bd..5606d7b627 100644 --- a/ports/samd/machine_i2c.c +++ b/ports/samd/machine_i2c.c @@ -71,8 +71,6 @@ typedef struct _machine_i2c_obj_t { uint8_t *buf; } machine_i2c_obj_t; -extern Sercom *sercom_instance[]; - STATIC void i2c_send_command(Sercom *i2c, uint8_t command) { i2c->I2CM.CTRLB.bit.CMD = command; while (i2c->I2CM.SYNCBUSY.bit.SYSOP) { diff --git a/ports/samd/machine_spi.c b/ports/samd/machine_spi.c index 99eb4e17f6..b00eb42716 100644 --- a/ports/samd/machine_spi.c +++ b/ports/samd/machine_spi.c @@ -60,8 +60,6 @@ typedef struct _machine_spi_obj_t { size_t rxlen; } machine_spi_obj_t; -extern Sercom *sercom_instance[]; - void common_spi_irq_handler(int spi_id) { // handle Sercom IRQ RXC machine_spi_obj_t *self = MP_STATE_PORT(sercom_table[spi_id]); diff --git a/ports/samd/machine_uart.c b/ports/samd/machine_uart.c index b95e158b3c..c081b8814b 100644 --- a/ports/samd/machine_uart.c +++ b/ports/samd/machine_uart.c @@ -24,17 +24,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "py/runtime.h" -#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_UART +// This file is never compiled standalone, it's included directly from +// extmod/machine_uart.c via MICROPY_PY_MACHINE_UART_INCLUDEFILE. #include "py/mphal.h" -#include "py/stream.h" #include "py/ringbuf.h" -#include "modmachine.h" #include "samd_soc.h" #include "pin_af.h" -#include "clock_config.h" #define DEFAULT_UART_BAUDRATE (115200) #define DEFAULT_BUFFER_SIZE (256) @@ -43,6 +40,8 @@ #define FLOW_CONTROL_RTS (1) #define FLOW_CONTROL_CTS (2) +#define MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS + typedef struct _machine_uart_obj_t { mp_obj_base_t base; uint8_t id; @@ -69,30 +68,6 @@ typedef struct _machine_uart_obj_t { #endif } machine_uart_obj_t; -Sercom *sercom_instance[] = SERCOM_INSTS; -MP_REGISTER_ROOT_POINTER(void *sercom_table[SERCOM_INST_NUM]); - -// Common Sercom functions used by all Serial devices -void sercom_enable(Sercom *uart, int state) { - uart->USART.CTRLA.bit.ENABLE = state; // Set the state on/off - // Wait for the Registers to update. - while (uart->USART.SYNCBUSY.bit.ENABLE) { - } -} - -void sercom_deinit_all(void) { - for (int i = 0; i < SERCOM_INST_NUM; i++) { - Sercom *uart = sercom_instance[i]; - uart->USART.INTENCLR.reg = 0xff; - sercom_register_irq(i, NULL); - sercom_enable(uart, 0); - MP_STATE_PORT(sercom_table[i]) = NULL; - } -} -#endif - -#if MICROPY_PY_MACHINE_UART - STATIC const char *_parity_name[] = {"None", "", "0", "1"}; // Is defined as 0, 2, 3 // Irq handler @@ -137,7 +112,7 @@ void common_uart_irq_handler(int uart_id) { } } -STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +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, " "timeout=%u, timeout_char=%u, rxbuf=%d" @@ -160,7 +135,7 @@ STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_pri ); } -STATIC mp_obj_t machine_uart_init_helper(machine_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_timeout, ARG_timeout_char, ARG_rxbuf, ARG_txbuf, ARG_rts, ARG_cts }; static const mp_arg_t allowed_args[] = { @@ -373,11 +348,9 @@ STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args sercom_enable(uart, 1); } - - return MP_OBJ_FROM_PTR(self); } -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) { +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 bus. @@ -405,17 +378,12 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - return machine_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); } -// uart.init(baud, [kwargs]) -STATIC mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - return machine_uart_init_helper(args[0], n_args - 1, args + 1, kw_args); -} -MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init); - -STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +STATIC void mp_machine_uart_deinit(machine_uart_obj_t *self) { // Check if it is the active object. if (MP_STATE_PORT(sercom_table)[self->id] == self) { Sercom *uart = sercom_instance[self->id]; @@ -426,18 +394,23 @@ STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) { sercom_enable(uart, 0); } } - return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit); -STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - return MP_OBJ_NEW_SMALL_INT(ringbuf_avail(&self->read_buffer)); +STATIC mp_int_t mp_machine_uart_any(machine_uart_obj_t *self) { + return ringbuf_avail(&self->read_buffer); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any); -STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +STATIC bool mp_machine_uart_txdone(machine_uart_obj_t *self) { + Sercom *uart = sercom_instance[self->id]; + + return uart->USART.INTFLAG.bit.DRE + #if MICROPY_HW_UART_TXBUF + && ringbuf_avail(&self->write_buffer) == 0 + #endif + && uart->USART.INTFLAG.bit.TXC; +} + +STATIC void mp_machine_uart_sendbreak(machine_uart_obj_t *self) { uint32_t break_time_us = 13 * 1000000 / self->baudrate; // Wait for the tx buffer to drain. @@ -457,43 +430,9 @@ STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { mp_hal_pin_high(self->tx); // Enable Mux again mp_hal_set_pin_mux(self->tx, self->tx_pad_config.alt_fct); - return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak); -STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - Sercom *uart = sercom_instance[self->id]; - - if (uart->USART.INTFLAG.bit.DRE - #if MICROPY_HW_UART_TXBUF - && ringbuf_avail(&self->write_buffer) == 0 - #endif - && uart->USART.INTFLAG.bit.TXC) { - return mp_const_true; - } else { - return mp_const_false; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone); - -STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) }, - - { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) }, - { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_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(machine_uart_locals_dict, machine_uart_locals_dict_table); - -STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { +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); Sercom *uart = sercom_instance[self->id]; uint64_t t = mp_hal_ticks_ms_64() + self->timeout; @@ -523,7 +462,7 @@ STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t siz return size; } -STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { +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); size_t i = 0; const uint8_t *src = buf_in; @@ -562,7 +501,7 @@ STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uin return size; } -STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { +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; Sercom *uart = sercom_instance[self->id]; @@ -588,7 +527,7 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint #endif ) * 13000 * 2 / self->baudrate; do { - if (machine_uart_txdone((mp_obj_t)self) == mp_const_true) { + if (mp_machine_uart_txdone(self)) { return 0; } MICROPY_EVENT_POLL_HOOK @@ -601,21 +540,3 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint } return ret; } - -STATIC const mp_stream_p_t uart_stream_p = { - .read = machine_uart_read, - .write = machine_uart_write, - .ioctl = machine_uart_ioctl, - .is_text = false, -}; - -MP_DEFINE_CONST_OBJ_TYPE( - machine_uart_type, - MP_QSTR_UART, - MP_TYPE_FLAG_ITER_IS_STREAM, - make_new, machine_uart_make_new, - print, machine_uart_print, - protocol, &uart_stream_p, - locals_dict, &machine_uart_locals_dict - ); -#endif diff --git a/ports/samd/modmachine.h b/ports/samd/modmachine.h index 81b3078171..4f287bde35 100644 --- a/ports/samd/modmachine.h +++ b/ports/samd/modmachine.h @@ -40,9 +40,6 @@ extern const mp_obj_type_t machine_pin_type; extern const mp_obj_type_t machine_spi_type; #endif extern const mp_obj_type_t machine_timer_type; -#if MICROPY_PY_MACHINE_UART -extern const mp_obj_type_t machine_uart_type; -#endif #if MICROPY_PY_MACHINE_RTC extern const mp_obj_type_t machine_rtc_type; #endif diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 201e657c68..801408ed47 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -116,6 +116,8 @@ #ifndef MICROPY_PY_MACHINE_UART #define MICROPY_PY_MACHINE_UART (1) #endif +#define MICROPY_PY_MACHINE_UART_INCLUDEFILE "ports/samd/machine_uart.c" +#define MICROPY_PY_MACHINE_UART_SENDBREAK (1) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_SOFT_TIMER_TICKS_MS systick_ms #define MICROPY_PY_OS_DUPTERM (3) diff --git a/ports/samd/samd_soc.c b/ports/samd/samd_soc.c index a81e7c6881..ad5910301c 100644 --- a/ports/samd/samd_soc.c +++ b/ports/samd/samd_soc.c @@ -128,3 +128,28 @@ void samd_init(void) { machine_rtc_start(false); #endif } + +#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_UART + +Sercom *sercom_instance[] = SERCOM_INSTS; +MP_REGISTER_ROOT_POINTER(void *sercom_table[SERCOM_INST_NUM]); + +// Common Sercom functions used by all Serial devices +void sercom_enable(Sercom *uart, int state) { + uart->USART.CTRLA.bit.ENABLE = state; // Set the state on/off + // Wait for the Registers to update. + while (uart->USART.SYNCBUSY.bit.ENABLE) { + } +} + +void sercom_deinit_all(void) { + for (int i = 0; i < SERCOM_INST_NUM; i++) { + Sercom *uart = sercom_instance[i]; + uart->USART.INTENCLR.reg = 0xff; + sercom_register_irq(i, NULL); + sercom_enable(uart, 0); + MP_STATE_PORT(sercom_table[i]) = NULL; + } +} + +#endif diff --git a/ports/samd/samd_soc.h b/ports/samd/samd_soc.h index e8560b50e8..1848cf7db1 100644 --- a/ports/samd/samd_soc.h +++ b/ports/samd/samd_soc.h @@ -30,6 +30,8 @@ #include "sam.h" #include "clock_config.h" +extern Sercom *sercom_instance[]; + void samd_init(void); void samd_main(void); diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index d1248e0bb8..d3b80ab5b1 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -335,7 +335,6 @@ SRC_C += \ machine_bitstream.c \ machine_i2c.c \ machine_spi.c \ - machine_uart.c \ modmachine.c \ modpyb.c \ modstm.c \ diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index ba8c1a9111..6f1a7f9a2d 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013-2018 Damien P. George + * Copyright (c) 2013-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,12 +24,11 @@ * THE SOFTWARE. */ -#include -#include -#include +// This file is never compiled standalone, it's included directly from +// extmod/machine_uart.c via MICROPY_PY_MACHINE_UART_INCLUDEFILE. + +#include -#include "py/runtime.h" -#include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" #include "shared/runtime/interrupt_char.h" @@ -38,43 +37,13 @@ #include "irq.h" #include "pendsv.h" -/// \moduleref pyb -/// \class UART - duplex serial communication bus -/// -/// UART implements the standard UART/USART duplex serial communications protocol. At -/// the physical level it consists of 2 lines: RX and TX. The unit of communication -/// is a character (not to be confused with a string character) which can be 8 or 9 -/// bits wide. -/// -/// UART objects can be created and initialised using: -/// -/// from pyb import UART -/// -/// uart = UART(1, 9600) # init with given baudrate -/// uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters -/// -/// Bits can be 8 or 9. Parity can be None, 0 (even) or 1 (odd). Stop can be 1 or 2. -/// -/// A UART object acts like a stream object and reading and writing is done -/// using the standard stream methods: -/// -/// uart.read(10) # read 10 characters, returns a bytes object -/// uart.read() # read all available characters -/// uart.readline() # read a line -/// uart.readinto(buf) # read and store into the given buffer -/// uart.write('abc') # write the 3 characters -/// -/// Individual characters can be read/written using: -/// -/// uart.readchar() # read 1 character and returns it as an integer -/// uart.writechar(42) # write 1 character -/// -/// To check if there is anything to be read, use: -/// -/// uart.any() # returns True if any characters waiting +#define MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS \ + { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) }, \ + { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HWCONTROL_CTS) }, \ + { MP_ROM_QSTR(MP_QSTR_IRQ_RXIDLE), MP_ROM_INT(UART_FLAG_IDLE) }, \ -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); +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); if (!self->is_enabled) { #if defined(LPUART1) if (self->uart_id == PYB_LPUART_1) { @@ -171,7 +140,7 @@ STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k /// - `timeout_char` is the timeout in milliseconds to wait between characters. /// - `flow` is RTS | CTS where RTS == 256, CTS == 512 /// - `read_buf_len` is the character length of the read buffer (0 to disable). -STATIC mp_obj_t 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) { static const mp_arg_t allowed_args[] = { { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 9600} }, { MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} }, @@ -292,8 +261,6 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const if (20 * baudrate_diff > actual_baudrate) { mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("set baudrate %d is not within 5%% of desired value"), actual_baudrate); } - - return mp_const_none; } /// \classmethod \constructor(bus, ...) @@ -311,7 +278,7 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const /// - `UART(6)` is on `YA`: `(TX, RX) = (Y1, Y2) = (PC6, PC7)` /// - `UART(3)` is on `YB`: `(TX, RX) = (Y9, Y10) = (PB10, PB11)` /// - `UART(2)` is on: `(TX, RX) = (X3, X4) = (PA2, PA3)` -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) { // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); @@ -391,59 +358,56 @@ STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("UART(%d) is reserved"), uart_id); } - pyb_uart_obj_t *self; - if (MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1] == NULL) { + machine_uart_obj_t *self; + if (MP_STATE_PORT(machine_uart_obj_all)[uart_id - 1] == NULL) { // create new UART object - self = m_new0(pyb_uart_obj_t, 1); - self->base.type = &pyb_uart_type; + self = m_new0(machine_uart_obj_t, 1); + self->base.type = &machine_uart_type; self->uart_id = uart_id; - MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1] = self; + MP_STATE_PORT(machine_uart_obj_all)[uart_id - 1] = self; } else { // reference existing UART object - self = MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1]; + self = MP_STATE_PORT(machine_uart_obj_all)[uart_id - 1]; } if (n_args > 1 || n_kw > 0) { // start 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) { - return pyb_uart_init_helper(MP_OBJ_TO_PTR(args[0]), n_args - 1, args + 1, kw_args); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init); - -/// \method deinit() -/// Turn off the UART bus. -STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) { - pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +// Turn off the UART bus. +STATIC void mp_machine_uart_deinit(machine_uart_obj_t *self) { uart_deinit(self); - return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_deinit_obj, pyb_uart_deinit); -/// \method any() -/// Return `True` if any characters waiting, else `False`. -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)); +// Return number of characters waiting. +STATIC mp_int_t mp_machine_uart_any(machine_uart_obj_t *self) { + return uart_rx_any(self); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_any_obj, pyb_uart_any); -/// \method writechar(char) -/// Write a single character on the bus. `char` is an integer to write. -/// Return value: `None`. -STATIC mp_obj_t pyb_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) { - pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +// Since uart.write() waits up to the last byte, uart.txdone() always returns True. +STATIC bool mp_machine_uart_txdone(machine_uart_obj_t *self) { + (void)self; + return true; +} - // get the character to write (might be 9 bits) - uint16_t data = mp_obj_get_int(char_in); +// Send a break condition. +STATIC void mp_machine_uart_sendbreak(machine_uart_obj_t *self) { + #if defined(STM32F0) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + self->uartx->RQR = USART_RQR_SBKRQ; // write-only register + #else + self->uartx->CR1 |= USART_CR1_SBK; + #endif +} +// Write a single character on the bus. `data` is an integer to write. +// The `data` can be up to 9 bits. +STATIC void mp_machine_uart_writechar(machine_uart_obj_t *self, uint16_t data) { // write the character int errcode; if (uart_tx_wait(self, self->timeout)) { @@ -455,49 +419,26 @@ STATIC mp_obj_t pyb_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) { if (errcode != 0) { mp_raise_OSError(errcode); } - - return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_uart_writechar_obj, pyb_uart_writechar); -/// \method readchar() -/// Receive a single character on the bus. -/// Return value: The character read, as an integer. Returns -1 on timeout. -STATIC mp_obj_t pyb_uart_readchar(mp_obj_t self_in) { - pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); +// Receive a single character on the bus. +// Return value: The character read, as an integer. Returns -1 on timeout. +STATIC mp_int_t mp_machine_uart_readchar(machine_uart_obj_t *self) { if (uart_rx_wait(self, self->timeout)) { - return MP_OBJ_NEW_SMALL_INT(uart_rx_char(self)); + return uart_rx_char(self); } else { // return -1 on timeout - return MP_OBJ_NEW_SMALL_INT(-1); + return -1; } } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_readchar_obj, pyb_uart_readchar); - -// uart.sendbreak() -STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) { - pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - #if defined(STM32F0) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) - self->uartx->RQR = USART_RQR_SBKRQ; // write-only register - #else - self->uartx->CR1 |= USART_CR1_SBK; - #endif - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_sendbreak_obj, pyb_uart_sendbreak); - -// irq(handler, trigger, hard) -STATIC mp_obj_t pyb_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - mp_arg_val_t args[MP_IRQ_ARG_INIT_NUM_ARGS]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_IRQ_ARG_INIT_NUM_ARGS, mp_irq_init_args, args); - pyb_uart_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); +STATIC mp_irq_obj_t *mp_machine_uart_irq(machine_uart_obj_t *self, bool any_args, mp_arg_val_t *args) { if (self->mp_irq_obj == NULL) { self->mp_irq_trigger = 0; self->mp_irq_obj = mp_irq_new(&uart_irq_methods, MP_OBJ_FROM_PTR(self)); } - if (n_args > 1 || kw_args->used != 0) { + if (any_args) { // Check the handler mp_obj_t handler = args[MP_IRQ_ARG_INIT_handler].u_obj; if (handler != mp_const_none && !mp_obj_is_callable(handler)) { @@ -519,51 +460,11 @@ STATIC mp_obj_t pyb_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t * uart_irq_config(self, true); } - return MP_OBJ_FROM_PTR(self->mp_irq_obj); + return self->mp_irq_obj; } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_irq_obj, 1, pyb_uart_irq); -// Since uart.write() waits up to the last byte, uart.txdone() always returns True. -STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) { - return mp_const_true; -} -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[] = { - // instance methods - - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_uart_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_uart_any_obj) }, - - /// \method read([nbytes]) - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, - /// \method readline() - { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)}, - /// \method readinto(buf[, nbytes]) - { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, - /// \method write(buf) - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, - { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, - { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&pyb_uart_irq_obj) }, - - { MP_ROM_QSTR(MP_QSTR_writechar), MP_ROM_PTR(&pyb_uart_writechar_obj) }, - { MP_ROM_QSTR(MP_QSTR_readchar), MP_ROM_PTR(&pyb_uart_readchar_obj) }, - { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&pyb_uart_sendbreak_obj) }, - { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) }, - - // class constants - { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) }, - { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HWCONTROL_CTS) }, - - // IRQ flags - { MP_ROM_QSTR(MP_QSTR_IRQ_RXIDLE), MP_ROM_INT(UART_FLAG_IDLE) }, -}; - -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); byte *buf = buf_in; // check that size is a multiple of character width @@ -604,8 +505,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; // check that size is a multiple of character width @@ -631,8 +532,8 @@ STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t } } -STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { - pyb_uart_obj_t *self = MP_OBJ_TO_PTR(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 = MP_OBJ_TO_PTR(self_in); mp_uint_t ret; if (request == MP_STREAM_POLL) { uintptr_t flags = arg; @@ -652,20 +553,3 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_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 - ); diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 9e5dafc9f6..06ba74f759 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -40,6 +40,7 @@ #include "lib/littlefs/lfs1_util.h" #include "lib/littlefs/lfs2.h" #include "lib/littlefs/lfs2_util.h" +#include "extmod/modmachine.h" #include "extmod/modnetwork.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" @@ -96,7 +97,7 @@ STATIC pyb_thread_t pyb_thread_main; #ifndef MICROPY_HW_UART_REPL_RXBUF #define MICROPY_HW_UART_REPL_RXBUF (260) #endif -STATIC pyb_uart_obj_t pyb_uart_repl_obj; +STATIC machine_uart_obj_t pyb_uart_repl_obj; STATIC uint8_t pyb_uart_repl_rxbuf[MICROPY_HW_UART_REPL_RXBUF]; #endif @@ -431,7 +432,7 @@ void stm32_main(uint32_t reset_mode) { #if defined(MICROPY_HW_UART_REPL) // Set up a UART REPL using a statically allocated object - pyb_uart_repl_obj.base.type = &pyb_uart_type; + pyb_uart_repl_obj.base.type = &machine_uart_type; pyb_uart_repl_obj.uart_id = MICROPY_HW_UART_REPL; pyb_uart_repl_obj.is_static = true; pyb_uart_repl_obj.timeout = 0; @@ -439,7 +440,7 @@ void stm32_main(uint32_t reset_mode) { uart_init(&pyb_uart_repl_obj, MICROPY_HW_UART_REPL_BAUD, UART_WORDLENGTH_8B, UART_PARITY_NONE, UART_STOPBITS_1, 0); uart_set_rxbuf(&pyb_uart_repl_obj, sizeof(pyb_uart_repl_rxbuf), pyb_uart_repl_rxbuf); uart_attach_to_repl(&pyb_uart_repl_obj, true); - MP_STATE_PORT(pyb_uart_obj_all)[MICROPY_HW_UART_REPL - 1] = &pyb_uart_repl_obj; + MP_STATE_PORT(machine_uart_obj_all)[MICROPY_HW_UART_REPL - 1] = &pyb_uart_repl_obj; MP_STATE_PORT(pyb_stdio_uart) = &pyb_uart_repl_obj; #endif diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index 070d0e1169..3bbac66879 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -448,7 +448,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { #if MICROPY_PY_MACHINE_I2S { MP_ROM_QSTR(MP_QSTR_I2S), MP_ROM_PTR(&machine_i2s_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_WDT { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) }, #endif diff --git a/ports/stm32/modos.c b/ports/stm32/modos.c index 43543aa55e..bd0101cab9 100644 --- a/ports/stm32/modos.c +++ b/ports/stm32/modos.c @@ -25,6 +25,7 @@ */ #include "py/runtime.h" +#include "extmod/modmachine.h" #include "rng.h" #include "usb.h" #include "uart.h" @@ -47,7 +48,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_os_urandom_obj, mp_os_urandom); bool mp_os_dupterm_is_builtin_stream(mp_const_obj_t stream) { const mp_obj_type_t *type = mp_obj_get_type(stream); - return type == &pyb_uart_type + return type == &machine_uart_type #if MICROPY_HW_ENABLE_USB || type == &pyb_usb_vcp_type #endif @@ -55,7 +56,7 @@ bool mp_os_dupterm_is_builtin_stream(mp_const_obj_t stream) { } void mp_os_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t stream_attached) { - if (mp_obj_get_type(stream_detached) == &pyb_uart_type) { + if (mp_obj_get_type(stream_detached) == &machine_uart_type) { uart_attach_to_repl(MP_OBJ_TO_PTR(stream_detached), false); } #if MICROPY_HW_ENABLE_USB @@ -64,7 +65,7 @@ void mp_os_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t s } #endif - if (mp_obj_get_type(stream_attached) == &pyb_uart_type) { + if (mp_obj_get_type(stream_attached) == &machine_uart_type) { uart_attach_to_repl(MP_OBJ_TO_PTR(stream_attached), true); } #if MICROPY_HW_ENABLE_USB diff --git a/ports/stm32/modpyb.c b/ports/stm32/modpyb.c index 831ece74a9..0bf2d6a2c3 100644 --- a/ports/stm32/modpyb.c +++ b/ports/stm32/modpyb.c @@ -52,6 +52,7 @@ #include "usb.h" #include "portmodules.h" #include "modmachine.h" +#include "extmod/modmachine.h" #include "extmod/modnetwork.h" #include "extmod/vfs.h" #include "extmod/modtime.h" @@ -103,7 +104,7 @@ STATIC mp_obj_t pyb_repl_uart(size_t n_args, const mp_obj_t *args) { uart_attach_to_repl(MP_STATE_PORT(pyb_stdio_uart), false); MP_STATE_PORT(pyb_stdio_uart) = NULL; } - } else if (mp_obj_get_type(args[0]) == &pyb_uart_type) { + } else if (mp_obj_get_type(args[0]) == &machine_uart_type) { MP_STATE_PORT(pyb_stdio_uart) = MP_OBJ_TO_PTR(args[0]); uart_attach_to_repl(MP_STATE_PORT(pyb_stdio_uart), true); } else { @@ -232,7 +233,7 @@ STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&pyb_i2c_type) }, #endif { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&pyb_spi_type) }, - { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, #if MICROPY_HW_ENABLE_CAN { MP_ROM_QSTR(MP_QSTR_CAN), MP_ROM_PTR(&pyb_can_type) }, #endif diff --git a/ports/stm32/mpbthciport.c b/ports/stm32/mpbthciport.c index fe061a1240..e764c69844 100644 --- a/ports/stm32/mpbthciport.c +++ b/ports/stm32/mpbthciport.c @@ -150,9 +150,10 @@ int mp_bluetooth_hci_uart_readpacket(mp_bluetooth_hci_uart_readchar_t handler) { /******************************************************************************/ // HCI over UART +#include "extmod/modmachine.h" #include "uart.h" -pyb_uart_obj_t mp_bluetooth_hci_uart_obj; +machine_uart_obj_t mp_bluetooth_hci_uart_obj; mp_irq_obj_t mp_bluetooth_hci_uart_irq_obj; static uint8_t hci_uart_rxbuf[768]; @@ -169,13 +170,13 @@ int mp_bluetooth_hci_uart_init(uint32_t port, uint32_t baudrate) { DEBUG_printf("mp_bluetooth_hci_uart_init (stm32)\n"); // bits (8), stop (1), parity (none) and flow (rts/cts) are assumed to match MYNEWT_VAL_BLE_HCI_UART_ constants in syscfg.h. - mp_bluetooth_hci_uart_obj.base.type = &pyb_uart_type; + mp_bluetooth_hci_uart_obj.base.type = &machine_uart_type; mp_bluetooth_hci_uart_obj.uart_id = port; mp_bluetooth_hci_uart_obj.is_static = true; // We don't want to block indefinitely, but expect flow control is doing its job. mp_bluetooth_hci_uart_obj.timeout = 200; mp_bluetooth_hci_uart_obj.timeout_char = 200; - MP_STATE_PORT(pyb_uart_obj_all)[mp_bluetooth_hci_uart_obj.uart_id - 1] = &mp_bluetooth_hci_uart_obj; + MP_STATE_PORT(machine_uart_obj_all)[mp_bluetooth_hci_uart_obj.uart_id - 1] = &mp_bluetooth_hci_uart_obj; // Initialise the UART. uart_init(&mp_bluetooth_hci_uart_obj, baudrate, UART_WORDLENGTH_8B, UART_PARITY_NONE, UART_STOPBITS_1, UART_HWCONTROL_RTS | UART_HWCONTROL_CTS); diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 0cb929f558..00ded86e16 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -128,6 +128,11 @@ #define MICROPY_PY_MACHINE_SPI_LSB (SPI_FIRSTBIT_LSB) #define MICROPY_PY_MACHINE_SOFTSPI (1) #define MICROPY_PY_MACHINE_TIMER (1) +#define MICROPY_PY_MACHINE_UART (1) +#define MICROPY_PY_MACHINE_UART_INCLUDEFILE "ports/stm32/machine_uart.c" +#define MICROPY_PY_MACHINE_UART_IRQ (1) +#define MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR (1) +#define MICROPY_PY_MACHINE_UART_SENDBREAK (1) #define MICROPY_PY_MACHINE_WDT (1) #define MICROPY_PY_MACHINE_WDT_INCLUDEFILE "ports/stm32/machine_wdt.c" #endif diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index 8edafa9bfc..f8a5d66fc9 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -182,4 +182,4 @@ void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest) { } } -MP_REGISTER_ROOT_POINTER(struct _pyb_uart_obj_t *pyb_stdio_uart); +MP_REGISTER_ROOT_POINTER(struct _machine_uart_obj_t *pyb_stdio_uart); diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index 908361874d..0d648a6fc1 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -117,12 +117,12 @@ #endif -typedef struct _pyb_uart_irq_map_t { +typedef struct _machine_uart_irq_map_t { uint16_t irq_en; uint16_t flag; -} pyb_uart_irq_map_t; +} machine_uart_irq_map_t; -STATIC const pyb_uart_irq_map_t mp_uart_irq_map[] = { +STATIC const machine_uart_irq_map_t mp_uart_irq_map[] = { { USART_CR1_IDLEIE, UART_FLAG_IDLE}, // RX idle { USART_CR1_PEIE, UART_FLAG_PE}, // parity error #if defined(STM32G0) || defined(STM32WL) @@ -162,18 +162,18 @@ void uart_init0(void) { // unregister all interrupt sources void uart_deinit_all(void) { - for (int i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(pyb_uart_obj_all)); i++) { - pyb_uart_obj_t *uart_obj = MP_STATE_PORT(pyb_uart_obj_all)[i]; + for (int i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(machine_uart_obj_all)); i++) { + machine_uart_obj_t *uart_obj = MP_STATE_PORT(machine_uart_obj_all)[i]; if (uart_obj != NULL && !uart_obj->is_static) { uart_deinit(uart_obj); - MP_STATE_PORT(pyb_uart_obj_all)[i] = NULL; + MP_STATE_PORT(machine_uart_obj_all)[i] = NULL; } } } bool uart_exists(int uart_id) { - if (uart_id > MP_ARRAY_SIZE(MP_STATE_PORT(pyb_uart_obj_all))) { - // safeguard against pyb_uart_obj_all array being configured too small + if (uart_id > MP_ARRAY_SIZE(MP_STATE_PORT(machine_uart_obj_all))) { + // safeguard against machine_uart_obj_all array being configured too small return false; } switch (uart_id) { @@ -243,7 +243,7 @@ bool uart_exists(int uart_id) { } // assumes Init parameters have been set up correctly -bool uart_init(pyb_uart_obj_t *uart_obj, +bool uart_init(machine_uart_obj_t *uart_obj, uint32_t baudrate, uint32_t bits, uint32_t parity, uint32_t stop, uint32_t flow) { USART_TypeDef *UARTx; IRQn_Type irqn; @@ -641,7 +641,7 @@ bool uart_init(pyb_uart_obj_t *uart_obj, return true; } -void uart_irq_config(pyb_uart_obj_t *self, bool enable) { +void uart_irq_config(machine_uart_obj_t *self, bool enable) { if (self->mp_irq_trigger) { for (size_t entry = 0; entry < MP_ARRAY_SIZE(mp_uart_irq_map); ++entry) { if (mp_uart_irq_map[entry].flag & MP_UART_RESERVED_FLAGS) { @@ -658,7 +658,7 @@ void uart_irq_config(pyb_uart_obj_t *self, bool enable) { } } -void uart_set_rxbuf(pyb_uart_obj_t *self, size_t len, void *buf) { +void uart_set_rxbuf(machine_uart_obj_t *self, size_t len, void *buf) { self->read_buf_head = 0; self->read_buf_tail = 0; self->read_buf_len = len; @@ -670,7 +670,7 @@ void uart_set_rxbuf(pyb_uart_obj_t *self, size_t len, void *buf) { } } -void uart_deinit(pyb_uart_obj_t *self) { +void uart_deinit(machine_uart_obj_t *self) { self->is_enabled = false; // Disable UART @@ -809,11 +809,11 @@ void uart_deinit(pyb_uart_obj_t *self) { } } -void uart_attach_to_repl(pyb_uart_obj_t *self, bool attached) { +void uart_attach_to_repl(machine_uart_obj_t *self, bool attached) { self->attached_to_repl = attached; } -uint32_t uart_get_source_freq(pyb_uart_obj_t *self) { +uint32_t uart_get_source_freq(machine_uart_obj_t *self) { uint32_t uart_clk = 0; #if defined(STM32F0) || defined(STM32G0) @@ -921,7 +921,7 @@ uint32_t uart_get_source_freq(pyb_uart_obj_t *self) { return uart_clk; } -uint32_t uart_get_baudrate(pyb_uart_obj_t *self) { +uint32_t uart_get_baudrate(machine_uart_obj_t *self) { #if defined(LPUART1) if (self->uart_id == PYB_LPUART_1) { return LL_LPUART_GetBaudRate(self->uartx, uart_get_source_freq(self) @@ -938,7 +938,7 @@ uint32_t uart_get_baudrate(pyb_uart_obj_t *self) { LL_USART_OVERSAMPLING_16); } -void uart_set_baudrate(pyb_uart_obj_t *self, uint32_t baudrate) { +void uart_set_baudrate(machine_uart_obj_t *self, uint32_t baudrate) { #if defined(LPUART1) if (self->uart_id == PYB_LPUART_1) { LL_LPUART_SetBaudRate(self->uartx, uart_get_source_freq(self), @@ -956,7 +956,7 @@ void uart_set_baudrate(pyb_uart_obj_t *self, uint32_t baudrate) { LL_USART_OVERSAMPLING_16, baudrate); } -mp_uint_t uart_rx_any(pyb_uart_obj_t *self) { +mp_uint_t uart_rx_any(machine_uart_obj_t *self) { int buffer_bytes = self->read_buf_head - self->read_buf_tail; if (buffer_bytes < 0) { return buffer_bytes + self->read_buf_len; @@ -970,7 +970,7 @@ mp_uint_t uart_rx_any(pyb_uart_obj_t *self) { // Waits at most timeout milliseconds for at least 1 char to become ready for // reading (from buf or for direct reading). // Returns true if something available, false if not. -bool uart_rx_wait(pyb_uart_obj_t *self, uint32_t timeout) { +bool uart_rx_wait(machine_uart_obj_t *self, uint32_t timeout) { uint32_t start = HAL_GetTick(); for (;;) { if (self->read_buf_tail != self->read_buf_head || UART_RXNE_IS_SET(self->uartx)) { @@ -984,7 +984,7 @@ bool uart_rx_wait(pyb_uart_obj_t *self, uint32_t timeout) { } // assumes there is a character available -int uart_rx_char(pyb_uart_obj_t *self) { +int uart_rx_char(machine_uart_obj_t *self) { if (self->read_buf_tail != self->read_buf_head) { // buffering via IRQ int data; @@ -1023,7 +1023,7 @@ int uart_rx_char(pyb_uart_obj_t *self) { // Waits at most timeout milliseconds for TX register to become empty. // Returns true if can write, false if can't. -bool uart_tx_wait(pyb_uart_obj_t *self, uint32_t timeout) { +bool uart_tx_wait(machine_uart_obj_t *self, uint32_t timeout) { uint32_t start = HAL_GetTick(); for (;;) { if (uart_tx_avail(self)) { @@ -1038,7 +1038,7 @@ bool uart_tx_wait(pyb_uart_obj_t *self, uint32_t timeout) { // Waits at most timeout milliseconds for UART flag to be set. // Returns true if flag is/was set, false on timeout. -STATIC bool uart_wait_flag_set(pyb_uart_obj_t *self, uint32_t flag, uint32_t timeout) { +STATIC bool uart_wait_flag_set(machine_uart_obj_t *self, uint32_t flag, uint32_t timeout) { // Note: we don't use WFI to idle in this loop because UART tx doesn't generate // an interrupt and the flag can be set quickly if the baudrate is large. uint32_t start = HAL_GetTick(); @@ -1062,7 +1062,7 @@ STATIC bool uart_wait_flag_set(pyb_uart_obj_t *self, uint32_t flag, uint32_t tim // num_chars - number of characters to send (9-bit chars count for 2 bytes from src) // *errcode - returns 0 for success, MP_Exxx on error // returns the number of characters sent (valid even if there was an error) -size_t uart_tx_data(pyb_uart_obj_t *self, const void *src_in, size_t num_chars, int *errcode) { +size_t uart_tx_data(machine_uart_obj_t *self, const void *src_in, size_t num_chars, int *errcode) { if (num_chars == 0) { *errcode = 0; return 0; @@ -1124,7 +1124,7 @@ size_t uart_tx_data(pyb_uart_obj_t *self, const void *src_in, size_t num_chars, return num_tx; } -void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len) { +void uart_tx_strn(machine_uart_obj_t *uart_obj, const char *str, uint len) { int errcode; uart_tx_data(uart_obj, str, len, &errcode); } @@ -1135,7 +1135,7 @@ void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len) { // - On STM32F4 the IRQ flags are cleared by reading SR then DR. void uart_irq_handler(mp_uint_t uart_id) { // get the uart object - pyb_uart_obj_t *self = MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1]; + machine_uart_obj_t *self = MP_STATE_PORT(machine_uart_obj_all)[uart_id - 1]; if (self == NULL) { // UART object has not been set, so we can't do anything, not @@ -1216,7 +1216,7 @@ void uart_irq_handler(mp_uint_t uart_id) { } STATIC mp_uint_t uart_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { - pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); uart_irq_config(self, false); self->mp_irq_trigger = new_trigger; uart_irq_config(self, true); @@ -1224,7 +1224,7 @@ STATIC mp_uint_t uart_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { } STATIC mp_uint_t uart_irq_info(mp_obj_t self_in, mp_uint_t info_type) { - pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); if (info_type == MP_IRQ_INFO_FLAGS) { return self->mp_irq_flags; } else if (info_type == MP_IRQ_INFO_TRIGGERS) { @@ -1238,4 +1238,4 @@ const mp_irq_methods_t uart_irq_methods = { .info = uart_irq_info, }; -MP_REGISTER_ROOT_POINTER(struct _pyb_uart_obj_t *pyb_uart_obj_all[MICROPY_HW_MAX_UART + MICROPY_HW_MAX_LPUART]); +MP_REGISTER_ROOT_POINTER(struct _machine_uart_obj_t *machine_uart_obj_all[MICROPY_HW_MAX_UART + MICROPY_HW_MAX_LPUART]); diff --git a/ports/stm32/uart.h b/ports/stm32/uart.h index 61d1ac4397..956cbb044f 100644 --- a/ports/stm32/uart.h +++ b/ports/stm32/uart.h @@ -57,7 +57,7 @@ typedef enum { // OR-ed IRQ flags which should not be touched by the user #define MP_UART_RESERVED_FLAGS UART_FLAG_RXNE -typedef struct _pyb_uart_obj_t { +typedef struct _machine_uart_obj_t { mp_obj_base_t base; USART_TypeDef *uartx; pyb_uart_t uart_id : 8; @@ -75,34 +75,33 @@ typedef struct _pyb_uart_obj_t { uint16_t mp_irq_trigger; // user IRQ trigger mask uint16_t mp_irq_flags; // user IRQ active IRQ flags mp_irq_obj_t *mp_irq_obj; // user IRQ object -} pyb_uart_obj_t; +} machine_uart_obj_t; -extern const mp_obj_type_t pyb_uart_type; extern const mp_irq_methods_t uart_irq_methods; void uart_init0(void); void uart_deinit_all(void); bool uart_exists(int uart_id); -bool uart_init(pyb_uart_obj_t *uart_obj, +bool uart_init(machine_uart_obj_t *uart_obj, uint32_t baudrate, uint32_t bits, uint32_t parity, uint32_t stop, uint32_t flow); -void uart_irq_config(pyb_uart_obj_t *self, bool enable); -void uart_set_rxbuf(pyb_uart_obj_t *self, size_t len, void *buf); -void uart_deinit(pyb_uart_obj_t *uart_obj); +void uart_irq_config(machine_uart_obj_t *self, bool enable); +void uart_set_rxbuf(machine_uart_obj_t *self, size_t len, void *buf); +void uart_deinit(machine_uart_obj_t *uart_obj); void uart_irq_handler(mp_uint_t uart_id); -void uart_attach_to_repl(pyb_uart_obj_t *self, bool attached); -uint32_t uart_get_source_freq(pyb_uart_obj_t *self); -uint32_t uart_get_baudrate(pyb_uart_obj_t *self); -void uart_set_baudrate(pyb_uart_obj_t *self, uint32_t baudrate); +void uart_attach_to_repl(machine_uart_obj_t *self, bool attached); +uint32_t uart_get_source_freq(machine_uart_obj_t *self); +uint32_t uart_get_baudrate(machine_uart_obj_t *self); +void uart_set_baudrate(machine_uart_obj_t *self, uint32_t baudrate); -mp_uint_t uart_rx_any(pyb_uart_obj_t *uart_obj); -bool uart_rx_wait(pyb_uart_obj_t *self, uint32_t timeout); -int uart_rx_char(pyb_uart_obj_t *uart_obj); -bool uart_tx_wait(pyb_uart_obj_t *self, uint32_t timeout); -size_t uart_tx_data(pyb_uart_obj_t *self, const void *src_in, size_t num_chars, int *errcode); -void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len); +mp_uint_t uart_rx_any(machine_uart_obj_t *uart_obj); +bool uart_rx_wait(machine_uart_obj_t *self, uint32_t timeout); +int uart_rx_char(machine_uart_obj_t *uart_obj); +bool uart_tx_wait(machine_uart_obj_t *self, uint32_t timeout); +size_t uart_tx_data(machine_uart_obj_t *self, const void *src_in, size_t num_chars, int *errcode); +void uart_tx_strn(machine_uart_obj_t *uart_obj, const char *str, uint len); -static inline bool uart_tx_avail(pyb_uart_obj_t *self) { +static inline bool uart_tx_avail(machine_uart_obj_t *self) { #if defined(STM32F4) || defined(STM32L1) return self->uartx->SR & USART_SR_TXE; #elif defined(STM32G0) || defined(STM32H7) || defined(STM32WL) diff --git a/ports/zephyr/CMakeLists.txt b/ports/zephyr/CMakeLists.txt index ddc613a2c0..8834aae96f 100644 --- a/ports/zephyr/CMakeLists.txt +++ b/ports/zephyr/CMakeLists.txt @@ -40,7 +40,6 @@ set(MICROPY_SOURCE_PORT machine_i2c.c machine_spi.c machine_pin.c - machine_uart.c modbluetooth_zephyr.c modmachine.c modsocket.c diff --git a/ports/zephyr/machine_uart.c b/ports/zephyr/machine_uart.c index b989c0f481..2c4b3a470b 100644 --- a/ports/zephyr/machine_uart.c +++ b/ports/zephyr/machine_uart.c @@ -25,18 +25,16 @@ * THE SOFTWARE. */ -#include -#include -#include +// This file is never compiled standalone, it's included directly from +// extmod/machine_uart.c via MICROPY_PY_MACHINE_UART_INCLUDEFILE. #include #include -#include "py/runtime.h" -#include "py/stream.h" #include "py/mperrno.h" -#include "py/objstr.h" -#include "modmachine.h" + +// The UART class doesn't have any constants for this port. +#define MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS typedef struct _machine_uart_obj_t { mp_obj_base_t base; @@ -50,7 +48,7 @@ STATIC const char *_stop_bits_name[] = {"0.5", "1", "1.5", "2"}; STATIC const char *_data_bits_name[] = {"5", "6", "7", "8", "9"}; STATIC const char *_flow_control_name[] = {"None", "RTS/CTS", "DTR/DSR"}; -STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +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); struct uart_config config; uart_config_get(self->dev, &config); @@ -60,7 +58,7 @@ STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_pri self->timeout, self->timeout_char); } -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) { +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_timeout, ARG_timeout_char }; static const mp_arg_t allowed_args[] = { { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, @@ -73,7 +71,7 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co self->timeout_char = args[ARG_timeout_char].u_int; } -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) { +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); machine_uart_obj_t *self = mp_obj_malloc(machine_uart_obj_t, &machine_uart_type); @@ -84,20 +82,26 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - machine_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 const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { - { 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(machine_uart_locals_dict, machine_uart_locals_dict_table); +STATIC void mp_machine_uart_deinit(machine_uart_obj_t *self) { + (void)self; +} -STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { +STATIC mp_int_t mp_machine_uart_any(machine_uart_obj_t *self) { + (void)self; + mp_raise_NotImplementedError(NULL); // TODO +} + +STATIC bool mp_machine_uart_txdone(machine_uart_obj_t *self) { + (void)self; + mp_raise_NotImplementedError(NULL); // TODO +} + +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); uint8_t *buffer = (uint8_t *)buf_in; uint8_t data; @@ -118,7 +122,7 @@ STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t siz return bytes_read; } -STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { +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); uint8_t *buffer = (uint8_t *)buf_in; @@ -129,7 +133,7 @@ STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uin return size; } -STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { +STATIC mp_uint_t mp_machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { mp_uint_t ret; if (request == MP_STREAM_POLL) { @@ -146,20 +150,3 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr } return ret; } - -STATIC const mp_stream_p_t uart_stream_p = { - .read = machine_uart_read, - .write = machine_uart_write, - .ioctl = machine_uart_ioctl, - .is_text = false, -}; - -MP_DEFINE_CONST_OBJ_TYPE( - machine_uart_type, - MP_QSTR_UART, - MP_TYPE_FLAG_ITER_IS_STREAM, - make_new, machine_uart_make_new, - print, machine_uart_print, - protocol, &uart_stream_p, - locals_dict, &machine_uart_locals_dict - ); diff --git a/ports/zephyr/modmachine.c b/ports/zephyr/modmachine.c index 6334168054..14ddf027ad 100644 --- a/ports/zephyr/modmachine.c +++ b/ports/zephyr/modmachine.c @@ -37,6 +37,7 @@ #include "extmod/machine_pulse.h" #include "extmod/machine_i2c.h" #include "extmod/machine_spi.h" +#include "extmod/modmachine.h" #include "modmachine.h" #if MICROPY_PY_MACHINE @@ -74,7 +75,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { #if MICROPY_PY_MACHINE_SPI { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, #endif + #if MICROPY_PY_MACHINE_UART { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, + #endif { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, diff --git a/ports/zephyr/modmachine.h b/ports/zephyr/modmachine.h index a605ada0de..520b363965 100644 --- a/ports/zephyr/modmachine.h +++ b/ports/zephyr/modmachine.h @@ -6,7 +6,6 @@ extern const mp_obj_type_t machine_pin_type; extern const mp_obj_type_t machine_i2c_type; extern const mp_obj_type_t machine_spi_type; -extern const mp_obj_type_t machine_uart_type; MP_DECLARE_CONST_FUN_OBJ_0(machine_info_obj); diff --git a/ports/zephyr/mpconfigport.h b/ports/zephyr/mpconfigport.h index 2f3e314db6..49d00f4ca6 100644 --- a/ports/zephyr/mpconfigport.h +++ b/ports/zephyr/mpconfigport.h @@ -69,6 +69,8 @@ #define MICROPY_PY_MACHINE_SPI_MSB (SPI_TRANSFER_MSB) #define MICROPY_PY_MACHINE_SPI_LSB (SPI_TRANSFER_LSB) #define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new +#define MICROPY_PY_MACHINE_UART (1) +#define MICROPY_PY_MACHINE_UART_INCLUDEFILE "ports/zephyr/machine_uart.c" #define MICROPY_PY_STRUCT (0) #ifdef CONFIG_NETWORKING // If we have networking, we likely want errno comfort