From 921dd94676815f794190484038ccacf001e68ea0 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Wed, 6 Jan 2021 20:19:29 +0200 Subject: [PATCH 0001/1041] nrf/main: Add startup and early-init board hook macros. Following stm32 for naming and location of the hooks. Also allow a board to provide custom .c files to implement code for these hooks. --- ports/nrf/Makefile | 1 + ports/nrf/main.c | 5 +++++ ports/nrf/mpconfigport.h | 8 ++++++++ 3 files changed, 14 insertions(+) diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index c32e09d2c9..55cce1906d 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -274,6 +274,7 @@ SRC_C += \ drivers/ticker.c \ drivers/bluetooth/ble_drv.c \ drivers/bluetooth/ble_uart.c \ + $(wildcard $(BOARD_DIR)/*.c) \ ifeq ($(MCU_SUB_VARIANT), nrf52840) diff --git a/ports/nrf/main.c b/ports/nrf/main.c index 2ec16194cb..091aa73f45 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -107,9 +107,14 @@ extern uint32_t _heap_start; extern uint32_t _heap_end; int main(int argc, char **argv) { + // Hook for a board to run code at start up, for example check if a + // bootloader should be entered instead of the main application. + MICROPY_BOARD_STARTUP(); + MICROPY_BOARD_EARLY_INIT(); soft_reset: + #if MICROPY_PY_TIME_TICKS rtc1_init_time_ticks(); #endif diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 29bdd3f80c..04bd5b4c26 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -366,3 +366,11 @@ extern const struct _mp_obj_module_t music_module; #ifndef MP_NEED_LOG2 #define MP_NEED_LOG2 (1) #endif + +#ifndef MICROPY_BOARD_STARTUP +#define MICROPY_BOARD_STARTUP() +#endif + +#ifndef MICROPY_BOARD_EARLY_INIT +#define MICROPY_BOARD_EARLY_INIT() +#endif From 0adf0dd3d7108404fa2a62f0db637baaddaf0da9 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Wed, 27 Apr 2022 10:58:09 +0200 Subject: [PATCH 0002/1041] stm32/modmachine: Allow boards to provide custom bootloader code. And expose the machine_bootloader() C function so it can be used elsewhere. --- ports/stm32/boardctrl.h | 4 ++++ ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h | 2 +- ports/stm32/modmachine.c | 5 ++++- ports/stm32/modmachine.h | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boardctrl.h b/ports/stm32/boardctrl.h index 0878a453b3..bc901f1c37 100644 --- a/ports/stm32/boardctrl.h +++ b/ports/stm32/boardctrl.h @@ -37,6 +37,10 @@ #define MICROPY_BOARD_STARTUP powerctrl_check_enter_bootloader #endif +#ifndef MICROPY_BOARD_ENTER_BOOTLOADER +#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) +#endif + #ifndef MICROPY_BOARD_EARLY_INIT #define MICROPY_BOARD_EARLY_INIT() #endif diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h b/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h index 30c909913c..31e19c9eb5 100644 --- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h +++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h @@ -38,7 +38,7 @@ void PORTENTA_board_startup(void); #define MICROPY_BOARD_EARLY_INIT PORTENTA_board_early_init void PORTENTA_board_early_init(void); -#define MICROPY_BOARD_ENTER_BOOTLOADER PORTENTA_board_enter_bootloader +#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) PORTENTA_board_enter_bootloader() void PORTENTA_board_enter_bootloader(void); void PORTENTA_board_low_power(int mode); diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index 5fca9b3e04..91061a3109 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -46,6 +46,7 @@ #include "gccollect.h" #include "irq.h" #include "powerctrl.h" +#include "boardctrl.h" #include "pybthread.h" #include "rng.h" #include "storage.h" @@ -270,7 +271,7 @@ STATIC mp_obj_t machine_soft_reset(void) { MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset); // Activate the bootloader without BOOT* pins. -STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) { +NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) { #if MICROPY_HW_ENABLE_USB pyb_usb_dev_deinit(); #endif @@ -280,6 +281,8 @@ STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) __disable_irq(); + MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args); + #if MICROPY_HW_USES_BOOTLOADER if (n_args == 0 || !mp_obj_is_true(args[0])) { // By default, with no args given, we enter the custom bootloader (mboot) diff --git a/ports/stm32/modmachine.h b/ports/stm32/modmachine.h index 0e6c000a80..9fa7851582 100644 --- a/ports/stm32/modmachine.h +++ b/ports/stm32/modmachine.h @@ -36,6 +36,7 @@ extern const mp_obj_type_t machine_i2s_type; void machine_init(void); void machine_deinit(void); void machine_i2s_init0(); +NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj); MP_DECLARE_CONST_FUN_OBJ_0(machine_unique_id_obj); From d8f56695322da9201d837c6348683fe3ee81b0af Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Wed, 27 Apr 2022 11:03:51 +0200 Subject: [PATCH 0003/1041] nrf/modmachine: Add machine.bootloader() and make it customisable. --- ports/nrf/modules/machine/modmachine.c | 8 ++++++++ ports/nrf/modules/machine/modmachine.h | 1 + ports/nrf/mpconfigport.h | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/ports/nrf/modules/machine/modmachine.c b/ports/nrf/modules/machine/modmachine.c index 1378ba8f4b..af659521e0 100644 --- a/ports/nrf/modules/machine/modmachine.c +++ b/ports/nrf/modules/machine/modmachine.c @@ -153,6 +153,13 @@ STATIC mp_obj_t machine_soft_reset(void) { } MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset); +NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) { + MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args); + for (;;) { + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj, 0, 1, machine_bootloader); + STATIC mp_obj_t machine_lightsleep(void) { __WFE(); return mp_const_none; @@ -196,6 +203,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_info_obj) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&machine_soft_reset_obj) }, + { MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&machine_lightsleep_obj) }, diff --git a/ports/nrf/modules/machine/modmachine.h b/ports/nrf/modules/machine/modmachine.h index 1ea6959eab..e5412673f8 100644 --- a/ports/nrf/modules/machine/modmachine.h +++ b/ports/nrf/modules/machine/modmachine.h @@ -38,5 +38,6 @@ MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj); MP_DECLARE_CONST_FUN_OBJ_0(machine_reset_obj); MP_DECLARE_CONST_FUN_OBJ_0(machine_lightsleep_obj); MP_DECLARE_CONST_FUN_OBJ_0(machine_deepsleep_obj); +NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args); #endif // __MICROPY_INCLUDED_NRF5_MODMACHINE_H__ diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 04bd5b4c26..102be3eaaf 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -371,6 +371,10 @@ extern const struct _mp_obj_module_t music_module; #define MICROPY_BOARD_STARTUP() #endif +#ifndef MICROPY_BOARD_ENTER_BOOTLOADER +#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) +#endif + #ifndef MICROPY_BOARD_EARLY_INIT #define MICROPY_BOARD_EARLY_INIT() #endif From f522aabab2c78697d5f178d7e60454781a7d1dbc Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Wed, 27 Apr 2022 11:11:24 +0200 Subject: [PATCH 0004/1041] rp2/modmachine: Allow boards to provide custom bootloader code. And expose the machine_bootloader() C function so it can be used elsewhere. --- ports/rp2/modmachine.c | 8 +++++--- ports/rp2/modmachine.h | 1 + ports/rp2/mpconfigport.h | 4 ++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ports/rp2/modmachine.c b/ports/rp2/modmachine.c index fbaf29ee16..b988afdf30 100644 --- a/ports/rp2/modmachine.c +++ b/ports/rp2/modmachine.c @@ -81,11 +81,13 @@ STATIC mp_obj_t machine_reset_cause(void) { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause); -STATIC mp_obj_t machine_bootloader(void) { +NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) { + MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args); reset_usb_boot(0, 0); - return mp_const_none; + for (;;) { + } } -MP_DEFINE_CONST_FUN_OBJ_0(machine_bootloader_obj, machine_bootloader); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj, 0, 1, machine_bootloader); STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { diff --git a/ports/rp2/modmachine.h b/ports/rp2/modmachine.h index 0635ff2487..503c1ca86c 100644 --- a/ports/rp2/modmachine.h +++ b/ports/rp2/modmachine.h @@ -18,5 +18,6 @@ void machine_pin_deinit(void); void machine_i2s_init0(void); struct _machine_spi_obj_t *spi_from_mp_obj(mp_obj_t o); +NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args); #endif // MICROPY_INCLUDED_RP2_MODMACHINE_H diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index d681a04af8..62388c6bce 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -130,6 +130,10 @@ #define mp_type_textio mp_type_vfs_lfs2_textio #endif +#ifndef MICROPY_BOARD_ENTER_BOOTLOADER +#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) +#endif + #if MICROPY_PY_NETWORK #define NETWORK_ROOT_POINTERS mp_obj_list_t mod_network_nic_list; #else From c5d26ee5e72331edf3c3ece342a577cbfe114310 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Tue, 7 Jun 2022 19:13:08 +0200 Subject: [PATCH 0005/1041] renesas-ra/modmachine: Allow boards to provide custom bootloader code. And expose the machine_bootloader() C function so it can be used elsewhere. --- ports/renesas-ra/boardctrl.h | 4 ++++ ports/renesas-ra/modmachine.c | 5 ++++- ports/renesas-ra/modmachine.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ports/renesas-ra/boardctrl.h b/ports/renesas-ra/boardctrl.h index cc7918c35f..1fc572a34e 100644 --- a/ports/renesas-ra/boardctrl.h +++ b/ports/renesas-ra/boardctrl.h @@ -37,6 +37,10 @@ #define MICROPY_BOARD_STARTUP powerctrl_check_enter_bootloader #endif +#ifndef MICROPY_BOARD_ENTER_BOOTLOADER +#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) +#endif + #ifndef MICROPY_BOARD_EARLY_INIT #define MICROPY_BOARD_EARLY_INIT() #endif diff --git a/ports/renesas-ra/modmachine.c b/ports/renesas-ra/modmachine.c index cd6e750340..e6f78747fd 100644 --- a/ports/renesas-ra/modmachine.c +++ b/ports/renesas-ra/modmachine.c @@ -47,6 +47,7 @@ #include "gccollect.h" #include "irq.h" #include "powerctrl.h" +#include "boardctrl.h" #include "pybthread.h" #include "storage.h" #include "pin.h" @@ -182,13 +183,15 @@ STATIC mp_obj_t machine_soft_reset(void) { MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset); // Activate the bootloader without BOOT* pins. -STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) { +NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) { #if MICROPY_HW_ENABLE_STORAGE storage_flush(); #endif __disable_irq(); + MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args); + #if MICROPY_HW_USES_BOOTLOADER // ToDo: need to review how to implement diff --git a/ports/renesas-ra/modmachine.h b/ports/renesas-ra/modmachine.h index 65077220df..de421c5db8 100644 --- a/ports/renesas-ra/modmachine.h +++ b/ports/renesas-ra/modmachine.h @@ -49,6 +49,7 @@ void machine_deinit(void); void machine_pin_init(void); void machine_pin_deinit(void); void machine_i2s_init0(void); +NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj); MP_DECLARE_CONST_FUN_OBJ_0(machine_unique_id_obj); From d8e7ecd23123247a6fc6f7d28833351e5b9d1fb6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 17 Jun 2022 13:57:47 +1000 Subject: [PATCH 0006/1041] stm32/modmachine: Factor out mboot enter code to a function. Signed-off-by: Damien George --- ports/stm32/boardctrl.c | 22 ++++++++++++++++++++++ ports/stm32/boardctrl.h | 5 +++++ ports/stm32/modmachine.c | 17 ----------------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/ports/stm32/boardctrl.c b/ports/stm32/boardctrl.c index 922f218e92..02a3759991 100644 --- a/ports/stm32/boardctrl.c +++ b/ports/stm32/boardctrl.c @@ -25,9 +25,11 @@ */ #include "py/runtime.h" +#include "py/objstr.h" #include "py/mphal.h" #include "shared/runtime/pyexec.h" #include "boardctrl.h" +#include "powerctrl.h" #include "led.h" #include "usrsw.h" @@ -43,6 +45,26 @@ STATIC void flash_error(int n) { led_state(PYB_LED_GREEN, 0); } +#if MICROPY_HW_USES_BOOTLOADER +void boardctrl_maybe_enter_mboot(size_t n_args, const void *args_in) { + const mp_obj_t *args = args_in; + + if (n_args == 0 || !mp_obj_is_true(args[0])) { + // By default, with no args given, we enter the custom bootloader (mboot) + powerctrl_enter_bootloader(0x70ad0000, MBOOT_VTOR); + } + + if (n_args == 1 && mp_obj_is_str_or_bytes(args[0])) { + // With a string/bytes given, pass its data to the custom bootloader + size_t len; + const char *data = mp_obj_str_get_data(args[0], &len); + void *mboot_region = (void *)*((volatile uint32_t *)MBOOT_VTOR); + memmove(mboot_region, data, len); + powerctrl_enter_bootloader(0x70ad0080, MBOOT_VTOR); + } +} +#endif + #if !MICROPY_HW_USES_BOOTLOADER STATIC uint update_reset_mode(uint reset_mode) { #if MICROPY_HW_HAS_SWITCH diff --git a/ports/stm32/boardctrl.h b/ports/stm32/boardctrl.h index bc901f1c37..afd4ab8510 100644 --- a/ports/stm32/boardctrl.h +++ b/ports/stm32/boardctrl.h @@ -38,8 +38,12 @@ #endif #ifndef MICROPY_BOARD_ENTER_BOOTLOADER +#if MICROPY_HW_USES_BOOTLOADER +#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) boardctrl_maybe_enter_mboot(nargs, args) +#else #define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) #endif +#endif #ifndef MICROPY_BOARD_EARLY_INIT #define MICROPY_BOARD_EARLY_INIT() @@ -106,6 +110,7 @@ typedef struct _boardctrl_state_t { bool log_soft_reset; } boardctrl_state_t; +void boardctrl_maybe_enter_mboot(size_t n_args, const void *args); void boardctrl_before_soft_reset_loop(boardctrl_state_t *state); void boardctrl_top_soft_reset_loop(boardctrl_state_t *state); int boardctrl_run_boot_py(boardctrl_state_t *state); diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index 91061a3109..34e78d2616 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -30,7 +30,6 @@ #include "modmachine.h" #include "py/gc.h" #include "py/runtime.h" -#include "py/objstr.h" #include "py/mperrno.h" #include "py/mphal.h" #include "extmod/machine_bitstream.h" @@ -283,22 +282,6 @@ NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) { MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args); - #if MICROPY_HW_USES_BOOTLOADER - if (n_args == 0 || !mp_obj_is_true(args[0])) { - // By default, with no args given, we enter the custom bootloader (mboot) - powerctrl_enter_bootloader(0x70ad0000, MBOOT_VTOR); - } - - if (n_args == 1 && mp_obj_is_str_or_bytes(args[0])) { - // With a string/bytes given, pass its data to the custom bootloader - size_t len; - const char *data = mp_obj_str_get_data(args[0], &len); - void *mboot_region = (void *)*((volatile uint32_t *)MBOOT_VTOR); - memmove(mboot_region, data, len); - powerctrl_enter_bootloader(0x70ad0080, MBOOT_VTOR); - } - #endif - #if defined(STM32F7) || defined(STM32H7) powerctrl_enter_bootloader(0, 0x1ff00000); #else From dea1ba33090589a195d9a6e83ff40bb7ec70d752 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 17 Jun 2022 14:57:58 +1000 Subject: [PATCH 0007/1041] tools/metrics.py: Add mimxrt and renesas-ra to list of available ports. Signed-off-by: Damien George --- tools/metrics.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/metrics.py b/tools/metrics.py index c857d0733e..c79b998e18 100755 --- a/tools/metrics.py +++ b/tools/metrics.py @@ -66,6 +66,8 @@ port_data = { "c": PortData("cc3200", "cc3200", "build/WIPY/release/application.axf", "BTARGET=application"), "8": PortData("esp8266", "esp8266", "build-GENERIC/firmware.elf"), "3": PortData("esp32", "esp32", "build-GENERIC/micropython.elf"), + "x": PortData("mimxrt", "mimxrt", "build-TEENSY40/firmware.elf"), + "e": PortData("renesas-ra", "renesas-ra", "build-RA6M2_EK/firmware.elf"), "r": PortData("nrf", "nrf", "build-pca10040/firmware.elf"), "p": PortData("rp2", "rp2", "build-PICO/firmware.elf"), "d": PortData("samd", "samd", "build-ADAFRUIT_ITSYBITSY_M4_EXPRESS/firmware.elf"), From 49c23ac08f21ab1b412083d64b4d0a704bf8973c Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 17 Jun 2022 14:58:42 +1000 Subject: [PATCH 0008/1041] renesas-ra/machine_i2c: Remove unnecessary start/stop dummy functions. The code in extmod/machine_i2c.c will check for NULL slots and raise an appropriate exception. Signed-off-by: Damien George --- ports/renesas-ra/machine_i2c.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/ports/renesas-ra/machine_i2c.c b/ports/renesas-ra/machine_i2c.c index 5f385f363e..bc1cea0cd9 100644 --- a/ports/renesas-ra/machine_i2c.c +++ b/ports/renesas-ra/machine_i2c.c @@ -150,22 +150,10 @@ STATIC int machine_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, si return ret; } -STATIC int machine_i2c_start(mp_obj_base_t *self) { - mp_raise_NotImplementedError(MP_ERROR_TEXT("start is not supported.")); - return 0; -} - -STATIC int machine_i2c_stop(mp_obj_base_t *self) { - mp_raise_NotImplementedError(MP_ERROR_TEXT("start is not supported.")); - return 0; -} - STATIC const mp_machine_i2c_p_t machine_i2c_p = { .init = machine_i2c_init, .transfer = mp_machine_i2c_transfer_adaptor, .transfer_single = machine_i2c_transfer_single, - .start = machine_i2c_start, - .stop = machine_i2c_stop, }; const mp_obj_type_t machine_i2c_type = { From 4fd54a475661953946e9e3c3f962b20619c82240 Mon Sep 17 00:00:00 2001 From: Maureen Helm Date: Mon, 23 May 2022 14:43:13 -0500 Subject: [PATCH 0009/1041] zephyr: Update include paths to use the zephyr namespace. Zephyr v3.1.0 moved all public headers to include/zephyr. Signed-off-by: Maureen Helm --- ports/zephyr/machine_i2c.c | 4 ++-- ports/zephyr/machine_pin.c | 4 ++-- ports/zephyr/machine_spi.c | 4 ++-- ports/zephyr/machine_uart.c | 4 ++-- ports/zephyr/main.c | 8 ++++---- ports/zephyr/modmachine.c | 2 +- ports/zephyr/modusocket.c | 10 +++++----- ports/zephyr/modutime.c | 2 +- ports/zephyr/modzephyr.c | 8 ++++---- ports/zephyr/modzsensor.c | 4 ++-- ports/zephyr/mpconfigport.h | 4 ++-- ports/zephyr/mphalport.h | 2 +- ports/zephyr/src/zephyr_getchar.c | 8 ++++---- ports/zephyr/src/zephyr_start.c | 4 ++-- ports/zephyr/uart_core.c | 4 ++-- ports/zephyr/zephyr_storage.c | 4 ++-- 16 files changed, 38 insertions(+), 38 deletions(-) diff --git a/ports/zephyr/machine_i2c.c b/ports/zephyr/machine_i2c.c index 86f7fd8e56..9bb63229dd 100644 --- a/ports/zephyr/machine_i2c.c +++ b/ports/zephyr/machine_i2c.c @@ -29,8 +29,8 @@ #include #include -#include -#include +#include +#include #include "py/runtime.h" #include "py/gc.h" diff --git a/ports/zephyr/machine_pin.c b/ports/zephyr/machine_pin.c index f9da2433c0..dee66a5c69 100644 --- a/ports/zephyr/machine_pin.c +++ b/ports/zephyr/machine_pin.c @@ -29,8 +29,8 @@ #include #include -#include -#include +#include +#include #include "py/runtime.h" #include "py/gc.h" diff --git a/ports/zephyr/machine_spi.c b/ports/zephyr/machine_spi.c index c54762aa05..2b0911c591 100644 --- a/ports/zephyr/machine_spi.c +++ b/ports/zephyr/machine_spi.c @@ -28,8 +28,8 @@ #include #include -#include -#include +#include +#include #include "py/runtime.h" #include "py/gc.h" diff --git a/ports/zephyr/machine_uart.c b/ports/zephyr/machine_uart.c index 95e33bb25b..47ca0945a5 100644 --- a/ports/zephyr/machine_uart.c +++ b/ports/zephyr/machine_uart.c @@ -29,8 +29,8 @@ #include #include -#include -#include +#include +#include #include "py/runtime.h" #include "py/stream.h" diff --git a/ports/zephyr/main.c b/ports/zephyr/main.c index 4f735b671f..c638f38920 100644 --- a/ports/zephyr/main.c +++ b/ports/zephyr/main.c @@ -29,16 +29,16 @@ #include #include -#include +#include #ifdef CONFIG_NETWORKING -#include +#include #endif #ifdef CONFIG_USB_DEVICE_STACK -#include +#include #endif -#include +#include #include "py/mperrno.h" #include "py/builtin.h" diff --git a/ports/zephyr/modmachine.c b/ports/zephyr/modmachine.c index f4b1c0849f..63bd336989 100644 --- a/ports/zephyr/modmachine.c +++ b/ports/zephyr/modmachine.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include "py/obj.h" #include "py/runtime.h" diff --git a/ports/zephyr/modusocket.c b/ports/zephyr/modusocket.c index 40d4aaac5b..2b6adf4773 100644 --- a/ports/zephyr/modusocket.c +++ b/ports/zephyr/modusocket.c @@ -31,14 +31,14 @@ #include "py/stream.h" #include -#include +#include // Zephyr's generated version header #include -#include -#include -#include +#include +#include +#include #ifdef CONFIG_NET_SOCKETS -#include +#include #endif #define DEBUG_PRINT 0 diff --git a/ports/zephyr/modutime.c b/ports/zephyr/modutime.c index 16ac9af6ee..c1c2be1c07 100644 --- a/ports/zephyr/modutime.c +++ b/ports/zephyr/modutime.c @@ -28,7 +28,7 @@ #include "py/mpconfig.h" #if MICROPY_PY_UTIME -#include +#include #include "py/runtime.h" #include "py/smallint.h" diff --git a/ports/zephyr/modzephyr.c b/ports/zephyr/modzephyr.c index 541dfe0b30..f87e2e33f3 100644 --- a/ports/zephyr/modzephyr.c +++ b/ports/zephyr/modzephyr.c @@ -29,10 +29,10 @@ #if MICROPY_PY_ZEPHYR #include -#include -#include -#include -#include +#include +#include +#include +#include #include "modzephyr.h" #include "py/runtime.h" diff --git a/ports/zephyr/modzsensor.c b/ports/zephyr/modzsensor.c index 6e8a5ca074..ba6717046f 100644 --- a/ports/zephyr/modzsensor.c +++ b/ports/zephyr/modzsensor.c @@ -28,8 +28,8 @@ #include "py/runtime.h" -#include -#include +#include +#include #if MICROPY_PY_ZSENSOR diff --git a/ports/zephyr/mpconfigport.h b/ports/zephyr/mpconfigport.h index 44231e1fc8..26610ccced 100644 --- a/ports/zephyr/mpconfigport.h +++ b/ports/zephyr/mpconfigport.h @@ -28,8 +28,8 @@ // Include Zephyr's autoconf.h, which should be made first by Zephyr makefiles #include "autoconf.h" // Included here to get basic Zephyr environment (macros, etc.) -#include -#include +#include +#include // Usually passed from Makefile #ifndef MICROPY_HEAP_SIZE diff --git a/ports/zephyr/mphalport.h b/ports/zephyr/mphalport.h index ffe68da246..6158593911 100644 --- a/ports/zephyr/mphalport.h +++ b/ports/zephyr/mphalport.h @@ -1,4 +1,4 @@ -#include +#include #include "shared/runtime/interrupt_char.h" void mp_hal_init(void); diff --git a/ports/zephyr/src/zephyr_getchar.c b/ports/zephyr/src/zephyr_getchar.c index 218fb18646..5bbf1a9f68 100644 --- a/ports/zephyr/src/zephyr_getchar.c +++ b/ports/zephyr/src/zephyr_getchar.c @@ -14,10 +14,10 @@ * limitations under the License. */ -#include -#include -#include -#include +#include +#include +#include +#include #include "zephyr_getchar.h" extern int mp_interrupt_char; diff --git a/ports/zephyr/src/zephyr_start.c b/ports/zephyr/src/zephyr_start.c index 7806eeeea3..b24e501c33 100644 --- a/ports/zephyr/src/zephyr_start.c +++ b/ports/zephyr/src/zephyr_start.c @@ -23,8 +23,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include -#include +#include +#include #include "zephyr_getchar.h" int real_main(void); diff --git a/ports/zephyr/uart_core.c b/ports/zephyr/uart_core.c index 1313a51ae2..1d37f22093 100644 --- a/ports/zephyr/uart_core.c +++ b/ports/zephyr/uart_core.c @@ -27,8 +27,8 @@ #include "py/mpconfig.h" #include "src/zephyr_getchar.h" // Zephyr headers -#include -#include +#include +#include /* * Core UART functions to implement for a port diff --git a/ports/zephyr/zephyr_storage.c b/ports/zephyr/zephyr_storage.c index 2761dcba80..1179c3fda8 100644 --- a/ports/zephyr/zephyr_storage.c +++ b/ports/zephyr/zephyr_storage.c @@ -32,11 +32,11 @@ #endif #ifdef CONFIG_DISK_ACCESS -#include +#include #endif #ifdef CONFIG_FLASH_MAP -#include +#include #endif #ifdef CONFIG_DISK_ACCESS From bada8b3cada2990d73e6402b029cfb699f3d9438 Mon Sep 17 00:00:00 2001 From: Maureen Helm Date: Thu, 16 Jun 2022 13:51:09 -0500 Subject: [PATCH 0010/1041] zephyr: Upgrade to Zephyr v3.1.0. Updates the Zephyr port build instructions and CI to use the latest Zephyr release tag. Tested on frdm_k64f. Signed-off-by: Maureen Helm --- docs/zephyr/tutorial/repl.rst | 4 ++-- ports/zephyr/README.md | 6 +++--- tools/ci.sh | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/zephyr/tutorial/repl.rst b/docs/zephyr/tutorial/repl.rst index 6e11c04cb3..8cd57c9435 100644 --- a/docs/zephyr/tutorial/repl.rst +++ b/docs/zephyr/tutorial/repl.rst @@ -31,8 +31,8 @@ With your serial program open (PuTTY, screen, picocom, etc) you may see a blank screen with a flashing cursor. Press Enter (or reset the board) and you should be presented with the following text:: - *** Booting Zephyr OS build zephyr-v3.0.0 *** - MicroPython v1.18-169-g665f0e2a6-dirty on 2022-03-02; zephyr-frdm_k64f with mk64f12 + *** Booting Zephyr OS build zephyr-v3.1.0 *** + MicroPython v1.19.1-9-g4fd54a475 on 2022-06-17; zephyr-frdm_k64f with mk64f12 Type "help()" for more information. >>> diff --git a/ports/zephyr/README.md b/ports/zephyr/README.md index 6b2b54fa29..f9bd45344b 100644 --- a/ports/zephyr/README.md +++ b/ports/zephyr/README.md @@ -4,7 +4,7 @@ MicroPython port to Zephyr RTOS This is a work-in-progress port of MicroPython to Zephyr RTOS (http://zephyrproject.org). -This port requires Zephyr version v3.0.0, and may also work on higher +This port requires Zephyr version v3.1.0, and may also work on higher versions. All boards supported by Zephyr (with standard level of features support, like UART console) should work with MicroPython (but not all were tested). @@ -39,13 +39,13 @@ setup is correct. If you already have Zephyr installed but are having issues building the MicroPython port then try installing the correct version of Zephyr via: - $ west init zephyrproject -m https://github.com/zephyrproject-rtos/zephyr --mr v3.0.0 + $ west init zephyrproject -m https://github.com/zephyrproject-rtos/zephyr --mr v3.1.0 Alternatively, you don't have to redo the Zephyr installation to just switch from master to a tagged release, you can instead do: $ cd zephyrproject/zephyr - $ git checkout v3.0.0 + $ git checkout v3.1.0 $ west update With Zephyr installed you may then need to configure your environment, diff --git a/tools/ci.sh b/tools/ci.sh index f92db66d70..5d9f8d4793 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -670,7 +670,7 @@ function ci_windows_build { ZEPHYR_DOCKER_VERSION=v0.21.0 ZEPHYR_SDK_VERSION=0.13.2 -ZEPHYR_VERSION=v3.0.0 +ZEPHYR_VERSION=v3.1.0 function ci_zephyr_setup { docker pull zephyrprojectrtos/ci:${ZEPHYR_DOCKER_VERSION} From 17f0297c1ac274b4e9f1040e8282a592715e8cb8 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 8 Jun 2022 11:32:17 -0500 Subject: [PATCH 0011/1041] tools/ci.sh: Drop ppa requirement for code formatting CI. The CI scripts were using a PPA to get a backported version of uncrustify on Ubuntu 20.04. However, this causes CI to intermittently fail due to connection issues to launchpad.net or the key server. Ubuntu 22.04 has a newer version of uncrustify removing the need for the PPA. Ubuntu 22.04 is now in beta on GitHub actions, so it can be used. Signed-off-by: David Lechner --- .github/workflows/code_formatting.yml | 2 +- tools/ci.sh | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/code_formatting.yml b/.github/workflows/code_formatting.yml index aab347d78e..5c0196d2ed 100644 --- a/.github/workflows/code_formatting.yml +++ b/.github/workflows/code_formatting.yml @@ -4,7 +4,7 @@ on: [push, pull_request] jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v2 - uses: actions/setup-python@v1 diff --git a/tools/ci.sh b/tools/ci.sh index 5d9f8d4793..6c3914b144 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -18,7 +18,6 @@ function ci_gcc_arm_setup { # code formatting function ci_code_formatting_setup { - sudo apt-add-repository --yes --update ppa:pybricks/ppa sudo apt-get install uncrustify pip3 install black uncrustify --version From fdbca3c1435910b23ad96d751a226f27e24b5aee Mon Sep 17 00:00:00 2001 From: chrismas9 Date: Mon, 13 Jun 2022 21:31:16 +1000 Subject: [PATCH 0012/1041] stm32/boards/stm32f091xc.ld: Allocate space for a small filesystem. Signed-off-by: Chris Mason --- ports/stm32/boards/stm32f091xc.ld | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/ports/stm32/boards/stm32f091xc.ld b/ports/stm32/boards/stm32f091xc.ld index 5bcc4c7275..a8f0d3316e 100644 --- a/ports/stm32/boards/stm32f091xc.ld +++ b/ports/stm32/boards/stm32f091xc.ld @@ -5,8 +5,8 @@ /* Specify the memory areas */ MEMORY { - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K - FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 256K + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 236K /* sectors 0-117 */ + FLASH_FS (r) : ORIGIN = 0x0803B000, LENGTH = 20K /* sectors 118-127 */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K } @@ -14,13 +14,21 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define the stack. The stack is full descending so begins just above last byte above last byte - of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; -_sstack = _estack - 6K; /* tunable */ +/* Define the stack. The stack is full descending so begins just above last byte of RAM, + or bottom of FS cache. Note that EABI requires the stack to be 8-byte aligned for a call. */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); + +_micropy_hw_internal_flash_storage_ram_cache_end = _ram_end; +_micropy_hw_internal_flash_storage_ram_cache_start = _micropy_hw_internal_flash_storage_ram_cache_end - 2K; /* fs cache = 2K */ + +_estack = _micropy_hw_internal_flash_storage_ram_cache_start - _estack_reserve; +_sstack = _estack - 6K; /* tunable */ + _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; + +_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); +_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); From 868f23b362171ee131bd6bfa784911fb8fc66202 Mon Sep 17 00:00:00 2001 From: chrismas9 Date: Mon, 13 Jun 2022 21:33:55 +1000 Subject: [PATCH 0013/1041] stm32/boards/NUCLEO_F091RC: Enable LFS1 filesystem. And disable some less common features to make space for it. Signed-off-by: Chris Mason --- ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h | 6 +++++- ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h index 38fcb2f28e..a68b939939 100644 --- a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h @@ -4,17 +4,21 @@ #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_OPT_COMPUTED_GOTO (0) +#define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_PY_IO_FILEIO (0) #define MICROPY_PY_USOCKET (0) #define MICROPY_PY_NETWORK (0) #define MICROPY_PY_STM (0) #define MICROPY_PY_PYB_LEGACY (0) +#define MICROPY_PY_UHEAPQ (0) +#define MICROPY_PY_UTIMEQ (0) +#define MICROPY_PY_FRAMEBUF (0) -#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_ADC (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_HAS_SWITCH (1) +#define MICROPY_HW_HAS_FLASH (1) // For system clock, enable one source: // #define MICROPY_HW_CLK_USE_HSI (1) // internal 8MHz -> PLL = 48MHz. diff --git a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk index 984fe2f900..4416188816 100644 --- a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk @@ -5,6 +5,7 @@ LD_FILES = boards/stm32f091xc.ld boards/common_basic.ld # MicroPython settings MICROPY_VFS_FAT = 0 +MICROPY_VFS_LFS1 ?= 1 # Don't include default frozen modules because MCU is tight on flash space FROZEN_MANIFEST ?= From c502cf73e0e0df685723a828ecac1562e3be1cf0 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Sat, 4 Jun 2022 12:07:30 +0200 Subject: [PATCH 0014/1041] extmod/network_cyw43: Rename WLAN keyword args to ssid/security/key. Rename WLAN keyword args to scan(), connect() and config() to be more consistent across ports and WLAN drivers. This change is backwards compatible and will support obsolete keyword args, except for positional "essid" which is now deprecated in favor of "ssid". The changed argument names are - "essid" changed to "ssid" - "auth" or "authmode" changed to "security" - "password" changed to "key" Addresses issue #8083. --- extmod/network_cyw43.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/extmod/network_cyw43.c b/extmod/network_cyw43.c index d2383c7187..ea2fbbd45e 100644 --- a/extmod/network_cyw43.c +++ b/extmod/network_cyw43.c @@ -163,9 +163,10 @@ STATIC int network_cyw43_scan_cb(void *env, const cyw43_ev_scan_result_t *res) { } STATIC mp_obj_t network_cyw43_scan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_passive, ARG_essid, ARG_bssid }; + enum { ARG_passive, ARG_ssid, ARG_essid, ARG_bssid }; static const mp_arg_t allowed_args[] = { { MP_QSTR_passive, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_ssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_essid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, }; @@ -174,13 +175,18 @@ STATIC mp_obj_t network_cyw43_scan(size_t n_args, const mp_obj_t *pos_args, mp_m mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + // Deprecated kwarg + if (args[ARG_essid].u_obj != mp_const_none) { + args[ARG_ssid].u_obj = args[ARG_essid].u_obj; + } + cyw43_wifi_scan_options_t opts; opts.scan_type = args[ARG_passive].u_bool ? 1 : 0; - if (args[ARG_essid].u_obj == mp_const_none) { + if (args[ARG_ssid].u_obj == mp_const_none) { opts.ssid_len = 0; } else { mp_buffer_info_t ssid; - mp_get_buffer_raise(args[ARG_essid].u_obj, &ssid, MP_BUFFER_READ); + mp_get_buffer_raise(args[ARG_ssid].u_obj, &ssid, MP_BUFFER_READ); opts.ssid_len = MIN(ssid.len, sizeof(opts.ssid)); memcpy(opts.ssid, ssid.buf, opts.ssid_len); } @@ -210,11 +216,12 @@ STATIC mp_obj_t network_cyw43_scan(size_t n_args, const mp_obj_t *pos_args, mp_m STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_cyw43_scan_obj, 1, network_cyw43_scan); STATIC mp_obj_t network_cyw43_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_essid, ARG_key, ARG_auth, ARG_bssid, ARG_channel }; + enum { ARG_ssid, ARG_key, ARG_auth, ARG_security, ARG_bssid, ARG_channel }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_essid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_key, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_auth, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, }; @@ -223,8 +230,13 @@ STATIC mp_obj_t network_cyw43_connect(size_t n_args, const mp_obj_t *pos_args, m mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + // Deprecated kwarg + if (args[ARG_auth].u_int != -1) { + args[ARG_security] = args[ARG_auth]; + } + mp_buffer_info_t ssid; - mp_get_buffer_raise(args[ARG_essid].u_obj, &ssid, MP_BUFFER_READ); + mp_get_buffer_raise(args[ARG_ssid].u_obj, &ssid, MP_BUFFER_READ); mp_buffer_info_t key; key.buf = NULL; if (args[ARG_key].u_obj != mp_const_none) { @@ -238,7 +250,8 @@ STATIC mp_obj_t network_cyw43_connect(size_t n_args, const mp_obj_t *pos_args, m mp_raise_ValueError(NULL); } } - int ret = cyw43_wifi_join(self->cyw, ssid.len, ssid.buf, key.len, key.buf, args[ARG_auth].u_int, bssid.buf, args[ARG_channel].u_int); + int ret = cyw43_wifi_join(self->cyw, ssid.len, ssid.buf, key.len, key.buf, + args[ARG_security].u_int, bssid.buf, args[ARG_channel].u_int); if (ret != 0) { mp_raise_OSError(-ret); } @@ -330,6 +343,7 @@ STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map cyw43_ioctl(self->cyw, CYW43_IOCTL_GET_CHANNEL, 4, buf, self->itf); return MP_OBJ_NEW_SMALL_INT(nw_get_le32(buf)); } + case MP_QSTR_ssid: case MP_QSTR_essid: { if (self->itf == CYW43_ITF_STA) { uint8_t buf[36]; @@ -376,6 +390,7 @@ STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map cyw43_wifi_ap_set_channel(self->cyw, mp_obj_get_int(e->value)); break; } + case MP_QSTR_ssid: case MP_QSTR_essid: { size_t len; const char *str = mp_obj_str_get_data(e->value, &len); @@ -397,6 +412,7 @@ STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map } break; } + case MP_QSTR_key: case MP_QSTR_password: { size_t len; const char *str = mp_obj_str_get_data(e->value, &len); From efa73ca8339a9ef67e8640c58c39ddac973c4744 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Fri, 17 Jun 2022 11:58:18 +0200 Subject: [PATCH 0015/1041] extmod/network_ninaw10: Rename WLAN connect argument from essid to ssid. Addresses issue #8083. --- extmod/network_ninaw10.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extmod/network_ninaw10.c b/extmod/network_ninaw10.c index 6921ed3f27..622e29ba68 100644 --- a/extmod/network_ninaw10.c +++ b/extmod/network_ninaw10.c @@ -196,9 +196,9 @@ STATIC mp_obj_t network_ninaw10_scan(mp_obj_t self_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_ninaw10_scan_obj, network_ninaw10_scan); STATIC mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_essid, ARG_key, ARG_security, ARG_channel }; + enum { ARG_ssid, ARG_key, ARG_security, ARG_channel }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_essid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_key, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = NINA_SEC_WPA_PSK} }, { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, @@ -210,7 +210,7 @@ STATIC mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get ssid - const char *ssid = mp_obj_str_get_str(args[ARG_essid].u_obj); + const char *ssid = mp_obj_str_get_str(args[ARG_ssid].u_obj); if (strlen(ssid) == 0) { mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("SSID can't be empty!")); @@ -304,7 +304,7 @@ STATIC mp_obj_t network_ninaw10_config(size_t n_args, const mp_obj_t *args, mp_m } switch (mp_obj_str_get_qstr(args[1])) { - case MP_QSTR_essid: { + case MP_QSTR_ssid: { nina_netinfo_t netinfo; nina_netinfo(&netinfo); return mp_obj_new_str(netinfo.ssid, strlen(netinfo.ssid)); From a7c7febe0ba939e1f3b06920d590d317c9100ae9 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Sat, 4 Jun 2022 12:22:55 +0200 Subject: [PATCH 0016/1041] esp32/network_wlan: Rename WLAN keyword args to ssid/security/key. The WLAN.config() method now supports "ssid", "security" and "key" as aliases to the existing "essid", "authmode" and "password", which are now deprecated. Addresses issue #8083. --- ports/esp32/network_wlan.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ports/esp32/network_wlan.c b/ports/esp32/network_wlan.c index 58c898d9a4..91099419ec 100644 --- a/ports/esp32/network_wlan.c +++ b/ports/esp32/network_wlan.c @@ -218,7 +218,7 @@ STATIC mp_obj_t network_wlan_active(size_t n_args, const mp_obj_t *args) { STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_wlan_active_obj, 1, 2, network_wlan_active); STATIC mp_obj_t network_wlan_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_ssid, ARG_password, ARG_bssid }; + enum { ARG_ssid, ARG_key, ARG_bssid }; static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} }, @@ -239,8 +239,8 @@ STATIC mp_obj_t network_wlan_connect(size_t n_args, const mp_obj_t *pos_args, mp p = mp_obj_str_get_data(args[ARG_ssid].u_obj, &len); memcpy(wifi_sta_config.sta.ssid, p, MIN(len, sizeof(wifi_sta_config.sta.ssid))); } - if (args[ARG_password].u_obj != mp_const_none) { - p = mp_obj_str_get_data(args[ARG_password].u_obj, &len); + if (args[ARG_key].u_obj != mp_const_none) { + p = mp_obj_str_get_data(args[ARG_key].u_obj, &len); memcpy(wifi_sta_config.sta.password, p, MIN(len, sizeof(wifi_sta_config.sta.password))); } if (args[ARG_bssid].u_obj != mp_const_none) { @@ -410,6 +410,7 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_ esp_exceptions(esp_wifi_set_mac(self->if_id, bufinfo.buf)); break; } + case MP_QSTR_ssid: case MP_QSTR_essid: { req_if = WIFI_IF_AP; size_t len; @@ -424,11 +425,13 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_ cfg.ap.ssid_hidden = mp_obj_is_true(kwargs->table[i].value); break; } + case MP_QSTR_security: case MP_QSTR_authmode: { req_if = WIFI_IF_AP; cfg.ap.authmode = mp_obj_get_int(kwargs->table[i].value); break; } + case MP_QSTR_key: case MP_QSTR_password: { req_if = WIFI_IF_AP; size_t len; @@ -503,6 +506,7 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_ goto unknown; } } + case MP_QSTR_ssid: case MP_QSTR_essid: switch (self->if_id) { case WIFI_IF_STA: @@ -519,6 +523,7 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_ req_if = WIFI_IF_AP; val = mp_obj_new_bool(cfg.ap.ssid_hidden); break; + case MP_QSTR_security: case MP_QSTR_authmode: req_if = WIFI_IF_AP; val = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode); From 82b8a2d193657f67cf7a301acc5804b946d662ad Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Sat, 4 Jun 2022 12:29:56 +0200 Subject: [PATCH 0017/1041] esp8266/modnetwork: Rename WLAN keyword args to ssid/security/key. The WLAN.config() method now supports "ssid", "security" and "key" as aliases to the existing "essid", "authmode" and "password", which are now deprecated. The help text and setup helper are also updated. Addresses issue #8083. --- ports/esp8266/help.c | 4 ++-- ports/esp8266/modnetwork.c | 11 ++++++++--- ports/esp8266/modules/inisetup.py | 4 ++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/ports/esp8266/help.c b/ports/esp8266/help.c index 4dd586c1a8..a755a10a76 100644 --- a/ports/esp8266/help.c +++ b/ports/esp8266/help.c @@ -37,11 +37,11 @@ const char esp_help_text[] = "import network\n" "sta_if = network.WLAN(network.STA_IF); sta_if.active(True)\n" "sta_if.scan() # Scan for available access points\n" - "sta_if.connect(\"\", \"\") # Connect to an AP\n" + "sta_if.connect(\"\", \"\") # Connect to an AP\n" "sta_if.isconnected() # Check for successful connection\n" "# Change name/password of ESP8266's AP:\n" "ap_if = network.WLAN(network.AP_IF)\n" - "ap_if.config(essid=\"\", authmode=network.AUTH_WPA_WPA2_PSK, password=\"\")\n" + "ap_if.config(ssid=\"\", security=network.AUTH_WPA_WPA2_PSK, key=\"\")\n" "\n" "Control commands:\n" " CTRL-A -- on a blank line, enter raw REPL mode\n" diff --git a/ports/esp8266/modnetwork.c b/ports/esp8266/modnetwork.c index dc1b435fb9..e32a0ff0c9 100644 --- a/ports/esp8266/modnetwork.c +++ b/ports/esp8266/modnetwork.c @@ -109,7 +109,7 @@ STATIC mp_obj_t esp_active(size_t n_args, const mp_obj_t *args) { STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_active_obj, 1, 2, esp_active); STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_ssid, ARG_password, ARG_bssid }; + enum { ARG_ssid, ARG_key, ARG_bssid }; static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} }, @@ -133,8 +133,8 @@ STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k memcpy(config.ssid, p, len); set_config = true; } - if (args[ARG_password].u_obj != mp_const_none) { - p = mp_obj_str_get_data(args[ARG_password].u_obj, &len); + if (args[ARG_key].u_obj != mp_const_none) { + p = mp_obj_str_get_data(args[ARG_key].u_obj, &len); len = MIN(len, sizeof(config.password)); memcpy(config.password, p, len); set_config = true; @@ -361,6 +361,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs wifi_set_macaddr(self->if_id, bufinfo.buf); break; } + case MP_QSTR_ssid: case MP_QSTR_essid: { req_if = SOFTAP_IF; size_t len; @@ -375,11 +376,13 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs cfg.ap.ssid_hidden = mp_obj_is_true(kwargs->table[i].value); break; } + case MP_QSTR_security: case MP_QSTR_authmode: { req_if = SOFTAP_IF; cfg.ap.authmode = mp_obj_get_int(kwargs->table[i].value); break; } + case MP_QSTR_key: case MP_QSTR_password: { req_if = SOFTAP_IF; size_t len; @@ -437,6 +440,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs wifi_get_macaddr(self->if_id, mac); return mp_obj_new_bytes(mac, sizeof(mac)); } + case MP_QSTR_ssid: case MP_QSTR_essid: if (self->if_id == STATION_IF) { val = mp_obj_new_str((char *)cfg.sta.ssid, strlen((char *)cfg.sta.ssid)); @@ -448,6 +452,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs req_if = SOFTAP_IF; val = mp_obj_new_bool(cfg.ap.ssid_hidden); break; + case MP_QSTR_security: case MP_QSTR_authmode: req_if = SOFTAP_IF; val = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode); diff --git a/ports/esp8266/modules/inisetup.py b/ports/esp8266/modules/inisetup.py index 9500b8048c..e5ce00138e 100644 --- a/ports/esp8266/modules/inisetup.py +++ b/ports/esp8266/modules/inisetup.py @@ -7,8 +7,8 @@ def wifi(): import ubinascii ap_if = network.WLAN(network.AP_IF) - essid = b"MicroPython-%s" % ubinascii.hexlify(ap_if.config("mac")[-3:]) - ap_if.config(essid=essid, authmode=network.AUTH_WPA_WPA2_PSK, password=b"micropythoN") + ssid = b"MicroPython-%s" % ubinascii.hexlify(ap_if.config("mac")[-3:]) + ap_if.config(ssid=ssid, security=network.AUTH_WPA_WPA2_PSK, key=b"micropythoN") def check_bootsec(): From 6e868d47dc5dd7a90444f1173118b7d57e1e4df7 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Sat, 4 Jun 2022 12:32:08 +0200 Subject: [PATCH 0018/1041] docs: Update to use new WLAN argument names for ssid/security/key. Addresses issue #8083. --- docs/esp32/quickref.rst | 6 +++--- docs/esp8266/quickref.rst | 6 +++--- docs/esp8266/tutorial/network_basics.rst | 4 ++-- docs/library/network.WLAN.rst | 24 ++++++++++++------------ docs/library/network.rst | 8 ++++---- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 894508f4c2..3cbb673c04 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -76,12 +76,12 @@ The :mod:`network` module:: wlan.active(True) # activate the interface wlan.scan() # scan for access points wlan.isconnected() # check if the station is connected to an AP - wlan.connect('essid', 'password') # connect to an AP + wlan.connect('ssid', 'key') # connect to an AP wlan.config('mac') # get the interface's MAC address wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses ap = network.WLAN(network.AP_IF) # create access-point interface - ap.config(essid='ESP-AP') # set the ESSID of the access point + ap.config(ssid='ESP-AP') # set the SSID of the access point ap.config(max_clients=10) # set how many clients can connect to the network ap.active(True) # activate the interface @@ -93,7 +93,7 @@ A useful function for connecting to your local WiFi network is:: wlan.active(True) if not wlan.isconnected(): print('connecting to network...') - wlan.connect('essid', 'password') + wlan.connect('ssid', 'key') while not wlan.isconnected(): pass print('network config:', wlan.ifconfig()) diff --git a/docs/esp8266/quickref.rst b/docs/esp8266/quickref.rst index 4e00a92260..ed21997370 100644 --- a/docs/esp8266/quickref.rst +++ b/docs/esp8266/quickref.rst @@ -57,13 +57,13 @@ The :mod:`network` module:: wlan.active(True) # activate the interface wlan.scan() # scan for access points wlan.isconnected() # check if the station is connected to an AP - wlan.connect('essid', 'password') # connect to an AP + wlan.connect('ssid', 'key') # connect to an AP wlan.config('mac') # get the interface's MAC address wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses ap = network.WLAN(network.AP_IF) # create access-point interface ap.active(True) # activate the interface - ap.config(essid='ESP-AP') # set the ESSID of the access point + ap.config(ssid='ESP-AP') # set the SSID of the access point A useful function for connecting to your local WiFi network is:: @@ -73,7 +73,7 @@ A useful function for connecting to your local WiFi network is:: wlan.active(True) if not wlan.isconnected(): print('connecting to network...') - wlan.connect('essid', 'password') + wlan.connect('ssid', 'key') while not wlan.isconnected(): pass print('network config:', wlan.ifconfig()) diff --git a/docs/esp8266/tutorial/network_basics.rst b/docs/esp8266/tutorial/network_basics.rst index 95d8cba4f9..dc3cd3dd5e 100644 --- a/docs/esp8266/tutorial/network_basics.rst +++ b/docs/esp8266/tutorial/network_basics.rst @@ -37,7 +37,7 @@ First activate the station interface:: Then connect to your WiFi network:: - >>> sta_if.connect('', '') + >>> sta_if.connect('', '') To check if the connection is established use:: @@ -61,7 +61,7 @@ connect to your WiFi network:: if not sta_if.isconnected(): print('connecting to network...') sta_if.active(True) - sta_if.connect('', '') + sta_if.connect('', '') while not sta_if.isconnected(): pass print('network config:', sta_if.ifconfig()) diff --git a/docs/library/network.WLAN.rst b/docs/library/network.WLAN.rst index 274681f178..bc416d1c2e 100644 --- a/docs/library/network.WLAN.rst +++ b/docs/library/network.WLAN.rst @@ -10,7 +10,7 @@ This class provides a driver for WiFi network processors. Example usage:: # enable station interface and connect to WiFi access point nic = network.WLAN(network.STA_IF) nic.active(True) - nic.connect('your-ssid', 'your-password') + nic.connect('your-ssid', 'your-key') # now use sockets as usual Constructors @@ -32,9 +32,9 @@ Methods argument is passed. Otherwise, query current state if no argument is provided. Most other methods require active interface. -.. method:: WLAN.connect(ssid=None, password=None, *, bssid=None) +.. method:: WLAN.connect(ssid=None, key=None, *, bssid=None) - Connect to the specified wireless network, using the specified password. + Connect to the specified wireless network, using the specified key. If *bssid* is given then the connection will be restricted to the access-point with that MAC address (the *ssid* must also be specified in this case). @@ -52,12 +52,12 @@ Methods Scanning is only possible on STA interface. Returns list of tuples with the information about WiFi access points: - (ssid, bssid, channel, RSSI, authmode, hidden) + (ssid, bssid, channel, RSSI, security, hidden) *bssid* is hardware address of an access point, in binary form, returned as bytes object. You can use `binascii.hexlify()` to convert it to ASCII form. - There are five values for authmode: + There are five values for security: * 0 -- open * 1 -- WEP @@ -112,10 +112,10 @@ Methods multiple parameters can be set at once. For querying, parameters name should be quoted as a string, and only one parameter can be queries at time:: - # Set WiFi access point name (formally known as ESSID) and WiFi channel - ap.config(essid='My AP', channel=11) + # Set WiFi access point name (formally known as SSID) and WiFi channel + ap.config(ssid='My AP', channel=11) # Query params one by one - print(ap.config('essid')) + print(ap.config('ssid')) print(ap.config('channel')) Following are commonly supported parameters (availability of a specific parameter @@ -125,11 +125,11 @@ Methods Parameter Description ============= =========== mac MAC address (bytes) - essid WiFi access point name (string) + ssid WiFi access point name (string) channel WiFi channel (integer) - hidden Whether ESSID is hidden (boolean) - authmode Authentication mode supported (enumeration, see module constants) - password Access password (string) + hidden Whether SSID is hidden (boolean) + security Security protocol supported (enumeration, see module constants) + key Access key (string) dhcp_hostname The DHCP hostname to use reconnects Number of reconnect attempts to make (integer, 0=none, -1=unlimited) txpower Maximum transmit power in dBm (integer or float) diff --git a/docs/library/network.rst b/docs/library/network.rst index 361e664b54..6742a2e073 100644 --- a/docs/library/network.rst +++ b/docs/library/network.rst @@ -89,7 +89,7 @@ parameter should be `id`. network media, there are different variants of predefined/ recommended tuple formats, among them: - * WiFi: (ssid, bssid, channel, RSSI, authmode, hidden). There + * WiFi: (ssid, bssid, channel, RSSI, security, hidden). There may be further fields, specific to a particular device. The function may accept additional keyword arguments to filter scan @@ -133,10 +133,10 @@ parameter should be `id`. querying, a parameter name should be quoted as a string, and only one parameter can be queried at a time:: - # Set WiFi access point name (formally known as ESSID) and WiFi channel - ap.config(essid='My AP', channel=11) + # Set WiFi access point name (formally known as SSID) and WiFi channel + ap.config(ssid='My AP', channel=11) # Query params one by one - print(ap.config('essid')) + print(ap.config('ssid')) print(ap.config('channel')) Specific network class implementations From 794773cdf26799e1ec2441d0a97c0b2a9da20f03 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 20 Jun 2022 13:05:53 +1000 Subject: [PATCH 0019/1041] github/ISSUE_TEMPLATE: Make minor improvements to placeholder text. Move the "delete placeholder" to the end, so it's not the first thing the reader does. And add extra text calling out "how do I?" questions. Signed-off-by: Jim Mussared --- .github/ISSUE_TEMPLATE/bug_report.md | 6 +++--- .github/ISSUE_TEMPLATE/documentation.md | 6 +++--- .github/ISSUE_TEMPLATE/feature_request.md | 6 +++--- .github/ISSUE_TEMPLATE/security.md | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index adddd33468..ac9d97041a 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -7,9 +7,7 @@ assignees: '' --- -* Remove all placeholder text below before submitting. - -* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, please see the MicroPython Forum -- https://forum.micropython.org/ +* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please see the MicroPython Forum (https://forum.micropython.org/) or raise a documentation request instead. * In your issue, please include a clear and concise description of what the bug is, the expected output, and how to replicate it. @@ -23,3 +21,5 @@ assignees: '' - firmware file name - git commit hash and port/board - version information shown in the REPL (hit Ctrl-B to see the startup message) + +* Remove all placeholder text above before submitting. diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md index 84ff2ba6f1..c86c1ec2b8 100644 --- a/.github/ISSUE_TEMPLATE/documentation.md +++ b/.github/ISSUE_TEMPLATE/documentation.md @@ -7,10 +7,10 @@ assignees: '' --- -* Remove all placeholder text below before submitting. - -* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, please see the MicroPython Forum -- https://forum.micropython.org/ +* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please see the MicroPython Forum -- https://forum.micropython.org/ * Describe what was missing from the documentation and/or what was incorrect/incomplete. * If possible, please link to the relevant page on https://docs.micropython.org/ + +* Remove all placeholder text above before submitting. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 1ac2055e01..3976699b28 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -7,9 +7,7 @@ assignees: '' --- -* Remove all placeholder text below before submitting. - -* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, please see the MicroPython Forum -- https://forum.micropython.org/ +* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please see the MicroPython Forum (https://forum.micropython.org/) or raise a documentation request instead. * Describe the feature you'd like to see added to MicroPython. In particular, what does this feature enable and why is it useful. MicroPython aims to strike a balance between functionality and code size, so please consider whether this feature can be optionally enabled and whether it can be provided in other ways (e.g. pure-Python library). @@ -22,3 +20,5 @@ assignees: '' * For drivers (e.g. for external hardware), please link to datasheets and/or existing drivers from other sources. * Who do you expect will implement the feature you are requesting? Would you be willing to sponsor this work? + +* Remove all placeholder text above before submitting. diff --git a/.github/ISSUE_TEMPLATE/security.md b/.github/ISSUE_TEMPLATE/security.md index fe60875f70..2bbfede6ce 100644 --- a/.github/ISSUE_TEMPLATE/security.md +++ b/.github/ISSUE_TEMPLATE/security.md @@ -7,10 +7,10 @@ assignees: '' --- -* Remove all placeholder text before submitting the new issue. - * If you need to raise this issue privately with the MicroPython team, please email contact@micropython.org instead. * Include a clear and concise description of what the security issue is. * What does this issue allow an attacker to do? + +* Remove all placeholder text above before submitting. From 0db046b67b8ed171f4898e851c3da39aab297ce9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 17 Jun 2022 23:01:55 +1000 Subject: [PATCH 0020/1041] py/vm: Change comparison for finally handler search from > to >=. The search in these cases should include all finally handlers that are after the current ip. If a handler starts at exactly ip then it is considered "after" the ip. This can happen when END_FINALLY is followed immediately by a finally handler (from a different finally). Consider the function: def f(): try: return 0 finally: print(1) The current bytecode emitter generates the following code: 00 SETUP_FINALLY 5 02 LOAD_CONST_SMALL_INT 0 03 RETURN_VALUE 04 LOAD_CONST_NONE **** 05 LOAD_GLOBAL print 07 LOAD_CONST_SMALL_INT 1 08 CALL_FUNCTION n=1 nkw=0 10 POP_TOP 11 END_FINALLY 12 LOAD_CONST_NONE 13 RETURN_VALUE The LOAD_CONST_NONE marked with **** is dead code because it follows a RETURN_VALUE, and nothing jumps to this LOAD_CONST_NONE. If the emitter could remove this this dead code it would produce: 00 SETUP_FINALLY 4 02 LOAD_CONST_SMALL_INT 0 03 RETURN_VALUE 04 LOAD_GLOBAL print 06 LOAD_CONST_SMALL_INT 1 07 CALL_FUNCTION n=1 nkw=0 09 POP_TOP 10 END_FINALLY 11 LOAD_CONST_NONE 12 RETURN_VALUE In this case the finally block (which starts at offset 4) immediately follows the RETURN_VALUE. When RETURN_VALUE executes ip will point to offset 4 in the bytecode (because the dispatch of the opcode does *ip++) and so the finally handler will only be found if a >= comparison is used. It's a similar story for break/continue: while True: try: break finally: print(1) Although technically in this case the > comparison still works because the extra byte from the UNWIND_JUMP (encoding the number of exception handlers to unwind) doesn't have a *ip++ (just a *ip) so ip remains pointing within the UNWIND_JUMP opcode, and not at the start of the following finally handler. Nevertheless, the change is made to use >= for consistency with the RETURN_VALUE change. Signed-off-by: Damien George --- py/vm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/py/vm.c b/py/vm.c index 02f8bc88c9..5a624e91f3 100644 --- a/py/vm.c +++ b/py/vm.c @@ -658,7 +658,7 @@ unwind_jump:; assert(exc_sp >= exc_stack); if (MP_TAGPTR_TAG1(exc_sp->val_sp)) { - if (exc_sp->handler > ip) { + if (exc_sp->handler >= ip) { // Found a finally handler that isn't active; run it. // Getting here the stack looks like: // (..., X, dest_ip) @@ -1079,7 +1079,7 @@ unwind_return: // Search for and execute finally handlers that aren't already active while (exc_sp >= exc_stack) { if (MP_TAGPTR_TAG1(exc_sp->val_sp)) { - if (exc_sp->handler > ip) { + if (exc_sp->handler >= ip) { // Found a finally handler that isn't active; run it. // Getting here the stack looks like: // (..., X, [iter0, iter1, ...,] ret_val) From e85a096302e8b186b82c74e7da4e1a29ef62d9c6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 17 Jun 2022 23:06:24 +1000 Subject: [PATCH 0021/1041] py/emit: Remove logic to detect last-emit-was-return-value. This optimisation to remove dead code is not as good as it could be. Signed-off-by: Damien George --- py/compile.c | 24 ++++++------------------ py/emit.h | 2 -- py/emitbc.c | 9 --------- py/emitnative.c | 15 +-------------- tests/cmdline/cmd_showbc.py.exp | 14 +++++++++----- 5 files changed, 16 insertions(+), 48 deletions(-) diff --git a/py/compile.c b/py/compile.c index 9cca5df401..ff3e5ffc6d 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1330,12 +1330,8 @@ STATIC void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { goto done; } - if ( - // optimisation: don't jump over non-existent elif/else blocks - !(MP_PARSE_NODE_IS_NULL(pns->nodes[2]) && MP_PARSE_NODE_IS_NULL(pns->nodes[3])) - // optimisation: don't jump if last instruction was return - && !EMIT(last_emit_was_return_value) - ) { + // optimisation: don't jump over non-existent elif/else blocks + if (!(MP_PARSE_NODE_IS_NULL(pns->nodes[2]) && MP_PARSE_NODE_IS_NULL(pns->nodes[3]))) { // jump over elif/else blocks EMIT_ARG(jump, l_end); } @@ -1362,10 +1358,7 @@ STATIC void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { goto done; } - // optimisation: don't jump if last instruction was return - if (!EMIT(last_emit_was_return_value)) { - EMIT_ARG(jump, l_end); - } + EMIT_ARG(jump, l_end); EMIT_ARG(label_assign, l_fail); } } @@ -1580,9 +1573,7 @@ STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { EMIT_ARG(for_iter, pop_label); c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable compile_node(comp, pns->nodes[2]); // body - if (!EMIT(last_emit_was_return_value)) { - EMIT_ARG(jump, continue_label); - } + EMIT_ARG(jump, continue_label); EMIT_ARG(label_assign, pop_label); EMIT(for_iter_end); @@ -3048,11 +3039,8 @@ STATIC bool compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { } compile_node(comp, pns->nodes[3]); // 3 is function body - // emit return if it wasn't the last opcode - if (!EMIT(last_emit_was_return_value)) { - EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); - EMIT(return_value); - } + EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); + EMIT(return_value); } else if (scope->kind == SCOPE_LAMBDA) { assert(MP_PARSE_NODE_IS_STRUCT(scope->pn)); mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)scope->pn; diff --git a/py/emit.h b/py/emit.h index 608734552a..4e8a55e77a 100644 --- a/py/emit.h +++ b/py/emit.h @@ -115,7 +115,6 @@ typedef struct _emit_method_table_t { void (*start_pass)(emit_t *emit, pass_kind_t pass, scope_t *scope); bool (*end_pass)(emit_t *emit); - bool (*last_emit_was_return_value)(emit_t *emit); void (*adjust_stack_size)(emit_t *emit, mp_int_t delta); void (*set_source_line)(emit_t *emit, mp_uint_t line); @@ -227,7 +226,6 @@ void emit_native_xtensawin_free(emit_t *emit); void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope); bool mp_emit_bc_end_pass(emit_t *emit); -bool mp_emit_bc_last_emit_was_return_value(emit_t *emit); void mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta); void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t line); diff --git a/py/emitbc.c b/py/emitbc.c index 2007975c5e..9c0d78d790 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -47,7 +47,6 @@ struct _emit_t { byte dummy_data[DUMMY_DATA_SIZE]; pass_kind_t pass : 8; - mp_uint_t last_emit_was_return_value : 8; int stack_size; @@ -272,7 +271,6 @@ STATIC void emit_write_bytecode_byte_label(emit_t *emit, int stack_adj, byte b1, void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { emit->pass = pass; emit->stack_size = 0; - emit->last_emit_was_return_value = false; emit->scope = scope; emit->last_source_line_offset = 0; emit->last_source_line = 1; @@ -397,10 +395,6 @@ bool mp_emit_bc_end_pass(emit_t *emit) { return true; } -bool mp_emit_bc_last_emit_was_return_value(emit_t *emit) { - return emit->last_emit_was_return_value; -} - void mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta) { if (emit->pass == MP_PASS_SCOPE) { return; @@ -410,7 +404,6 @@ void mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta) { if (emit->stack_size > emit->scope->stack_size) { emit->scope->stack_size = emit->stack_size; } - emit->last_emit_was_return_value = false; } void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t source_line) { @@ -773,7 +766,6 @@ void mp_emit_bc_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_ke void mp_emit_bc_return_value(emit_t *emit) { emit_write_bytecode_byte(emit, -1, MP_BC_RETURN_VALUE); - emit->last_emit_was_return_value = true; } void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) { @@ -806,7 +798,6 @@ const emit_method_table_t emit_bc_method_table = { mp_emit_bc_start_pass, mp_emit_bc_end_pass, - mp_emit_bc_last_emit_was_return_value, mp_emit_bc_adjust_stack_size, mp_emit_bc_set_source_line, diff --git a/py/emitnative.c b/py/emitnative.c index 6683ea4202..5b695a22a7 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -276,8 +276,6 @@ struct _emit_t { uint16_t n_info; uint16_t n_cell; - bool last_emit_was_return_value; - scope_t *scope; ASM_T *as; @@ -370,7 +368,6 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop emit->pass = pass; emit->do_viper_types = scope->emit_options == MP_EMIT_OPT_VIPER; emit->stack_size = 0; - emit->last_emit_was_return_value = false; emit->scope = scope; // allocate memory for keeping track of the types of locals @@ -733,10 +730,6 @@ STATIC bool emit_native_end_pass(emit_t *emit) { return true; } -STATIC bool emit_native_last_emit_was_return_value(emit_t *emit) { - return emit->last_emit_was_return_value; -} - STATIC void ensure_extra_stack(emit_t *emit, size_t delta) { if (emit->stack_size + delta > emit->stack_info_alloc) { size_t new_alloc = (emit->stack_size + delta + 8) & ~3; @@ -793,7 +786,7 @@ STATIC void emit_native_set_source_line(emit_t *emit, mp_uint_t source_line) { // this must be called at start of emit functions STATIC void emit_native_pre(emit_t *emit) { - emit->last_emit_was_return_value = false; + (void)emit; } // depth==0 is top, depth==1 is before top, etc @@ -917,7 +910,6 @@ STATIC void emit_fold_stack_top(emit_t *emit, int reg_dest) { // If stacked value is in a register and the register is not r1 or r2, then // *reg_dest is set to that register. Otherwise the value is put in *reg_dest. STATIC void emit_pre_pop_reg_flexible(emit_t *emit, vtype_kind_t *vtype, int *reg_dest, int not_r1, int not_r2) { - emit->last_emit_was_return_value = false; stack_info_t *si = peek_stack(emit, 0); if (si->kind == STACK_REG && si->data.u_reg != not_r1 && si->data.u_reg != not_r2) { *vtype = si->vtype; @@ -930,12 +922,10 @@ STATIC void emit_pre_pop_reg_flexible(emit_t *emit, vtype_kind_t *vtype, int *re } STATIC void emit_pre_pop_discard(emit_t *emit) { - emit->last_emit_was_return_value = false; adjust_stack(emit, -1); } STATIC void emit_pre_pop_reg(emit_t *emit, vtype_kind_t *vtype, int reg_dest) { - emit->last_emit_was_return_value = false; emit_access_stack(emit, 1, vtype, reg_dest); adjust_stack(emit, -1); } @@ -2771,7 +2761,6 @@ STATIC void emit_native_return_value(emit_t *emit) { // Do the unwinding jump to get to the return handler emit_native_unwind_jump(emit, emit->exit_label, emit->exc_stack_size); - emit->last_emit_was_return_value = true; return; } @@ -2809,7 +2798,6 @@ STATIC void emit_native_return_value(emit_t *emit) { ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_RET_VAL(emit), REG_PARENT_RET); } emit_native_unwind_jump(emit, emit->exit_label, emit->exc_stack_size); - emit->last_emit_was_return_value = true; } STATIC void emit_native_raise_varargs(emit_t *emit, mp_uint_t n_args) { @@ -2928,7 +2916,6 @@ const emit_method_table_t EXPORT_FUN(method_table) = { emit_native_start_pass, emit_native_end_pass, - emit_native_last_emit_was_return_value, emit_native_adjust_stack_size, emit_native_set_source_line, diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp index 45a1d169b6..2eeb8eadd0 100644 --- a/tests/cmdline/cmd_showbc.py.exp +++ b/tests/cmdline/cmd_showbc.py.exp @@ -48,12 +48,12 @@ arg names: 43 LOAD_CONST_NONE 44 RETURN_VALUE File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 45\[46\] bytes) -Raw bytecode (code_info_size=8\[46\], bytecode_size=370): +Raw bytecode (code_info_size=8\[46\], bytecode_size=372): a8 12 9\[bf\] 03 05 60 60 26 22 24 64 22 24 25 25 24 26 23 63 22 22 25 23 23 2f 6c 25 65 25 25 69 68 26 65 27 6a 62 20 23 62 2a 29 69 24 25 28 67 26 ######## -\.\+81 63 +\.\+51 63 arg names: (N_STATE 22) (N_EXC_STACK 2) @@ -403,6 +403,8 @@ arg names: 367 RETURN_VALUE 368 LOAD_CONST_SMALL_INT 1 369 RETURN_VALUE +370 LOAD_CONST_NONE +371 RETURN_VALUE File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 59 bytes) Raw bytecode (code_info_size=8, bytecode_size=51): a8 10 0a 05 80 82 34 38 81 57 c0 57 c1 57 c2 57 @@ -621,9 +623,9 @@ arg names: * 08 DELETE_DEREF 0 10 LOAD_CONST_NONE 11 RETURN_VALUE -File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 13 bytes) -Raw bytecode (code_info_size=8, bytecode_size=5): - 9a 01 0a 05 03 08 80 8b b1 25 00 f2 63 +File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 15 bytes) +Raw bytecode (code_info_size=8, bytecode_size=7): + 9a 01 0a 05 03 08 80 8b b1 25 00 f2 63 51 63 arg names: * b (N_STATE 4) (N_EXC_STACK 0) @@ -633,6 +635,8 @@ arg names: * b 01 LOAD_DEREF 0 03 BINARY_OP 27 __add__ 04 RETURN_VALUE +05 LOAD_CONST_NONE +06 RETURN_VALUE mem: total=\\d\+, current=\\d\+, peak=\\d\+ stack: \\d\+ out of \\d\+ GC: total: \\d\+, used: \\d\+, free: \\d\+ From a506335524a69fbccad245d486f5f641a0cf8919 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 17 Jun 2022 23:14:32 +1000 Subject: [PATCH 0022/1041] py/emit: Suppress unreachable bytecode/native code that follows jump. This new logic tracks when an unconditional jump/raise occurs in the emitted code stream (bytecode or native machine code) and suppresses all subsequent code, until a label is assigned. This eliminates a lot of cases of dead code, with relatively simple logic. This commit combined with the previous one (that removed the existing dead-code finding logic) has the following code size change: bare-arm: -16 -0.028% minimal x86: -60 -0.036% unix x64: -368 -0.070% unix nanbox: -80 -0.017% stm32: -204 -0.052% PYBV10 cc3200: +0 +0.000% esp8266: -232 -0.033% GENERIC esp32: -224 -0.015% GENERIC[incl -40(data)] mimxrt: -192 -0.054% TEENSY40 renesas-ra: -200 -0.032% RA6M2_EK nrf: +28 +0.015% pca10040 rp2: -256 -0.050% PICO samd: -12 -0.009% ADAFRUIT_ITSYBITSY_M4_EXPRESS Signed-off-by: Damien George --- py/asmbase.c | 10 +++ py/asmbase.h | 11 ++- py/emitbc.c | 22 +++++ py/emitnative.c | 2 + tests/cmdline/cmd_showbc.py | 8 +- tests/cmdline/cmd_showbc.py.exp | 126 ++++++++++++++-------------- tests/cmdline/cmd_showbc_opt.py | 33 ++++++++ tests/cmdline/cmd_showbc_opt.py.exp | 122 +++++++++++++++++++++++++++ 8 files changed, 268 insertions(+), 66 deletions(-) create mode 100644 tests/cmdline/cmd_showbc_opt.py create mode 100644 tests/cmdline/cmd_showbc_opt.py.exp diff --git a/py/asmbase.c b/py/asmbase.c index 4a3fd089cb..da4273506a 100644 --- a/py/asmbase.c +++ b/py/asmbase.c @@ -55,15 +55,20 @@ void mp_asm_base_start_pass(mp_asm_base_t *as, int pass) { assert(as->code_base != NULL); } as->pass = pass; + as->suppress = false; as->code_offset = 0; } // all functions must go through this one to emit bytes // if as->pass < MP_ASM_PASS_EMIT, then this function just counts the number // of bytes needed and returns NULL, and callers should not store any data +// It also returns NULL if generated code should be suppressed at this point. uint8_t *mp_asm_base_get_cur_to_write_bytes(void *as_in, size_t num_bytes_to_write) { mp_asm_base_t *as = as_in; uint8_t *c = NULL; + if (as->suppress) { + return c; + } if (as->pass == MP_ASM_PASS_EMIT) { assert(as->code_offset + num_bytes_to_write <= as->code_size); c = as->code_base + as->code_offset; @@ -74,6 +79,11 @@ uint8_t *mp_asm_base_get_cur_to_write_bytes(void *as_in, size_t num_bytes_to_wri void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label) { assert(label < as->max_num_labels); + + // Assiging a label ends any dead-code region, and all following machine + // code should be emitted (until another mp_asm_base_suppress_code() call). + as->suppress = false; + if (as->pass < MP_ASM_PASS_EMIT) { // assign label offset assert(as->label_offsets[label] == (size_t)-1); diff --git a/py/asmbase.h b/py/asmbase.h index 960be7685f..352d2f54cc 100644 --- a/py/asmbase.h +++ b/py/asmbase.h @@ -33,7 +33,12 @@ #define MP_ASM_PASS_EMIT (2) typedef struct _mp_asm_base_t { - int pass; + uint8_t pass; + + // Set to true using mp_asm_base_suppress_code() if the code generator + // should suppress emitted code due to it being dead code. + bool suppress; + size_t code_offset; size_t code_size; uint8_t *code_base; @@ -50,6 +55,10 @@ void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label); void mp_asm_base_align(mp_asm_base_t *as, unsigned int align); void mp_asm_base_data(mp_asm_base_t *as, unsigned int bytesize, uintptr_t val); +static inline void mp_asm_base_suppress_code(mp_asm_base_t *as) { + as->suppress = true; +} + static inline size_t mp_asm_base_get_code_pos(mp_asm_base_t *as) { return as->code_offset; } diff --git a/py/emitbc.c b/py/emitbc.c index 9c0d78d790..70a4d8b12e 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -48,6 +48,11 @@ struct _emit_t { pass_kind_t pass : 8; + // Set to true if the code generator should suppress emitted code due to it + // being dead code. This can happen when opcodes immediately follow an + // unconditional flow control (eg jump or raise). + bool suppress; + int stack_size; mp_emit_common_t *emit_common; @@ -140,6 +145,9 @@ STATIC void emit_write_code_info_bytes_lines(emit_t *emit, mp_uint_t bytes_to_sk // all functions must go through this one to emit byte code STATIC uint8_t *emit_get_cur_to_write_bytecode(void *emit_in, size_t num_bytes_to_write) { emit_t *emit = emit_in; + if (emit->suppress) { + return emit->dummy_data; + } if (emit->pass < MP_PASS_EMIT) { emit->bytecode_offset += num_bytes_to_write; return emit->dummy_data; @@ -222,6 +230,10 @@ STATIC void emit_write_bytecode_byte_child(emit_t *emit, int stack_adj, byte b, STATIC void emit_write_bytecode_byte_label(emit_t *emit, int stack_adj, byte b1, mp_uint_t label) { mp_emit_bc_adjust_stack_size(emit, stack_adj); + if (emit->suppress) { + return; + } + // Determine if the jump offset is signed or unsigned, based on the opcode. const bool is_signed = b1 <= MP_BC_POP_JUMP_IF_FALSE; @@ -271,6 +283,7 @@ STATIC void emit_write_bytecode_byte_label(emit_t *emit, int stack_adj, byte b1, void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { emit->pass = pass; emit->stack_size = 0; + emit->suppress = false; emit->scope = scope; emit->last_source_line_offset = 0; emit->last_source_line = 1; @@ -426,6 +439,10 @@ void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t source_line) { } void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) { + // Assiging a label ends any dead-code region, and all following opcodes + // should be emitted (until another unconditional flow control). + emit->suppress = false; + mp_emit_bc_adjust_stack_size(emit, 0); if (emit->pass == MP_PASS_SCOPE) { return; @@ -589,6 +606,7 @@ void mp_emit_bc_rot_three(emit_t *emit) { void mp_emit_bc_jump(emit_t *emit, mp_uint_t label) { emit_write_bytecode_byte_label(emit, 0, MP_BC_JUMP, label); + emit->suppress = true; } void mp_emit_bc_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label) { @@ -622,6 +640,7 @@ void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_dept emit_write_bytecode_byte_label(emit, 0, MP_BC_UNWIND_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR); emit_write_bytecode_raw_byte(emit, ((label & MP_EMIT_BREAK_FROM_FOR) ? 0x80 : 0) | except_depth); } + emit->suppress = true; } void mp_emit_bc_setup_block(emit_t *emit, mp_uint_t label, int kind) { @@ -663,6 +682,7 @@ void mp_emit_bc_for_iter_end(emit_t *emit) { void mp_emit_bc_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) { (void)within_exc_handler; emit_write_bytecode_byte_label(emit, 0, MP_BC_POP_EXCEPT_JUMP, label); + emit->suppress = true; } void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op) { @@ -766,6 +786,7 @@ void mp_emit_bc_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_ke void mp_emit_bc_return_value(emit_t *emit) { emit_write_bytecode_byte(emit, -1, MP_BC_RETURN_VALUE); + emit->suppress = true; } void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) { @@ -773,6 +794,7 @@ void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) { MP_STATIC_ASSERT(MP_BC_RAISE_LAST + 2 == MP_BC_RAISE_FROM); assert(n_args <= 2); emit_write_bytecode_byte(emit, -n_args, MP_BC_RAISE_LAST + n_args); + emit->suppress = true; } void mp_emit_bc_yield(emit_t *emit, int kind) { diff --git a/py/emitnative.c b/py/emitnative.c index 5b695a22a7..957e713fdd 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -1966,6 +1966,7 @@ STATIC void emit_native_jump(emit_t *emit, mp_uint_t label) { need_stack_settled(emit); ASM_JUMP(emit->as, label); emit_post(emit); + mp_asm_base_suppress_code(&emit->as->base); } STATIC void emit_native_jump_helper(emit_t *emit, bool cond, mp_uint_t label, bool pop) { @@ -2810,6 +2811,7 @@ STATIC void emit_native_raise_varargs(emit_t *emit, mp_uint_t n_args) { } // TODO probably make this 1 call to the runtime (which could even call convert, native_raise(obj, type)) emit_call(emit, MP_F_NATIVE_RAISE); + mp_asm_base_suppress_code(&emit->as->base); } STATIC void emit_native_yield(emit_t *emit, int kind) { diff --git a/tests/cmdline/cmd_showbc.py b/tests/cmdline/cmd_showbc.py index e5874f990a..4a2e6500aa 100644 --- a/tests/cmdline/cmd_showbc.py +++ b/tests/cmdline/cmd_showbc.py @@ -119,12 +119,12 @@ def f(): #from sys import * # tested at module scope # raise - raise - raise 1 + if a: raise + if a: raise 1 # return - return - return 1 + if a: return + if a: return 1 # function with lots of locals def f(): diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp index 2eeb8eadd0..db06de9237 100644 --- a/tests/cmdline/cmd_showbc.py.exp +++ b/tests/cmdline/cmd_showbc.py.exp @@ -47,8 +47,8 @@ arg names: 42 IMPORT_STAR 43 LOAD_CONST_NONE 44 RETURN_VALUE -File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 45\[46\] bytes) -Raw bytecode (code_info_size=8\[46\], bytecode_size=372): +File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 46\[68\] bytes) +Raw bytecode (code_info_size=8\[46\], bytecode_size=382): a8 12 9\[bf\] 03 05 60 60 26 22 24 64 22 24 25 25 24 26 23 63 22 22 25 23 23 2f 6c 25 65 25 25 69 68 26 65 27 6a 62 20 23 62 2a 29 69 24 25 28 67 26 @@ -126,19 +126,18 @@ arg names: bc=313 line=100 bc=315 line=101 ######## - bc=321 line=103 - bc=327 line=106 - bc=331 line=107 - bc=337 line=110 - bc=340 line=111 - bc=346 line=114 - bc=346 line=117 - bc=351 line=118 - bc=363 line=121 - bc=363 line=122 - bc=364 line=123 - bc=366 line=126 - bc=368 line=127 + bc=325 line=106 + bc=329 line=107 + bc=335 line=110 + bc=338 line=111 + bc=344 line=114 + bc=344 line=117 + bc=349 line=118 + bc=361 line=121 + bc=361 line=122 + bc=365 line=123 + bc=370 line=126 + bc=375 line=127 00 LOAD_CONST_NONE 01 LOAD_CONST_FALSE 02 BINARY_OP 27 __add__ @@ -363,48 +362,55 @@ arg names: 308 LOAD_FAST 1 309 POP_TOP 310 END_FINALLY -311 JUMP 324 -313 SETUP_EXCEPT 320 -315 UNWIND_JUMP 327 1 -318 POP_EXCEPT_JUMP 324 -320 POP_TOP -321 POP_EXCEPT_JUMP 324 -323 END_FINALLY -324 LOAD_FAST 0 -325 POP_JUMP_IF_TRUE 313 -327 LOAD_FAST 0 -328 SETUP_WITH 335 -330 POP_TOP -331 LOAD_DEREF 14 -333 POP_TOP -334 LOAD_CONST_NONE -335 WITH_CLEANUP -336 END_FINALLY -337 LOAD_CONST_SMALL_INT 1 -338 STORE_DEREF 16 -340 LOAD_FAST_N 16 -342 MAKE_CLOSURE \.\+ 1 -345 STORE_FAST 13 -346 LOAD_CONST_SMALL_INT 0 -347 LOAD_CONST_NONE -348 IMPORT_NAME 'a' -350 STORE_FAST 0 -351 LOAD_CONST_SMALL_INT 0 -352 LOAD_CONST_STRING 'b' -354 BUILD_TUPLE 1 -356 IMPORT_NAME 'a' -358 IMPORT_FROM 'b' -360 STORE_DEREF 14 -362 POP_TOP -363 RAISE_LAST -364 LOAD_CONST_SMALL_INT 1 -365 RAISE_OBJ -366 LOAD_CONST_NONE -367 RETURN_VALUE +311 JUMP 322 +313 SETUP_EXCEPT 318 +315 UNWIND_JUMP 325 1 +318 POP_TOP +319 POP_EXCEPT_JUMP 322 +321 END_FINALLY +322 LOAD_FAST 0 +323 POP_JUMP_IF_TRUE 313 +325 LOAD_FAST 0 +326 SETUP_WITH 333 +328 POP_TOP +329 LOAD_DEREF 14 +331 POP_TOP +332 LOAD_CONST_NONE +333 WITH_CLEANUP +334 END_FINALLY +335 LOAD_CONST_SMALL_INT 1 +336 STORE_DEREF 16 +338 LOAD_FAST_N 16 +340 MAKE_CLOSURE \.\+ 1 +343 STORE_FAST 13 +344 LOAD_CONST_SMALL_INT 0 +345 LOAD_CONST_NONE +346 IMPORT_NAME 'a' +348 STORE_FAST 0 +349 LOAD_CONST_SMALL_INT 0 +350 LOAD_CONST_STRING 'b' +352 BUILD_TUPLE 1 +354 IMPORT_NAME 'a' +356 IMPORT_FROM 'b' +358 STORE_DEREF 14 +360 POP_TOP +361 LOAD_FAST 0 +362 POP_JUMP_IF_FALSE 365 +364 RAISE_LAST +365 LOAD_FAST 0 +366 POP_JUMP_IF_FALSE 370 368 LOAD_CONST_SMALL_INT 1 -369 RETURN_VALUE -370 LOAD_CONST_NONE -371 RETURN_VALUE +369 RAISE_OBJ +370 LOAD_FAST 0 +371 POP_JUMP_IF_FALSE 375 +373 LOAD_CONST_NONE +374 RETURN_VALUE +375 LOAD_FAST 0 +376 POP_JUMP_IF_FALSE 380 +378 LOAD_CONST_SMALL_INT 1 +379 RETURN_VALUE +380 LOAD_CONST_NONE +381 RETURN_VALUE File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 59 bytes) Raw bytecode (code_info_size=8, bytecode_size=51): a8 10 0a 05 80 82 34 38 81 57 c0 57 c1 57 c2 57 @@ -623,9 +629,9 @@ arg names: * 08 DELETE_DEREF 0 10 LOAD_CONST_NONE 11 RETURN_VALUE -File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 15 bytes) -Raw bytecode (code_info_size=8, bytecode_size=7): - 9a 01 0a 05 03 08 80 8b b1 25 00 f2 63 51 63 +File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 13 bytes) +Raw bytecode (code_info_size=8, bytecode_size=5): + 9a 01 0a 05 03 08 80 8b b1 25 00 f2 63 arg names: * b (N_STATE 4) (N_EXC_STACK 0) @@ -635,8 +641,6 @@ arg names: * b 01 LOAD_DEREF 0 03 BINARY_OP 27 __add__ 04 RETURN_VALUE -05 LOAD_CONST_NONE -06 RETURN_VALUE mem: total=\\d\+, current=\\d\+, peak=\\d\+ stack: \\d\+ out of \\d\+ GC: total: \\d\+, used: \\d\+, free: \\d\+ diff --git a/tests/cmdline/cmd_showbc_opt.py b/tests/cmdline/cmd_showbc_opt.py new file mode 100644 index 0000000000..02785860d9 --- /dev/null +++ b/tests/cmdline/cmd_showbc_opt.py @@ -0,0 +1,33 @@ +# cmdline: -v -v +# test printing of bytecode when it's optimised away + + +def f0(): + return 0 + print(1) + + +def f1(x): + if x: + return + print(1) + print(2) + + +def f2(x): + raise Exception + print(1) + + +def f3(x): + while x: + break + print(1) + print(2) + + +def f4(x): + while x: + continue + print(1) + print(2) diff --git a/tests/cmdline/cmd_showbc_opt.py.exp b/tests/cmdline/cmd_showbc_opt.py.exp new file mode 100644 index 0000000000..9e4e4fae10 --- /dev/null +++ b/tests/cmdline/cmd_showbc_opt.py.exp @@ -0,0 +1,122 @@ +File cmdline/cmd_showbc_opt.py, code block '' (descriptor: \.\+, bytecode @\.\+ 35 bytes) +Raw bytecode (code_info_size=13, bytecode_size=22): + 00 16 01 60 20 64 40 84 07 64 40 84 07 32 00 16 + 02 32 01 16 03 32 02 16 04 32 03 16 05 32 04 16 + 06 51 63 +arg names: +(N_STATE 1) +(N_EXC_STACK 0) + bc=0 line=1 + bc=0 line=4 + bc=0 line=5 + bc=4 line=8 + bc=4 line=10 + bc=8 line=17 + bc=12 line=20 + bc=12 line=22 + bc=16 line=29 +00 MAKE_FUNCTION \.\+ +02 STORE_NAME f0 +04 MAKE_FUNCTION \.\+ +06 STORE_NAME f1 +08 MAKE_FUNCTION \.\+ +10 STORE_NAME f2 +12 MAKE_FUNCTION \.\+ +14 STORE_NAME f3 +16 MAKE_FUNCTION \.\+ +18 STORE_NAME f4 +20 LOAD_CONST_NONE +21 RETURN_VALUE +File cmdline/cmd_showbc_opt.py, code block 'f0' (descriptor: \.\+, bytecode @\.\+ 8 bytes) +Raw bytecode (code_info_size=6, bytecode_size=2): + 08 08 02 60 40 22 80 63 +arg names: +(N_STATE 2) +(N_EXC_STACK 0) + bc=0 line=1 + bc=0 line=4 + bc=0 line=6 + bc=2 line=7 +00 LOAD_CONST_SMALL_INT 0 +01 RETURN_VALUE +File cmdline/cmd_showbc_opt.py, code block 'f1' (descriptor: \.\+, bytecode @\.\+ 22 bytes) +Raw bytecode (code_info_size=9, bytecode_size=13): + 11 0e 03 08 80 0a 23 22 20 b0 44 42 51 63 12 07 + 82 34 01 59 51 63 +arg names: x +(N_STATE 3) +(N_EXC_STACK 0) + bc=0 line=1 + bc=0 line=11 + bc=3 line=12 + bc=5 line=13 + bc=5 line=14 +00 LOAD_FAST 0 +01 POP_JUMP_IF_FALSE 5 +03 LOAD_CONST_NONE +04 RETURN_VALUE +05 LOAD_GLOBAL print +07 LOAD_CONST_SMALL_INT 2 +08 CALL_FUNCTION n=1 nkw=0 +10 POP_TOP +11 LOAD_CONST_NONE +12 RETURN_VALUE +File cmdline/cmd_showbc_opt.py, code block 'f2' (descriptor: \.\+, bytecode @\.\+ 10 bytes) +Raw bytecode (code_info_size=7, bytecode_size=3): + 11 0a 04 08 80 11 23 12 09 65 +arg names: x +(N_STATE 3) +(N_EXC_STACK 0) + bc=0 line=1 + bc=0 line=18 + bc=3 line=19 +00 LOAD_GLOBAL Exception +02 RAISE_OBJ +File cmdline/cmd_showbc_opt.py, code block 'f3' (descriptor: \.\+, bytecode @\.\+ 24 bytes) +Raw bytecode (code_info_size=9, bytecode_size=15): + 11 0e 05 08 80 16 22 22 23 42 42 42 43 b0 43 3b + 12 07 82 34 01 59 51 63 +arg names: x +(N_STATE 3) +(N_EXC_STACK 0) + bc=0 line=1 + bc=0 line=23 + bc=2 line=24 + bc=4 line=25 + bc=7 line=26 +00 JUMP 4 +02 JUMP 7 +04 LOAD_FAST 0 +05 POP_JUMP_IF_TRUE 2 +07 LOAD_GLOBAL print +09 LOAD_CONST_SMALL_INT 2 +10 CALL_FUNCTION n=1 nkw=0 +12 POP_TOP +13 LOAD_CONST_NONE +14 RETURN_VALUE +File cmdline/cmd_showbc_opt.py, code block 'f4' (descriptor: \.\+, bytecode @\.\+ 24 bytes) +Raw bytecode (code_info_size=9, bytecode_size=15): + 11 0e 06 08 80 1d 22 22 23 42 42 42 40 b0 43 3b + 12 07 82 34 01 59 51 63 +arg names: x +(N_STATE 3) +(N_EXC_STACK 0) + bc=0 line=1 + bc=0 line=30 + bc=2 line=31 + bc=4 line=32 + bc=7 line=33 +00 JUMP 4 +02 JUMP 4 +04 LOAD_FAST 0 +05 POP_JUMP_IF_TRUE 2 +07 LOAD_GLOBAL print +09 LOAD_CONST_SMALL_INT 2 +10 CALL_FUNCTION n=1 nkw=0 +12 POP_TOP +13 LOAD_CONST_NONE +14 RETURN_VALUE +mem: total=\\d\+, current=\\d\+, peak=\\d\+ +stack: \\d\+ out of \\d\+ +GC: total: \\d\+, used: \\d\+, free: \\d\+ + No. of 1-blocks: \\d\+, 2-blocks: \\d\+, max blk sz: \\d\+, max free sz: \\d\+ From 5d3a0bb59c08c201c3e9e89db7c9e9386193dea9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 19 Jun 2022 00:54:40 +1000 Subject: [PATCH 0023/1041] py/objcell: Make cell get/set funcs static-inline to reduce code size. Change in code size is: bare-arm: -36 -0.062% minimal x86: -92 -0.056% unix x64: -72 -0.014% unix nanbox: -276 -0.060% stm32: +0 +0.000% PYBV10 stm32: -40 +0.021% NUCLEO_L073RZ cc3200: -16 -0.009% esp8266: +176 +0.025% GENERIC esp32: -28 -0.002% GENERIC mimxrt: -56 -0.016% TEENSY40 renesas-ra: +0 +0.000% RA6M2_EK nrf: +0 +0.000% pca10040 rp2: -64 -0.013% PICO samd: -32 -0.023% ADAFRUIT_ITSYBITSY_M4_EXPRESS Ports like stm32 that build the VM with -O3 have no change because the savings from the inlining are offset by additional gcc performance optimisations in the VM. Signed-off-by: Damien George --- py/obj.h | 17 +++++++++++++++-- py/objcell.c | 15 --------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/py/obj.h b/py/obj.h index 29cd1855c1..84ca94213c 100644 --- a/py/obj.h +++ b/py/obj.h @@ -838,8 +838,21 @@ mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val); mp_obj_t mp_generic_unary_op(mp_unary_op_t op, mp_obj_t o_in); // cell -mp_obj_t mp_obj_cell_get(mp_obj_t self_in); -void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj); + +typedef struct _mp_obj_cell_t { + mp_obj_base_t base; + mp_obj_t obj; +} mp_obj_cell_t; + +static inline mp_obj_t mp_obj_cell_get(mp_obj_t self_in) { + mp_obj_cell_t *self = (mp_obj_cell_t *)MP_OBJ_TO_PTR(self_in); + return self->obj; +} + +static inline void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj) { + mp_obj_cell_t *self = (mp_obj_cell_t *)MP_OBJ_TO_PTR(self_in); + self->obj = obj; +} // int // For long int, returns value truncated to mp_int_t diff --git a/py/objcell.c b/py/objcell.c index 2702ca5350..cab0d0b030 100644 --- a/py/objcell.c +++ b/py/objcell.c @@ -26,21 +26,6 @@ #include "py/obj.h" -typedef struct _mp_obj_cell_t { - mp_obj_base_t base; - mp_obj_t obj; -} mp_obj_cell_t; - -mp_obj_t mp_obj_cell_get(mp_obj_t self_in) { - mp_obj_cell_t *self = MP_OBJ_TO_PTR(self_in); - return self->obj; -} - -void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj) { - mp_obj_cell_t *self = MP_OBJ_TO_PTR(self_in); - self->obj = obj; -} - #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED STATIC void cell_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; From 1842efbdd9fce3a6ea68ee640e1377bd7ba4441e Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 19 Jun 2022 01:16:24 +1000 Subject: [PATCH 0024/1041] stm32/Makefile: Set CSUPEROPT to -Os for F0 and G0 MCUs to save space. Saves 1804 bytes on NUCLEO_F091RC, and 1080 bytes on NUCLEO_G0B1RE. Signed-off-by: Damien George --- ports/stm32/Makefile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 1a4616f022..d6d379b387 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -325,11 +325,8 @@ SRC_O += \ $(STARTUP_FILE) \ $(SYSTEM_FILE) -ifeq ($(MCU_SERIES),l0) -CSUPEROPT = -Os # save some code space -endif - ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 g0 l0)) +CSUPEROPT = -Os # save some code space SRC_O += \ resethandler_m0.o \ shared/runtime/gchelper_m0.o From f5769698e5fca8fbae5b86c649204e915b22b19f Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 19 Jun 2022 01:29:41 +1000 Subject: [PATCH 0025/1041] extmod/modlwip: Clean up inclusion of modlwip in build process. The following changes are made: - Guard entire file with MICROPY_PY_LWIP, so it can be included in the build while still being disabled (for consistency with other extmod modules). - Add modlwip.c to list of all extmod source in py/py.mk and extmod/extmod.cmake so all ports can easily use it. - Move generic modlwip GIT_SUBMODULES build configuration code from ports/rp2/CMakeLists.txt to extmod/extmod.cmake, so it can be reused by other ports. - Remove now unnecessary inclusion of modlwip.c in EXTMOD_SRC_C in esp8266 port, and in SRC_QSTR in mimxrt port. Signed-off-by: Damien George --- extmod/extmod.cmake | 3 +++ extmod/extmod.mk | 2 +- extmod/modlwip.c | 4 ++-- ports/esp8266/Makefile | 1 - ports/mimxrt/Makefile | 1 - ports/rp2/CMakeLists.txt | 6 ------ py/py.mk | 1 + 7 files changed, 7 insertions(+), 11 deletions(-) diff --git a/extmod/extmod.cmake b/extmod/extmod.cmake index 551dec714c..966511fac5 100644 --- a/extmod/extmod.cmake +++ b/extmod/extmod.cmake @@ -16,6 +16,7 @@ set(MICROPY_SOURCE_EXTMOD ${MICROPY_EXTMOD_DIR}/modbluetooth.c ${MICROPY_EXTMOD_DIR}/modbtree.c ${MICROPY_EXTMOD_DIR}/modframebuf.c + ${MICROPY_EXTMOD_DIR}/modlwip.c ${MICROPY_EXTMOD_DIR}/modnetwork.c ${MICROPY_EXTMOD_DIR}/modonewire.c ${MICROPY_EXTMOD_DIR}/moduasyncio.c @@ -246,4 +247,6 @@ if(MICROPY_PY_LWIP) list(APPEND MICROPY_INC_CORE ${MICROPY_LIB_LWIP_DIR}/include ) + + string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/lwip) endif() diff --git a/extmod/extmod.mk b/extmod/extmod.mk index ff24a549a9..60f59183d5 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -153,7 +153,7 @@ LWIP_DIR = lib/lwip/src INC += -I$(TOP)/$(LWIP_DIR)/include CFLAGS_MOD += -DMICROPY_PY_LWIP=1 $(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS_MOD += -Wno-address -SRC_MOD += extmod/modlwip.c shared/netutils/netutils.c +SRC_MOD += shared/netutils/netutils.c SRC_MOD += $(addprefix $(LWIP_DIR)/,\ apps/mdns/mdns.c \ core/def.c \ diff --git a/extmod/modlwip.c b/extmod/modlwip.c index ec5f3bfd63..bbfd3a2253 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -35,6 +35,8 @@ #include "py/mperrno.h" #include "py/mphal.h" +#if MICROPY_PY_LWIP + #include "shared/netutils/netutils.h" #include "lwip/init.h" @@ -1741,8 +1743,6 @@ STATIC mp_obj_t lwip_print_pcbs() { } MP_DEFINE_CONST_FUN_OBJ_0(lwip_print_pcbs_obj, lwip_print_pcbs); -#if MICROPY_PY_LWIP - STATIC const mp_rom_map_elem_t mp_module_lwip_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_lwip) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&mod_lwip_reset_obj) }, diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index 705f4f1eeb..96dff46e3e 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -109,7 +109,6 @@ SRC_C = \ $(SRC_MOD) EXTMOD_SRC_C = $(addprefix extmod/,\ - modlwip.c \ modonewire.c \ ) diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index cfcdb9f7d5..bb6d4d8653 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -150,7 +150,6 @@ SRC_ETH_C += \ $(MCU_DIR)/drivers/fsl_enet.c \ SRC_QSTR += \ - extmod/modlwip.c \ extmod/modnetwork.c \ extmod/moduwebsocket.c \ extmod/modusocket.c \ diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index a7a192ea33..d6a428c91c 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -182,12 +182,6 @@ if (MICROPY_PY_LWIP) target_compile_definitions(${MICROPY_TARGET} PRIVATE MICROPY_PY_LWIP=1 ) - - list(APPEND MICROPY_SOURCE_EXTMOD - ${MICROPY_EXTMOD_DIR}/modlwip.c - ) - - string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/lwip) endif() if(MICROPY_PY_BLUETOOTH) diff --git a/py/py.mk b/py/py.mk index 57fdb6d9b5..49b94b279a 100644 --- a/py/py.mk +++ b/py/py.mk @@ -194,6 +194,7 @@ PY_EXTMOD_O_BASENAME = \ extmod/machine_i2c.o \ extmod/machine_spi.o \ extmod/modbluetooth.o \ + extmod/modlwip.o \ extmod/modussl_axtls.o \ extmod/modussl_mbedtls.o \ extmod/moduplatform.o\ From 4802b6d3af42918aec842ce4117a667523b1ab25 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 19 Jun 2022 22:44:34 +1000 Subject: [PATCH 0026/1041] extmod/extmod.cmake: Only include modbtree in build if it's enabled. Following how it's done in extmod.mk. Signed-off-by: Damien George --- extmod/extmod.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/extmod/extmod.cmake b/extmod/extmod.cmake index 966511fac5..8fe83a0ada 100644 --- a/extmod/extmod.cmake +++ b/extmod/extmod.cmake @@ -14,7 +14,6 @@ set(MICROPY_SOURCE_EXTMOD ${MICROPY_EXTMOD_DIR}/machine_signal.c ${MICROPY_EXTMOD_DIR}/machine_spi.c ${MICROPY_EXTMOD_DIR}/modbluetooth.c - ${MICROPY_EXTMOD_DIR}/modbtree.c ${MICROPY_EXTMOD_DIR}/modframebuf.c ${MICROPY_EXTMOD_DIR}/modlwip.c ${MICROPY_EXTMOD_DIR}/modnetwork.c @@ -97,6 +96,10 @@ if(MICROPY_PY_BTREE) __DBINTERFACE_PRIVATE=1 "virt_fd_t=void*" ) + + list(APPEND MICROPY_SOURCE_EXTMOD + ${MICROPY_EXTMOD_DIR}/modbtree.c + ) endif() # Library for mbedtls From c118b5d0e428094bd64a003d97b078c2d7c7500d Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 17 Jun 2022 11:11:30 -0500 Subject: [PATCH 0027/1041] extmod/extmod.mk: Separate out extmod file list from py.mk to extmod.mk. This separates extmod source files from `py.mk`. Previously, `py.mk` assumed that every consumer of the py/ directory also wanted to include extmod/. However, this is not the case. For example, building mpy-cross uses py/ but doesn't need extmod/. This commit moves all extmod-specific items from `py.mk` to `extmod.mk` and explicitly includes `extmod.mk` in ports that use it. Signed-off-by: David Lechner --- docs/develop/porting.rst | 1 + examples/embedding/Makefile.upylib | 1 + extmod/extmod.mk | 53 +++++++++++++++++++++++++++++- ports/cc3200/Makefile | 1 + ports/esp8266/Makefile | 1 + ports/javascript/Makefile | 1 + ports/mimxrt/Makefile | 1 + ports/nrf/Makefile | 1 + ports/pic16bit/Makefile | 1 + ports/powerpc/Makefile | 1 + ports/qemu-arm/Makefile | 1 + ports/renesas-ra/Makefile | 1 + ports/samd/Makefile | 1 + ports/stm32/Makefile | 1 + ports/teensy/Makefile | 1 + ports/unix/Makefile | 1 + ports/windows/Makefile | 1 + py/py.mk | 53 ++---------------------------- 18 files changed, 70 insertions(+), 52 deletions(-) diff --git a/docs/develop/porting.rst b/docs/develop/porting.rst index bc25f47ed8..3d0553205c 100644 --- a/docs/develop/porting.rst +++ b/docs/develop/porting.rst @@ -95,6 +95,7 @@ We also need a Makefile at this point for the port: # Include py core make definitions. include $(TOP)/py/py.mk + include $(TOP)/extmod/extmod.mk # Set CFLAGS and libraries. CFLAGS = -I. -I$(BUILD) -I$(TOP) diff --git a/examples/embedding/Makefile.upylib b/examples/embedding/Makefile.upylib index 80f7eed159..217f2643c9 100644 --- a/examples/embedding/Makefile.upylib +++ b/examples/embedding/Makefile.upylib @@ -9,6 +9,7 @@ UNAME_S := $(shell uname -s) # include py core make definitions include $(MPTOP)/py/py.mk +include $(MPTOP)/extmod/extmod.mk INC += -I. INC += -I.. diff --git a/extmod/extmod.mk b/extmod/extmod.mk index 60f59183d5..93b2a11766 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -1,4 +1,55 @@ -# This makefile fragment provides rules to build 3rd-party components for extmod modules +# This makefile fragment adds the source code files for the core extmod modules +# and provides rules to build 3rd-party components for extmod modules. + +PY_EXTMOD_O_BASENAME = \ + extmod/moduasyncio.o \ + extmod/moductypes.o \ + extmod/modujson.o \ + extmod/moduos.o \ + extmod/modure.o \ + extmod/moduzlib.o \ + extmod/moduheapq.o \ + extmod/modutimeq.o \ + extmod/moduhashlib.o \ + extmod/moducryptolib.o \ + extmod/modubinascii.o \ + extmod/virtpin.o \ + extmod/machine_bitstream.o \ + extmod/machine_mem.o \ + extmod/machine_pinbase.o \ + extmod/machine_signal.o \ + extmod/machine_pulse.o \ + extmod/machine_pwm.o \ + extmod/machine_i2c.o \ + extmod/machine_spi.o \ + extmod/modbluetooth.o \ + extmod/modlwip.o \ + extmod/modussl_axtls.o \ + extmod/modussl_mbedtls.o \ + extmod/moduplatform.o\ + extmod/modurandom.o \ + extmod/moduselect.o \ + extmod/moduwebsocket.o \ + extmod/modwebrepl.o \ + extmod/modframebuf.o \ + extmod/vfs.o \ + extmod/vfs_blockdev.o \ + extmod/vfs_reader.o \ + extmod/vfs_posix.o \ + extmod/vfs_posix_file.o \ + extmod/vfs_fat.o \ + extmod/vfs_fat_diskio.o \ + extmod/vfs_fat_file.o \ + extmod/vfs_lfs.o \ + extmod/utime_mphal.o \ + extmod/uos_dupterm.o \ + shared/libc/abort_.o \ + shared/libc/printf.o \ + +PY_EXTMOD_O = $(addprefix $(BUILD)/, $(PY_EXTMOD_O_BASENAME)) + +PY_O += $(PY_EXTMOD_O) +SRC_QSTR += $(PY_EXTMOD_O_BASENAME:.o=.c) ################################################################################ # VFS FAT FS diff --git a/ports/cc3200/Makefile b/ports/cc3200/Makefile index 560fc8e96d..90be4529d8 100644 --- a/ports/cc3200/Makefile +++ b/ports/cc3200/Makefile @@ -39,6 +39,7 @@ MICROPY_ROM_TEXT_COMPRESSION ?= 1 # include MicroPython make definitions include $(TOP)/py/py.mk +include $(TOP)/extmod/extmod.mk include application.mk else ifeq ($(BTARGET), bootloader) diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index 96dff46e3e..f70fbd2284 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -30,6 +30,7 @@ FROZEN_MANIFEST ?= boards/manifest.py # include py core make definitions include $(TOP)/py/py.mk +include $(TOP)/extmod/extmod.mk GIT_SUBMODULES = lib/axtls lib/berkeley-db-1.xx diff --git a/ports/javascript/Makefile b/ports/javascript/Makefile index ba2680b2a8..aea9d6ec37 100644 --- a/ports/javascript/Makefile +++ b/ports/javascript/Makefile @@ -5,6 +5,7 @@ CROSS = 0 QSTR_DEFS = qstrdefsport.h include $(TOP)/py/py.mk +include $(TOP)/extmod/extmod.mk CC = emcc LD = emcc diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index bb6d4d8653..759fb5c459 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -42,6 +42,7 @@ MICROPY_VFS_FAT ?= 1 # Include py core make definitions include $(TOP)/py/py.mk +include $(TOP)/extmod/extmod.mk GIT_SUBMODULES = lib/tinyusb lib/nxp_driver lib/lwip lib/mbedtls diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 55cce1906d..25b8c03d1a 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -56,6 +56,7 @@ FROZEN_MANIFEST ?= modules/manifest.py # include py core make definitions include ../../py/py.mk +include ../../extmod/extmod.mk GIT_SUBMODULES = lib/nrfx lib/tinyusb diff --git a/ports/pic16bit/Makefile b/ports/pic16bit/Makefile index f0d55ec875..392196cbc2 100644 --- a/ports/pic16bit/Makefile +++ b/ports/pic16bit/Makefile @@ -5,6 +5,7 @@ QSTR_DEFS = qstrdefsport.h # include py core make definitions include $(TOP)/py/py.mk +include $(TOP)/extmod/extmod.mk XCVERSION ?= 1.35 XC16 ?= /opt/microchip/xc16/v$(XCVERSION) diff --git a/ports/powerpc/Makefile b/ports/powerpc/Makefile index cca170dc02..a1e6fa4dac 100644 --- a/ports/powerpc/Makefile +++ b/ports/powerpc/Makefile @@ -5,6 +5,7 @@ QSTR_DEFS = qstrdefsport.h # include py core make definitions include $(TOP)/py/py.mk +include $(TOP)/extmod/extmod.mk # potato or lpc_serial UART ?= potato diff --git a/ports/qemu-arm/Makefile b/ports/qemu-arm/Makefile index 08c2d82498..7ae7955cf4 100644 --- a/ports/qemu-arm/Makefile +++ b/ports/qemu-arm/Makefile @@ -9,6 +9,7 @@ MICROPY_ROM_TEXT_COMPRESSION ?= 1 # include py core make definitions include $(TOP)/py/py.mk +include $(TOP)/extmod/extmod.mk BOARD ?= mps2-an385 diff --git a/ports/renesas-ra/Makefile b/ports/renesas-ra/Makefile index efbcb5f70f..832b7db9fa 100644 --- a/ports/renesas-ra/Makefile +++ b/ports/renesas-ra/Makefile @@ -67,6 +67,7 @@ FROZEN_MANIFEST ?= boards/manifest.py # include py core make definitions include $(TOP)/py/py.mk +include $(TOP)/extmod/extmod.mk GIT_SUBMODULES += lib/fsp diff --git a/ports/samd/Makefile b/ports/samd/Makefile index ab74b80c16..17dd811690 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -22,6 +22,7 @@ FROZEN_MANIFEST ?= boards/manifest.py # Include py core make definitions include $(TOP)/py/py.mk +include $(TOP)/extmod/extmod.mk GIT_SUBMODULES = lib/asf4 lib/tinyusb diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index d6d379b387..5cde84e67c 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -33,6 +33,7 @@ MBOOT_TEXT0_ADDR ?= 0x08000000 # include py core make definitions include $(TOP)/py/py.mk +include $(TOP)/extmod/extmod.mk GIT_SUBMODULES += lib/libhydrogen lib/lwip lib/mbedtls lib/stm32lib diff --git a/ports/teensy/Makefile b/ports/teensy/Makefile index fe46b0e061..745f530d7a 100644 --- a/ports/teensy/Makefile +++ b/ports/teensy/Makefile @@ -44,6 +44,7 @@ endif # USE_FROZEN # include py core make definitions include $(TOP)/py/py.mk +include $(TOP)/extmod/extmod.mk # If you set USE_ARDUINO_TOOLCHAIN=1 then this makefile will attempt to use # the toolchain that comes with Teensyduino diff --git a/ports/unix/Makefile b/ports/unix/Makefile index d93cdf5d7f..1067c9c055 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -28,6 +28,7 @@ UNAME_S := $(shell uname -s) # include py core make definitions include $(TOP)/py/py.mk +include $(TOP)/extmod/extmod.mk GIT_SUBMODULES += lib/axtls lib/berkeley-db-1.xx lib/libffi diff --git a/ports/windows/Makefile b/ports/windows/Makefile index 3b89ef51ef..45d61b0b50 100644 --- a/ports/windows/Makefile +++ b/ports/windows/Makefile @@ -25,6 +25,7 @@ QSTR_GLOBAL_DEPENDENCIES = $(VARIANT_DIR)/mpconfigvariant.h # include py core make definitions include $(TOP)/py/py.mk +include $(TOP)/extmod/extmod.mk INC += -I. INC += -I$(TOP) diff --git a/py/py.mk b/py/py.mk index 49b94b279a..dacfa1bd06 100644 --- a/py/py.mk +++ b/py/py.mk @@ -172,57 +172,11 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ frozenmod.o \ ) -PY_EXTMOD_O_BASENAME = \ - extmod/moduasyncio.o \ - extmod/moductypes.o \ - extmod/modujson.o \ - extmod/moduos.o \ - extmod/modure.o \ - extmod/moduzlib.o \ - extmod/moduheapq.o \ - extmod/modutimeq.o \ - extmod/moduhashlib.o \ - extmod/moducryptolib.o \ - extmod/modubinascii.o \ - extmod/virtpin.o \ - extmod/machine_bitstream.o \ - extmod/machine_mem.o \ - extmod/machine_pinbase.o \ - extmod/machine_signal.o \ - extmod/machine_pulse.o \ - extmod/machine_pwm.o \ - extmod/machine_i2c.o \ - extmod/machine_spi.o \ - extmod/modbluetooth.o \ - extmod/modlwip.o \ - extmod/modussl_axtls.o \ - extmod/modussl_mbedtls.o \ - extmod/moduplatform.o\ - extmod/modurandom.o \ - extmod/moduselect.o \ - extmod/moduwebsocket.o \ - extmod/modwebrepl.o \ - extmod/modframebuf.o \ - extmod/vfs.o \ - extmod/vfs_blockdev.o \ - extmod/vfs_reader.o \ - extmod/vfs_posix.o \ - extmod/vfs_posix_file.o \ - extmod/vfs_fat.o \ - extmod/vfs_fat_diskio.o \ - extmod/vfs_fat_file.o \ - extmod/vfs_lfs.o \ - extmod/utime_mphal.o \ - extmod/uos_dupterm.o \ - shared/libc/abort_.o \ - shared/libc/printf.o \ - # prepend the build destination prefix to the py object files PY_CORE_O = $(addprefix $(BUILD)/, $(PY_CORE_O_BASENAME)) -PY_EXTMOD_O = $(addprefix $(BUILD)/, $(PY_EXTMOD_O_BASENAME)) # this is a convenience variable for ports that want core, extmod and frozen code -PY_O = $(PY_CORE_O) $(PY_EXTMOD_O) +PY_O += $(PY_CORE_O) # object file for frozen code specified via a manifest ifneq ($(FROZEN_MANIFEST),) @@ -231,7 +185,7 @@ endif # Sources that may contain qstrings SRC_QSTR_IGNORE = py/nlr% -SRC_QSTR += $(SRC_MOD) $(filter-out $(SRC_QSTR_IGNORE),$(PY_CORE_O_BASENAME:.o=.c)) $(PY_EXTMOD_O_BASENAME:.o=.c) +SRC_QSTR += $(SRC_MOD) $(filter-out $(SRC_QSTR_IGNORE),$(PY_CORE_O_BASENAME:.o=.c)) # Anything that depends on FORCE will be considered out-of-date FORCE: @@ -286,6 +240,3 @@ $(PY_BUILD)/vm.o: CFLAGS += $(CSUPEROPT) # http://hg.python.org/cpython/file/b127046831e2/Python/ceval.c#l828 # http://www.emulators.com/docs/nx25_nostradamus.htm #-fno-crossjumping - -# Include rules for extmod related code -include $(TOP)/extmod/extmod.mk From a565811f23c675ccbeed636c065828cdaf5fa96a Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 10 Jun 2022 12:28:56 -0500 Subject: [PATCH 0028/1041] extmod/modbtree: Use buffer protocol for keys/values. This changes the btree implementation to use the buffer protocol for reading key/values in all methods. `str` and `bytes` objects are not the only bytes-like objects that could be used. Documentation and tests are also updated. Addresses issue #8748. Signed-off-by: David Lechner --- docs/library/btree.rst | 5 +++-- extmod/modbtree.c | 29 ++++++++++++++++++----------- tests/extmod/btree1.py | 7 +++++-- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/docs/library/btree.rst b/docs/library/btree.rst index c093f970fa..9d1dcf1110 100644 --- a/docs/library/btree.rst +++ b/docs/library/btree.rst @@ -11,8 +11,9 @@ value, a database also supports efficient ordered range scans (retrieval of values with the keys in a given range). On the application interface side, BTree database work as close a possible to a way standard `dict` type works, one notable difference is that both keys and values must -be `bytes` objects (so, if you want to store objects of other types, you -need to serialize them to `bytes` first). +be `bytes`-like objects (so, if you want to store objects of other types, you +need to first serialize them to `str` or `bytes` or another type that supports +the buffer protocol). The module is based on the well-known BerkelyDB library, version 1.xx. diff --git a/extmod/modbtree.c b/extmod/modbtree.c index 60a5beec68..7a1daacb41 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -76,6 +76,13 @@ STATIC mp_obj_btree_t *btree_new(DB *db, mp_obj_t stream) { return o; } +STATIC void buf_to_dbt(mp_obj_t obj, DBT *dbt) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(obj, &bufinfo, MP_BUFFER_READ); + dbt->data = bufinfo.buf; + dbt->size = bufinfo.len; +} + STATIC void btree_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in); @@ -98,8 +105,8 @@ STATIC mp_obj_t btree_put(size_t n_args, const mp_obj_t *args) { (void)n_args; mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]); DBT key, val; - key.data = (void *)mp_obj_str_get_data(args[1], &key.size); - val.data = (void *)mp_obj_str_get_data(args[2], &val.size); + buf_to_dbt(args[1], &key); + buf_to_dbt(args[2], &val); return MP_OBJ_NEW_SMALL_INT(__bt_put(self->db, &key, &val, 0)); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_put_obj, 3, 4, btree_put); @@ -107,7 +114,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_put_obj, 3, 4, btree_put); STATIC mp_obj_t btree_get(size_t n_args, const mp_obj_t *args) { mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]); DBT key, val; - key.data = (void *)mp_obj_str_get_data(args[1], &key.size); + buf_to_dbt(args[1], &key); int res = __bt_get(self->db, &key, &val, 0); if (res == RET_SPECIAL) { if (n_args > 2) { @@ -126,7 +133,7 @@ STATIC mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) { int flags = MP_OBJ_SMALL_INT_VALUE(args[1]); DBT key, val; if (n_args > 2) { - key.data = (void *)mp_obj_str_get_data(args[2], &key.size); + buf_to_dbt(args[2], &key); } int res = __bt_seq(self->db, &key, &val, flags); @@ -201,7 +208,7 @@ STATIC mp_obj_t btree_iternext(mp_obj_t self_in) { if (self->start_key != MP_OBJ_NULL) { int flags = R_FIRST; if (self->start_key != mp_const_none) { - key.data = (void *)mp_obj_str_get_data(self->start_key, &key.size); + buf_to_dbt(self->start_key, &key); flags = R_CURSOR; } else if (desc) { flags = R_LAST; @@ -219,7 +226,7 @@ STATIC mp_obj_t btree_iternext(mp_obj_t self_in) { if (self->end_key != mp_const_none) { DBT end_key; - end_key.data = (void *)mp_obj_str_get_data(self->end_key, &end_key.size); + buf_to_dbt(self->end_key, &end_key); BTREE *t = self->db->internal; int cmp = t->bt_cmp(&key, &end_key); if (desc) { @@ -254,7 +261,7 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete DBT key; - key.data = (void *)mp_obj_str_get_data(index, &key.size); + buf_to_dbt(index, &key); int res = __bt_delete(self->db, &key, 0); if (res == RET_SPECIAL) { mp_raise_type(&mp_type_KeyError); @@ -264,7 +271,7 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } else if (value == MP_OBJ_SENTINEL) { // load DBT key, val; - key.data = (void *)mp_obj_str_get_data(index, &key.size); + buf_to_dbt(index, &key); int res = __bt_get(self->db, &key, &val, 0); if (res == RET_SPECIAL) { mp_raise_type(&mp_type_KeyError); @@ -274,8 +281,8 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } else { // store DBT key, val; - key.data = (void *)mp_obj_str_get_data(index, &key.size); - val.data = (void *)mp_obj_str_get_data(value, &val.size); + buf_to_dbt(index, &key); + buf_to_dbt(value, &val); int res = __bt_put(self->db, &key, &val, 0); CHECK_ERROR(res); return mp_const_none; @@ -287,7 +294,7 @@ STATIC mp_obj_t btree_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs switch (op) { case MP_BINARY_OP_CONTAINS: { DBT key, val; - key.data = (void *)mp_obj_str_get_data(rhs_in, &key.size); + buf_to_dbt(rhs_in, &key); int res = __bt_get(self->db, &key, &val, 0); CHECK_ERROR(res); return mp_obj_new_bool(res != RET_SPECIAL); diff --git a/tests/extmod/btree1.py b/tests/extmod/btree1.py index 1f4853eaa3..876bce4f87 100644 --- a/tests/extmod/btree1.py +++ b/tests/extmod/btree1.py @@ -10,10 +10,13 @@ except ImportError: f = uio.BytesIO() db = btree.open(f, pagesize=512) +mv = memoryview(b"bar1foo1") + db[b"foo3"] = b"bar3" db[b"foo1"] = b"bar1" -db[b"foo2"] = b"bar2" -db[b"bar1"] = b"foo1" +# any type that implements buffer protocol works for key and value +db["foo2"] = "bar2" +db[mv[:4]] = mv[4:] dbstr = str(db) print(dbstr[:7], dbstr[-1:]) From 89e1e67748e681da5f414dc597e89eaee8822817 Mon Sep 17 00:00:00 2001 From: Howard Lovatt Date: Sat, 10 Oct 2020 08:35:50 +1100 Subject: [PATCH 0029/1041] docs/library/pyb.Timer: Document `brk` argument and its constants. --- docs/library/pyb.Timer.rst | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/library/pyb.Timer.rst b/docs/library/pyb.Timer.rst index cc7a01f580..639ae1dcd1 100644 --- a/docs/library/pyb.Timer.rst +++ b/docs/library/pyb.Timer.rst @@ -62,7 +62,7 @@ Constructors Methods ------- -.. method:: Timer.init(*, freq, prescaler, period, mode=Timer.UP, div=1, callback=None, deadtime=0) +.. method:: Timer.init(*, freq, prescaler, period, mode=Timer.UP, div=1, callback=None, deadtime=0, brk=Timer.BRK_OFF) Initialise the timer. Initialisation must be either by frequency (in Hz) or by prescaler and period:: @@ -107,6 +107,12 @@ Methods measures ticks of ``source_freq`` divided by ``div`` clock ticks. ``deadtime`` is only available on timers 1 and 8. + - ``brk`` - specifies if the break mode is used to kill the output of + the PWM when the ``BRK_IN`` input is asserted. The value of this + argument determines if break is enabled and what the polarity is, and + can be one of ``Timer.BRK_OFF``, ``Timer.BRK_LOW`` or + ``Timer.BRK_HIGH``. + You must either specify freq or both of period and prescaler. .. method:: Timer.deinit() @@ -271,3 +277,9 @@ Constants Timer.CENTER Configures the timer to count Up, Down, or from 0 to ARR and then back down to 0. + +.. data:: Timer.BRK_OFF + Timer.BRK_LOW + Timer.BRK_HIGH + + Configures the break mode when passed to the ``brk`` keyword argument. From 9175482f29264b017534902bb65e23a2d6485006 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 21 Jun 2022 14:33:23 +1000 Subject: [PATCH 0030/1041] docs/library: Remove unnecessary "pyb." prefix on class names. Otherwise these classes are refered to with a double prefix, like pyb.pyb.ADC. Signed-off-by: Damien George --- docs/library/pyb.ADC.rst | 2 +- docs/library/pyb.Accel.rst | 2 +- docs/library/pyb.CAN.rst | 2 +- docs/library/pyb.DAC.rst | 2 +- docs/library/pyb.ExtInt.rst | 2 +- docs/library/pyb.Flash.rst | 4 ++-- docs/library/pyb.I2C.rst | 2 +- docs/library/pyb.LCD.rst | 2 +- docs/library/pyb.LED.rst | 2 +- docs/library/pyb.Pin.rst | 2 +- docs/library/pyb.RTC.rst | 2 +- docs/library/pyb.SPI.rst | 2 +- docs/library/pyb.Servo.rst | 2 +- docs/library/pyb.Switch.rst | 2 +- docs/library/pyb.Timer.rst | 2 +- docs/library/pyb.UART.rst | 2 +- docs/library/pyb.USB_HID.rst | 2 +- docs/library/pyb.USB_VCP.rst | 2 +- 18 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/library/pyb.ADC.rst b/docs/library/pyb.ADC.rst index 1b16e0c2fc..9410e5194b 100644 --- a/docs/library/pyb.ADC.rst +++ b/docs/library/pyb.ADC.rst @@ -23,7 +23,7 @@ Usage:: Constructors ------------ -.. class:: pyb.ADC(pin) +.. class:: ADC(pin) Create an ADC object associated with the given pin. This allows you to then read analog values on that pin. diff --git a/docs/library/pyb.Accel.rst b/docs/library/pyb.Accel.rst index d5c0ca8634..7f5c60f4ce 100644 --- a/docs/library/pyb.Accel.rst +++ b/docs/library/pyb.Accel.rst @@ -16,7 +16,7 @@ Raw values are between -32 and 31. Constructors ------------ -.. class:: pyb.Accel() +.. class:: Accel() Create and return an accelerometer object. diff --git a/docs/library/pyb.CAN.rst b/docs/library/pyb.CAN.rst index 69704d09b2..54377091db 100644 --- a/docs/library/pyb.CAN.rst +++ b/docs/library/pyb.CAN.rst @@ -31,7 +31,7 @@ for both classic and FD CAN controllers, unless otherwise stated. Constructors ------------ -.. class:: pyb.CAN(bus, ...) +.. class:: CAN(bus, ...) Construct a CAN object on the given bus. *bus* can be 1-2, or ``'YA'`` or ``'YB'``. With no additional parameters, the CAN object is created but not diff --git a/docs/library/pyb.DAC.rst b/docs/library/pyb.DAC.rst index 0eb469bef4..aa79342895 100644 --- a/docs/library/pyb.DAC.rst +++ b/docs/library/pyb.DAC.rst @@ -49,7 +49,7 @@ To output a continuous sine-wave at 12-bit resolution:: Constructors ------------ -.. class:: pyb.DAC(port, bits=8, *, buffering=None) +.. class:: DAC(port, bits=8, *, buffering=None) Construct a new DAC object. diff --git a/docs/library/pyb.ExtInt.rst b/docs/library/pyb.ExtInt.rst index 7741cc51e2..f49fbb1a14 100644 --- a/docs/library/pyb.ExtInt.rst +++ b/docs/library/pyb.ExtInt.rst @@ -51,7 +51,7 @@ usrsw.h for an example of using this. Constructors ------------ -.. class:: pyb.ExtInt(pin, mode, pull, callback) +.. class:: ExtInt(pin, mode, pull, callback) Create an ExtInt object: diff --git a/docs/library/pyb.Flash.rst b/docs/library/pyb.Flash.rst index 01b3a0ac9e..984e13f458 100644 --- a/docs/library/pyb.Flash.rst +++ b/docs/library/pyb.Flash.rst @@ -15,7 +15,7 @@ application. Constructors ------------ -.. class:: pyb.Flash() +.. class:: Flash() Create and return a block device that represents the flash device presented to the USB mass storage interface. @@ -25,7 +25,7 @@ Constructors This constructor is deprecated and will be removed in a future version of MicroPython. -.. class:: pyb.Flash(*, start=-1, len=-1) +.. class:: Flash(*, start=-1, len=-1) :noindex: Create and return a block device that accesses the flash at the specified offset. The length defaults to the remaining size of the device. diff --git a/docs/library/pyb.I2C.rst b/docs/library/pyb.I2C.rst index f60b506861..24b9cb8c3a 100644 --- a/docs/library/pyb.I2C.rst +++ b/docs/library/pyb.I2C.rst @@ -56,7 +56,7 @@ Master also has other methods:: Constructors ------------ -.. class:: pyb.I2C(bus, ...) +.. class:: I2C(bus, ...) Construct an I2C object on the given bus. ``bus`` can be 1 or 2, 'X' or 'Y'. With no additional parameters, the I2C object is created but not diff --git a/docs/library/pyb.LCD.rst b/docs/library/pyb.LCD.rst index 018902ca68..ba394d36a8 100644 --- a/docs/library/pyb.LCD.rst +++ b/docs/library/pyb.LCD.rst @@ -41,7 +41,7 @@ For example, to make a bouncing dot, try:: Constructors ------------ -.. class:: pyb.LCD(skin_position) +.. class:: LCD(skin_position) Construct an LCD object in the given skin position. ``skin_position`` can be 'X' or 'Y', and should match the position where the LCD pyskin is plugged in. diff --git a/docs/library/pyb.LED.rst b/docs/library/pyb.LED.rst index d3ab965e7e..de07c7d1c3 100644 --- a/docs/library/pyb.LED.rst +++ b/docs/library/pyb.LED.rst @@ -10,7 +10,7 @@ The LED object controls an individual LED (Light Emitting Diode). Constructors ------------ -.. class:: pyb.LED(id) +.. class:: LED(id) Create an LED object associated with the given LED: diff --git a/docs/library/pyb.Pin.rst b/docs/library/pyb.Pin.rst index 33b994e390..d13cb9741c 100644 --- a/docs/library/pyb.Pin.rst +++ b/docs/library/pyb.Pin.rst @@ -74,7 +74,7 @@ gpio pins. Constructors ------------ -.. class:: pyb.Pin(id, ...) +.. class:: Pin(id, ...) Create a new Pin object associated with the id. If additional arguments are given, they are used to initialise the pin. See :meth:`pin.init`. diff --git a/docs/library/pyb.RTC.rst b/docs/library/pyb.RTC.rst index c477e7f035..040b1fe6b2 100644 --- a/docs/library/pyb.RTC.rst +++ b/docs/library/pyb.RTC.rst @@ -17,7 +17,7 @@ Example usage:: Constructors ------------ -.. class:: pyb.RTC() +.. class:: RTC() Create an RTC object. diff --git a/docs/library/pyb.SPI.rst b/docs/library/pyb.SPI.rst index 14b90a2240..4903a2c33f 100644 --- a/docs/library/pyb.SPI.rst +++ b/docs/library/pyb.SPI.rst @@ -28,7 +28,7 @@ Additional methods for SPI:: Constructors ------------ -.. class:: pyb.SPI(bus, ...) +.. class:: SPI(bus, ...) Construct an SPI object on the given bus. ``bus`` can be 1 or 2, or 'X' or 'Y'. With no additional parameters, the SPI object is created but diff --git a/docs/library/pyb.Servo.rst b/docs/library/pyb.Servo.rst index b3ce71d11a..c52ee705f6 100644 --- a/docs/library/pyb.Servo.rst +++ b/docs/library/pyb.Servo.rst @@ -30,7 +30,7 @@ Example usage:: Constructors ------------ -.. class:: pyb.Servo(id) +.. class:: Servo(id) Create a servo object. ``id`` is 1-4, and corresponds to pins X1 through X4. diff --git a/docs/library/pyb.Switch.rst b/docs/library/pyb.Switch.rst index 1edcbf8488..9ddf8c4170 100644 --- a/docs/library/pyb.Switch.rst +++ b/docs/library/pyb.Switch.rst @@ -23,7 +23,7 @@ Example:: Constructors ------------ -.. class:: pyb.Switch() +.. class:: Switch() Create and return a switch object. diff --git a/docs/library/pyb.Timer.rst b/docs/library/pyb.Timer.rst index 639ae1dcd1..53213666ba 100644 --- a/docs/library/pyb.Timer.rst +++ b/docs/library/pyb.Timer.rst @@ -53,7 +53,7 @@ limitation. Constructors ------------ -.. class:: pyb.Timer(id, ...) +.. class:: Timer(id, ...) Construct a new timer object of the given id. If additional arguments are given, then the timer is initialised by ``init(...)``. diff --git a/docs/library/pyb.UART.rst b/docs/library/pyb.UART.rst index e1735403c4..2bd9c6b34e 100644 --- a/docs/library/pyb.UART.rst +++ b/docs/library/pyb.UART.rst @@ -46,7 +46,7 @@ Earlier versions use ``uart.send`` and ``uart.recv``. Constructors ------------ -.. class:: pyb.UART(bus, ...) +.. class:: UART(bus, ...) Construct a UART object on the given bus. For Pyboard ``bus`` can be 1-4, 6, 'XA', 'XB', 'YA', or 'YB'. diff --git a/docs/library/pyb.USB_HID.rst b/docs/library/pyb.USB_HID.rst index 7e23d1313d..80162cc565 100644 --- a/docs/library/pyb.USB_HID.rst +++ b/docs/library/pyb.USB_HID.rst @@ -13,7 +13,7 @@ Before you can use this class, you need to use :meth:`pyb.usb_mode()` to set the Constructors ------------ -.. class:: pyb.USB_HID() +.. class:: USB_HID() Create a new USB_HID object. diff --git a/docs/library/pyb.USB_VCP.rst b/docs/library/pyb.USB_VCP.rst index 1cca8dcadf..17d2ecff4a 100644 --- a/docs/library/pyb.USB_VCP.rst +++ b/docs/library/pyb.USB_VCP.rst @@ -12,7 +12,7 @@ the connected host. Constructors ------------ -.. class:: pyb.USB_VCP(id=0) +.. class:: USB_VCP(id=0) Create a new USB_VCP object. The *id* argument specifies which USB VCP port to use. From f12754af06c83f06f2651f50109b84a9b700e12a Mon Sep 17 00:00:00 2001 From: "Stewart C. Russell" Date: Sun, 17 Jan 2021 22:56:29 -0500 Subject: [PATCH 0031/1041] docs: Set LaTeX engine to XeLaTeX for PDF generation. Also added to suggested packages list for PDF build. See comment in Sphinx project for (some) details: https://github.com/sphinx-doc/sphinx/pull/5693#pullrequestreview-180444650 --- docs/README.md | 6 +++--- docs/conf.py | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index 1591911c34..892726ba17 100644 --- a/docs/README.md +++ b/docs/README.md @@ -47,7 +47,7 @@ This can be achieved with: make latexpdf -but require rather complete install of LaTeX with various extensions. On -Debian/Ubuntu, try (500MB+ download): +but requires a rather complete install of LaTeX with various extensions. On +Debian/Ubuntu, try (1GB+ download): - apt-get install texlive-latex-recommended texlive-latex-extra + apt install texlive-latex-recommended texlive-latex-extra texlive-xetex texlive-fonts-extra cm-super xindy diff --git a/docs/conf.py b/docs/conf.py index d0c989eeaa..a7a4ab08c5 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -259,6 +259,8 @@ latex_documents = [ # If false, no module index is generated. #latex_domain_indices = True +# Enable better Unicode support so that `make latexpdf` doesn't fail +latex_engine = "xelatex" # -- Options for manual page output --------------------------------------- From 3d58bb23c28394fedd26151ab69cc4ba793043f1 Mon Sep 17 00:00:00 2001 From: Patrick Joy <74940387+ThinkTransit@users.noreply.github.com> Date: Wed, 13 Apr 2022 21:32:13 +1000 Subject: [PATCH 0032/1041] docs/library/machine: Add note on interrupts being critical to system. --- docs/library/machine.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/library/machine.rst b/docs/library/machine.rst index d66423d0d4..c3bf438961 100644 --- a/docs/library/machine.rst +++ b/docs/library/machine.rst @@ -48,6 +48,23 @@ Reset related functions Interrupt related functions --------------------------- +The following functions allow control over interrupts. Some systems require +interrupts to operate correctly so disabling them for long periods may +compromise core functionality, for example watchdog timers may trigger +unexpectedly. Interrupts should only be disabled for a minimum amount of time +and then re-enabled to their previous state. For example:: + + import machine + + # Disable interrupts + state = machine.disable_irq() + + # Do a small amount of time-critical work here + + # Enable interrupts + machine.enable_irq(state) + + .. function:: disable_irq() Disable interrupt requests. From 7861eddd0fe7c9e290cdbc4586dde24d10b68c96 Mon Sep 17 00:00:00 2001 From: Luiz Brandao Date: Thu, 14 Apr 2022 12:24:35 -0400 Subject: [PATCH 0033/1041] docs/library/uasyncio: Consistently use "uasyncio" instead of "asyncio". --- docs/library/uasyncio.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/library/uasyncio.rst b/docs/library/uasyncio.rst index a842cc64d4..0c71702420 100644 --- a/docs/library/uasyncio.rst +++ b/docs/library/uasyncio.rst @@ -71,9 +71,9 @@ Additional functions than *timeout* seconds. If *awaitable* is not a task then a task will be created from it. - If a timeout occurs, it cancels the task and raises ``asyncio.TimeoutError``: + If a timeout occurs, it cancels the task and raises ``uasyncio.TimeoutError``: this should be trapped by the caller. The task receives - ``asyncio.CancelledError`` which may be ignored or trapped using ``try...except`` + ``uasyncio.CancelledError`` which may be ignored or trapped using ``try...except`` or ``try...finally`` to run cleanup code. Returns the return value of *awaitable*. @@ -108,7 +108,7 @@ class Task .. method:: Task.cancel() - Cancel the task by injecting ``asyncio.CancelledError`` into it. The task may + Cancel the task by injecting ``uasyncio.CancelledError`` into it. The task may ignore this exception. Cleanup code may be run by trapping it, or via ``try ... finally``. @@ -148,7 +148,7 @@ class ThreadSafeFlag .. class:: ThreadSafeFlag() Create a new flag which can be used to synchronise a task with code running - outside the asyncio loop, such as other threads, IRQs, or scheduler + outside the uasyncio loop, such as other threads, IRQs, or scheduler callbacks. Flags start in the cleared state. .. method:: ThreadSafeFlag.set() From 0172292762649db91f588107b2163ab6449dc7ca Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 7 Aug 2021 02:16:59 +1000 Subject: [PATCH 0034/1041] py/parsenum: Support parsing complex numbers of the form "a+bj". To conform with CPython. Signed-off-by: Jim Mussared --- py/parsenum.c | 37 ++++++++++++++++++++++++++++++++----- tests/float/complex1.py | 12 ++++++++++++ 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/py/parsenum.c b/py/parsenum.c index 1cfe842577..848a7732d9 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -166,6 +166,12 @@ value_error: } } +enum { + REAL_IMAG_STATE_START = 0, + REAL_IMAG_STATE_HAVE_REAL = 1, + REAL_IMAG_STATE_HAVE_IMAG = 2, +}; + typedef enum { PARSE_DEC_IN_INTG, PARSE_DEC_IN_FRAC, @@ -196,7 +202,12 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool const char *top = str + len; mp_float_t dec_val = 0; bool dec_neg = false; - bool imag = false; + unsigned int real_imag_state = REAL_IMAG_STATE_START; + + #if MICROPY_PY_BUILTINS_COMPLEX + mp_float_t dec_real = 0; +parse_start: + #endif // skip leading space for (; str < top && unichar_isspace(*str); str++) { @@ -281,7 +292,7 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool goto value_error; } } else if (allow_imag && (dig | 0x20) == 'j') { - imag = true; + real_imag_state |= REAL_IMAG_STATE_HAVE_IMAG; break; } else if (dig == '_') { continue; @@ -332,18 +343,34 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool // check we reached the end of the string if (str != top) { + #if MICROPY_PY_BUILTINS_COMPLEX + if (force_complex && real_imag_state == REAL_IMAG_STATE_START) { + // If we've only seen a real so far, keep parsing for the imaginary part. + dec_real = dec_val; + dec_val = 0; + real_imag_state |= REAL_IMAG_STATE_HAVE_REAL; + goto parse_start; + } + #endif goto value_error; } + #if MICROPY_PY_BUILTINS_COMPLEX + if (real_imag_state == REAL_IMAG_STATE_HAVE_REAL) { + // We're on the second part, but didn't get the expected imaginary number. + goto value_error; + } + #endif + // return the object #if MICROPY_PY_BUILTINS_COMPLEX - if (imag) { - return mp_obj_new_complex(0, dec_val); + if (real_imag_state != REAL_IMAG_STATE_START) { + return mp_obj_new_complex(dec_real, dec_val); } else if (force_complex) { return mp_obj_new_complex(dec_val, 0); } #else - if (imag || force_complex) { + if (real_imag_state != REAL_IMAG_STATE_START || force_complex) { raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, MP_ERROR_TEXT("complex values not supported")), lex); } #endif diff --git a/tests/float/complex1.py b/tests/float/complex1.py index 139bb0c509..feede0eab3 100644 --- a/tests/float/complex1.py +++ b/tests/float/complex1.py @@ -7,6 +7,11 @@ print(complex(1.2j)) print(complex("1")) print(complex("1.2")) print(complex("1.2j")) +print(complex("1+2j")) +print(complex("-1-2j")) +print(complex("+1-2j")) +print(complex(" -1-2j ")) +print(complex(" +1-2j ")) print(complex(1, 2)) print(complex(1j, 2j)) @@ -72,6 +77,13 @@ print(float("-nan") * 1j) print(float("inf") * (1 + 1j)) print(float("-inf") * (1 + 1j)) +# malformed complex strings +for test in ("1+2", "1j+2", "1+2j+3", "1+2+3j", "1 + 2j"): + try: + complex(test) + except ValueError: + print("ValueError", test) + # can't assign to attributes try: (1j).imag = 0 From 61ce260ff73b1191a9190c8cac7a7a1bd5b2f274 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 21 Jun 2022 23:45:27 +1000 Subject: [PATCH 0035/1041] py/parsenum: Fix parsing of complex "j" and also "nanj", "infj". Prior to this commit, complex("j") would return 0j, and complex("nanj") would return nan+0j. This commit makes sure "j" is tested for after parsing the number (nan, inf or a decimal), and also supports the case of "j" on its own. Signed-off-by: Damien George --- py/parsenum.c | 12 +++++++++--- tests/float/complex1.py | 5 +++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/py/parsenum.c b/py/parsenum.c index 848a7732d9..b90dfaaafb 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -291,9 +291,6 @@ parse_start: if (str == top) { goto value_error; } - } else if (allow_imag && (dig | 0x20) == 'j') { - real_imag_state |= REAL_IMAG_STATE_HAVE_IMAG; - break; } else if (dig == '_') { continue; } else { @@ -327,6 +324,15 @@ parse_start: } } + if (allow_imag && str < top && (*str | 0x20) == 'j') { + if (str == str_val_start) { + // Convert "j" to "1j". + dec_val = 1; + } + ++str; + real_imag_state |= REAL_IMAG_STATE_HAVE_IMAG; + } + // negate value if needed if (dec_neg) { dec_val = -dec_val; diff --git a/tests/float/complex1.py b/tests/float/complex1.py index feede0eab3..f4107a1390 100644 --- a/tests/float/complex1.py +++ b/tests/float/complex1.py @@ -4,14 +4,19 @@ print(complex(1)) print(complex(1.2)) print(complex(1.2j)) +print(complex("j")) +print(complex("J")) print(complex("1")) print(complex("1.2")) print(complex("1.2j")) +print(complex("1+j")) print(complex("1+2j")) print(complex("-1-2j")) print(complex("+1-2j")) print(complex(" -1-2j ")) print(complex(" +1-2j ")) +print(complex("nanj")) +print(complex("nan-infj")) print(complex(1, 2)) print(complex(1j, 2j)) From 627ba381545b73a383b9e56a4b29c03ac5914a4d Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 22 Jun 2022 10:37:48 +1000 Subject: [PATCH 0036/1041] py/parsenum: Optimise when building with complex disabled. To reduce code size when MICROPY_PY_BUILTINS_COMPLEX is disabled. Signed-off-by: Damien George --- extmod/modujson.c | 2 +- py/objcomplex.c | 2 +- py/objfloat.c | 2 +- py/parse.c | 2 +- py/parsenum.c | 23 ++++++++++++++--------- py/parsenum.h | 14 ++++++++++++++ py/persistentcode.c | 2 +- 7 files changed, 33 insertions(+), 14 deletions(-) diff --git a/extmod/modujson.c b/extmod/modujson.c index bee432db25..9a73e4501e 100644 --- a/extmod/modujson.c +++ b/extmod/modujson.c @@ -270,7 +270,7 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) { S_NEXT(s); } if (flt) { - next = mp_parse_num_decimal(vstr.buf, vstr.len, false, false, NULL); + next = mp_parse_num_float(vstr.buf, vstr.len, false, NULL); } else { next = mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL); } diff --git a/py/objcomplex.c b/py/objcomplex.c index 56c8353e90..157617e156 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -83,7 +83,7 @@ STATIC mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, si // a string, parse it size_t l; const char *s = mp_obj_str_get_data(args[0], &l); - return mp_parse_num_decimal(s, l, true, true, NULL); + return mp_parse_num_complex(s, l, NULL); } else if (mp_obj_is_type(args[0], &mp_type_complex)) { // a complex, just return it return args[0]; diff --git a/py/objfloat.c b/py/objfloat.c index 0855baac83..8e89b3da37 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -137,7 +137,7 @@ STATIC mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size mp_buffer_info_t bufinfo; if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ)) { // a textual representation, parse it - return mp_parse_num_decimal(bufinfo.buf, bufinfo.len, false, false, NULL); + return mp_parse_num_float(bufinfo.buf, bufinfo.len, false, NULL); } else if (mp_obj_is_float(args[0])) { // a float, just return it return args[0]; diff --git a/py/parse.c b/py/parse.c index 14f5f6c105..d58098af2e 100644 --- a/py/parse.c +++ b/py/parse.c @@ -591,7 +591,7 @@ STATIC void push_result_token(parser_t *parser, uint8_t rule_id) { mp_obj_t o = mp_parse_num_integer(lex->vstr.buf, lex->vstr.len, 0, lex); pn = make_node_const_object_optimised(parser, lex->tok_line, o); } else if (lex->tok_kind == MP_TOKEN_FLOAT_OR_IMAG) { - mp_obj_t o = mp_parse_num_decimal(lex->vstr.buf, lex->vstr.len, true, false, lex); + mp_obj_t o = mp_parse_num_float(lex->vstr.buf, lex->vstr.len, true, lex); pn = make_node_const_object(parser, lex->tok_line, o); } else if (lex->tok_kind == MP_TOKEN_STRING) { // Don't automatically intern all strings. Doc strings (which are usually large) diff --git a/py/parsenum.c b/py/parsenum.c index b90dfaaafb..5e8e5dfe8c 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -178,7 +178,12 @@ typedef enum { PARSE_DEC_IN_EXP, } parse_dec_in_t; -mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex) { +#if MICROPY_PY_BUILTINS_COMPLEX +mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex) +#else +mp_obj_t mp_parse_num_float(const char *str, size_t len, bool allow_imag, mp_lexer_t *lex) +#endif +{ #if MICROPY_PY_BUILTINS_FLOAT // DEC_VAL_MAX only needs to be rough and is used to retain precision while not overflowing @@ -202,9 +207,9 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool const char *top = str + len; mp_float_t dec_val = 0; bool dec_neg = false; - unsigned int real_imag_state = REAL_IMAG_STATE_START; #if MICROPY_PY_BUILTINS_COMPLEX + unsigned int real_imag_state = REAL_IMAG_STATE_START; mp_float_t dec_real = 0; parse_start: #endif @@ -325,12 +330,16 @@ parse_start: } if (allow_imag && str < top && (*str | 0x20) == 'j') { + #if MICROPY_PY_BUILTINS_COMPLEX if (str == str_val_start) { // Convert "j" to "1j". dec_val = 1; } ++str; real_imag_state |= REAL_IMAG_STATE_HAVE_IMAG; + #else + raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, MP_ERROR_TEXT("complex values not supported")), lex); + #endif } // negate value if needed @@ -369,20 +378,16 @@ parse_start: #endif // return the object + #if MICROPY_PY_BUILTINS_COMPLEX if (real_imag_state != REAL_IMAG_STATE_START) { return mp_obj_new_complex(dec_real, dec_val); } else if (force_complex) { return mp_obj_new_complex(dec_val, 0); } - #else - if (real_imag_state != REAL_IMAG_STATE_START || force_complex) { - raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, MP_ERROR_TEXT("complex values not supported")), lex); - } #endif - else { - return mp_obj_new_float(dec_val); - } + + return mp_obj_new_float(dec_val); value_error: raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, MP_ERROR_TEXT("invalid syntax for number")), lex); diff --git a/py/parsenum.h b/py/parsenum.h index a5bed731d2..f444632d23 100644 --- a/py/parsenum.h +++ b/py/parsenum.h @@ -31,7 +31,21 @@ #include "py/obj.h" // these functions raise a SyntaxError if lex!=NULL, else a ValueError + mp_obj_t mp_parse_num_integer(const char *restrict str, size_t len, int base, mp_lexer_t *lex); + +#if MICROPY_PY_BUILTINS_COMPLEX mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex); +static inline mp_obj_t mp_parse_num_float(const char *str, size_t len, bool allow_imag, mp_lexer_t *lex) { + return mp_parse_num_decimal(str, len, allow_imag, false, lex); +} + +static inline mp_obj_t mp_parse_num_complex(const char *str, size_t len, mp_lexer_t *lex) { + return mp_parse_num_decimal(str, len, true, true, lex); +} +#else +mp_obj_t mp_parse_num_float(const char *str, size_t len, bool allow_imag, mp_lexer_t *lex); +#endif + #endif // MICROPY_INCLUDED_PY_PARSENUM_H diff --git a/py/persistentcode.c b/py/persistentcode.c index 6304d1ff08..fbef0b2c0f 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -207,7 +207,7 @@ STATIC mp_obj_t load_obj(mp_reader_t *reader) { return mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL); } else { assert(obj_type == MP_PERSISTENT_OBJ_FLOAT || obj_type == MP_PERSISTENT_OBJ_COMPLEX); - return mp_parse_num_decimal(vstr.buf, vstr.len, obj_type == MP_PERSISTENT_OBJ_COMPLEX, false, NULL); + return mp_parse_num_float(vstr.buf, vstr.len, obj_type == MP_PERSISTENT_OBJ_COMPLEX, NULL); } } } From ad7b98c8290ba5f4235fe0cd8fbf542e5bcace54 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 23 Jun 2022 12:58:11 +1000 Subject: [PATCH 0037/1041] esp8266/mpconfigport: Switch to ROM feature level configuration. This is a no-op in terms of board configuration. Signed-off-by: Damien George --- ports/esp8266/boards/GENERIC/mpconfigboard.h | 8 -- .../esp8266/boards/GENERIC_1M/mpconfigboard.h | 8 +- .../boards/GENERIC_512K/mpconfigboard.h | 8 ++ ports/esp8266/mpconfigport.h | 75 +++++++++---------- 4 files changed, 46 insertions(+), 53 deletions(-) diff --git a/ports/esp8266/boards/GENERIC/mpconfigboard.h b/ports/esp8266/boards/GENERIC/mpconfigboard.h index e4991ba970..1d9b8e6f70 100644 --- a/ports/esp8266/boards/GENERIC/mpconfigboard.h +++ b/ports/esp8266/boards/GENERIC/mpconfigboard.h @@ -11,12 +11,4 @@ #define MICROPY_READER_VFS (MICROPY_VFS) #define MICROPY_VFS (1) -#define MICROPY_PY_FSTRINGS (1) -#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) -#define MICROPY_PY_ALL_SPECIAL_METHODS (1) -#define MICROPY_PY_IO_FILEIO (1) -#define MICROPY_PY_SYS_STDIO_BUFFER (1) -#define MICROPY_PY_UASYNCIO (1) -#define MICROPY_PY_URE_SUB (1) #define MICROPY_PY_UCRYPTOLIB (1) -#define MICROPY_PY_FRAMEBUF (1) diff --git a/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h b/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h index ed50729936..10e8adcda7 100644 --- a/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h +++ b/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h @@ -11,10 +11,6 @@ #define MICROPY_READER_VFS (MICROPY_VFS) #define MICROPY_VFS (1) -#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) -#define MICROPY_PY_ALL_SPECIAL_METHODS (1) -#define MICROPY_PY_IO_FILEIO (1) -#define MICROPY_PY_SYS_STDIO_BUFFER (1) -#define MICROPY_PY_URE_SUB (1) +#define MICROPY_PY_FSTRINGS (0) +#define MICROPY_PY_UASYNCIO (0) #define MICROPY_PY_UCRYPTOLIB (1) -#define MICROPY_PY_FRAMEBUF (1) diff --git a/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h b/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h index 0693232aa1..ef37e22fb6 100644 --- a/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h +++ b/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h @@ -2,3 +2,11 @@ #define MICROPY_HW_MCU_NAME "ESP8266" #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) + +#define MICROPY_PY_FSTRINGS (0) +#define MICROPY_PY_BUILTINS_SLICE_ATTRS (0) +#define MICROPY_PY_ALL_SPECIAL_METHODS (0) +#define MICROPY_PY_SYS_STDIO_BUFFER (0) +#define MICROPY_PY_UASYNCIO (0) +#define MICROPY_PY_URE_SUB (0) +#define MICROPY_PY_FRAMEBUF (0) diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 583d3648af..365327aa4c 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -6,6 +6,42 @@ #include +// Set the rom feature level. +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) + +// Disable items from the extra level that are not wanted. +#define MICROPY_COMP_MODULE_CONST (0) +#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0) +#define MICROPY_COMP_RETURN_IF_EXPR (0) +#define MICROPY_OPT_LOAD_ATTR_FAST_PATH (0) +#define MICROPY_OPT_MAP_LOOKUP_CACHE (0) +#define MICROPY_OPT_MPZ_BITWISE (0) +#define MICROPY_OPT_MATH_FACTORIAL (0) +#define MICROPY_REPL_EMACS_KEYS (0) +#define MICROPY_PY_BUILTINS_COMPLEX (0) +#define MICROPY_MODULE_ATTR_DELEGATION (0) +#define MICROPY_PY_FUNCTION_ATTRS (0) +#define MICROPY_PY_DELATTR_SETATTR (0) +#define MICROPY_PY_BUILTINS_STR_CENTER (0) +#define MICROPY_PY_BUILTINS_STR_PARTITION (0) +#define MICROPY_PY_BUILTINS_STR_SPLITLINES (0) +#define MICROPY_PY_BUILTINS_SLICE_INDICES (0) +#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0) +#define MICROPY_PY_BUILTINS_COMPILE (0) +#define MICROPY_PY_BUILTINS_EXECFILE (0) +#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (0) +#define MICROPY_PY_BUILTINS_POW3 (0) +#define MICROPY_PY___FILE__ (0) +#define MICROPY_PY_MATH_CONSTANTS (0) +#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (0) +#define MICROPY_PY_MATH_FACTORIAL (0) +#define MICROPY_PY_MATH_ISCLOSE (0) +#define MICROPY_PY_IO_FILEIO (MICROPY_VFS) +#define MICROPY_PY_SYS_PS1_PS2 (0) +#define MICROPY_PY_UBINASCII_CRC32 (0) +#define MICROPY_PY_URANDOM_EXTRA_FUNCS (0) + +// Configure other options. #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_C) #define MICROPY_GC_STACK_ENTRY_TYPE uint16_t #define MICROPY_ALLOC_PATH_MAX (128) @@ -16,50 +52,14 @@ #define MICROPY_ALLOC_PARSE_CHUNK_INIT (64) #define MICROPY_DEBUG_PRINTER (&mp_debug_print) #define MICROPY_ENABLE_GC (1) -#define MICROPY_ENABLE_FINALISER (1) -#define MICROPY_STACK_CHECK (1) #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) -#define MICROPY_KBD_EXCEPTION (1) #define MICROPY_REPL_EVENT_DRIVEN (0) -#define MICROPY_REPL_AUTO_INDENT (1) -#define MICROPY_HELPER_REPL (1) -#define MICROPY_ENABLE_SOURCE_LINE (1) -#define MICROPY_MODULE_BUILTIN_INIT (1) -#define MICROPY_MODULE_WEAK_LINKS (1) -#define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_USE_INTERNAL_ERRNO (1) -#define MICROPY_ENABLE_SCHEDULER (1) -#define MICROPY_PY_DESCRIPTORS (1) -#define MICROPY_PY_BUILTINS_COMPLEX (0) -#define MICROPY_PY_BUILTINS_STR_UNICODE (1) -#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) -#define MICROPY_PY_BUILTINS_FROZENSET (1) -#define MICROPY_PY_BUILTINS_ROUND_INT (1) -#define MICROPY_PY_BUILTINS_INPUT (1) -#define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_TEXT esp_help_text -#define MICROPY_PY_BUILTINS_HELP_MODULES (1) -#define MICROPY_PY___FILE__ (0) -#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) -#define MICROPY_PY_COLLECTIONS_DEQUE (1) -#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) -#define MICROPY_PY_IO_IOBASE (1) -#define MICROPY_PY_SYS_MAXSIZE (1) -#define MICROPY_PY_SYS_STDFILES (1) -#define MICROPY_PY_UERRNO (1) -#define MICROPY_PY_UBINASCII (1) -#define MICROPY_PY_UCTYPES (1) -#define MICROPY_PY_UHASHLIB (1) #define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL && MICROPY_SSL_AXTLS) -#define MICROPY_PY_UHEAPQ (1) #define MICROPY_PY_UTIMEQ (1) -#define MICROPY_PY_UJSON (1) -#define MICROPY_PY_URANDOM (1) #define MICROPY_PY_URANDOM_SEED_INIT_FUNC (*WDEV_HWRNG) -#define MICROPY_PY_URE (1) -#define MICROPY_PY_USELECT (1) #define MICROPY_PY_UTIME_MP_HAL (1) -#define MICROPY_PY_UZLIB (1) #define MICROPY_PY_LWIP (1) #define MICROPY_PY_LWIP_SOCK_RAW (1) #define MICROPY_PY_MACHINE (1) @@ -79,8 +79,6 @@ #define MICROPY_PY_WEBREPL (1) #define MICROPY_PY_WEBREPL_DELAY (20) #define MICROPY_PY_WEBREPL_STATIC_FILEBUF (1) -#define MICROPY_PY_MICROPYTHON_MEM_INFO (1) -#define MICROPY_PY_UOS (1) #define MICROPY_PY_UOS_INCLUDEFILE "ports/esp8266/moduos.c" #define MICROPY_PY_OS_DUPTERM (2) #define MICROPY_PY_UOS_DUPTERM_NOTIFY (1) @@ -92,7 +90,6 @@ #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #define MICROPY_WARNINGS (1) #define MICROPY_PY_STR_BYTES_CMP_WARN (1) -#define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_STREAMS_POSIX_API (1) #define MICROPY_MODULE_FROZEN_LEXER mp_lexer_new_from_str32 From 226b2d77ee14ca488cbd34c90491aa6dd291c9e0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 23 Jun 2022 13:05:56 +1000 Subject: [PATCH 0038/1041] esp8266/mpconfigport: Disable MICROPY_PY_UTIMEQ. This is no longer needed with new uasyncio v3, and disabling it saves 900 bytes. Signed-off-by: Damien George --- ports/esp8266/mpconfigport.h | 1 - 1 file changed, 1 deletion(-) diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 365327aa4c..c78ae3ce0b 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -57,7 +57,6 @@ #define MICROPY_USE_INTERNAL_ERRNO (1) #define MICROPY_PY_BUILTINS_HELP_TEXT esp_help_text #define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL && MICROPY_SSL_AXTLS) -#define MICROPY_PY_UTIMEQ (1) #define MICROPY_PY_URANDOM_SEED_INIT_FUNC (*WDEV_HWRNG) #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_LWIP (1) From 6c1495b5fedb6034dd067b654cf437c34f5fe98b Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Thu, 21 Apr 2022 15:57:32 +0200 Subject: [PATCH 0039/1041] stm32/usbd_cdc_interface: Add support for Arduino 1200bps touch. If the serial port is closed with baudrate at 1200 then the board will enter its bootloader. --- ports/stm32/usbd_cdc_interface.c | 37 ++++++++++++++++++++------------ ports/stm32/usbd_cdc_interface.h | 1 + 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/ports/stm32/usbd_cdc_interface.c b/ports/stm32/usbd_cdc_interface.c index b369524ca7..474aced7ab 100644 --- a/ports/stm32/usbd_cdc_interface.c +++ b/ports/stm32/usbd_cdc_interface.c @@ -42,9 +42,11 @@ #include "usbd_cdc_interface.h" #include "pendsv.h" -#include "py/obj.h" +#include "py/runtime.h" +#include "py/mphal.h" #include "shared/runtime/interrupt_char.h" #include "irq.h" +#include "modmachine.h" #if MICROPY_HW_ENABLE_USB @@ -62,6 +64,14 @@ // Used to control the connect_state variable when USB host opens the serial port static uint8_t usbd_cdc_connect_tx_timer; +#if MICROPY_HW_USB_CDC_1200BPS_TOUCH +static mp_sched_node_t mp_bootloader_sched_node; +STATIC void usbd_cdc_run_bootloader_task(mp_sched_node_t *node) { + mp_hal_delay_ms(250); + machine_bootloader(0, NULL); +} +#endif + uint8_t *usbd_cdc_init(usbd_cdc_state_t *cdc_in) { usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t *)cdc_in; @@ -81,6 +91,7 @@ uint8_t *usbd_cdc_init(usbd_cdc_state_t *cdc_in) { } else { cdc->flow |= USBD_CDC_FLOWCONTROL_CTS; } + cdc->bitrate = 0; // Return the buffer to place the first USB OUT packet return cdc->rx_packet_buf; @@ -121,22 +132,14 @@ int8_t usbd_cdc_control(usbd_cdc_state_t *cdc_in, uint8_t cmd, uint8_t *pbuf, ui break; case CDC_SET_LINE_CODING: - #if 0 - LineCoding.bitrate = (uint32_t)(pbuf[0] | (pbuf[1] << 8) | \ - (pbuf[2] << 16) | (pbuf[3] << 24)); - LineCoding.format = pbuf[4]; - LineCoding.paritytype = pbuf[5]; - LineCoding.datatype = pbuf[6]; - /* Set the new configuration */ - #endif + cdc->bitrate = *((uint32_t *)pbuf); break; case CDC_GET_LINE_CODING: - /* Add your code here */ - pbuf[0] = (uint8_t)(115200); - pbuf[1] = (uint8_t)(115200 >> 8); - pbuf[2] = (uint8_t)(115200 >> 16); - pbuf[3] = (uint8_t)(115200 >> 24); + pbuf[0] = (uint8_t)(cdc->bitrate); + pbuf[1] = (uint8_t)(cdc->bitrate >> 8); + pbuf[2] = (uint8_t)(cdc->bitrate >> 16); + pbuf[3] = (uint8_t)(cdc->bitrate >> 24); pbuf[4] = 0; // stop bits (1) pbuf[5] = 0; // parity (none) pbuf[6] = 8; // number of bits (8) @@ -157,6 +160,12 @@ int8_t usbd_cdc_control(usbd_cdc_state_t *cdc_in, uint8_t cmd, uint8_t *pbuf, ui #endif } else { cdc->connect_state = USBD_CDC_CONNECT_STATE_DISCONNECTED; + #if MICROPY_HW_USB_CDC_1200BPS_TOUCH + if (cdc->bitrate == 1200) { + // Delay bootloader jump to allow the USB stack to service endpoints. + mp_sched_schedule_node(&mp_bootloader_sched_node, usbd_cdc_run_bootloader_task); + } + #endif } break; } diff --git a/ports/stm32/usbd_cdc_interface.h b/ports/stm32/usbd_cdc_interface.h index 76b5c9e79b..2daa43a521 100644 --- a/ports/stm32/usbd_cdc_interface.h +++ b/ports/stm32/usbd_cdc_interface.h @@ -62,6 +62,7 @@ typedef struct _usbd_cdc_itf_t { volatile uint8_t connect_state; // indicates if we are connected uint8_t attached_to_repl; // indicates if interface is connected to REPL uint8_t flow; // USBD_CDC_FLOWCONTROL_* setting flags + uint32_t bitrate; } usbd_cdc_itf_t; // This is implemented in usb.c From 9f6f8b2fdd0a90394b9fcc9b0d9198d32aee2cf5 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Fri, 17 Jun 2022 15:34:50 +0200 Subject: [PATCH 0040/1041] shared/runtime/tinyusb_helpers: Add TinyUSB helper functions. Currently this file only includes a CDC jump-to-bootloader helper function. --- shared/runtime/tinyusb_helpers.c | 54 ++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 shared/runtime/tinyusb_helpers.c diff --git a/shared/runtime/tinyusb_helpers.c b/shared/runtime/tinyusb_helpers.c new file mode 100644 index 0000000000..00b72e74b7 --- /dev/null +++ b/shared/runtime/tinyusb_helpers.c @@ -0,0 +1,54 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Ibrahim Abdelkader + * + * 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/mphal.h" +#include "modmachine.h" + +#if MICROPY_HW_USB_CDC_1200BPS_TOUCH + +#include "tusb.h" + +static mp_sched_node_t mp_bootloader_sched_node; + +STATIC void usbd_cdc_run_bootloader_task(mp_sched_node_t *node) { + mp_hal_delay_ms(250); + machine_bootloader(0, NULL); +} + +void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { + if (dtr == false && rts == false) { + // Device is disconnected. + cdc_line_coding_t line_coding; + tud_cdc_n_get_line_coding(itf, &line_coding); + if (line_coding.bit_rate == 1200) { + // Delay bootloader jump to allow the USB stack to service endpoints. + mp_sched_schedule_node(&mp_bootloader_sched_node, usbd_cdc_run_bootloader_task); + } + } +} + +#endif From de823e7741bcb817df7c231620103cc30beab0ba Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Thu, 21 Apr 2022 16:04:19 +0200 Subject: [PATCH 0041/1041] rp2/boards/ARDUINO_NANO_RP2040_CONNECT: Enable Arduino 1200bps touch. --- ports/rp2/CMakeLists.txt | 1 + ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h | 1 + 2 files changed, 2 insertions(+) diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index d6a428c91c..0088ba2c6d 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -83,6 +83,7 @@ set(MICROPY_SOURCE_LIB ${MICROPY_DIR}/shared/runtime/pyexec.c ${MICROPY_DIR}/shared/runtime/stdout_helpers.c ${MICROPY_DIR}/shared/runtime/sys_stdio_mphal.c + ${MICROPY_DIR}/shared/runtime/tinyusb_helpers.c ${MICROPY_DIR}/shared/timeutils/timeutils.c ) diff --git a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h index 6d04e3e1d0..3f18596155 100644 --- a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h +++ b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h @@ -19,6 +19,7 @@ #define MICROPY_HW_USB_MSC (1) #define MICROPY_HW_USB_VID (0x2341) #define MICROPY_HW_USB_PID (0x025e) +#define MICROPY_HW_USB_CDC_1200BPS_TOUCH (1) // UART 1 config. #define MICROPY_HW_UART1_TX (8) From 425d8fc0d652a58f1a6e81d953281beb5784e18b Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Thu, 21 Apr 2022 16:35:59 +0200 Subject: [PATCH 0042/1041] nrf: Enable optional support for Arduino 1200bps touch. Individual boards must enable it via MICROPY_HW_USB_CDC_1200BPS_TOUCH. --- ports/nrf/Makefile | 1 + ports/nrf/mpconfigport.h | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 25b8c03d1a..d022892641 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -232,6 +232,7 @@ SRC_LIB += $(addprefix shared/,\ runtime/pyexec.c \ runtime/sys_stdio_mphal.c \ runtime/interrupt_char.c \ + runtime/tinyusb_helpers.c \ timeutils/timeutils.c \ ) diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 102be3eaaf..243c30809a 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -157,6 +157,10 @@ #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_USE_INTERNAL_ERRNO (1) +#if MICROPY_HW_USB_CDC_1200BPS_TOUCH +#define MICROPY_ENABLE_SCHEDULER (1) +#define MICROPY_SCHEDULER_STATIC_NODES (1) +#endif #define MICROPY_PY_FUNCTION_ATTRS (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) From 5f4539b0ca5c3d832122b3a44c5a075d4ceb6203 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 19 Jun 2022 08:44:13 +0200 Subject: [PATCH 0043/1041] esp32/machine_uart: Implement the functionality of timeout_char arg. Using it for the rx-timeout. The value is given as ms, which is then converted to character times. A value of less than a character time will cause the rx call to return immediately after 1 character, which may be inefficient at high transmission rates. Addresses #8778. --- ports/esp32/machine_uart.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/ports/esp32/machine_uart.c b/ports/esp32/machine_uart.c index c0eedb80b3..49ce78b1b2 100644 --- a/ports/esp32/machine_uart.c +++ b/ports/esp32/machine_uart.c @@ -267,12 +267,18 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co } // set timeout_char - // make sure it is at least as long as a whole character (13 bits to be safe) + // make sure it is at least as long as a whole character (12 bits here) if (args[ARG_timeout_char].u_int != -1) { self->timeout_char = args[ARG_timeout_char].u_int; - uint32_t min_timeout_char = 13000 / baudrate + 1; - if (self->timeout_char < min_timeout_char) { - self->timeout_char = min_timeout_char; + uint32_t char_time_ms = 12000 / baudrate + 1; + uint32_t rx_timeout = self->timeout_char / char_time_ms; + if (rx_timeout < 1) { + #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 1, 0) + uart_set_rx_full_threshold(self->uart_num, 1); + #endif + uart_set_rx_timeout(self->uart_num, 1); + } else { + uart_set_rx_timeout(self->uart_num, rx_timeout); } } From cf550ad9d1f15d862d7e9fb3526cd57e1ea69057 Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Sat, 28 May 2022 23:01:04 +0200 Subject: [PATCH 0044/1041] esp32/boards: Increase 512 bytes limit on ULP programs to 2040. Allow esp32.ULP.load_binary() to use the maximum amount of memory available again, which is 2040 bytes unless MICROPY_HW_RTC_USER_MEM_MAX is customized. This value regressed in 3d49b157b89a59774fc4958dcaacd2c96ba6eaa4 --- ports/esp32/boards/sdkconfig.base | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/esp32/boards/sdkconfig.base b/ports/esp32/boards/sdkconfig.base index 4b29013434..6b891aa006 100644 --- a/ports/esp32/boards/sdkconfig.base +++ b/ports/esp32/boards/sdkconfig.base @@ -49,6 +49,7 @@ CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y # ULP coprocessor support CONFIG_ESP32_ULP_COPROC_ENABLED=y +CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=2040 # For cmake build CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y From ba21f76f89d05150b7d6ec2dfac45476ffc4866c Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Thu, 26 May 2022 16:29:26 +0200 Subject: [PATCH 0045/1041] esp32/modesp32: Add wake_on_ulp() so ULP can wake CPU from deepsleep. Add esp32.wake_on_ulp() to give access to esp_sleep_enable_ulp_wakeup(), which is needed to allow the ULP co-processor to wake the main CPU from deep sleep. --- docs/library/esp32.rst | 5 +++++ ports/esp32/machine_rtc.h | 1 + ports/esp32/modesp32.c | 10 ++++++++++ ports/esp32/modmachine.c | 6 ++++++ 4 files changed, 22 insertions(+) diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index 3348003499..f0f0c8ef1f 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -18,6 +18,11 @@ Functions Configure whether or not a touch will wake the device from sleep. *wake* should be a boolean value. +.. function:: wake_on_ulp(wake) + + Configure whether or not the Ultra-Low-Power co-processor can wake the + device from sleep. *wake* should be a boolean value. + .. function:: wake_on_ext0(pin, level) Configure how EXT0 wakes the device from sleep. *pin* can be ``None`` diff --git a/ports/esp32/machine_rtc.h b/ports/esp32/machine_rtc.h index 6e70f74385..ce2a5482a2 100644 --- a/ports/esp32/machine_rtc.h +++ b/ports/esp32/machine_rtc.h @@ -34,6 +34,7 @@ typedef struct { uint64_t ext1_pins; // set bit == pin# int8_t ext0_pin; // just the pin#, -1 == None bool wake_on_touch : 1; + bool wake_on_ulp : 1; bool ext0_level : 1; wake_type_t ext0_wake_types; bool ext1_level : 1; diff --git a/ports/esp32/modesp32.c b/ports/esp32/modesp32.c index 0dbd7efda3..017db36e22 100644 --- a/ports/esp32/modesp32.c +++ b/ports/esp32/modesp32.c @@ -131,6 +131,15 @@ STATIC mp_obj_t esp32_wake_on_ext1(size_t n_args, const mp_obj_t *pos_args, mp_m } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_wake_on_ext1_obj, 0, esp32_wake_on_ext1); +STATIC mp_obj_t esp32_wake_on_ulp(const mp_obj_t wake) { + if (machine_rtc_config.ext0_pin != -1) { + mp_raise_ValueError(MP_ERROR_TEXT("no resources")); + } + machine_rtc_config.wake_on_ulp = mp_obj_is_true(wake); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_wake_on_ulp_obj, esp32_wake_on_ulp); + STATIC mp_obj_t esp32_gpio_deep_sleep_hold(const mp_obj_t enable) { if (mp_obj_is_true(enable)) { gpio_deep_sleep_hold_en(); @@ -197,6 +206,7 @@ STATIC const mp_rom_map_elem_t esp32_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_wake_on_touch), MP_ROM_PTR(&esp32_wake_on_touch_obj) }, { MP_ROM_QSTR(MP_QSTR_wake_on_ext0), MP_ROM_PTR(&esp32_wake_on_ext0_obj) }, { MP_ROM_QSTR(MP_QSTR_wake_on_ext1), MP_ROM_PTR(&esp32_wake_on_ext1_obj) }, + { MP_ROM_QSTR(MP_QSTR_wake_on_ulp), MP_ROM_PTR(&esp32_wake_on_ulp_obj) }, { MP_ROM_QSTR(MP_QSTR_gpio_deep_sleep_hold), MP_ROM_PTR(&esp32_gpio_deep_sleep_hold_obj) }, #if CONFIG_IDF_TARGET_ESP32 { MP_ROM_QSTR(MP_QSTR_raw_temperature), MP_ROM_PTR(&esp32_raw_temperature_obj) }, diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index aee3be0e74..db77becf87 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -144,6 +144,12 @@ STATIC mp_obj_t machine_sleep_helper(wake_type_t wake_type, size_t n_args, const } } + if (machine_rtc_config.wake_on_ulp) { + if (esp_sleep_enable_ulp_wakeup() != ESP_OK) { + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("esp_sleep_enable_ulp_wakeup() failed")); + } + } + #endif switch (wake_type) { From c21452a1d23a7cf70fdd6b2c069d460c1a5a7be8 Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Tue, 21 Apr 2020 13:18:55 -0700 Subject: [PATCH 0046/1041] extmod/uasyncio: Attempt to write immediately in Stream.write method. The main aim of this change is to reduce the number of heap allocations when writing data to a stream. This is done in two ways: 1. Eliminate appending of data when .write() is called multiple times before calling .drain(). With this commit, the data is written out immediately if the underlying stream is not blocked, so there is no accumulation of the data in a temporary buffer. 2. Eliminate copying of non-bytes objects passed to .write(). Prior to this commit, passing a bytearray or memoryview to .write() would always result in a copy of it being made and turned into a bytes object. That won't happen now if the underlying stream is not blocked. Also, this change makes .write () more closely implement the CPython documented semantics: "The method attempts to write the data to the underlying socket immediately. If that fails, the data is queued in an internal write buffer until it can be sent." --- extmod/uasyncio/stream.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/extmod/uasyncio/stream.py b/extmod/uasyncio/stream.py index af3b8feab3..750d8e9740 100644 --- a/extmod/uasyncio/stream.py +++ b/extmod/uasyncio/stream.py @@ -56,9 +56,19 @@ class Stream: return l def write(self, buf): + if not self.out_buf: + # Try to write immediately to the underlying stream. + ret = self.s.write(buf) + if ret == len(buf): + return + if ret is not None: + buf = buf[ret:] self.out_buf += buf async def drain(self): + if not self.out_buf: + # Drain must always yield, so a tight loop of write+drain can't block the scheduler. + return await core.sleep_ms(0) mv = memoryview(self.out_buf) off = 0 while off < len(mv): From 2a2589738c7bcc0a318f9054562de9a62575d8cc Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 24 Jun 2022 16:39:45 +1000 Subject: [PATCH 0047/1041] tests/extmod: Add heap-lock test for stream writing. Signed-off-by: Damien George --- tests/extmod/uasyncio_heaplock.py | 32 +++++++++++++++++++++++++-- tests/extmod/uasyncio_heaplock.py.exp | 3 +++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/tests/extmod/uasyncio_heaplock.py b/tests/extmod/uasyncio_heaplock.py index 34a51cd370..a6b4a0819c 100644 --- a/tests/extmod/uasyncio_heaplock.py +++ b/tests/extmod/uasyncio_heaplock.py @@ -1,4 +1,8 @@ -# test that basic scheduling of tasks, and uasyncio.sleep_ms, does not use the heap +# test that the following do not use the heap: +# - basic scheduling of tasks +# - uasyncio.sleep_ms +# - StreamWriter.write, stream is blocked and data to write is a bytes object +# - StreamWriter.write, when stream is not blocked import micropython @@ -22,6 +26,17 @@ except ImportError: raise SystemExit +class TestStream: + def __init__(self, blocked): + self.blocked = blocked + + def write(self, data): + print("TestStream.write", data) + if self.blocked: + return None + return len(data) + + async def task(id, n, t): for i in range(n): print(id, i) @@ -32,14 +47,27 @@ async def main(): t1 = asyncio.create_task(task(1, 4, 100)) t2 = asyncio.create_task(task(2, 2, 250)) + # test scheduling tasks, and calling sleep_ms micropython.heap_lock() - print("start") await asyncio.sleep_ms(5) print("sleep") await asyncio.sleep_ms(350) print("finish") + micropython.heap_unlock() + # test writing to a stream, when the underlying stream is blocked + s = asyncio.StreamWriter(TestStream(True), None) + micropython.heap_lock() + s.write(b"12") + micropython.heap_unlock() + + # test writing to a stream, when the underlying stream is not blocked + buf = bytearray(b"56") + s = asyncio.StreamWriter(TestStream(False), None) + micropython.heap_lock() + s.write(b"34") + s.write(buf) micropython.heap_unlock() diff --git a/tests/extmod/uasyncio_heaplock.py.exp b/tests/extmod/uasyncio_heaplock.py.exp index 68c6366c6f..5c7b4e3dba 100644 --- a/tests/extmod/uasyncio_heaplock.py.exp +++ b/tests/extmod/uasyncio_heaplock.py.exp @@ -7,3 +7,6 @@ sleep 2 1 1 3 finish +TestStream.write b'12' +TestStream.write b'34' +TestStream.write bytearray(b'56') From db7682e02d3ffd3338f20effc9ad4735a48bf774 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 22 Aug 2020 16:39:15 +1000 Subject: [PATCH 0048/1041] extmod/uasyncio: Implement stream read(-1) to read all data up to EOF. Fixes issue #6355. Signed-off-by: Damien George --- docs/library/uasyncio.rst | 6 ++- extmod/uasyncio/stream.py | 14 +++-- tests/multi_net/uasyncio_tcp_readall.py | 60 +++++++++++++++++++++ tests/multi_net/uasyncio_tcp_readall.py.exp | 8 +++ 4 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 tests/multi_net/uasyncio_tcp_readall.py create mode 100644 tests/multi_net/uasyncio_tcp_readall.py.exp diff --git a/docs/library/uasyncio.rst b/docs/library/uasyncio.rst index 0c71702420..0abbf8dd8d 100644 --- a/docs/library/uasyncio.rst +++ b/docs/library/uasyncio.rst @@ -237,9 +237,11 @@ TCP stream connections This is a coroutine. -.. method:: Stream.read(n) +.. method:: Stream.read(n=-1) - Read up to *n* bytes and return them. + Read up to *n* bytes and return them. If *n* is not provided or -1 then read all + bytes until EOF. The returned value will be an empty bytes object if EOF is + encountered before any bytes are read. This is a coroutine. diff --git a/extmod/uasyncio/stream.py b/extmod/uasyncio/stream.py index 750d8e9740..785e43555d 100644 --- a/extmod/uasyncio/stream.py +++ b/extmod/uasyncio/stream.py @@ -26,9 +26,17 @@ class Stream: # TODO yield? self.s.close() - async def read(self, n): - yield core._io_queue.queue_read(self.s) - return self.s.read(n) + async def read(self, n=-1): + r = b"" + while True: + yield core._io_queue.queue_read(self.s) + r2 = self.s.read(n) + if r2 is not None: + if n >= 0: + return r2 + if not len(r2): + return r + r += r2 async def readinto(self, buf): yield core._io_queue.queue_read(self.s) diff --git a/tests/multi_net/uasyncio_tcp_readall.py b/tests/multi_net/uasyncio_tcp_readall.py new file mode 100644 index 0000000000..c411f1c69d --- /dev/null +++ b/tests/multi_net/uasyncio_tcp_readall.py @@ -0,0 +1,60 @@ +# Test uasyncio stream read(-1) method using TCP server/client + +try: + import uasyncio as asyncio +except ImportError: + try: + import asyncio + except ImportError: + print("SKIP") + raise SystemExit + +PORT = 8000 + + +async def handle_connection(reader, writer): + writer.write(b"a") + await writer.drain() + + # Split the first 2 bytes up so the client must wait for the second one + await asyncio.sleep(0.1) + + writer.write(b"b") + await writer.drain() + + writer.write(b"c") + await writer.drain() + + print("close") + writer.close() + await writer.wait_closed() + + print("done") + ev.set() + + +async def tcp_server(): + global ev + ev = asyncio.Event() + server = await asyncio.start_server(handle_connection, "0.0.0.0", PORT) + print("server running") + multitest.next() + async with server: + await asyncio.wait_for(ev.wait(), 2) + + +async def tcp_client(): + reader, writer = await asyncio.open_connection(IP, PORT) + print(await reader.read()) + print(await reader.read()) # should be empty + print(await reader.read(1)) # should be empty + + +def instance0(): + multitest.globals(IP=multitest.get_network_ip()) + asyncio.run(tcp_server()) + + +def instance1(): + multitest.next() + asyncio.run(tcp_client()) diff --git a/tests/multi_net/uasyncio_tcp_readall.py.exp b/tests/multi_net/uasyncio_tcp_readall.py.exp new file mode 100644 index 0000000000..0bf3dcba60 --- /dev/null +++ b/tests/multi_net/uasyncio_tcp_readall.py.exp @@ -0,0 +1,8 @@ +--- instance0 --- +server running +close +done +--- instance1 --- +b'abc' +b'' +b'' From fbc50196ad60fa548e79f8d1e5d87c3fa93c7848 Mon Sep 17 00:00:00 2001 From: Philipp Ebensberger Date: Sun, 19 Jun 2022 23:00:38 +0200 Subject: [PATCH 0049/1041] mimxrt/Makefile: Refactor Makefile and divide it into sections. Reworks grouping of Makefile variables and reorders variable values in alphabetic order. --- ports/mimxrt/Makefile | 365 ++++++++++++++++++++++++++---------------- 1 file changed, 227 insertions(+), 138 deletions(-) diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index 759fb5c459..7f93a6826d 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -1,72 +1,61 @@ +# ============================================================================= +# Parameter Configuration +# ============================================================================= + BOARD ?= TEENSY40 BOARD_DIR ?= boards/$(BOARD) BUILD ?= build-$(BOARD) - PORT ?= /dev/ttyACM0 - CROSS_COMPILE ?= arm-none-eabi- - -ifeq ($(wildcard $(BOARD_DIR)/.),) -$(error Invalid BOARD specified: $(BOARD_DIR)) -endif - -include ../../py/mkenv.mk -include $(BOARD_DIR)/mpconfigboard.mk - -LD_MEMORY_CONFIG_DEFINES += \ - MICROPY_HW_FLASH_TYPE=$(MICROPY_HW_FLASH_TYPE) \ - MICROPY_HW_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE) - -ifdef MICROPY_HW_FLASH_RESERVED -LD_MEMORY_CONFIG_DEFINES += MICROPY_HW_FLASH_RESERVED=$(MICROPY_HW_FLASH_RESERVED) -endif - -ifdef MICROPY_HW_SDRAM_AVAIL -CFLAGS += \ - -DMICROPY_HW_SDRAM_AVAIL=$(MICROPY_HW_SDRAM_AVAIL) \ - -DMICROPY_HW_SDRAM_SIZE=$(MICROPY_HW_SDRAM_SIZE) - -LD_MEMORY_CONFIG_DEFINES += \ - MICROPY_HW_SDRAM_AVAIL=$(MICROPY_HW_SDRAM_AVAIL) \ - MICROPY_HW_SDRAM_SIZE=$(MICROPY_HW_SDRAM_SIZE) -endif - -# Qstr definitions (must come before including py.mk) -QSTR_DEFS = qstrdefsport.h -QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h +GIT_SUBMODULES = lib/tinyusb lib/nxp_driver lib/lwip lib/mbedtls # MicroPython feature configurations FROZEN_MANIFEST ?= boards/manifest.py MICROPY_VFS_LFS2 ?= 1 MICROPY_VFS_FAT ?= 1 +# qstr definitions (must come before including py.mk) +QSTR_DEFS = qstrdefsport.h +QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h + +# Generation scripts +MAKE_PINS = boards/make-pins.py +MAKE_FLEXRAM_LD = boards/make-flexram-config.py + +# Include py make environment +include ../../py/mkenv.mk + +# Include micropython configuration board makefile +ifeq ($(wildcard $(BOARD_DIR)/.),) +$(error Invalid BOARD specified: $(BOARD_DIR)) +endif +include $(BOARD_DIR)/mpconfigboard.mk + # Include py core make definitions include $(TOP)/py/py.mk include $(TOP)/extmod/extmod.mk -GIT_SUBMODULES = lib/tinyusb lib/nxp_driver lib/lwip lib/mbedtls - +# Set SDK directory based on MCU_SERIES MCU_DIR = lib/nxp_driver/sdk/devices/$(MCU_SERIES) + +# Select linker scripts based on MCU_SERIES LD_FILES = boards/$(MCU_SERIES).ld boards/common.ld -MAKE_PINS = boards/make-pins.py -MAKE_FLEXRAM_LD = boards/make-flexram-config.py -BOARD_PINS = $(BOARD_DIR)/pins.csv +# Parameter configurations for generation AF_FILE = boards/$(MCU_SERIES)_af.csv +BOARD_PINS = $(BOARD_DIR)/pins.csv PREFIX_FILE = boards/mimxrt_prefix.c -GEN_PINS_SRC = $(BUILD)/pins_gen.c -GEN_PINS_HDR = $(HEADER_BUILD)/pins.h -GEN_PINS_QSTR = $(BUILD)/pins_qstr.h +GEN_FLEXRAM_CONFIG_SRC = $(BUILD)/flexram_config.s GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h GEN_PINS_AF_PY = $(BUILD)/pins_af.py -GEN_FLEXRAM_CONFIG_SRC = $(BUILD)/flexram_config.s +GEN_PINS_HDR = $(HEADER_BUILD)/pins.h +GEN_PINS_QSTR = $(BUILD)/pins_qstr.h +GEN_PINS_SRC = $(BUILD)/pins_gen.c -# mcu driver cause following warnings -#CFLAGS += -Wno-error=float-equal -Wno-error=nested-externs -CFLAGS += -Wno-error=unused-parameter +# ============================================================================= +# Includes +# ============================================================================= -INC += -I. -INC += -Ihal INC += -I$(BOARD_DIR) INC += -I$(BUILD) INC += -I$(TOP) @@ -77,90 +66,19 @@ INC += -I$(TOP)/lib/oofatfs INC += -I$(TOP)/lib/tinyusb/hw INC += -I$(TOP)/lib/tinyusb/hw/bsp/teensy_40 INC += -I$(TOP)/lib/tinyusb/src - -CFLAGS_MCU = -mtune=cortex-m7 -mcpu=cortex-m7 -CFLAGS += $(INC) -Wall -Werror -Wdouble-promotion -Wfloat-conversion -std=c99 -nostdlib -mthumb $(CFLAGS_MCU) -CFLAGS += -DCPU_$(MCU_SERIES) -DCPU_$(MCU_VARIANT) -DBOARD_$(BOARD) -CFLAGS += -DXIP_EXTERNAL_FLASH=1 \ - -DXIP_BOOT_HEADER_ENABLE=1 \ - -DFSL_SDK_ENABLE_DRIVER_CACHE_CONTROL=1 \ - -DCFG_TUSB_MCU=OPT_MCU_MIMXRT10XX \ - -D__STARTUP_CLEAR_BSS \ - -D__STARTUP_INITIALIZE_RAMFUNCTION \ - -D__START=main \ - -DCPU_HEADER_H='<$(MCU_SERIES).h>' \ - -DCLOCK_CONFIG_H='' \ - -DBOARD_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE) \ - -DMICROPY_HW_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE) \ - -CFLAGS += -DI2C_RETRY_TIMES=1000000 -DSPI_RETRY_TIMES=1000000 -DUART_RETRY_TIMES=1000000 - -ifeq ($(MICROPY_PY_MACHINE_SDCARD),1) -CFLAGS += -DMICROPY_PY_MACHINE_SDCARD=1 -endif - -CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) - -# Configure floating point support -ifeq ($(MICROPY_FLOAT_IMPL),double) -CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_DOUBLE -CFLAGS_MCU += -mfloat-abi=hard -mfpu=fpv5-d16 -else -ifeq ($(MICROPY_FLOAT_IMPL),none) -CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_NONE -else -CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_FLOAT -CFLAGS += -fsingle-precision-constant -CFLAGS_MCU += -mfloat-abi=softfp -mfpu=fpv5-sp-d16 -endif -endif - -SUPPORTS_HARDWARE_FP_SINGLE = 0 -SUPPORTS_HARDWARE_FP_DOUBLE = 0 - -LDFLAGS = -Map=$@.map --cref --print-memory-usage -LDDEFINES = $(addprefix -D, $(LD_MEMORY_CONFIG_DEFINES)) -LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) - -# Tune for Debugging or Optimization -ifeq ($(DEBUG),1) -CFLAGS += -Og -ggdb -LDFLAGS += --gc-sections -CFLAGS += -fdata-sections -ffunction-sections -else -CFLAGS += -Os -DNDEBUG -LDFLAGS += --gc-sections -CFLAGS += -fdata-sections -ffunction-sections -endif +INC += -I. +INC += -Ihal # All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP ifeq ($(MICROPY_PY_LWIP), 1) - INC += -Ilwip_inc INC += -Ihal/phy - -SRC_MOD := $(filter-out %/mbedtls/library/error.c, $(SRC_MOD)) - -SRC_ETH_C += \ - hal/phy/mdio/enet/fsl_enet_mdio.c \ - hal/phy/device/phydp83825/fsl_phydp83825.c \ - hal/phy/device/phydp83848/fsl_phydp83848.c \ - hal/phy/device/phyksz8081/fsl_phyksz8081.c \ - hal/phy/device/phylan8720/fsl_phylan8720.c \ - lib/mbedtls_errors/mp_mbedtls_errors.c \ - $(MCU_DIR)/drivers/fsl_enet.c \ - -SRC_QSTR += \ - extmod/modnetwork.c \ - extmod/moduwebsocket.c \ - extmod/modusocket.c \ - network_lan.c \ - -CFLAGS += -DFSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE=1 \ - -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' - endif +# ============================================================================= +# Sources +# ============================================================================= + # TinyUSB Stack source SRC_TINYUSB_C += \ lib/tinyusb/src/class/cdc/cdc_device.c \ @@ -176,6 +94,20 @@ SRC_TINYUSB_C += \ lib/tinyusb/src/portable/nxp/transdimension/dcd_transdimension.c \ lib/tinyusb/src/tusb.c +# All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP +ifeq ($(MICROPY_PY_LWIP), 1) +SRC_MOD := $(filter-out %/mbedtls/library/error.c, $(SRC_MOD)) +SRC_ETH_C += \ + $(MCU_DIR)/drivers/fsl_enet.c \ + hal/phy/device/phydp83825/fsl_phydp83825.c \ + hal/phy/device/phydp83848/fsl_phydp83848.c \ + hal/phy/device/phyksz8081/fsl_phyksz8081.c \ + hal/phy/device/phylan8720/fsl_phylan8720.c \ + hal/phy/mdio/enet/fsl_enet_mdio.c \ + lib/mbedtls_errors/mp_mbedtls_errors.c +endif + +# NXP SDK sources SRC_HAL_IMX_C += \ $(MCU_DIR)/drivers/fsl_adc.c \ $(MCU_DIR)/drivers/fsl_cache.c \ @@ -213,6 +145,7 @@ SRC_HAL_IMX_C += \ $(MCU_DIR)/drivers/fsl_qtmr.c endif +# C source files SRC_C += \ board_init.c \ boards/$(MCU_SERIES)_clock_config.c \ @@ -254,9 +187,9 @@ SRC_C += \ sdcard.c \ shared/libc/printf.c \ shared/libc/string0.c \ + shared/netutils/dhcpserver.c \ shared/netutils/netutils.c \ shared/netutils/trace.c \ - shared/netutils/dhcpserver.c \ shared/readline/readline.c \ shared/runtime/gchelper_native.c \ shared/runtime/interrupt_char.c \ @@ -273,33 +206,28 @@ SRC_C += \ $(SRC_ETH_C) \ ifeq ($(MICROPY_HW_FLASH_TYPE), qspi_nor) -CFLAGS += -DBOARD_FLASH_OPS_HEADER_H=\"hal/flexspi_nor_flash.h\" SRC_C += hal/flexspi_nor_flash.c ifeq ($(MICROPY_HW_BOARD_FLASH_FILES), 1) -CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"$(BOARD)_flexspi_flash_config.h\" SRC_C += $(BOARD_DIR)/qspi_nor_flash_config.c else -CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"hal/flexspi_flash_config.h\" SRC_C += hal/qspi_nor_flash_config.c -endif +endif # qspi_nor # else ifeq ($(MICROPY_HW_FLASH_TYPE), hyperflash) -CFLAGS += -DBOARD_FLASH_OPS_HEADER_H=\"hal/flexspi_hyper_flash.h\" SRC_C += hal/flexspi_hyper_flash.c ifeq ($(MICROPY_HW_BOARD_FLASH_FILES), 1) -CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"$(BOARD)_flexspi_flash_config.h\" SRC_C += $(BOARD_DIR)/qspi_hyper_flash_config.c else -CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"hal/flexspi_flash_config.h\" SRC_C += hal/qspi_hyper_flash_config.c -endif +endif # hyperflash # else $(error Error: Unknown board flash type $(MICROPY_HW_FLASH_TYPE)) endif +# Math library source files ifeq ($(MICROPY_FLOAT_IMPL),double) LIBM_SRC_C += $(addprefix lib/libm_dbl/,\ __cos.c \ @@ -386,19 +314,31 @@ LIBM_SRC_C += lib/libm/ef_sqrt.c endif endif -LIBM_O = $(addprefix $(BUILD)/, $(LIBM_SRC_C:.c=.o)) - -# Too many warnings in libm_dbl, disable for now. -ifeq ($(MICROPY_FLOAT_IMPL),double) -$(LIBM_O): CFLAGS := $(filter-out -Wdouble-promotion -Wfloat-conversion, $(CFLAGS)) -endif +# Reset variables +SUPPORTS_HARDWARE_FP_SINGLE = 0 +SUPPORTS_HARDWARE_FP_DOUBLE = 0 +# Assembly source files SRC_SS = \ $(MCU_DIR)/gcc/startup_$(MCU_SERIES).S \ hal/resethandler_MIMXRT10xx.S SRC_S += shared/runtime/gchelper_m3.s \ +# ============================================================================= +# QSTR Sources +# ============================================================================= + +# All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP +ifeq ($(MICROPY_PY_LWIP), 1) +SRC_QSTR += \ + extmod/modlwip.c \ + extmod/modnetwork.c \ + extmod/modusocket.c \ + extmod/moduwebsocket.c \ + network_lan.c +endif + # List of sources for qstr extraction SRC_QSTR += \ extmod/modonewire.c \ @@ -421,7 +361,150 @@ SRC_QSTR += \ pin.c \ shared/runtime/mpirq.c \ shared/runtime/sys_stdio_mphal.c \ - $(GEN_PINS_SRC) \ + $(GEN_PINS_SRC) + +# ============================================================================= +# Compiler Flags +# ============================================================================= + +ifeq ($(DEBUG),1) +CFLAGS += -Og -ggdb +else +CFLAGS += -Os -DNDEBUG +endif + +# Configure default compiler flags +CFLAGS += \ + $(INC) \ + -D__START=main \ + -D__STARTUP_CLEAR_BSS \ + -D__STARTUP_INITIALIZE_RAMFUNCTION \ + -DBOARD_$(BOARD) \ + -DBOARD_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE) \ + -DCFG_TUSB_MCU=OPT_MCU_MIMXRT10XX \ + -DCLOCK_CONFIG_H='' \ + -DCPU_$(MCU_SERIES) \ + -DCPU_$(MCU_VARIANT) \ + -DCPU_HEADER_H='<$(MCU_SERIES).h>' \ + -DFSL_SDK_ENABLE_DRIVER_CACHE_CONTROL=1 \ + -DI2C_RETRY_TIMES=1000000 \ + -DMICROPY_HW_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE) \ + -DSPI_RETRY_TIMES=1000000 \ + -DUART_RETRY_TIMES=1000000 \ + -DXIP_BOOT_HEADER_ENABLE=1 \ + -DXIP_EXTERNAL_FLASH=1 \ + -fdata-sections \ + -ffunction-sections \ + -mcpu=cortex-m7 \ + -mthumb \ + -mtune=cortex-m7 \ + -nostdlib \ + -std=c99 \ + -Wall \ + -Wdouble-promotion \ + -Werror \ + -Wfloat-conversion \ + -Wno-error=unused-parameter + +ifeq ($(MICROPY_HW_FLASH_TYPE), qspi_nor) +CFLAGS += -DBOARD_FLASH_OPS_HEADER_H=\"hal/flexspi_nor_flash.h\" + +ifeq ($(MICROPY_HW_BOARD_FLASH_FILES), 1) +CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"$(BOARD)_flexspi_flash_config.h\" +else +CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"hal/flexspi_flash_config.h\" +endif # qspi_nor +# +else ifeq ($(MICROPY_HW_FLASH_TYPE), hyperflash) +CFLAGS += -DBOARD_FLASH_OPS_HEADER_H=\"hal/flexspi_hyper_flash.h\" + +ifeq ($(MICROPY_HW_BOARD_FLASH_FILES), 1) +CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"$(BOARD)_flexspi_flash_config.h\" +else +CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"hal/flexspi_flash_config.h\" +endif # hyperflash +# +else +$(error Error: Unknown board flash type $(MICROPY_HW_FLASH_TYPE)) +endif + +# Configure floating point support +ifeq ($(MICROPY_FLOAT_IMPL),double) +CFLAGS += \ + -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_DOUBLE \ + -mfloat-abi=hard \ + -mfpu=fpv5-d16 +else +ifeq ($(MICROPY_FLOAT_IMPL),none) +CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_NONE +else +CFLAGS += \ + -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_FLOAT \ + -fsingle-precision-constant \ + -mfloat-abi=softfp \ + -mfpu=fpv5-sp-d16 +endif +endif + +# Configure feature specific compiler flags +ifeq ($(MICROPY_PY_MACHINE_SDCARD),1) +CFLAGS += -DMICROPY_PY_MACHINE_SDCARD=1 +endif + +# All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP +ifeq ($(MICROPY_PY_LWIP), 1) +CFLAGS += \ + -DFSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE=1 \ + -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' +endif + +ifdef MICROPY_HW_SDRAM_AVAIL +CFLAGS += \ + -DMICROPY_HW_SDRAM_AVAIL=$(MICROPY_HW_SDRAM_AVAIL) \ + -DMICROPY_HW_SDRAM_SIZE=$(MICROPY_HW_SDRAM_SIZE) +endif + +CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) + +# ============================================================================= +# Linker Flags +# ============================================================================= + +LDFLAGS = \ + --cref \ + --gc-sections \ + --print-memory-usage \ + -Map=$@.map + +# LDDEFINES are used for link time adaptation of linker scripts, utilizing +# the C preprocessor. Therefore keep LDDEFINES separated from LDFLAGS! + +LDDEFINES = \ + -DMICROPY_HW_FLASH_TYPE=$(MICROPY_HW_FLASH_TYPE) \ + -DMICROPY_HW_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE) + +ifdef MICROPY_HW_FLASH_RESERVED +LDDEFINES += -DMICROPY_HW_FLASH_RESERVED=$(MICROPY_HW_FLASH_RESERVED) +endif + +ifdef MICROPY_HW_SDRAM_AVAIL +LDDEFINES += \ + -DMICROPY_HW_SDRAM_AVAIL=$(MICROPY_HW_SDRAM_AVAIL) \ + -DMICROPY_HW_SDRAM_SIZE=$(MICROPY_HW_SDRAM_SIZE) +endif + +# ============================================================================= +# Library and Object files +# ============================================================================= + +LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) +LIBM_O = $(addprefix $(BUILD)/, $(LIBM_SRC_C:.c=.o)) + +# Too many warnings in libm_dbl, disable for now. +ifeq ($(MICROPY_FLOAT_IMPL),double) +$(LIBM_O): CFLAGS := $(filter-out -Wdouble-promotion -Wfloat-conversion, $(CFLAGS)) +endif + OBJ += $(PY_O) OBJ += $(LIBM_O) @@ -434,8 +517,14 @@ OBJ += $(BUILD)/pins_gen.o # Workaround for bug in older gcc, warning on "static usbd_device_t _usbd_dev = { 0 };" $(BUILD)/lib/tinyusb/src/device/usbd.o: CFLAGS += -Wno-missing-braces +# ============================================================================= +# Build targets +# ============================================================================= + all: $(BUILD)/firmware.hex $(BUILD)/firmware.bin +# Process linker scripts with C preprocessor to exchange LDDEFINES and +# aggregate output of preprocessor in a single linker script `link.ld` $(BUILD)/firmware.elf: $(OBJ) $(ECHO) "PREPROCESS LINK $@" $(Q)$(CC) -E -x c $(LDDEFINES) $(LD_FILES) | grep -v '^#' > $(BUILD)/link.ld From b1aec393b132b69bab94ec88ea1fdc4ace081313 Mon Sep 17 00:00:00 2001 From: Philipp Ebensberger Date: Wed, 22 Jun 2022 20:39:23 +0200 Subject: [PATCH 0050/1041] mimxrt/Makefile: Modify handling of SDRAM option. Replaces preprocessor macro for SDRAM option from #ifdef to #if in order to allow always setting the define `MICROPY_HW_SDRAM_AVAIL` just with the appropriate value 0/1. This eliminates one `if` in the Makefile. --- ports/mimxrt/Makefile | 12 ++++++------ ports/mimxrt/board_init.c | 2 +- ports/mimxrt/boards/MIMXRT1021.ld | 4 ++-- ports/mimxrt/boards/MIMXRT1052.ld | 4 ++-- ports/mimxrt/boards/MIMXRT1062.ld | 4 ++-- ports/mimxrt/boards/MIMXRT1064.ld | 4 ++-- ports/mimxrt/boards/common.ld | 4 ++-- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index 7f93a6826d..ed7cc0630a 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -373,6 +373,10 @@ else CFLAGS += -Os -DNDEBUG endif +# Set default values for optional variables +MICROPY_HW_SDRAM_AVAIL ?= 0 +MICROPY_HW_SDRAM_SIZE ?= 0 + # Configure default compiler flags CFLAGS += \ $(INC) \ @@ -389,6 +393,8 @@ CFLAGS += \ -DFSL_SDK_ENABLE_DRIVER_CACHE_CONTROL=1 \ -DI2C_RETRY_TIMES=1000000 \ -DMICROPY_HW_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE) \ + -DMICROPY_HW_SDRAM_AVAIL=$(MICROPY_HW_SDRAM_AVAIL) \ + -DMICROPY_HW_SDRAM_SIZE=$(MICROPY_HW_SDRAM_SIZE) \ -DSPI_RETRY_TIMES=1000000 \ -DUART_RETRY_TIMES=1000000 \ -DXIP_BOOT_HEADER_ENABLE=1 \ @@ -458,12 +464,6 @@ CFLAGS += \ -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' endif -ifdef MICROPY_HW_SDRAM_AVAIL -CFLAGS += \ - -DMICROPY_HW_SDRAM_AVAIL=$(MICROPY_HW_SDRAM_AVAIL) \ - -DMICROPY_HW_SDRAM_SIZE=$(MICROPY_HW_SDRAM_SIZE) -endif - CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) # ============================================================================= diff --git a/ports/mimxrt/board_init.c b/ports/mimxrt/board_init.c index c3dbb652bc..12496890ac 100644 --- a/ports/mimxrt/board_init.c +++ b/ports/mimxrt/board_init.c @@ -52,7 +52,7 @@ void board_init(void) { CLOCK_EnableClock(kCLOCK_Iomuxc); // ------------- SDRAM ------------ // - #ifdef MICROPY_HW_SDRAM_AVAIL + #if MICROPY_HW_SDRAM_AVAIL mimxrt_sdram_init(); #endif diff --git a/ports/mimxrt/boards/MIMXRT1021.ld b/ports/mimxrt/boards/MIMXRT1021.ld index 1263cd336c..60557f1bbf 100644 --- a/ports/mimxrt/boards/MIMXRT1021.ld +++ b/ports/mimxrt/boards/MIMXRT1021.ld @@ -27,7 +27,7 @@ dtcm_size = 0x00018000; ocrm_start = 0x20200000; ocrm_size = 0x00018000; -#ifdef MICROPY_HW_SDRAM_AVAIL +#if MICROPY_HW_SDRAM_AVAIL sdram_start = 0x80000000; sdram_size = MICROPY_HW_SDRAM_SIZE; #endif @@ -37,7 +37,7 @@ __stack_size__ = 0x6000; _estack = __StackTop; _sstack = __StackLimit; -#ifdef MICROPY_HW_SDRAM_AVAIL +#if MICROPY_HW_SDRAM_AVAIL _gc_heap_start = ORIGIN(m_sdram); _gc_heap_end = ORIGIN(m_sdram) + LENGTH(m_sdram); #else diff --git a/ports/mimxrt/boards/MIMXRT1052.ld b/ports/mimxrt/boards/MIMXRT1052.ld index f7c60d24f4..3e5739acf5 100644 --- a/ports/mimxrt/boards/MIMXRT1052.ld +++ b/ports/mimxrt/boards/MIMXRT1052.ld @@ -29,7 +29,7 @@ dtcm_size = 0x00020000; ocrm_start = 0x20200000; ocrm_size = 0x00040000; -#ifdef MICROPY_HW_SDRAM_AVAIL +#if MICROPY_HW_SDRAM_AVAIL sdram_start = 0x80000000; sdram_size = MICROPY_HW_SDRAM_SIZE; #endif @@ -39,7 +39,7 @@ __stack_size__ = 0x6000; _estack = __StackTop; _sstack = __StackLimit; -#ifdef MICROPY_HW_SDRAM_AVAIL +#if MICROPY_HW_SDRAM_AVAIL _gc_heap_start = ORIGIN(m_sdram); _gc_heap_end = ORIGIN(m_sdram) + LENGTH(m_sdram); #else diff --git a/ports/mimxrt/boards/MIMXRT1062.ld b/ports/mimxrt/boards/MIMXRT1062.ld index f588e5bd9e..fc4eb20c07 100644 --- a/ports/mimxrt/boards/MIMXRT1062.ld +++ b/ports/mimxrt/boards/MIMXRT1062.ld @@ -29,7 +29,7 @@ dtcm_size = 0x00020000; ocrm_start = 0x20200000; ocrm_size = 0x000C0000; -#ifdef MICROPY_HW_SDRAM_AVAIL +#if MICROPY_HW_SDRAM_AVAIL sdram_start = 0x80000000; sdram_size = MICROPY_HW_SDRAM_SIZE; #endif @@ -39,7 +39,7 @@ __stack_size__ = 0x8000; _estack = __StackTop; _sstack = __StackLimit; -#ifdef MICROPY_HW_SDRAM_AVAIL +#if MICROPY_HW_SDRAM_AVAIL _gc_heap_start = ORIGIN(m_sdram); _gc_heap_end = ORIGIN(m_sdram) + LENGTH(m_sdram); #else diff --git a/ports/mimxrt/boards/MIMXRT1064.ld b/ports/mimxrt/boards/MIMXRT1064.ld index b36c528453..148f1f23e2 100644 --- a/ports/mimxrt/boards/MIMXRT1064.ld +++ b/ports/mimxrt/boards/MIMXRT1064.ld @@ -31,7 +31,7 @@ dtcm_size = 0x00020000; ocrm_start = 0x20200000; ocrm_size = 0x000C0000; -#ifdef MICROPY_HW_SDRAM_AVAIL +#if MICROPY_HW_SDRAM_AVAIL sdram_start = 0x80000000; sdram_size = MICROPY_HW_SDRAM_SIZE; #endif @@ -41,7 +41,7 @@ __stack_size__ = 0x6000; _estack = __StackTop; _sstack = __StackLimit; -#ifdef MICROPY_HW_SDRAM_AVAIL +#if MICROPY_HW_SDRAM_AVAIL _gc_heap_start = ORIGIN(m_sdram); _gc_heap_end = ORIGIN(m_sdram) + LENGTH(m_sdram); #else diff --git a/ports/mimxrt/boards/common.ld b/ports/mimxrt/boards/common.ld index 7aee66e2e8..fbc99da3dd 100644 --- a/ports/mimxrt/boards/common.ld +++ b/ports/mimxrt/boards/common.ld @@ -46,7 +46,7 @@ MEMORY m_dtcm (RW) : ORIGIN = dtcm_start, LENGTH = dtcm_size m_ocrm (RW) : ORIGIN = ocrm_start, LENGTH = ocrm_size - #ifdef MICROPY_HW_SDRAM_AVAIL + #if MICROPY_HW_SDRAM_AVAIL m_sdram (RX) : ORIGIN = sdram_start, LENGTH = sdram_size #endif } @@ -55,7 +55,7 @@ MEMORY SECTIONS { __flash_start = flash_start; - #ifdef MICROPY_HW_SDRAM_AVAIL + #if MICROPY_HW_SDRAM_AVAIL __sdram_start = sdram_start; #endif __vfs_start = ORIGIN(m_vfs); From 84339aa8ec7839e803147d022533a68e3bdd532a Mon Sep 17 00:00:00 2001 From: Philipp Ebensberger Date: Wed, 22 Jun 2022 20:43:27 +0200 Subject: [PATCH 0051/1041] mimxrt/Makefile: Modify handling of SDCARD option. Removes separate `if` case in Makefile for setting SDCARD option define. --- ports/mimxrt/Makefile | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index ed7cc0630a..ee8281dd68 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -376,6 +376,7 @@ endif # Set default values for optional variables MICROPY_HW_SDRAM_AVAIL ?= 0 MICROPY_HW_SDRAM_SIZE ?= 0 +MICROPY_PY_MACHINE_SDCARD ?= 0 # Configure default compiler flags CFLAGS += \ @@ -395,6 +396,7 @@ CFLAGS += \ -DMICROPY_HW_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE) \ -DMICROPY_HW_SDRAM_AVAIL=$(MICROPY_HW_SDRAM_AVAIL) \ -DMICROPY_HW_SDRAM_SIZE=$(MICROPY_HW_SDRAM_SIZE) \ + -DMICROPY_PY_MACHINE_SDCARD=$(MICROPY_PY_MACHINE_SDCARD) \ -DSPI_RETRY_TIMES=1000000 \ -DUART_RETRY_TIMES=1000000 \ -DXIP_BOOT_HEADER_ENABLE=1 \ @@ -452,11 +454,6 @@ CFLAGS += \ endif endif -# Configure feature specific compiler flags -ifeq ($(MICROPY_PY_MACHINE_SDCARD),1) -CFLAGS += -DMICROPY_PY_MACHINE_SDCARD=1 -endif - # All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP ifeq ($(MICROPY_PY_LWIP), 1) CFLAGS += \ From bec0524dbf75bc9a90b0331ab52cdf6c5f6d9121 Mon Sep 17 00:00:00 2001 From: Philipp Ebensberger Date: Wed, 22 Jun 2022 21:26:54 +0200 Subject: [PATCH 0052/1041] mimxrt/Makefile: Rework board flash type handling. Reworks handling and configuration of different board flash types in the Makefile, linker scripts and board makefile fragments. --- ports/mimxrt/Makefile | 64 ++++++++----------- .../boards/MIMXRT1010_EVK/mpconfigboard.mk | 2 +- ports/mimxrt/boards/MIMXRT1011.ld | 2 +- ports/mimxrt/boards/MIMXRT1015.ld | 2 +- .../boards/MIMXRT1015_EVK/mpconfigboard.mk | 2 +- .../boards/MIMXRT1020_EVK/mpconfigboard.mk | 2 +- ports/mimxrt/boards/MIMXRT1021.ld | 2 +- .../boards/MIMXRT1050_EVK/mpconfigboard.mk | 2 +- ports/mimxrt/boards/MIMXRT1052.ld | 4 +- .../boards/MIMXRT1060_EVK/mpconfigboard.mk | 2 +- ports/mimxrt/boards/MIMXRT1062.ld | 4 +- ports/mimxrt/boards/MIMXRT1064.ld | 6 +- .../boards/MIMXRT1064_EVK/mpconfigboard.mk | 2 +- .../boards/OLIMEX_RT1010/mpconfigboard.mk | 2 +- .../boards/SEEED_ARCH_MIX/mpconfigboard.mk | 2 +- ports/mimxrt/boards/TEENSY40/mpconfigboard.mk | 2 +- ports/mimxrt/boards/TEENSY41/mpconfigboard.mk | 2 +- 17 files changed, 45 insertions(+), 59 deletions(-) diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index ee8281dd68..32861c26ae 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -203,28 +203,21 @@ SRC_C += \ tusb_port.c \ $(SRC_TINYUSB_C) \ $(SRC_HAL_IMX_C) \ - $(SRC_ETH_C) \ + $(SRC_ETH_C) -ifeq ($(MICROPY_HW_FLASH_TYPE), qspi_nor) -SRC_C += hal/flexspi_nor_flash.c - -ifeq ($(MICROPY_HW_BOARD_FLASH_FILES), 1) -SRC_C += $(BOARD_DIR)/qspi_nor_flash_config.c +# Add sources for respective board flash type +ifeq ($(MICROPY_HW_FLASH_TYPE),$(filter $(MICROPY_HW_FLASH_TYPE),qspi_nor_flash qspi_hyper_flash)) + # Add hal/flexspi_nor_flash.c or hal/flashspi_hyper_flash.c respectively + SRC_C += hal/flexspi_$(subst qspi_,,$(MICROPY_HW_FLASH_TYPE)).c + # + # Add custom (board specific) or default configuration + ifeq ($(MICROPY_HW_BOARD_FLASH_FILES), 1) + SRC_C += $(BOARD_DIR)/$(MICROPY_HW_FLASH_TYPE)_config.c + else + SRC_C += hal/$(MICROPY_HW_FLASH_TYPE)_config.c + endif else -SRC_C += hal/qspi_nor_flash_config.c -endif # qspi_nor -# -else ifeq ($(MICROPY_HW_FLASH_TYPE), hyperflash) -SRC_C += hal/flexspi_hyper_flash.c - -ifeq ($(MICROPY_HW_BOARD_FLASH_FILES), 1) -SRC_C += $(BOARD_DIR)/qspi_hyper_flash_config.c -else -SRC_C += hal/qspi_hyper_flash_config.c -endif # hyperflash -# -else -$(error Error: Unknown board flash type $(MICROPY_HW_FLASH_TYPE)) + $(error Error: Unknown board flash type $(MICROPY_HW_FLASH_TYPE)) endif # Math library source files @@ -414,26 +407,19 @@ CFLAGS += \ -Wfloat-conversion \ -Wno-error=unused-parameter -ifeq ($(MICROPY_HW_FLASH_TYPE), qspi_nor) -CFLAGS += -DBOARD_FLASH_OPS_HEADER_H=\"hal/flexspi_nor_flash.h\" - -ifeq ($(MICROPY_HW_BOARD_FLASH_FILES), 1) -CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"$(BOARD)_flexspi_flash_config.h\" +# Configure respective board flash type +ifeq ($(MICROPY_HW_FLASH_TYPE),$(filter $(MICROPY_HW_FLASH_TYPE),qspi_nor_flash qspi_hyper_flash)) + # Add hal/flexspi_nor_flash.h or hal/flexspi_hyper_flash.h respectively + CFLAGS += -DBOARD_FLASH_OPS_HEADER_H=\"hal/flexspi_$(subst qspi_,,$(MICROPY_HW_FLASH_TYPE)).h\" + # + # Add custom (board specific) or default configuration + ifeq ($(MICROPY_HW_BOARD_FLASH_FILES), 1) + CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"$(BOARD)_flexspi_flash_config.h\" + else + CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"hal/flexspi_flash_config.h\" + endif else -CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"hal/flexspi_flash_config.h\" -endif # qspi_nor -# -else ifeq ($(MICROPY_HW_FLASH_TYPE), hyperflash) -CFLAGS += -DBOARD_FLASH_OPS_HEADER_H=\"hal/flexspi_hyper_flash.h\" - -ifeq ($(MICROPY_HW_BOARD_FLASH_FILES), 1) -CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"$(BOARD)_flexspi_flash_config.h\" -else -CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"hal/flexspi_flash_config.h\" -endif # hyperflash -# -else -$(error Error: Unknown board flash type $(MICROPY_HW_FLASH_TYPE)) + $(error Error: Unknown board flash type $(MICROPY_HW_FLASH_TYPE)) endif # Configure floating point support diff --git a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk index c2a50d722b..af705e0b90 100644 --- a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk @@ -3,7 +3,7 @@ MCU_VARIANT = MIMXRT1011DAE5A MICROPY_FLOAT_IMPL = single MICROPY_PY_MACHINE_SDCARD = 0 -MICROPY_HW_FLASH_TYPE ?= qspi_nor +MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash MICROPY_HW_FLASH_SIZE ?= 0x1000000 # 16MB JLINK_PATH ?= /media/RT1010-EVK/ diff --git a/ports/mimxrt/boards/MIMXRT1011.ld b/ports/mimxrt/boards/MIMXRT1011.ld index 19bbc27701..908eefffd6 100644 --- a/ports/mimxrt/boards/MIMXRT1011.ld +++ b/ports/mimxrt/boards/MIMXRT1011.ld @@ -3,7 +3,7 @@ reserved_size = MICROPY_HW_FLASH_RESERVED; #endif -#if MICROPY_HW_FLASH_TYPE==qspi_nor +#if MICROPY_HW_FLASH_TYPE == qspi_nor_flash flash_start = 0x60000000; #else #error Unknown MICROPY_HW_FLASH_TYPE diff --git a/ports/mimxrt/boards/MIMXRT1015.ld b/ports/mimxrt/boards/MIMXRT1015.ld index 6d34200a9f..90336a2437 100644 --- a/ports/mimxrt/boards/MIMXRT1015.ld +++ b/ports/mimxrt/boards/MIMXRT1015.ld @@ -3,7 +3,7 @@ reserved_size = MICROPY_HW_FLASH_RESERVED; #endif -#if MICROPY_HW_FLASH_TYPE == qspi_nor +#if MICROPY_HW_FLASH_TYPE == qspi_nor_flash flash_start = 0x60000000; #else #error Unknown MICROPY_HW_FLASH_TYPE diff --git a/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk index 5d959b31d4..a2661a4897 100644 --- a/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk @@ -3,7 +3,7 @@ MCU_VARIANT = MIMXRT1015DAF5A MICROPY_FLOAT_IMPL = single MICROPY_PY_MACHINE_SDCARD = 0 -MICROPY_HW_FLASH_TYPE ?= qspi_nor +MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash MICROPY_HW_FLASH_SIZE ?= 0x1000000 # 16MB MICROPY_BOOT_BUFFER_SIZE = (32 * 1024) diff --git a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk index c1e1678e59..98262e2370 100644 --- a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk @@ -3,7 +3,7 @@ MCU_VARIANT = MIMXRT1021DAG5A MICROPY_FLOAT_IMPL = double MICROPY_PY_MACHINE_SDCARD = 1 -MICROPY_HW_FLASH_TYPE ?= qspi_nor +MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash MICROPY_HW_FLASH_SIZE ?= 0x800000 # 8MB MICROPY_HW_SDRAM_AVAIL = 1 diff --git a/ports/mimxrt/boards/MIMXRT1021.ld b/ports/mimxrt/boards/MIMXRT1021.ld index 60557f1bbf..bef0c13df5 100644 --- a/ports/mimxrt/boards/MIMXRT1021.ld +++ b/ports/mimxrt/boards/MIMXRT1021.ld @@ -3,7 +3,7 @@ reserved_size = MICROPY_HW_FLASH_RESERVED; #endif -#if MICROPY_HW_FLASH_TYPE == qspi_nor +#if MICROPY_HW_FLASH_TYPE == qspi_nor_flash flash_start = 0x60000000; #else #error Unknown MICROPY_HW_FLASH_TYPE diff --git a/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk index 65e3d30963..4cdf18b62b 100644 --- a/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk @@ -3,7 +3,7 @@ MCU_VARIANT = MIMXRT1052DVL6B MICROPY_FLOAT_IMPL = double MICROPY_PY_MACHINE_SDCARD = 1 -MICROPY_HW_FLASH_TYPE ?= hyperflash +MICROPY_HW_FLASH_TYPE ?= qspi_hyper_flash MICROPY_HW_FLASH_SIZE ?= 0x4000000 # 64MB MICROPY_HW_SDRAM_AVAIL = 1 diff --git a/ports/mimxrt/boards/MIMXRT1052.ld b/ports/mimxrt/boards/MIMXRT1052.ld index 3e5739acf5..ca656711a5 100644 --- a/ports/mimxrt/boards/MIMXRT1052.ld +++ b/ports/mimxrt/boards/MIMXRT1052.ld @@ -3,9 +3,9 @@ reserved_size = MICROPY_HW_FLASH_RESERVED; #endif -#if MICROPY_HW_FLASH_TYPE==qspi_nor +#if MICROPY_HW_FLASH_TYPE == qspi_nor_flash flash_start = 0x60000000; -#elif MICROPY_HW_FLASH_TYPE==hyperflash +#elif MICROPY_HW_FLASH_TYPE == qspi_hyper_flash flash_start = 0x60000000; #else #error Unknown MICROPY_HW_FLASH_TYPE diff --git a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk index 56ccba6e59..ecdd7ec0cb 100644 --- a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk @@ -3,7 +3,7 @@ MCU_VARIANT = MIMXRT1062DVJ6A MICROPY_FLOAT_IMPL = double MICROPY_PY_MACHINE_SDCARD = 1 -MICROPY_HW_FLASH_TYPE ?= qspi_nor +MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash MICROPY_HW_FLASH_SIZE ?= 0x800000 # 8MB MICROPY_HW_SDRAM_AVAIL = 1 diff --git a/ports/mimxrt/boards/MIMXRT1062.ld b/ports/mimxrt/boards/MIMXRT1062.ld index fc4eb20c07..5b91550d97 100644 --- a/ports/mimxrt/boards/MIMXRT1062.ld +++ b/ports/mimxrt/boards/MIMXRT1062.ld @@ -3,9 +3,9 @@ reserved_size = MICROPY_HW_FLASH_RESERVED; #endif -#if MICROPY_HW_FLASH_TYPE==qspi_nor +#if MICROPY_HW_FLASH_TYPE == qspi_nor_flash flash_start = 0x60000000; -#elif MICROPY_HW_FLASH_TYPE==hyperflash +#elif MICROPY_HW_FLASH_TYPE == qspi_hyper_flash flash_start = 0x60000000; #else #error Unknown MICROPY_HW_FLASH_TYPE diff --git a/ports/mimxrt/boards/MIMXRT1064.ld b/ports/mimxrt/boards/MIMXRT1064.ld index 148f1f23e2..1fbc855fa1 100644 --- a/ports/mimxrt/boards/MIMXRT1064.ld +++ b/ports/mimxrt/boards/MIMXRT1064.ld @@ -3,11 +3,11 @@ reserved_size = MICROPY_HW_FLASH_RESERVED; #endif -#if MICROPY_HW_FLASH_TYPE==qspi_nor +#if MICROPY_HW_FLASH_TYPE == qspi_nor_flash flash_start = 0x60000000; -#elif MICROPY_HW_FLASH_TYPE==hyperflash +#elif MICROPY_HW_FLASH_TYPE == qspi_hyper_flash flash_start = 0x60000000; -#elif MICROPY_HW_FLASH_TYPE==internal +#elif MICROPY_HW_FLASH_TYPE == internal flash_start = 0x70000000; #else #error Unknown MICROPY_HW_FLASH_TYPE diff --git a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk index 5cd7d49abd..f524a81e60 100644 --- a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk @@ -3,7 +3,7 @@ MCU_VARIANT = MIMXRT1064DVL6A MICROPY_FLOAT_IMPL = double MICROPY_PY_MACHINE_SDCARD = 1 -MICROPY_HW_FLASH_TYPE ?= hyperflash +MICROPY_HW_FLASH_TYPE ?= qspi_hyper_flash MICROPY_HW_FLASH_SIZE ?= 0x4000000 # 64MB MICROPY_HW_SDRAM_AVAIL = 1 diff --git a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk index e4f904903d..96aaa57764 100644 --- a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk +++ b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk @@ -3,7 +3,7 @@ MCU_VARIANT = MIMXRT1011DAE5A MICROPY_FLOAT_IMPL = single MICROPY_PY_MACHINE_SDCARD ?= 0 -MICROPY_HW_FLASH_TYPE ?= qspi_nor +MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash MICROPY_HW_FLASH_SIZE ?= 0x200000 # 2MB MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB diff --git a/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk b/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk index 90edc5d517..7a87496b94 100644 --- a/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk +++ b/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk @@ -3,7 +3,7 @@ MCU_VARIANT = MIMXRT1052DVL6B MICROPY_FLOAT_IMPL = double MICROPY_PY_MACHINE_SDCARD = 1 -MICROPY_HW_FLASH_TYPE ?= qspi_nor +MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash MICROPY_HW_FLASH_SIZE ?= 0x800000 # 8MB MICROPY_HW_SDRAM_AVAIL = 1 diff --git a/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk b/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk index 94e427cc16..aa903a0604 100644 --- a/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk +++ b/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk @@ -3,7 +3,7 @@ MCU_VARIANT = MIMXRT1062DVJ6A MICROPY_FLOAT_IMPL = double MICROPY_PY_MACHINE_SDCARD = 1 -MICROPY_HW_FLASH_TYPE ?= qspi_nor +MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash MICROPY_HW_FLASH_SIZE ?= 0x200000 # 2MB MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB diff --git a/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk b/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk index a012444caa..454967f04f 100755 --- a/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk +++ b/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk @@ -3,7 +3,7 @@ MCU_VARIANT = MIMXRT1062DVJ6A MICROPY_FLOAT_IMPL = double MICROPY_PY_MACHINE_SDCARD = 1 -MICROPY_HW_FLASH_TYPE ?= qspi_nor +MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash MICROPY_HW_FLASH_SIZE ?= 0x800000 # 8MB MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB From c957c76f4db6244add47494a8a679652b85acff8 Mon Sep 17 00:00:00 2001 From: Philipp Ebensberger Date: Wed, 22 Jun 2022 21:41:42 +0200 Subject: [PATCH 0053/1041] mimxrt/Makefile: Rework floating point config. Reworks source file and compile flags selection for floating point support. --- ports/mimxrt/Makefile | 132 ++++++++++++------------------------------ 1 file changed, 36 insertions(+), 96 deletions(-) diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index 32861c26ae..745aa1d3f3 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -222,89 +222,27 @@ endif # Math library source files ifeq ($(MICROPY_FLOAT_IMPL),double) -LIBM_SRC_C += $(addprefix lib/libm_dbl/,\ - __cos.c \ - __expo2.c \ - __fpclassify.c \ - __rem_pio2.c \ - __rem_pio2_large.c \ - __signbit.c \ - __sin.c \ - __tan.c \ - acos.c \ - acosh.c \ - asin.c \ - asinh.c \ - atan.c \ - atan2.c \ - atanh.c \ - ceil.c \ - copysign.c \ - cos.c \ - cosh.c \ - erf.c \ - exp.c \ - expm1.c \ - floor.c \ - fmod.c \ - frexp.c \ - ldexp.c \ - lgamma.c \ - log.c \ - log10.c \ - log1p.c \ - modf.c \ - nearbyint.c \ - pow.c \ - rint.c \ - round.c \ - scalbn.c \ - sin.c \ - sinh.c \ - tan.c \ - tanh.c \ - tgamma.c \ - trunc.c \ - ) -ifeq ($(SUPPORTS_HARDWARE_FP_DOUBLE),1) -LIBM_SRC_C += lib/libm_dbl/thumb_vfp_sqrt.c + LIBM_SRC_C += $(addprefix lib/libm_dbl/,\ + __cos.c __expo2.c __fpclassify.c __rem_pio2.c __rem_pio2_large.c __signbit.c __sin.c __tan.c acos.c acosh.c \ + asin.c asinh.c atan.c atan2.c atanh.c ceil.c copysign.c cos.c cosh.c erf.c exp.c expm1.c floor.c fmod.c \ + frexp.c ldexp.c lgamma.c log.c log10.c log1p.c modf.c nearbyint.c pow.c rint.c round.c scalbn.c sin.c \ + sinh.c tan.c tanh.c tgamma.c trunc.c) + # + ifeq ($(SUPPORTS_HARDWARE_FP_DOUBLE),1) + LIBM_SRC_C += lib/libm_dbl/thumb_vfp_sqrt.c + else + LIBM_SRC_C += lib/libm_dbl/sqrt.c + endif else -LIBM_SRC_C += lib/libm_dbl/sqrt.c -endif -else -LIBM_SRC_C += $(addprefix lib/libm/,\ - acoshf.c \ - asinfacosf.c \ - asinhf.c \ - atan2f.c \ - atanf.c \ - atanhf.c \ - ef_rem_pio2.c \ - erf_lgamma.c \ - fmodf.c \ - kf_cos.c \ - kf_rem_pio2.c \ - kf_sin.c \ - kf_tan.c \ - log1pf.c \ - math.c \ - nearbyintf.c \ - roundf.c \ - sf_cos.c \ - sf_erf.c \ - sf_frexp.c \ - sf_ldexp.c \ - sf_modf.c \ - sf_sin.c \ - sf_tan.c \ - wf_lgamma.c \ - wf_tgamma.c \ - ) -ifeq ($(SUPPORTS_HARDWARE_FP_SINGLE),1) -LIBM_SRC_C += lib/libm/thumb_vfp_sqrtf.c -else -LIBM_SRC_C += lib/libm/ef_sqrt.c -endif + LIBM_SRC_C += $(addprefix lib/libm/,\ + acoshf.c asinfacosf.c asinhf.c atan2f.c atanf.c atanhf.c ef_rem_pio2.c erf_lgamma.c fmodf.c kf_cos.c \ + kf_rem_pio2.c kf_sin.c kf_tan.c log1pf.c math.c nearbyintf.c roundf.c sf_cos.c sf_erf.c sf_frexp.c sf_ldexp.c \ + sf_modf.c sf_sin.c sf_tan.c wf_lgamma.c wf_tgamma.c) + ifeq ($(SUPPORTS_HARDWARE_FP_SINGLE),1) + LIBM_SRC_C += lib/libm/thumb_vfp_sqrtf.c + else + LIBM_SRC_C += lib/libm/ef_sqrt.c + endif endif # Reset variables @@ -423,23 +361,25 @@ else endif # Configure floating point support -ifeq ($(MICROPY_FLOAT_IMPL),double) -CFLAGS += \ - -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_DOUBLE \ - -mfloat-abi=hard \ - -mfpu=fpv5-d16 +ifeq ($(MICROPY_FLOAT_IMPL),single) + CFLAGS += \ + -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_FLOAT \ + -fsingle-precision-constant \ + -mfloat-abi=softfp \ + -mfpu=fpv5-sp-d16 +else ifeq ($(MICROPY_FLOAT_IMPL),double) + CFLAGS += \ + -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_DOUBLE \ + -mfloat-abi=hard \ + -mfpu=fpv5-d16 +else ifeq ($(MICROPY_FLOAT_IMPL),none) + CFLAGS += \ + -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_NONE else -ifeq ($(MICROPY_FLOAT_IMPL),none) -CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_NONE -else -CFLAGS += \ - -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_FLOAT \ - -fsingle-precision-constant \ - -mfloat-abi=softfp \ - -mfpu=fpv5-sp-d16 -endif + $(error Error: Unknown floating point implementation $(MICROPY_FLOAT_IMPL)) endif + # All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP ifeq ($(MICROPY_PY_LWIP), 1) CFLAGS += \ From 434974ec7707e20faab5ac9752bb70525966ff5c Mon Sep 17 00:00:00 2001 From: Philipp Ebensberger Date: Wed, 22 Jun 2022 21:44:04 +0200 Subject: [PATCH 0054/1041] mimxrt/Makefile: Fix some minor formatting inconsistencies. --- ports/mimxrt/Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index 745aa1d3f3..7ae3f91837 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -27,7 +27,7 @@ include ../../py/mkenv.mk # Include micropython configuration board makefile ifeq ($(wildcard $(BOARD_DIR)/.),) -$(error Invalid BOARD specified: $(BOARD_DIR)) + $(error Invalid BOARD specified: $(BOARD_DIR)) endif include $(BOARD_DIR)/mpconfigboard.mk @@ -70,7 +70,7 @@ INC += -I. INC += -Ihal # All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP -ifeq ($(MICROPY_PY_LWIP), 1) +ifeq ($(MICROPY_PY_LWIP),1) INC += -Ilwip_inc INC += -Ihal/phy endif @@ -95,7 +95,7 @@ SRC_TINYUSB_C += \ lib/tinyusb/src/tusb.c # All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP -ifeq ($(MICROPY_PY_LWIP), 1) +ifeq ($(MICROPY_PY_LWIP),1) SRC_MOD := $(filter-out %/mbedtls/library/error.c, $(SRC_MOD)) SRC_ETH_C += \ $(MCU_DIR)/drivers/fsl_enet.c \ @@ -132,7 +132,7 @@ SRC_HAL_IMX_C += \ $(MCU_DIR)/system_$(MCU_SERIES).c \ $(MCU_DIR)/xip/fsl_flexspi_nor_boot.c \ -ifeq ($(MICROPY_HW_SDRAM_AVAIL), 1) +ifeq ($(MICROPY_HW_SDRAM_AVAIL),1) SRC_HAL_IMX_C += $(MCU_DIR)/drivers/fsl_semc.c endif @@ -211,7 +211,7 @@ ifeq ($(MICROPY_HW_FLASH_TYPE),$(filter $(MICROPY_HW_FLASH_TYPE),qspi_nor_flash SRC_C += hal/flexspi_$(subst qspi_,,$(MICROPY_HW_FLASH_TYPE)).c # # Add custom (board specific) or default configuration - ifeq ($(MICROPY_HW_BOARD_FLASH_FILES), 1) + ifeq ($(MICROPY_HW_BOARD_FLASH_FILES),1) SRC_C += $(BOARD_DIR)/$(MICROPY_HW_FLASH_TYPE)_config.c else SRC_C += hal/$(MICROPY_HW_FLASH_TYPE)_config.c @@ -261,7 +261,7 @@ SRC_S += shared/runtime/gchelper_m3.s \ # ============================================================================= # All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP -ifeq ($(MICROPY_PY_LWIP), 1) +ifeq ($(MICROPY_PY_LWIP),1) SRC_QSTR += \ extmod/modlwip.c \ extmod/modnetwork.c \ @@ -351,7 +351,7 @@ ifeq ($(MICROPY_HW_FLASH_TYPE),$(filter $(MICROPY_HW_FLASH_TYPE),qspi_nor_flash CFLAGS += -DBOARD_FLASH_OPS_HEADER_H=\"hal/flexspi_$(subst qspi_,,$(MICROPY_HW_FLASH_TYPE)).h\" # # Add custom (board specific) or default configuration - ifeq ($(MICROPY_HW_BOARD_FLASH_FILES), 1) + ifeq ($(MICROPY_HW_BOARD_FLASH_FILES),1) CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"$(BOARD)_flexspi_flash_config.h\" else CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"hal/flexspi_flash_config.h\" @@ -381,7 +381,7 @@ endif # All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP -ifeq ($(MICROPY_PY_LWIP), 1) +ifeq ($(MICROPY_PY_LWIP),1) CFLAGS += \ -DFSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE=1 \ -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' From 4ce1adab3153bb0dd5afcd0ddefc219b91d1a13e Mon Sep 17 00:00:00 2001 From: Philipp Ebensberger Date: Thu, 23 Jun 2022 19:00:54 +0200 Subject: [PATCH 0055/1041] mimxrt/boards: Remove conditional assignment of flash type/size. Removes conditional assignment because respective variables should only be set in board makefile fragments. Hence no conditional assignment needed. --- ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk | 4 ++-- ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk | 4 ++-- ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk | 4 ++-- ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk | 4 ++-- ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk | 4 ++-- ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk | 4 ++-- ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk | 4 ++-- ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk | 4 ++-- ports/mimxrt/boards/TEENSY40/mpconfigboard.mk | 4 ++-- ports/mimxrt/boards/TEENSY41/mpconfigboard.mk | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk index af705e0b90..19db53c3f8 100644 --- a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk @@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1011DAE5A MICROPY_FLOAT_IMPL = single MICROPY_PY_MACHINE_SDCARD = 0 -MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash -MICROPY_HW_FLASH_SIZE ?= 0x1000000 # 16MB +MICROPY_HW_FLASH_TYPE = qspi_nor_flash +MICROPY_HW_FLASH_SIZE = 0x1000000 # 16MB JLINK_PATH ?= /media/RT1010-EVK/ JLINK_COMMANDER_SCRIPT = $(BUILD)/script.jlink diff --git a/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk index a2661a4897..ba7d61f6d4 100644 --- a/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk @@ -3,7 +3,7 @@ MCU_VARIANT = MIMXRT1015DAF5A MICROPY_FLOAT_IMPL = single MICROPY_PY_MACHINE_SDCARD = 0 -MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash -MICROPY_HW_FLASH_SIZE ?= 0x1000000 # 16MB +MICROPY_HW_FLASH_TYPE = qspi_nor_flash +MICROPY_HW_FLASH_SIZE = 0x1000000 # 16MB MICROPY_BOOT_BUFFER_SIZE = (32 * 1024) diff --git a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk index 98262e2370..e8922e4b7a 100644 --- a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk @@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1021DAG5A MICROPY_FLOAT_IMPL = double MICROPY_PY_MACHINE_SDCARD = 1 -MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash -MICROPY_HW_FLASH_SIZE ?= 0x800000 # 8MB +MICROPY_HW_FLASH_TYPE = qspi_nor_flash +MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB MICROPY_HW_SDRAM_AVAIL = 1 MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB diff --git a/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk index 4cdf18b62b..0084335049 100644 --- a/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk @@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1052DVL6B MICROPY_FLOAT_IMPL = double MICROPY_PY_MACHINE_SDCARD = 1 -MICROPY_HW_FLASH_TYPE ?= qspi_hyper_flash -MICROPY_HW_FLASH_SIZE ?= 0x4000000 # 64MB +MICROPY_HW_FLASH_TYPE = qspi_hyper_flash +MICROPY_HW_FLASH_SIZE = 0x4000000 # 64MB MICROPY_HW_SDRAM_AVAIL = 1 MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB diff --git a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk index ecdd7ec0cb..96afe276f7 100644 --- a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk @@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1062DVJ6A MICROPY_FLOAT_IMPL = double MICROPY_PY_MACHINE_SDCARD = 1 -MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash -MICROPY_HW_FLASH_SIZE ?= 0x800000 # 8MB +MICROPY_HW_FLASH_TYPE = qspi_nor_flash +MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB MICROPY_HW_SDRAM_AVAIL = 1 MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB diff --git a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk index f524a81e60..ceb1e9796e 100644 --- a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk @@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1064DVL6A MICROPY_FLOAT_IMPL = double MICROPY_PY_MACHINE_SDCARD = 1 -MICROPY_HW_FLASH_TYPE ?= qspi_hyper_flash -MICROPY_HW_FLASH_SIZE ?= 0x4000000 # 64MB +MICROPY_HW_FLASH_TYPE = qspi_hyper_flash +MICROPY_HW_FLASH_SIZE = 0x4000000 # 64MB MICROPY_HW_SDRAM_AVAIL = 1 MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB diff --git a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk index 96aaa57764..135c43257c 100644 --- a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk +++ b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk @@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1011DAE5A MICROPY_FLOAT_IMPL = single MICROPY_PY_MACHINE_SDCARD ?= 0 -MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash -MICROPY_HW_FLASH_SIZE ?= 0x200000 # 2MB +MICROPY_HW_FLASH_TYPE = qspi_nor_flash +MICROPY_HW_FLASH_SIZE = 0x200000 # 2MB MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB CFLAGS += -DMICROPY_HW_FLASH_DQS=kFlexSPIReadSampleClk_LoopbackInternally diff --git a/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk b/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk index 7a87496b94..2312d11311 100644 --- a/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk +++ b/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk @@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1052DVL6B MICROPY_FLOAT_IMPL = double MICROPY_PY_MACHINE_SDCARD = 1 -MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash -MICROPY_HW_FLASH_SIZE ?= 0x800000 # 8MB +MICROPY_HW_FLASH_TYPE = qspi_nor_flash +MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB MICROPY_HW_SDRAM_AVAIL = 1 MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB diff --git a/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk b/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk index aa903a0604..4482c629f7 100644 --- a/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk +++ b/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk @@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1062DVJ6A MICROPY_FLOAT_IMPL = double MICROPY_PY_MACHINE_SDCARD = 1 -MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash -MICROPY_HW_FLASH_SIZE ?= 0x200000 # 2MB +MICROPY_HW_FLASH_TYPE = qspi_nor_flash +MICROPY_HW_FLASH_SIZE = 0x200000 # 2MB MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB deploy: $(BUILD)/firmware.hex diff --git a/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk b/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk index 454967f04f..601a2cfe86 100755 --- a/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk +++ b/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk @@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1062DVJ6A MICROPY_FLOAT_IMPL = double MICROPY_PY_MACHINE_SDCARD = 1 -MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash -MICROPY_HW_FLASH_SIZE ?= 0x800000 # 8MB +MICROPY_HW_FLASH_TYPE = qspi_nor_flash +MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB MICROPY_PY_LWIP = 1 From 3ce21945b1e80ed754b4278efb8dccacdfe9cfa5 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 24 Jun 2022 13:02:44 +1000 Subject: [PATCH 0056/1041] docs/library/bluetooth: Add link to aioble. Signed-off-by: Jim Mussared --- docs/library/bluetooth.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/library/bluetooth.rst b/docs/library/bluetooth.rst index 7663199e91..052f7a5c78 100644 --- a/docs/library/bluetooth.rst +++ b/docs/library/bluetooth.rst @@ -13,6 +13,9 @@ concurrently. Pairing (and bonding) is supported on some ports. This API is intended to match the low-level Bluetooth protocol and provide building-blocks for higher-level abstractions such as specific device types. +.. note:: For most applications, we recommend using the higher-level + `aioble library `_. + .. note:: This module is still under development and its classes, functions, methods and constants are subject to change. From 432b65f17849fdc94a96df4fd7db490257bd0a2c Mon Sep 17 00:00:00 2001 From: Koen De Vleeschauwer Date: Thu, 15 Oct 2020 12:51:52 +0200 Subject: [PATCH 0057/1041] stm32/usb: Expose USB HID device instance via usbd_hid_get(). This is needed to implement a HID device in user C modules. --- ports/stm32/usb.c | 18 ++++++++++++++++++ ports/stm32/usbd_hid_interface.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 9a9600f89d..cf9faed112 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -367,6 +367,24 @@ usbd_cdc_itf_t *usb_vcp_get(int idx) { return &usb_device.usbd_cdc_itf[idx]; } +#if MICROPY_HW_USB_HID + +// return hid interface if hid is configured, NULL otherwise +usbd_hid_itf_t *usbd_hid_get(void) { + #if defined(USE_HOST_MODE) + return NULL; + #else + uint8_t usb_mode = USBD_GetMode(&usb_device.usbd_cdc_msc_hid_state) & USBD_MODE_IFACE_MASK; + if (usb_mode == USBD_MODE_HID || usb_mode == USBD_MODE_CDC_HID || usb_mode == USBD_MODE_MSC_HID) { + return &usb_device.usbd_hid_itf; + } else { + return NULL; + } + #endif +} + +#endif + /******************************************************************************/ // MicroPython bindings for USB diff --git a/ports/stm32/usbd_hid_interface.h b/ports/stm32/usbd_hid_interface.h index 5d2c9ad870..b97d273f15 100644 --- a/ports/stm32/usbd_hid_interface.h +++ b/ports/stm32/usbd_hid_interface.h @@ -16,6 +16,8 @@ typedef struct _usbd_hid_itf_t { uint8_t report_in_buf[HID_DATA_FS_MAX_PACKET_SIZE]; } usbd_hid_itf_t; +usbd_hid_itf_t *usbd_hid_get(void); + static inline int usbd_hid_rx_num(usbd_hid_itf_t *hid) { return hid->report_in_len != USBD_HID_REPORT_INVALID; } From d68532558d0f60737ccd5a38ae33f719333520a4 Mon Sep 17 00:00:00 2001 From: Michael Bentley Date: Sun, 3 Oct 2021 00:05:27 -0600 Subject: [PATCH 0058/1041] py/objclosure: Forward function attributes for closures. Add .attr attribute which forwards to self->fun. A closure is intended to wrap around a function object, so forward any requested attributes to the wrapped function object. Signed-off-by: Michael Bentley --- py/objclosure.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/py/objclosure.c b/py/objclosure.c index 9dc3e54532..5b9923a44b 100644 --- a/py/objclosure.c +++ b/py/objclosure.c @@ -78,6 +78,14 @@ STATIC void closure_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_ } #endif +#if MICROPY_PY_FUNCTION_ATTRS +STATIC void mp_obj_closure_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + // forward to self_in->fun + mp_obj_closure_t *o = MP_OBJ_TO_PTR(self_in); + mp_load_method_maybe(o->fun, attr, dest); +} +#endif + const mp_obj_type_t mp_type_closure = { { &mp_type_type }, .flags = MP_TYPE_FLAG_BINDS_SELF, @@ -86,6 +94,9 @@ const mp_obj_type_t mp_type_closure = { .print = closure_print, #endif .call = closure_call, + #if MICROPY_PY_FUNCTION_ATTRS + .attr = mp_obj_closure_attr, + #endif }; mp_obj_t mp_obj_new_closure(mp_obj_t fun, size_t n_closed_over, const mp_obj_t *closed) { From 268ec1e3eb818c92f2ad0015902afef4c4c59ba5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 24 Jun 2022 23:34:15 +1000 Subject: [PATCH 0059/1041] tests/basics: Add tests for __name__ and __globals__ attrs on closures. Signed-off-by: Damien George --- tests/basics/fun_globals.py | 15 +++++++++++++++ tests/basics/fun_name.py | 2 ++ 2 files changed, 17 insertions(+) diff --git a/tests/basics/fun_globals.py b/tests/basics/fun_globals.py index 3f32e8bdb0..69f8638e8d 100644 --- a/tests/basics/fun_globals.py +++ b/tests/basics/fun_globals.py @@ -19,3 +19,18 @@ try: foo.__globals__ = None except AttributeError: print("AttributeError") + +# test closures have the __globals__ attribute + + +def outer(): + x = 1 + + def inner(): + return x + + return inner + + +print(outer.__globals__ is globals()) +print(outer().__globals__ is globals()) diff --git a/tests/basics/fun_name.py b/tests/basics/fun_name.py index bb1f14992f..b2642280a2 100644 --- a/tests/basics/fun_name.py +++ b/tests/basics/fun_name.py @@ -24,9 +24,11 @@ except AttributeError: pass # name of a function that has closed over variables +# and also the name of the inner closure def outer(): x = 1 def inner(): return x return inner print(outer.__name__) +print(outer().__name__) From e22b7fb4afbf62a9ca3162539c2d0236aefd8945 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 25 Jun 2022 00:05:39 +1000 Subject: [PATCH 0060/1041] py/objfun: Support function attributes on native functions. Native functions can just reuse the bytecode function attribute code. Signed-off-by: Damien George --- py/objfun.c | 6 ++++++ tests/micropython/native_fun_attrs.py | 25 +++++++++++++++++++++++ tests/micropython/native_fun_attrs.py.exp | 4 ++++ tests/run-tests.py | 1 + 4 files changed, 36 insertions(+) create mode 100644 tests/micropython/native_fun_attrs.py create mode 100644 tests/micropython/native_fun_attrs.py.exp diff --git a/py/objfun.c b/py/objfun.c index 8f0c3eb6d4..37c1eaa549 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -421,8 +421,14 @@ STATIC const mp_obj_type_t mp_type_fun_native = { { &mp_type_type }, .flags = MP_TYPE_FLAG_BINDS_SELF, .name = MP_QSTR_function, + #if MICROPY_CPYTHON_COMPAT + .print = fun_bc_print, + #endif .call = fun_native_call, .unary_op = mp_generic_unary_op, + #if MICROPY_PY_FUNCTION_ATTRS + .attr = mp_obj_fun_bc_attr, + #endif }; mp_obj_t mp_obj_new_fun_native(const mp_obj_t *def_args, const void *fun_data, const mp_module_context_t *mc, struct _mp_raw_code_t *const *child_table) { diff --git a/tests/micropython/native_fun_attrs.py b/tests/micropython/native_fun_attrs.py new file mode 100644 index 0000000000..e61c869755 --- /dev/null +++ b/tests/micropython/native_fun_attrs.py @@ -0,0 +1,25 @@ +# test native function attributes + + +def f(): + pass + + +if not hasattr(f, "__name__"): + print("SKIP") + raise SystemExit + + +@micropython.native +def native_f(): + pass + + +print(type(native_f.__name__)) +print(type(native_f.__globals__)) +print(native_f.__globals__ is globals()) + +try: + native_f.__name__ = None +except AttributeError: + print("AttributeError") diff --git a/tests/micropython/native_fun_attrs.py.exp b/tests/micropython/native_fun_attrs.py.exp new file mode 100644 index 0000000000..8be35e2f69 --- /dev/null +++ b/tests/micropython/native_fun_attrs.py.exp @@ -0,0 +1,4 @@ + + +True +AttributeError diff --git a/tests/run-tests.py b/tests/run-tests.py index 7377e8ae2c..2d6dbaaf1c 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -603,6 +603,7 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): skip_tests.add("basics/del_deref.py") # requires checking for unbound local skip_tests.add("basics/del_local.py") # requires checking for unbound local skip_tests.add("basics/exception_chain.py") # raise from is not supported + skip_tests.add("basics/fun_name.py") # requires proper names for native functions skip_tests.add("basics/scope_implicit.py") # requires checking for unbound local skip_tests.add("basics/sys_tracebacklimit.py") # requires traceback info skip_tests.add("basics/try_finally_return2.py") # requires raise_varargs From 5b66d086090e16134e58db62160257d7ca109be4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 27 Jun 2022 10:37:28 +1000 Subject: [PATCH 0061/1041] py/builtin: Remove unnecessary module declarations. Signed-off-by: Damien George --- py/builtin.h | 35 +++-------------------------------- 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/py/builtin.h b/py/builtin.h index a6f824ca20..fb11627841 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -120,45 +120,16 @@ MP_DECLARE_CONST_FUN_OBJ_2(mp_op_getitem_obj); MP_DECLARE_CONST_FUN_OBJ_3(mp_op_setitem_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_op_delitem_obj); +// Modules needed by the runtime. +extern const mp_obj_dict_t mp_module_builtins_globals; extern const mp_obj_module_t mp_module___main__; extern const mp_obj_module_t mp_module_builtins; -extern const mp_obj_module_t mp_module_uarray; -extern const mp_obj_module_t mp_module_collections; -extern const mp_obj_module_t mp_module_io; -extern const mp_obj_module_t mp_module_math; -extern const mp_obj_module_t mp_module_cmath; -extern const mp_obj_module_t mp_module_micropython; -extern const mp_obj_module_t mp_module_ustruct; extern const mp_obj_module_t mp_module_sys; -extern const mp_obj_module_t mp_module_gc; -extern const mp_obj_module_t mp_module_thread; -extern const mp_obj_dict_t mp_module_builtins_globals; - -// extmod modules -extern const mp_obj_module_t mp_module_uasyncio; +// Modules needed by the parser when MICROPY_COMP_MODULE_CONST is enabled. extern const mp_obj_module_t mp_module_uerrno; extern const mp_obj_module_t mp_module_uctypes; -extern const mp_obj_module_t mp_module_uzlib; -extern const mp_obj_module_t mp_module_ujson; -extern const mp_obj_module_t mp_module_uos; -extern const mp_obj_module_t mp_module_ure; -extern const mp_obj_module_t mp_module_uheapq; -extern const mp_obj_module_t mp_module_uhashlib; -extern const mp_obj_module_t mp_module_ucryptolib; -extern const mp_obj_module_t mp_module_ubinascii; -extern const mp_obj_module_t mp_module_urandom; -extern const mp_obj_module_t mp_module_uselect; -extern const mp_obj_module_t mp_module_ussl; -extern const mp_obj_module_t mp_module_utimeq; extern const mp_obj_module_t mp_module_machine; -extern const mp_obj_module_t mp_module_lwip; -extern const mp_obj_module_t mp_module_uwebsocket; -extern const mp_obj_module_t mp_module_webrepl; -extern const mp_obj_module_t mp_module_framebuf; -extern const mp_obj_module_t mp_module_btree; -extern const mp_obj_module_t mp_module_ubluetooth; -extern const mp_obj_module_t mp_module_uplatform; extern const char MICROPY_PY_BUILTINS_HELP_TEXT[]; From 2c015375d1e795b4c1a996e50b27234e07f3f638 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 7 Jun 2022 17:44:21 +1000 Subject: [PATCH 0062/1041] stm32: Use a separate symbol name for the bootloader state pointer. Prerequisite for enabling Link Time Optimisation. The _bl_state address is the same as _estack, but _estack is referred to as a uint32_t elsewhere in the code. LTO doesn't like it when the same symbol has two different types. Signed-off-by: Angus Gratton --- ports/stm32/boards/common_bss_heap_stack.ld | 4 ++++ ports/stm32/powerctrl.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/common_bss_heap_stack.ld b/ports/stm32/boards/common_bss_heap_stack.ld index 1bb2249e96..b079313c44 100644 --- a/ports/stm32/boards/common_bss_heap_stack.ld +++ b/ports/stm32/boards/common_bss_heap_stack.ld @@ -26,3 +26,7 @@ . = . + _minimum_stack_size; . = ALIGN(4); } >RAM + +/* _bl_state symbol is used by MICROPY_HW_ENTER_BOOTLOADER_VIA_RESET, this is + the end of stack address but is accessed as a different type. */ +_bl_state = _estack; diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index 3b4a2d86e1..f3f1837ece 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -78,7 +78,7 @@ // Location in RAM of bootloader state (just after the top of the stack). // STM32H7 has ECC and writes to RAM must be 64-bit so they are fully committed // to actual SRAM before a system reset occurs. -#define BL_STATE_PTR ((uint64_t *)&_estack) +#define BL_STATE_PTR ((uint64_t *)&_bl_state) #define BL_STATE_KEY (0x5a5) #define BL_STATE_KEY_MASK (0xfff) #define BL_STATE_KEY_SHIFT (32) @@ -87,7 +87,7 @@ #define BL_STATE_GET_REG(s) ((s) & 0xffffffff) #define BL_STATE_GET_KEY(s) (((s) >> BL_STATE_KEY_SHIFT) & BL_STATE_KEY_MASK) #define BL_STATE_GET_ADDR(s) (((s) >> BL_STATE_KEY_SHIFT) & ~BL_STATE_KEY_MASK) -extern uint64_t _estack[]; +extern uint64_t _bl_state[]; #endif static inline void powerctrl_disable_hsi_if_unused(void) { From e76d88b531ec42a75833800d04962e0dc660cef0 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 7 Jun 2022 17:34:40 +1000 Subject: [PATCH 0063/1041] stm32/Makefile: Enable link-time-optimisation via LTO=1 make option. When tested, this reduces default MP binary sizes by approx 2-2.5%, and very marginally increases performance in benchmarks. Build times seem very similar to non-LTO when using gcc 12. See #8733 for further discussion. Signed-off-by: Angus Gratton --- ports/stm32/Makefile | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 5cde84e67c..53d1bb4ac4 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -96,13 +96,22 @@ CFLAGS += -fsingle-precision-constant endif endif -LDFLAGS = -nostdlib -L $(LD_DIR) $(addprefix -T,$(LD_FILES)) -Map=$(@:.elf=.map) --cref -LDFLAGS += --defsym=_estack_reserve=8 +LDFLAGS = -nostdlib -L $(LD_DIR) $(addprefix -T,$(LD_FILES)) -Wl,-Map=$(@:.elf=.map) -Wl,--cref +LDFLAGS += -Wl,--defsym=_estack_reserve=8 LIBS += "$(shell $(CC) $(CFLAGS) -print-libgcc-file-name)" # Remove uncalled code from the final image. CFLAGS += -fdata-sections -ffunction-sections -LDFLAGS += --gc-sections +LDFLAGS += -Wl,--gc-sections + +ifeq ($(LTO),1) +CFLAGS += -flto=auto +# LTO requires passing compiler flags to the linker as it will run the assembler. +# To avoid risk of missing something relevant, pass all flags except for preprocessor args +LDFLAGS += $(filter-out -I%,$(filter-out -D%,$(CFLAGS))) + +$(BUILD)/stm32_it.o $(BUILD)/pendsv.o: CFLAGS += -fno-lto +endif # Debugging/Optimization ifeq ($(DEBUG), 1) @@ -592,7 +601,7 @@ endef define GENERATE_ELF $(ECHO) "LINK $(1)" - $(Q)$(LD) $(LDFLAGS) -o $(1) $(2) $(LDFLAGS_MOD) $(LIBS) + $(Q)$(CC) $(LDFLAGS) -o $(1) $(2) $(LDFLAGS_MOD) $(LIBS) $(Q)$(SIZE) $(1) $(if $(filter-out $(TEXT0_ADDR),0x08000000), \ $(ECHO) "INFO: this build requires mboot to be installed first") From 5568c324bad71018a9480a22e1e4d60f5ea8c6d5 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 7 Jun 2022 17:46:08 +1000 Subject: [PATCH 0064/1041] tests/perf_bench: Add some configurations for N=32, M=10. For STM32L072 and similar, very low end targets. The other perf_bench tests run out of memory, crash, or fail on prerequisite features. Signed-off-by: Angus Gratton --- tests/perf_bench/bm_fannkuch.py | 1 + tests/perf_bench/bm_nqueens.py | 2 +- tests/perf_bench/bm_pidigits.py | 1 + tests/perf_bench/core_import_mpy_multi.py | 2 +- tests/perf_bench/core_qstr.py | 2 +- tests/run-perfbench.py | 4 +++- 6 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/perf_bench/bm_fannkuch.py b/tests/perf_bench/bm_fannkuch.py index 9f7ae797f0..49ab05d1e9 100644 --- a/tests/perf_bench/bm_fannkuch.py +++ b/tests/perf_bench/bm_fannkuch.py @@ -51,6 +51,7 @@ def fannkuch(n): # Benchmark interface bm_params = { + (32, 10): (3,), (50, 10): (5,), (100, 10): (6,), (500, 10): (7,), diff --git a/tests/perf_bench/bm_nqueens.py b/tests/perf_bench/bm_nqueens.py index 773dd3f7ed..c5a91bf304 100644 --- a/tests/perf_bench/bm_nqueens.py +++ b/tests/perf_bench/bm_nqueens.py @@ -46,7 +46,7 @@ def n_queens(queen_count): # Benchmark interface bm_params = { - (50, 25): (1, 5), + (32, 10): (1, 5), (100, 25): (1, 6), (1000, 100): (1, 7), (5000, 100): (1, 8), diff --git a/tests/perf_bench/bm_pidigits.py b/tests/perf_bench/bm_pidigits.py index 5949b93063..bdaa73cec7 100644 --- a/tests/perf_bench/bm_pidigits.py +++ b/tests/perf_bench/bm_pidigits.py @@ -36,6 +36,7 @@ def gen_pi_digits(n): # Benchmark interface bm_params = { + (32, 10): (1, 20), (50, 25): (1, 35), (100, 100): (1, 65), (1000, 1000): (2, 250), diff --git a/tests/perf_bench/core_import_mpy_multi.py b/tests/perf_bench/core_import_mpy_multi.py index 682c36328a..99c4721d29 100644 --- a/tests/perf_bench/core_import_mpy_multi.py +++ b/tests/perf_bench/core_import_mpy_multi.py @@ -73,7 +73,7 @@ def test(r): # Benchmark interface bm_params = { - (100, 10): (50,), + (32, 10): (50,), (1000, 10): (500,), (5000, 10): (5000,), } diff --git a/tests/perf_bench/core_qstr.py b/tests/perf_bench/core_qstr.py index b87e2c0658..64d6c59e92 100644 --- a/tests/perf_bench/core_qstr.py +++ b/tests/perf_bench/core_qstr.py @@ -10,7 +10,7 @@ def test(r): # Benchmark interface bm_params = { - (100, 10): (400,), + (32, 10): (400,), (1000, 10): (4000,), (5000, 10): (40000,), } diff --git a/tests/run-perfbench.py b/tests/run-perfbench.py index a2e9e8079a..f76aa511ad 100755 --- a/tests/run-perfbench.py +++ b/tests/run-perfbench.py @@ -260,7 +260,9 @@ def main(): ) cmd_parser.add_argument("--via-mpy", action="store_true", help="compile code to .mpy first") cmd_parser.add_argument("--mpy-cross-flags", default="", help="flags to pass to mpy-cross") - cmd_parser.add_argument("N", nargs=1, help="N parameter (approximate target CPU frequency)") + cmd_parser.add_argument( + "N", nargs=1, help="N parameter (approximate target CPU frequency in MHz)" + ) cmd_parser.add_argument("M", nargs=1, help="M parameter (approximate target heap in kbytes)") cmd_parser.add_argument("files", nargs="*", help="input test files") args = cmd_parser.parse_args() From dd77dbd4f72734da2b11ff52c553d636d1eee614 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 24 Jun 2022 12:04:47 +1000 Subject: [PATCH 0065/1041] stm32/boards: Enable LTO by default on boards with smaller flash size. Signed-off-by: Angus Gratton --- ports/stm32/README.md | 17 +++++++++++++++++ .../boards/B_L072Z_LRWAN1/mpconfigboard.mk | 3 +++ .../stm32/boards/NUCLEO_F091RC/mpconfigboard.mk | 3 +++ .../stm32/boards/NUCLEO_G0B1RE/mpconfigboard.mk | 3 +++ .../stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk | 3 +++ .../stm32/boards/NUCLEO_L432KC/mpconfigboard.mk | 3 +++ 6 files changed, 32 insertions(+) diff --git a/ports/stm32/README.md b/ports/stm32/README.md index 6b5f096d73..15025c5ae1 100644 --- a/ports/stm32/README.md +++ b/ports/stm32/README.md @@ -68,6 +68,23 @@ can be built via: For more information about mboot see mboot/README.md. +### Link Time Optimization + +Link Time Optimization (LTO) reduces the firmware binary size when enabled +(typically 2-3% smaller). However it may make build time longer, particularly on +older GCC versions. + +Currently LTO is enabled by default for some smaller STM32 boards with less +flash, but disabled on other boards. + +To enable LTO, pass `LTO=1` on the command line: + + $ make BOARD=boardname LTO=1 + +To disable LTO, pass `LTO=0` in the same way. + +Note that `make clean BOARD=boardname` will be needed before changing the `LTO` +setting of a firmware that is already built. ### Flashing the Firmware using DFU mode diff --git a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk index 03561f90ad..708c3cf133 100644 --- a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk +++ b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk @@ -9,3 +9,6 @@ MICROPY_VFS_FAT = 0 # Don't include default frozen modules because MCU is tight on flash space FROZEN_MANIFEST ?= + +# LTO reduces final binary size, may be slower to build depending on gcc version and hardware +LTO ?= 1 diff --git a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk index 4416188816..bb7142d1b3 100644 --- a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk @@ -9,3 +9,6 @@ MICROPY_VFS_LFS1 ?= 1 # Don't include default frozen modules because MCU is tight on flash space FROZEN_MANIFEST ?= + +# LTO reduces final binary size, may be slower to build depending on gcc version and hardware +LTO ?= 1 diff --git a/ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.mk index 371e10d154..b8bbfb4534 100644 --- a/ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.mk @@ -2,3 +2,6 @@ MCU_SERIES = g0 CMSIS_MCU = STM32G0B1xx AF_FILE = boards/stm32g0b1_af.csv LD_FILES = boards/stm32g0b1xe.ld boards/common_basic.ld + +# LTO reduces final binary size, may be slower to build depending on gcc version and hardware +LTO ?= 1 diff --git a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk index f3673f0060..72b13a70b2 100644 --- a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk @@ -8,3 +8,6 @@ MICROPY_VFS_FAT = 0 # Don't include default frozen modules because MCU is tight on flash space FROZEN_MANIFEST ?= + +# LTO reduces final binary size, may be slower to build depending on gcc version and hardware +LTO ?= 1 diff --git a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk index a87b4710e7..c3fff81002 100644 --- a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk @@ -10,3 +10,6 @@ MICROPY_VFS_LFS1 ?= 1 # Don't include default frozen modules because MCU is tight on flash space FROZEN_MANIFEST ?= + +# LTO reduces final binary size, may be slower to build depending on gcc version and hardware +LTO ?= 1 From ccaf1978072a1d8e63b5e2ee350f15d875dfc1fd Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 28 Jun 2022 13:15:10 +1000 Subject: [PATCH 0066/1041] esp32/network_wlan: Don't raise exception when scan returns no results. Prior to this commit, running scan() without any APs available would give: >>> wl.scan() Traceback (most recent call last): File "", line 1, in RuntimeError: Wifi Unknown Error 0x0102 Signed-off-by: Damien George --- ports/esp32/network_wlan.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ports/esp32/network_wlan.c b/ports/esp32/network_wlan.c index 91099419ec..48b398c8f0 100644 --- a/ports/esp32/network_wlan.c +++ b/ports/esp32/network_wlan.c @@ -345,6 +345,12 @@ STATIC mp_obj_t network_wlan_scan(mp_obj_t self_in) { if (status == 0) { uint16_t count = 0; esp_exceptions(esp_wifi_scan_get_ap_num(&count)); + if (count == 0) { + // esp_wifi_scan_get_ap_records must be called to free internal buffers from the scan. + // But it returns an error if wifi_ap_records==NULL. So allocate at least 1 AP entry. + // esp_wifi_scan_get_ap_records will then return the actual number of APs in count. + count = 1; + } wifi_ap_record_t *wifi_ap_records = calloc(count, sizeof(wifi_ap_record_t)); esp_exceptions(esp_wifi_scan_get_ap_records(&count, wifi_ap_records)); for (uint16_t i = 0; i < count; i++) { From ad308bc32285f27725299aa329ca0d00cb3805e7 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 24 Jun 2022 13:23:10 +1000 Subject: [PATCH 0067/1041] tests: Add an explanation of run-perfbench.py. Also changes this file to a Markdown file. Signed-off-by: Angus Gratton --- tests/README | 27 --------- tests/README.md | 149 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+), 27 deletions(-) delete mode 100644 tests/README create mode 100644 tests/README.md diff --git a/tests/README b/tests/README deleted file mode 100644 index 8794202e15..0000000000 --- a/tests/README +++ /dev/null @@ -1,27 +0,0 @@ -This directory contains tests for various functionality areas of MicroPython. -To run all stable tests, run "run-tests.py" script in this directory. - -Tests of capabilities not supported on all platforms should be written -to check for the capability being present. If it is not, the test -should merely output 'SKIP' followed by the line terminator, and call -sys.exit() to raise SystemExit, instead of attempting to test the -missing capability. The testing framework (run-tests.py in this -directory, test_main.c in qemu_arm) recognizes this as a skipped test. - -There are a few features for which this mechanism cannot be used to -condition a test. The run-tests.py script uses small scripts in the -feature_check directory to check whether each such feature is present, -and skips the relevant tests if not. - -Tests are generally verified by running the test both in MicroPython and -in CPython and comparing the outputs. If the output differs the test fails -and the outputs are saved in a .out and a .exp file respectively. -For tests that cannot be run in CPython, for example because they use -the machine module, a .exp file can be provided next to the test's .py -file. A convenient way to generate that is to run the test, let it fail -(because CPython cannot run it) and then copy the .out file (but not -before checking it manually!) - -When creating new tests, anything that relies on float support should go in the -float/ subdirectory. Anything that relies on import x, where x is not a built-in -module, should go in the import/ subdirectory. diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000000..b0bff4872e --- /dev/null +++ b/tests/README.md @@ -0,0 +1,149 @@ +# MicroPython Test Suite + +This directory contains tests for various functionality areas of MicroPython. +To run all stable tests, run "run-tests.py" script in this directory. + +Tests of capabilities not supported on all platforms should be written +to check for the capability being present. If it is not, the test +should merely output 'SKIP' followed by the line terminator, and call +sys.exit() to raise SystemExit, instead of attempting to test the +missing capability. The testing framework (run-tests.py in this +directory, test_main.c in qemu_arm) recognizes this as a skipped test. + +There are a few features for which this mechanism cannot be used to +condition a test. The run-tests.py script uses small scripts in the +feature_check directory to check whether each such feature is present, +and skips the relevant tests if not. + +Tests are generally verified by running the test both in MicroPython and +in CPython and comparing the outputs. If the output differs the test fails +and the outputs are saved in a .out and a .exp file respectively. +For tests that cannot be run in CPython, for example because they use +the machine module, a .exp file can be provided next to the test's .py +file. A convenient way to generate that is to run the test, let it fail +(because CPython cannot run it) and then copy the .out file (but not +before checking it manually!) + +When creating new tests, anything that relies on float support should go in the +float/ subdirectory. Anything that relies on import x, where x is not a built-in +module, should go in the import/ subdirectory. + +## perf_bench + +The `perf_bench` directory contains some performance benchmarks that can be used +to benchmark different MicroPython firmwares or host ports. + +The runner utility is `run-perfbench,py`. Execute `./run-perfbench.py --help` +for a full list of command line options. + +### Benchmarking a target + +To run tests on a firmware target using `pyboard.py`, run the command line like +this: + +``` +./run-perfbench.py -p -d /dev/ttyACM0 168 100 +``` + +* `-p` indicates running on a remote target via pyboard.py, not the host. +* `-d PORTNAME` is the serial port, `/dev/ttyACM0` is the default if not + provided. +* `168` is value `N`, the approximate CPU frequency in MHz (in this case Pyboard + V1.1 is 168MHz). It's possible to choose other values as well: lower values + like `10` will run much the tests much quicker, higher values like `1000` will + run much longer. +* `100` is value `M`, the approximate heap size in kilobytes (can get this from + `import micropython; micropython.mem_info()` or estimate it). It's possible to + choose other values here too: lower values like `10` will run shorter/smaller + tests, and higher values will run bigger tests. The maximum value of `M` is + limited by available heap, and the tests are written so the "recommended" + value is approximately the upper limit. + +### Benchmarking the host + +To benchmark the host build (unix/Windows), run like this: + +``` +./run-perfbench.py 2000 10000 +``` + +The output of perfbench is a list of tests and times/scores, like this: + +``` +N=2000 M=10000 n_average=8 +perf_bench/bm_chaos.py: SKIP +perf_bench/bm_fannkuch.py: 94550.38 2.9145 84.68 2.8499 +perf_bench/bm_fft.py: 79920.38 10.0771 129269.74 8.8205 +perf_bench/bm_float.py: 43844.62 17.8229 353219.64 17.7693 +perf_bench/bm_hexiom.py: 32959.12 15.0243 775.77 14.8893 +perf_bench/bm_nqueens.py: 40855.00 10.7297 247776.15 11.3647 +perf_bench/bm_pidigits.py: 64547.75 2.5609 7751.36 2.5996 +perf_bench/core_import_mpy_multi.py: 15433.38 14.2733 33065.45 14.2368 +perf_bench/core_import_mpy_single.py: 263.00 11.3910 3858.35 12.9021 +perf_bench/core_qstr.py: 4929.12 1.8434 8117.71 1.7921 +perf_bench/core_yield_from.py: 16274.25 6.2584 12334.13 5.8125 +perf_bench/misc_aes.py: 57425.25 5.5226 17888.60 5.7482 +perf_bench/misc_mandel.py: 40809.25 8.2007 158107.00 9.8864 +perf_bench/misc_pystone.py: 39821.75 6.4145 100867.62 6.5043 +perf_bench/misc_raytrace.py: 36293.75 6.8501 26906.93 6.8402 +perf_bench/viper_call0.py: 15573.00 14.9931 19644.99 13.1550 +perf_bench/viper_call1a.py: 16725.75 9.8205 18099.96 9.2752 +perf_bench/viper_call1b.py: 20752.62 8.3372 14565.60 9.0663 +perf_bench/viper_call1c.py: 20849.88 5.8783 14444.80 6.6295 +perf_bench/viper_call2a.py: 16156.25 11.2956 18818.59 11.7959 +perf_bench/viper_call2b.py: 22047.38 8.9484 13725.73 9.6800 +``` + +The numbers across each line are times and scores for the test: + +* Runtime average (microseconds, lower is better) +* Runtime standard deviation as a percentage +* Score average (units depend on the benchmark, higher is better) +* Score standard deviation as a percentage + +### Comparing performance + +Usually you want to know if something is faster or slower than a reference. To +do this, copy the output of each `run-perfbench.py` run to a text file. + +This can be done multiple ways, but one way on Linux/macOS is with the `tee` +utility: `./run-perfbench.py -p 168 100 | tee pyb-run1.txt` + +Once you have two files with output from two different runs (maybe with +different code or configuration), compare the runtimes with `./run-perfbench.py +-t pybv-run1.txt pybv-run2.txt` or compare scores with `./run-perfbench.py -s +pybv-run1.txt pybv-run2.txt`: + +``` +> ./run-perfbench.py -s pyb-run1.txt pyb-run2.txt +diff of scores (higher is better) +N=168 M=100 pyb-run1.txt -> pyb-run2.txt diff diff% (error%) +bm_chaos.py 352.90 -> 352.63 : -0.27 = -0.077% (+/-0.00%) +bm_fannkuch.py 77.52 -> 77.45 : -0.07 = -0.090% (+/-0.01%) +bm_fft.py 2516.80 -> 2519.74 : +2.94 = +0.117% (+/-0.00%) +bm_float.py 5749.27 -> 5749.65 : +0.38 = +0.007% (+/-0.00%) +bm_hexiom.py 42.22 -> 42.30 : +0.08 = +0.189% (+/-0.00%) +bm_nqueens.py 4407.55 -> 4414.44 : +6.89 = +0.156% (+/-0.00%) +bm_pidigits.py 638.09 -> 632.14 : -5.95 = -0.932% (+/-0.25%) +core_import_mpy_multi.py 477.74 -> 477.57 : -0.17 = -0.036% (+/-0.00%) +core_import_mpy_single.py 58.74 -> 58.72 : -0.02 = -0.034% (+/-0.00%) +core_qstr.py 63.11 -> 63.11 : +0.00 = +0.000% (+/-0.01%) +core_yield_from.py 357.57 -> 357.57 : +0.00 = +0.000% (+/-0.00%) +misc_aes.py 397.27 -> 396.47 : -0.80 = -0.201% (+/-0.00%) +misc_mandel.py 3375.70 -> 3375.84 : +0.14 = +0.004% (+/-0.00%) +misc_pystone.py 2265.36 -> 2265.97 : +0.61 = +0.027% (+/-0.01%) +misc_raytrace.py 367.61 -> 368.15 : +0.54 = +0.147% (+/-0.01%) +viper_call0.py 605.92 -> 605.92 : +0.00 = +0.000% (+/-0.00%) +viper_call1a.py 576.78 -> 576.78 : +0.00 = +0.000% (+/-0.00%) +viper_call1b.py 452.45 -> 452.46 : +0.01 = +0.002% (+/-0.01%) +viper_call1c.py 457.39 -> 457.39 : +0.00 = +0.000% (+/-0.00%) +viper_call2a.py 561.37 -> 561.37 : +0.00 = +0.000% (+/-0.00%) +viper_call2b.py 389.49 -> 389.50 : +0.01 = +0.003% (+/-0.01%) +``` + +Note in particular the error percentages at the end of each line. If these are +high relative to the percentage difference then it indicates high variability in +the test runs, and the absolute difference value is unreliable. High error +percentages are particularly common on PC builds, where the host OS may +influence test run times. Increasing the `N` value may help average this out by +running each test longer. From e024a4c59cb4af6a8d05104df161c61702c2ce4b Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 24 Jun 2022 13:27:25 +1000 Subject: [PATCH 0068/1041] tests: Fix run-perfbench parsing "no matching params" case. Signed-off-by: Angus Gratton --- tests/perf_bench/benchrun.py | 2 +- tests/run-perfbench.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/perf_bench/benchrun.py b/tests/perf_bench/benchrun.py index 90c303dd29..ed43297d15 100644 --- a/tests/perf_bench/benchrun.py +++ b/tests/perf_bench/benchrun.py @@ -15,7 +15,7 @@ def bm_run(N, M): cur_nm = nm param = p if param is None: - print(-1, -1, "no matching params") + print(-1, -1, "SKIP: no matching params") return # Run and time benchmark diff --git a/tests/run-perfbench.py b/tests/run-perfbench.py index f76aa511ad..d70b996937 100755 --- a/tests/run-perfbench.py +++ b/tests/run-perfbench.py @@ -187,7 +187,7 @@ def parse_output(filename): m = int(m.split("=")[1]) data = [] for l in f: - if l.find(": ") != -1 and l.find(": SKIP") == -1 and l.find("CRASH: ") == -1: + if ": " in l and ": SKIP" not in l and "CRASH: " not in l: name, values = l.strip().split(": ") values = tuple(float(v) for v in values.split()) data.append((name,) + values) From 6e83bb47ebeed8f8334925755bed5fea5b3f2475 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 28 Jun 2022 16:31:43 +1000 Subject: [PATCH 0069/1041] py/builtinhelp: Don't show help for an MP_MODULE_ATTR_DELEGATION_ENTRY. Otherwise it can lead to a crash. Fixes issue #8816. Signed-off-by: Damien George --- py/builtinhelp.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/py/builtinhelp.c b/py/builtinhelp.c index 84d69caf35..94f8beaff2 100644 --- a/py/builtinhelp.c +++ b/py/builtinhelp.c @@ -149,8 +149,14 @@ STATIC void mp_help_print_obj(const mp_obj_t obj) { } if (map != NULL) { for (uint i = 0; i < map->alloc; i++) { - if (map->table[i].key != MP_OBJ_NULL) { - mp_help_print_info_about_object(map->table[i].key, map->table[i].value); + mp_obj_t key = map->table[i].key; + if (key != MP_OBJ_NULL + #if MICROPY_MODULE_ATTR_DELEGATION + // MP_MODULE_ATTR_DELEGATION_ENTRY entries have MP_QSTRnull as qstr key. + && key != MP_OBJ_NEW_QSTR(MP_QSTRnull) + #endif + ) { + mp_help_print_info_about_object(key, map->table[i].value); } } } From fe55d3e0166b6c6ff189fb7a854847bad4fcd6b6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 29 Jun 2022 12:08:12 +1000 Subject: [PATCH 0070/1041] unix/variants: Move setting of MICROPY_PY_USELECT to port config file. The default is the same as before: MICROPY_PY_USELECT=0 and MICROPY_PY_USELECT_POSIX=1. But now this can be easily overridden at the make command-line using, eg: make VARIANT=dev CFLAGS_EXTRA=-DMICROPY_PY_USELECT=1 Signed-off-by: Damien George --- ports/unix/mpconfigport.h | 5 ++++- ports/unix/variants/coverage/mpconfigvariant.h | 1 - ports/unix/variants/dev/mpconfigvariant.h | 1 - ports/unix/variants/standard/mpconfigvariant.h | 1 - 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index a483c3e086..232bfb857c 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -179,8 +179,11 @@ #define MICROPY_PY_UHASHLIB_SHA1 (1) #define MICROPY_PY_UCRYPTOLIB (1) #endif +#ifndef MICROPY_PY_USELECT +#define MICROPY_PY_USELECT (0) +#endif #ifndef MICROPY_PY_USELECT_POSIX -#define MICROPY_PY_USELECT_POSIX (1) +#define MICROPY_PY_USELECT_POSIX (!MICROPY_PY_USELECT) #endif #define MICROPY_PY_UWEBSOCKET (1) #define MICROPY_PY_MACHINE (1) diff --git a/ports/unix/variants/coverage/mpconfigvariant.h b/ports/unix/variants/coverage/mpconfigvariant.h index bf68dcb63a..47ed4bc46c 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.h +++ b/ports/unix/variants/coverage/mpconfigvariant.h @@ -33,7 +33,6 @@ // Disable some features that come enabled by default with the feature level. #define MICROPY_PY_BUILTINS_EXECFILE (0) #define MICROPY_PY_SYS_STDIO_BUFFER (0) -#define MICROPY_PY_USELECT (0) // Enable additional features. #define MICROPY_DEBUG_PARSE_RULE_NAME (1) diff --git a/ports/unix/variants/dev/mpconfigvariant.h b/ports/unix/variants/dev/mpconfigvariant.h index 61092394cd..0603394247 100644 --- a/ports/unix/variants/dev/mpconfigvariant.h +++ b/ports/unix/variants/dev/mpconfigvariant.h @@ -30,7 +30,6 @@ // Disable some features that come enabled by default with the feature level. #define MICROPY_PY_BUILTINS_EXECFILE (0) #define MICROPY_PY_SYS_STDIO_BUFFER (0) -#define MICROPY_PY_USELECT (0) // Enable some additional features. #define MICROPY_REPL_EMACS_WORDS_MOVE (1) diff --git a/ports/unix/variants/standard/mpconfigvariant.h b/ports/unix/variants/standard/mpconfigvariant.h index 1ec46ef92d..31618652e9 100644 --- a/ports/unix/variants/standard/mpconfigvariant.h +++ b/ports/unix/variants/standard/mpconfigvariant.h @@ -38,7 +38,6 @@ #define MICROPY_PY_MATH_FACTORIAL (0) #define MICROPY_PY_SYS_PS1_PS2 (0) #define MICROPY_PY_SYS_STDIO_BUFFER (0) -#define MICROPY_PY_USELECT (0) #define MICROPY_PY_UASYNCIO (0) #define MICROPY_PY_URE_SUB (0) #define MICROPY_PY_URANDOM_EXTRA_FUNCS (0) From fad978ae5f2dbb939b0ce82a8a77f4b757557f4e Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 29 Jun 2022 12:19:05 +1000 Subject: [PATCH 0071/1041] unix/variants: Enable remaining options on dev,coverage from ROM extra. So that the default configuration for the dev and coverage variants includes all options set by MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES. Note that enabling MICROPY_PY_SYS_STDIO_BUFFER on unix doesn't do anything because unix doesn't use shared/runtime/sys_stdio_mphal.c. Signed-off-by: Damien George --- ports/unix/variants/coverage/mpconfigvariant.h | 4 ---- ports/unix/variants/dev/mpconfigvariant.h | 4 ---- 2 files changed, 8 deletions(-) diff --git a/ports/unix/variants/coverage/mpconfigvariant.h b/ports/unix/variants/coverage/mpconfigvariant.h index 47ed4bc46c..9c98ca2f62 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.h +++ b/ports/unix/variants/coverage/mpconfigvariant.h @@ -30,10 +30,6 @@ // Set base feature level. #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) -// Disable some features that come enabled by default with the feature level. -#define MICROPY_PY_BUILTINS_EXECFILE (0) -#define MICROPY_PY_SYS_STDIO_BUFFER (0) - // Enable additional features. #define MICROPY_DEBUG_PARSE_RULE_NAME (1) #define MICROPY_TRACKED_ALLOC (1) diff --git a/ports/unix/variants/dev/mpconfigvariant.h b/ports/unix/variants/dev/mpconfigvariant.h index 0603394247..0084d00dd6 100644 --- a/ports/unix/variants/dev/mpconfigvariant.h +++ b/ports/unix/variants/dev/mpconfigvariant.h @@ -27,10 +27,6 @@ // Set base feature level. #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) -// Disable some features that come enabled by default with the feature level. -#define MICROPY_PY_BUILTINS_EXECFILE (0) -#define MICROPY_PY_SYS_STDIO_BUFFER (0) - // Enable some additional features. #define MICROPY_REPL_EMACS_WORDS_MOVE (1) #define MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE (1) From 510bea9383b1baa5b22431e98d054f739dfe5d52 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 29 Jun 2022 12:42:04 +1000 Subject: [PATCH 0072/1041] unix/variants/coverage: Change config to use ROM level everything. This ROM level is not yet fully defined, but it at least enables MICROPY_PY_SYS_TRACEBACKLIMIT. The coverage build should have everything enabled, so it makes sense to use this ROM level for it. Signed-off-by: Damien George --- ports/unix/variants/coverage/mpconfigvariant.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ports/unix/variants/coverage/mpconfigvariant.h b/ports/unix/variants/coverage/mpconfigvariant.h index 9c98ca2f62..30e3a4e5d2 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.h +++ b/ports/unix/variants/coverage/mpconfigvariant.h @@ -28,7 +28,7 @@ // for coverage testing. // Set base feature level. -#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EVERYTHING) // Enable additional features. #define MICROPY_DEBUG_PARSE_RULE_NAME (1) @@ -42,7 +42,6 @@ #define MICROPY_PY_BUILTINS_NEXT2 (1) #define MICROPY_PY_BUILTINS_RANGE_BINOP (1) #define MICROPY_PY_SYS_GETSIZEOF (1) -#define MICROPY_PY_SYS_TRACEBACKLIMIT (1) #define MICROPY_PY_IO_BUFFEREDWRITER (1) #define MICROPY_PY_URANDOM_SEED_INIT_FUNC (mp_urandom_seed_init()) #define MICROPY_PY_URE_DEBUG (1) From afa4d0a4b75bc8d21ae95cc76627952d61df93d0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 29 Jun 2022 12:47:14 +1000 Subject: [PATCH 0073/1041] unix/variants/dev: Allow all config options to be overridden. They can be overridden on the make command line, for example. Signed-off-by: Damien George --- ports/unix/variants/dev/mpconfigvariant.h | 6 ++++++ ports/unix/variants/dev/mpconfigvariant.mk | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ports/unix/variants/dev/mpconfigvariant.h b/ports/unix/variants/dev/mpconfigvariant.h index 0084d00dd6..2522f1861f 100644 --- a/ports/unix/variants/dev/mpconfigvariant.h +++ b/ports/unix/variants/dev/mpconfigvariant.h @@ -28,7 +28,13 @@ #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) // Enable some additional features. +#ifndef MICROPY_REPL_EMACS_WORDS_MOVE #define MICROPY_REPL_EMACS_WORDS_MOVE (1) +#endif +#ifndef MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE #define MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE (1) +#endif +#ifndef MICROPY_PY_SYS_SETTRACE #define MICROPY_PY_SYS_SETTRACE (1) +#endif #define MICROPY_PY_URANDOM_SEED_INIT_FUNC (mp_urandom_seed_init()) diff --git a/ports/unix/variants/dev/mpconfigvariant.mk b/ports/unix/variants/dev/mpconfigvariant.mk index 91bd28da9b..78588d379b 100644 --- a/ports/unix/variants/dev/mpconfigvariant.mk +++ b/ports/unix/variants/dev/mpconfigvariant.mk @@ -3,8 +3,8 @@ PROG ?= micropython-dev FROZEN_MANIFEST ?= $(VARIANT_DIR)/manifest.py MICROPY_ROM_TEXT_COMPRESSION = 1 -MICROPY_VFS_FAT = 1 -MICROPY_VFS_LFS1 = 1 -MICROPY_VFS_LFS2 = 1 +MICROPY_VFS_FAT ?= 1 +MICROPY_VFS_LFS1 ?= 1 +MICROPY_VFS_LFS2 ?= 1 MICROPY_PY_BLUETOOTH ?= 1 From 932556d5fc09a196139170fe52436ea8a02020c1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 29 Jun 2022 12:48:42 +1000 Subject: [PATCH 0074/1041] tests/micropython: Add test for builtin execfile() function. Signed-off-by: Damien George --- tests/micropython/builtin_execfile.py | 70 +++++++++++++++++++++++ tests/micropython/builtin_execfile.py.exp | 6 ++ 2 files changed, 76 insertions(+) create mode 100644 tests/micropython/builtin_execfile.py create mode 100644 tests/micropython/builtin_execfile.py.exp diff --git a/tests/micropython/builtin_execfile.py b/tests/micropython/builtin_execfile.py new file mode 100644 index 0000000000..8a8ce79f78 --- /dev/null +++ b/tests/micropython/builtin_execfile.py @@ -0,0 +1,70 @@ +# Test builtin execfile function using VFS. + +try: + import uio, uos + + execfile + uio.IOBase + uos.mount +except (ImportError, NameError, AttributeError): + print("SKIP") + raise SystemExit + + +class File(uio.IOBase): + def __init__(self, data): + self.data = data + self.off = 0 + + def ioctl(self, request, arg): + return 0 + + def readinto(self, buf): + buf[:] = memoryview(self.data)[self.off : self.off + len(buf)] + self.off += len(buf) + return len(buf) + + +class Filesystem: + def __init__(self, files): + self.files = files + + def mount(self, readonly, mkfs): + print("mount", readonly, mkfs) + + def umount(self): + print("umount") + + def open(self, file, mode): + print("open", file, mode) + if file not in self.files: + raise OSError(2) # ENOENT + return File(self.files[file]) + + +# First umount any existing mount points the target may have. +try: + uos.umount("/") +except OSError: + pass +for path in uos.listdir("/"): + uos.umount("/" + path) + +# Create and mount the VFS object. +files = { + "/test.py": "print(123)", +} +fs = Filesystem(files) +uos.mount(fs, "/test_mnt") + +# Test execfile with a file that doesn't exist. +try: + execfile("/test_mnt/noexist.py") +except OSError: + print("OSError") + +# Test execfile with a file that does exist. +execfile("/test_mnt/test.py") + +# Unmount the VFS object. +uos.umount(fs) diff --git a/tests/micropython/builtin_execfile.py.exp b/tests/micropython/builtin_execfile.py.exp new file mode 100644 index 0000000000..1d5d8ee571 --- /dev/null +++ b/tests/micropython/builtin_execfile.py.exp @@ -0,0 +1,6 @@ +mount False False +open /noexist.py rb +OSError +open /test.py rb +123 +umount From b004e7e397577d95404fd31aec68a5c54904a48c Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 29 Jun 2022 00:22:49 +1000 Subject: [PATCH 0075/1041] rp2/modmachine: Implement lightsleep() with optional sleep period. This gets basic machine.lightsleep([n]) behaviour working on the rp2 port. It supports: - Calling lightsleep without a specified period, in which case it uses xosc dormant mode. There's currently no way to wake it up from this state, unless you write to raw registers to enable a GPIO wake up source. - Calling lightsleep with a period n in milliseconds. This period must be less than about 72 minutes and uses timer alarm3 to wake it up. The RTC continues to run during lightsleep, but other peripherals have their clock turned off during the sleep. It doesn't yet support longer periods than 72 minutes, or waking up from GPIO IRQ. Measured current consumption from the USB port on a PICO board is about 1.5mA when doing machine.lightsleep(5000), and about 0.9mA when doing machine.lightsleep(). Addresses issue #8770. Signed-off-by: Damien George --- ports/rp2/CMakeLists.txt | 2 + ports/rp2/modmachine.c | 80 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 0088ba2c6d..9f71f65840 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -150,6 +150,7 @@ set(PICO_SDK_COMPONENTS hardware_i2c hardware_irq hardware_pio + hardware_pll hardware_pwm hardware_regs hardware_rtc @@ -159,6 +160,7 @@ set(PICO_SDK_COMPONENTS hardware_timer hardware_uart hardware_watchdog + hardware_xosc pico_base_headers pico_binary_info pico_bootrom diff --git a/ports/rp2/modmachine.c b/ports/rp2/modmachine.c index b988afdf30..3c8922c417 100644 --- a/ports/rp2/modmachine.c +++ b/ports/rp2/modmachine.c @@ -38,7 +38,12 @@ #include "modmachine.h" #include "uart.h" #include "hardware/clocks.h" +#include "hardware/pll.h" +#include "hardware/structs/rosc.h" +#include "hardware/structs/scb.h" +#include "hardware/structs/syscfg.h" #include "hardware/watchdog.h" +#include "hardware/xosc.h" #include "pico/bootrom.h" #include "pico/stdlib.h" #include "pico/unique_id.h" @@ -83,6 +88,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause); NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) { MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args); + rosc_hw->ctrl = ROSC_CTRL_ENABLE_VALUE_ENABLE << ROSC_CTRL_ENABLE_LSB; reset_usb_boot(0, 0); for (;;) { } @@ -113,13 +119,77 @@ STATIC mp_obj_t machine_idle(void) { STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle); STATIC mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) { - if (n_args == 0) { - for (;;) { - MICROPY_EVENT_POLL_HOOK + mp_int_t delay_ms = 0; + bool use_timer_alarm = false; + + if (n_args == 1) { + delay_ms = mp_obj_get_int(args[0]); + if (delay_ms <= 1) { + // Sleep is too small, just use standard delay. + mp_hal_delay_ms(delay_ms); + return mp_const_none; + } + use_timer_alarm = delay_ms < (1ULL << 32) / 1000; + if (use_timer_alarm) { + // Use timer alarm to wake. + } else { + // TODO: Use RTC alarm to wake. + mp_raise_ValueError(MP_ERROR_TEXT("sleep too long")); } - } else { - mp_hal_delay_ms(mp_obj_get_int(args[0])); } + + const uint32_t xosc_hz = XOSC_MHZ * 1000000; + + // Disable USB and ADC clocks. + clock_stop(clk_usb); + clock_stop(clk_adc); + + // CLK_REF = XOSC + clock_configure(clk_ref, CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC, 0, xosc_hz, xosc_hz); + + // CLK_SYS = CLK_REF + clock_configure(clk_sys, CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF, 0, xosc_hz, xosc_hz); + + // CLK_RTC = XOSC / 256 + clock_configure(clk_rtc, 0, CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_XOSC_CLKSRC, xosc_hz, xosc_hz / 256); + + // CLK_PERI = CLK_SYS + clock_configure(clk_peri, 0, CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS, xosc_hz, xosc_hz); + + // Disable PLLs. + pll_deinit(pll_sys); + pll_deinit(pll_usb); + + // Disable ROSC. + rosc_hw->ctrl = ROSC_CTRL_ENABLE_VALUE_DISABLE << ROSC_CTRL_ENABLE_LSB; + + if (n_args == 0) { + xosc_dormant(); + } else { + uint32_t sleep_en0 = clocks_hw->sleep_en0; + uint32_t sleep_en1 = clocks_hw->sleep_en1; + clocks_hw->sleep_en0 = CLOCKS_SLEEP_EN0_CLK_RTC_RTC_BITS; + if (use_timer_alarm) { + // Use timer alarm to wake. + clocks_hw->sleep_en1 = CLOCKS_SLEEP_EN1_CLK_SYS_TIMER_BITS; + timer_hw->alarm[3] = timer_hw->timerawl + delay_ms * 1000; + } else { + // TODO: Use RTC alarm to wake. + clocks_hw->sleep_en1 = 0; + } + scb_hw->scr |= M0PLUS_SCR_SLEEPDEEP_BITS; + __wfi(); + scb_hw->scr &= ~M0PLUS_SCR_SLEEPDEEP_BITS; + clocks_hw->sleep_en0 = sleep_en0; + clocks_hw->sleep_en1 = sleep_en1; + } + + // Enable ROSC. + rosc_hw->ctrl = ROSC_CTRL_ENABLE_VALUE_ENABLE << ROSC_CTRL_ENABLE_LSB; + + // Bring back all clocks. + clocks_init(); + return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lightsleep_obj, 0, 1, machine_lightsleep); From 797a83ac3ef8f9bbf67faf59da665b5509db428b Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 29 Jun 2022 13:56:12 +1000 Subject: [PATCH 0076/1041] rp2/mpthreadport: Ensure core1 doesn't hold gc lock in deinit. Prior to this commit the following code would lock up the device when Ctrl-D is entered at the REPL: import gc, _thread def collect_thread(): while True: gc.collect() _thread.start_new_thread(collect_thread, []) Fixes part of #8494. Signed-off-by: Jim Mussared --- ports/rp2/mpthreadport.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ports/rp2/mpthreadport.c b/ports/rp2/mpthreadport.c index cdb5945d21..187f74bb57 100644 --- a/ports/rp2/mpthreadport.c +++ b/ports/rp2/mpthreadport.c @@ -47,8 +47,13 @@ void mp_thread_init(void) { } void mp_thread_deinit(void) { + assert(get_core_num() == 0); + // Must ensure that core1 is not currently holding the GC lock, otherwise + // it will be terminated while holding the lock. + mp_thread_mutex_lock(&MP_STATE_MEM(gc_mutex), 1); multicore_reset_core1(); core1_entry = NULL; + mp_thread_mutex_unlock(&MP_STATE_MEM(gc_mutex)); } void mp_thread_gc_others(void) { From f1b5761ced7f19676b744ef24c201fb0ff084c2a Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jun 2022 13:49:47 +1000 Subject: [PATCH 0077/1041] py/mkrules.cmake: Improve printing of git-submodules error. Signed-off-by: Damien George --- py/mkrules.cmake | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/py/mkrules.cmake b/py/mkrules.cmake index d0dc019625..4d0bbd22ad 100644 --- a/py/mkrules.cmake +++ b/py/mkrules.cmake @@ -182,6 +182,9 @@ endif() # Update submodules if(ECHO_SUBMODULES) # If cmake is run with GIT_SUBMODULES defined on command line, process the port / board - # settings then print the final GIT_SUBMODULES variable as a fatal error and exit. - message(FATAL_ERROR "GIT_SUBMODULES=${GIT_SUBMODULES}") + # settings then print the final GIT_SUBMODULES variable and exit. + # Note: the GIT_SUBMODULES is done via echo rather than message, as message splits + # the output onto multiple lines + execute_process(COMMAND ${CMAKE_COMMAND} -E echo "GIT_SUBMODULES=${GIT_SUBMODULES}") + message(FATAL_ERROR "Done") endif() From f75e61105457732db355788e5ec1b734c348e4e0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jun 2022 13:54:50 +1000 Subject: [PATCH 0078/1041] extmod/vfs: Prevent uninitialized variable warning for path_out. The warning can appear when building in Release mode on the rp2 port. Signed-off-by: Damien George --- extmod/vfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extmod/vfs.c b/extmod/vfs.c index 8e5e036326..8bcead190d 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -100,6 +100,8 @@ STATIC mp_vfs_mount_t *lookup_path(mp_obj_t path_in, mp_obj_t *path_out) { if (vfs != MP_VFS_NONE && vfs != MP_VFS_ROOT) { *path_out = mp_obj_new_str_of_type(mp_obj_get_type(path_in), (const byte *)p_out, strlen(p_out)); + } else { + *path_out = MP_OBJ_NULL; } return vfs; } From 7dd818052e62a6fffeec3e566063c424dad6af25 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jun 2022 14:10:58 +1000 Subject: [PATCH 0079/1041] extmod/network_cyw43: Support new cyw43-driver. Signed-off-by: Damien George --- extmod/network_cyw43.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/extmod/network_cyw43.c b/extmod/network_cyw43.c index ea2fbbd45e..8823e3fa25 100644 --- a/extmod/network_cyw43.c +++ b/extmod/network_cyw43.c @@ -33,10 +33,15 @@ #if MICROPY_PY_NETWORK_CYW43 #include "lwip/netif.h" -#include "drivers/cyw43/cyw43.h" #include "extmod/network_cyw43.h" #include "modnetwork.h" +#if MICROPY_PY_NETWORK_CYW43_USE_LIB_DRIVER +#include "lib/cyw43-driver/src/cyw43.h" +#else +#include "drivers/cyw43/cyw43.h" +#endif + typedef struct _network_cyw43_obj_t { mp_obj_base_t base; cyw43_t *cyw; @@ -119,7 +124,11 @@ STATIC mp_obj_t network_cyw43_active(size_t n_args, const mp_obj_t *args) { if (n_args == 1) { return mp_obj_new_bool(cyw43_tcpip_link_status(self->cyw, self->itf)); } else { + #if MICROPY_PY_NETWORK_CYW43_USE_LIB_DRIVER + cyw43_wifi_set_up(self->cyw, self->itf, mp_obj_is_true(args[1]), MICROPY_CYW43_COUNTRY); + #else cyw43_wifi_set_up(self->cyw, self->itf, mp_obj_is_true(args[1])); + #endif return mp_const_none; } } From 4f30c60dcbfabb86ae5711a69445c913a5652304 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jun 2022 14:48:47 +1000 Subject: [PATCH 0080/1041] extmod/modnetwork: Include cyw43-driver header if it's enabled. Signed-off-by: Damien George --- extmod/modnetwork.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/extmod/modnetwork.c b/extmod/modnetwork.c index 87e155e091..e05bfdb11d 100644 --- a/extmod/modnetwork.c +++ b/extmod/modnetwork.c @@ -44,6 +44,11 @@ #include "lwip/apps/mdns.h" #endif +#if MICROPY_PY_NETWORK_CYW43 && MICROPY_PY_NETWORK_CYW43_USE_LIB_DRIVER +// So that CYW43_LINK_xxx constants are available to MICROPY_PORT_NETWORK_INTERFACES. +#include "lib/cyw43-driver/src/cyw43.h" +#endif + /// \module network - network configuration /// /// This module provides network drivers and routing configuration. From 18a010b5b1b50df34ffaab6d48404a19242f1930 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jun 2022 15:58:19 +1000 Subject: [PATCH 0081/1041] lib/cyw43-driver: Add new submodule for CYW43xx WiFi driver. Signed-off-by: Damien George --- .gitmodules | 3 +++ lib/cyw43-driver | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/cyw43-driver diff --git a/.gitmodules b/.gitmodules index 118e023deb..3d1e2fea74 100644 --- a/.gitmodules +++ b/.gitmodules @@ -50,3 +50,6 @@ url = https://github.com/andrewleech/wiznet_ioLibrary_Driver.git # Requires https://github.com/Wiznet/ioLibrary_Driver/pull/120 # url = https://github.com/Wiznet/ioLibrary_Driver.git +[submodule "lib/cyw43-driver"] + path = lib/cyw43-driver + url = https://github.com/georgerobotics/cyw43-driver.git diff --git a/lib/cyw43-driver b/lib/cyw43-driver new file mode 160000 index 0000000000..195dfcc10b --- /dev/null +++ b/lib/cyw43-driver @@ -0,0 +1 @@ +Subproject commit 195dfcc10bb6f379e3dea45147590db2203d3c7b From f525e17793d29fec0cc545dfaf290c75b12e8411 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jun 2022 14:15:13 +1000 Subject: [PATCH 0082/1041] lib/pico-sdk: Update to version 1.4.0. Signed-off-by: Damien George --- lib/pico-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pico-sdk b/lib/pico-sdk index 2062372d20..2e6142b15b 160000 --- a/lib/pico-sdk +++ b/lib/pico-sdk @@ -1 +1 @@ -Subproject commit 2062372d203b372849d573f252cf7c6dc2800c0a +Subproject commit 2e6142b15b8a75c1227dd3edbe839193b2bf9041 From 11f920f8adeaa012a1f893160850c33ad72f6e33 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jun 2022 14:23:30 +1000 Subject: [PATCH 0083/1041] rp2/mbedtls: Enable some more mbedtls options. Signed-off-by: Damien George --- ports/rp2/mbedtls/mbedtls_config.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ports/rp2/mbedtls/mbedtls_config.h b/ports/rp2/mbedtls/mbedtls_config.h index 8e054ed517..4bf606f5ea 100644 --- a/ports/rp2/mbedtls/mbedtls_config.h +++ b/ports/rp2/mbedtls/mbedtls_config.h @@ -26,6 +26,10 @@ #ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H #define MICROPY_INCLUDED_MBEDTLS_CONFIG_H +// If you want to debug MBEDTLS uncomment the following and +// Pass 3 to mbedtls_debug_set_threshold in socket_new +// #define MBEDTLS_DEBUG_C + // Set mbedtls configuration #define MBEDTLS_PLATFORM_MEMORY #define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS @@ -45,6 +49,8 @@ #define MBEDTLS_ECP_DP_BP384R1_ENABLED #define MBEDTLS_ECP_DP_BP512R1_ENABLED #define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_ECP_NIST_OPTIM +#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED #define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED #define MBEDTLS_NO_PLATFORM_ENTROPY #define MBEDTLS_PKCS1_V15 @@ -65,9 +71,11 @@ #define MBEDTLS_BIGNUM_C #define MBEDTLS_CIPHER_C #define MBEDTLS_CTR_DRBG_C -// #define MBEDTLS_ECP_C +#define MBEDTLS_ECDH_C +#define MBEDTLS_ECP_C #define MBEDTLS_ENTROPY_C #define MBEDTLS_ERROR_C +#define MBEDTLS_GCM_C #define MBEDTLS_MD_C #define MBEDTLS_MD5_C #define MBEDTLS_OID_C @@ -82,6 +90,7 @@ #define MBEDTLS_SSL_CLI_C #define MBEDTLS_SSL_SRV_C #define MBEDTLS_SSL_TLS_C +#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE #define MBEDTLS_X509_CRT_PARSE_C #define MBEDTLS_X509_USE_C From c95f99105af3ca5c27ea63d5672c790c531faf89 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jun 2022 14:24:57 +1000 Subject: [PATCH 0084/1041] rp2/lwip_inc: Enable lwIP status callback. Signed-off-by: Damien George --- ports/rp2/lwip_inc/lwipopts.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/rp2/lwip_inc/lwipopts.h b/ports/rp2/lwip_inc/lwipopts.h index 55926af7e5..691b228db5 100644 --- a/ports/rp2/lwip_inc/lwipopts.h +++ b/ports/rp2/lwip_inc/lwipopts.h @@ -24,6 +24,7 @@ #define LWIP_STATS 0 #define LWIP_NETIF_HOSTNAME 1 #define LWIP_NETIF_EXT_STATUS_CALLBACK 1 +#define LWIP_NETIF_STATUS_CALLBACK 1 #define LWIP_IPV6 0 #define LWIP_DHCP 1 From 7cdad05e54397969c4416737042659541dfc5d17 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jun 2022 14:27:13 +1000 Subject: [PATCH 0085/1041] rp2/rp2_flash: Add asserts for size of flash filesystem partition. Signed-off-by: Damien George --- ports/rp2/rp2_flash.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ports/rp2/rp2_flash.c b/ports/rp2/rp2_flash.c index 80bc1dc1df..db6b9f3bfe 100644 --- a/ports/rp2/rp2_flash.c +++ b/ports/rp2/rp2_flash.c @@ -37,6 +37,7 @@ #ifndef MICROPY_HW_FLASH_STORAGE_BYTES #define MICROPY_HW_FLASH_STORAGE_BYTES (1408 * 1024) #endif +static_assert(MICROPY_HW_FLASH_STORAGE_BYTES % 4096 == 0, "Flash storage size must be a multiple of 4K"); #ifndef MICROPY_HW_FLASH_STORAGE_BASE #define MICROPY_HW_FLASH_STORAGE_BASE (PICO_FLASH_SIZE_BYTES - MICROPY_HW_FLASH_STORAGE_BYTES) @@ -72,6 +73,11 @@ STATIC mp_obj_t rp2_flash_make_new(const mp_obj_type_t *type, size_t n_args, siz // Check args. mp_arg_check_num(n_args, n_kw, 0, 0, false); + #ifndef NDEBUG + extern char __flash_binary_end; + assert((uintptr_t)&__flash_binary_end - XIP_BASE <= MICROPY_HW_FLASH_STORAGE_BASE); + #endif + // Return singleton object. return MP_OBJ_FROM_PTR(&rp2_flash_obj); } From c001cfa603ef0dcb95196f1942ce2e4d5bd6385b Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jun 2022 14:53:05 +1000 Subject: [PATCH 0086/1041] rp2/mpnetworkport: Convert network task scheduling to use PendSV IRQ. It is more reliable and scales better when more components need it. Work done in collaboration with Graham Sanderson and Peter Harper. Signed-off-by: Damien George --- ports/rp2/CMakeLists.txt | 2 ++ ports/rp2/mpnetworkport.c | 60 ++++++++------------------------- ports/rp2/pendsv.c | 70 +++++++++++++++++++++++++++++++++++++++ ports/rp2/pendsv.h | 49 +++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 47 deletions(-) create mode 100644 ports/rp2/pendsv.c create mode 100644 ports/rp2/pendsv.h diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 9f71f65840..50afa55a97 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -111,6 +111,7 @@ set(MICROPY_SOURCE_PORT mphalport.c mpnetworkport.c mpthreadport.c + pendsv.c rp2_flash.c rp2_pio.c tusb_port.c @@ -141,6 +142,7 @@ set(MICROPY_SOURCE_QSTR ) set(PICO_SDK_COMPONENTS + cmsis_core hardware_adc hardware_base hardware_clocks diff --git a/ports/rp2/mpnetworkport.c b/ports/rp2/mpnetworkport.c index 124907f538..2b01b62192 100644 --- a/ports/rp2/mpnetworkport.c +++ b/ports/rp2/mpnetworkport.c @@ -26,6 +26,7 @@ #include "py/runtime.h" #include "py/mphal.h" +#include "pendsv.h" #if MICROPY_PY_LWIP @@ -36,14 +37,14 @@ #define LWIP_TICK_RATE_MS 64 static alarm_id_t lwip_alarm_id = -1; -static bool lwip_can_poll = true; -static bool lwip_poll_pending = false; #if MICROPY_PY_NETWORK_WIZNET5K -static bool wiznet_poll_pending = false; - void wiznet5k_poll(void); void wiznet5k_deinit(void); + +void wiznet5k_try_poll(void) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_WIZNET, wiznet5k_poll); +} #endif u32_t sys_now(void) { @@ -51,62 +52,27 @@ u32_t sys_now(void) { return mp_hal_ticks_ms(); } -STATIC uint32_t lwip_poll(void) { +STATIC void lwip_poll(void) { // Run the lwIP internal updates sys_check_timeouts(); - - return MAX(5, MIN(sys_timeouts_sleeptime(), LWIP_TICK_RATE_MS)); } void lwip_lock_acquire(void) { - lwip_can_poll = false; + // Prevent PendSV from running. + pendsv_suspend(); } void lwip_lock_release(void) { - lwip_can_poll = false; - #if MICROPY_PY_NETWORK_WIZNET5K - if (wiznet_poll_pending) { - wiznet5k_poll(); - wiznet_poll_pending = false; - } - #endif - - if (lwip_poll_pending) { - lwip_poll(); - lwip_poll_pending = false; - } - lwip_can_poll = true; + // Allow PendSV to run again. + pendsv_resume(); } -uint32_t lwip_try_poll(void) { - uint32_t ret = LWIP_TICK_RATE_MS; - if (lwip_can_poll) { - lwip_can_poll = false; - ret = lwip_poll(); - lwip_can_poll = true; - } else { - lwip_poll_pending = true; - } - return ret; -} - -#if MICROPY_PY_NETWORK_WIZNET5K -void wiznet5k_try_poll(void) { - if (lwip_can_poll) { - lwip_can_poll = false; - wiznet5k_poll(); - lwip_can_poll = true; - } else { - wiznet_poll_pending = true; - } -} -#endif - STATIC int64_t alarm_callback(alarm_id_t id, void *user_data) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_LWIP, lwip_poll); #if MICROPY_PY_NETWORK_WIZNET5K - wiznet5k_try_poll(); + pendsv_schedule_dispatch(PENDSV_DISPATCH_WIZNET, wiznet5k_poll); #endif - return (int64_t)lwip_try_poll() * 1000; + return LWIP_TICK_RATE_MS * 1000; } void mod_network_lwip_init(void) { diff --git a/ports/rp2/pendsv.c b/ports/rp2/pendsv.c new file mode 100644 index 0000000000..006303d46f --- /dev/null +++ b/ports/rp2/pendsv.c @@ -0,0 +1,70 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 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 +#include "pendsv.h" +#include "RP2040.h" + +static pendsv_dispatch_t pendsv_dispatch_table[PENDSV_DISPATCH_NUM_SLOTS]; +static int pendsv_lock; + +void pendsv_suspend(void) { + pendsv_lock++; +} + +void pendsv_resume(void) { + pendsv_lock--; + assert(pendsv_lock >= 0); + // Run pendsv if needed. Find an entry with a dispatch and call pendsv dispatch + // with it. If pendsv runs it will service all slots. + int count = PENDSV_DISPATCH_NUM_SLOTS; + while (count--) { + if (pendsv_dispatch_table[count]) { + pendsv_schedule_dispatch(count, pendsv_dispatch_table[count]); + break; + } + } +} + +void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f) { + assert(pendsv_lock >= 0); + pendsv_dispatch_table[slot] = f; + if (pendsv_lock == 0) { + SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; + } +} + +// PendSV interrupt handler to perform background processing. +void PendSV_Handler(void) { + assert(pendsv_lock == 0); + for (size_t i = 0; i < PENDSV_DISPATCH_NUM_SLOTS; ++i) { + if (pendsv_dispatch_table[i] != NULL) { + pendsv_dispatch_t f = pendsv_dispatch_table[i]; + pendsv_dispatch_table[i] = NULL; + f(); + } + } +} diff --git a/ports/rp2/pendsv.h b/ports/rp2/pendsv.h new file mode 100644 index 0000000000..7bb43208ab --- /dev/null +++ b/ports/rp2/pendsv.h @@ -0,0 +1,49 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 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. + */ +#ifndef MICROPY_INCLUDED_RP2_PENDSV_H +#define MICROPY_INCLUDED_RP2_PENDSV_H + +#include + +enum { + #if MICROPY_PY_LWIP + PENDSV_DISPATCH_LWIP, + #endif + #if MICROPY_PY_NETWORK_WIZNET5K + PENDSV_DISPATCH_WIZNET, + #endif + PENDSV_DISPATCH_MAX +}; + +#define PENDSV_DISPATCH_NUM_SLOTS PENDSV_DISPATCH_MAX + +typedef void (*pendsv_dispatch_t)(void); + +void pendsv_suspend(void); +void pendsv_resume(void); +void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f); + +#endif // MICROPY_INCLUDED_RP2_PENDSV_H From 50e46552c0c83b0c8570aba098a0ba4e68ae9eac Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jun 2022 16:01:02 +1000 Subject: [PATCH 0087/1041] rp2: Integrate CYW43xx WiFi driver. This includes: - Configuration file for the cyw43-driver. - Integration of cyw43-driver into the build, using lwIP. - Enhancements to machine.Pin to support extension IO pins provided by the CYW43xx. - More mp-hal pin helper functions. - mp_hal_get_mac_ascii MAC address helper function. - Addition of rp2.country() function to set the country code. A board can enable this driver by setting MICROPY_PY_NETWORK_CYW43 in their cmake snippet. Work done in collaboration with Graham Sanderson and Peter Harper. Signed-off-by: Damien George --- ports/rp2/CMakeLists.txt | 29 +++ ports/rp2/Makefile | 4 +- ports/rp2/README.md | 7 + ports/rp2/cyw43_configport.h | 98 ++++++++++ ports/rp2/machine_pin.c | 360 ++++++++++++++++++++++++++++------- ports/rp2/main.c | 29 +++ ports/rp2/modrp2.c | 26 +++ ports/rp2/mpconfigport.h | 22 +++ ports/rp2/mphalport.c | 23 +++ ports/rp2/mphalport.h | 13 ++ ports/rp2/mpnetworkport.c | 35 ++++ ports/rp2/pendsv.c | 13 ++ ports/rp2/pendsv.h | 3 + ports/rp2/rp2_pio.c | 5 + 14 files changed, 600 insertions(+), 67 deletions(-) create mode 100644 ports/rp2/cyw43_configport.h diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 50afa55a97..9185c7d649 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -16,6 +16,10 @@ endif() # Use the local tinyusb instead of the one in pico-sdk set(PICO_TINYUSB_PATH ${MICROPY_DIR}/lib/tinyusb) +# Use the local cyw43_driver instead of the one in pico-sdk +set(PICO_CYW43_DRIVER_PATH ${MICROPY_DIR}/lib/cyw43-driver) +# Use the local lwip instead of the one in pico-sdk +set(PICO_LWIP_PATH ${MICROPY_DIR}/lib/lwip) # Set the location of this port's directory. set(MICROPY_PORT_DIR ${CMAKE_SOURCE_DIR}) @@ -73,6 +77,7 @@ set(MICROPY_SOURCE_LIB ${MICROPY_DIR}/lib/mbedtls_errors/mp_mbedtls_errors.c ${MICROPY_DIR}/lib/oofatfs/ff.c ${MICROPY_DIR}/lib/oofatfs/ffunicode.c + ${MICROPY_DIR}/shared/netutils/dhcpserver.c ${MICROPY_DIR}/shared/netutils/netutils.c ${MICROPY_DIR}/shared/netutils/trace.c ${MICROPY_DIR}/shared/readline/readline.c @@ -216,6 +221,30 @@ if(MICROPY_BLUETOOTH_NIMBLE) list(APPEND MICROPY_INC_CORE ${NIMBLE_INCLUDE}) endif() +if (MICROPY_PY_NETWORK_CYW43) + string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/cyw43-driver) + + target_compile_definitions(${MICROPY_TARGET} PRIVATE + MICROPY_PY_NETWORK_CYW43=1 + MICROPY_PY_NETWORK_CYW43_USE_LIB_DRIVER=1 + MICROPY_PY_SOCKET_DEFAULT_TIMEOUT_MS=30000 # default socket timeout + ) + if (CMAKE_BUILD_TYPE MATCHES Debug) + target_compile_definitions(${MICROPY_TARGET} PRIVATE + CYW43_USE_STATS=1 + ) + endif() + + list(APPEND MICROPY_SOURCE_EXTMOD + ${MICROPY_DIR}/extmod/network_cyw43.c + ) + + target_link_libraries(${MICROPY_TARGET} + cyw43_driver_picow + cmsis_core + ) +endif() + if (MICROPY_PY_NETWORK_NINAW10) target_compile_definitions(${MICROPY_TARGET} PRIVATE MICROPY_PY_NETWORK_NINAW10=1 diff --git a/ports/rp2/Makefile b/ports/rp2/Makefile index c2138a340a..87c1d650e0 100644 --- a/ports/rp2/Makefile +++ b/ports/rp2/Makefile @@ -29,9 +29,11 @@ all: clean: $(RM) -rf $(BUILD) -GIT_SUBMODULES += lib/mbedtls lib/pico-sdk lib/tinyusb +GIT_SUBMODULES += lib/mbedtls lib/tinyusb submodules: + # lib/pico-sdk is required for the cmake build to function (as used for boards other than PICO below) + $(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="lib/pico-sdk" submodules ifeq ($(BOARD),PICO) # Run the standard submodules target with minimum required submodules above $(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="$(GIT_SUBMODULES)" submodules diff --git a/ports/rp2/README.md b/ports/rp2/README.md index 5836ac0cd8..078919ce81 100644 --- a/ports/rp2/README.md +++ b/ports/rp2/README.md @@ -37,6 +37,13 @@ You can also build the standard CMake way. The final firmware is found in the top-level of the CMake build directory (`build` by default) and is called `firmware.uf2`. +If you are using a different board other than a Rasoberry Pi Pico, then you should +pass the board name to the build; e.g. for Raspberry Pi Pico W: + + $ make BOARD=PICO_W submodules + $ make BOARD=PICO_W clean + $ make BOARD=PICO_W + ## Deploying firmware to the device Firmware can be deployed to the device by putting it into bootloader mode diff --git a/ports/rp2/cyw43_configport.h b/ports/rp2/cyw43_configport.h new file mode 100644 index 0000000000..6173964cb2 --- /dev/null +++ b/ports/rp2/cyw43_configport.h @@ -0,0 +1,98 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 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. + */ +#ifndef MICROPY_INCLUDED_RP2_CYW43_CONFIGPORT_H +#define MICROPY_INCLUDED_RP2_CYW43_CONFIGPORT_H + +// The board-level config will be included here, so it can set some CYW43 values. +#include "py/mpconfig.h" +#include "py/mperrno.h" +#include "py/mphal.h" +#include "pendsv.h" + +#define CYW43_IOCTL_TIMEOUT_US (1000000) +#define CYW43_SLEEP_MAX (10) +#define CYW43_NETUTILS (1) +#define CYW43_USE_OTP_MAC (1) + +#define CYW43_EPERM MP_EPERM // Operation not permitted +#define CYW43_EIO MP_EIO // I/O error +#define CYW43_EINVAL MP_EINVAL // Invalid argument +#define CYW43_ETIMEDOUT MP_ETIMEDOUT // Connection timed out + +#define CYW43_THREAD_ENTER MICROPY_PY_LWIP_ENTER +#define CYW43_THREAD_EXIT MICROPY_PY_LWIP_EXIT +#define CYW43_THREAD_LOCK_CHECK + +#define CYW43_SDPCM_SEND_COMMON_WAIT __WFI(); +#define CYW43_DO_IOCTL_WAIT __WFI(); + +#define CYW43_ARRAY_SIZE(a) MP_ARRAY_SIZE(a) + +#define CYW43_HAL_PIN_MODE_INPUT MP_HAL_PIN_MODE_INPUT +#define CYW43_HAL_PIN_MODE_OUTPUT MP_HAL_PIN_MODE_OUTPUT +#define CYW43_HAL_PIN_PULL_NONE MP_HAL_PIN_PULL_NONE +#define CYW43_HAL_PIN_PULL_UP MP_HAL_PIN_PULL_UP +#define CYW43_HAL_PIN_PULL_DOWN MP_HAL_PIN_PULL_DOWN + +#define CYW43_HAL_MAC_WLAN0 MP_HAL_MAC_WLAN0 + +// set in SDK board header +#define CYW43_NUM_GPIOS CYW43_WL_GPIO_COUNT + +#define CYW43_POST_POLL_HOOK cyw43_post_poll_hook(); + +#define cyw43_hal_ticks_us mp_hal_ticks_us +#define cyw43_hal_ticks_ms mp_hal_ticks_ms + +#define cyw43_hal_pin_obj_t mp_hal_pin_obj_t +#define cyw43_hal_pin_config mp_hal_pin_config +#define cyw43_hal_pin_read mp_hal_pin_read +#define cyw43_hal_pin_low mp_hal_pin_low +#define cyw43_hal_pin_high mp_hal_pin_high + +#define cyw43_hal_get_mac mp_hal_get_mac +#define cyw43_hal_get_mac_ascii mp_hal_get_mac_ascii +#define cyw43_hal_generate_laa_mac mp_hal_generate_laa_mac + +#define cyw43_schedule_internal_poll_dispatch(func) pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, func) + +void cyw43_post_poll_hook(void); + +static inline void cyw43_delay_us(uint32_t us) { + uint32_t start = mp_hal_ticks_us(); + while (mp_hal_ticks_us() - start < us) { + } +} + +static inline void cyw43_delay_ms(uint32_t ms) { + uint32_t us = ms * 1000; + int32_t start = mp_hal_ticks_us(); + while (mp_hal_ticks_us() - start < us) { + __WFI(); + } +} + +#endif // MICROPY_INCLUDED_RP2_CYW43_CONFIGPORT_H diff --git a/ports/rp2/machine_pin.c b/ports/rp2/machine_pin.c index ca8de6ce25..a0c5dead90 100644 --- a/ports/rp2/machine_pin.c +++ b/ports/rp2/machine_pin.c @@ -58,9 +58,18 @@ // Open drain behaviour is simulated. #define GPIO_IS_OPEN_DRAIN(id) (machine_pin_open_drain_mask & (1 << (id))) +#ifndef MICROPY_HW_PIN_RESERVED +#define MICROPY_HW_PIN_RESERVED(i) (0) +#endif + typedef struct _machine_pin_obj_t { mp_obj_base_t base; - uint32_t id; + uint8_t id; + #if MICROPY_HW_PIN_CYW43_COUNT + bool is_cyw43; + bool is_output; + bool last_output_value; + #endif } machine_pin_obj_t; typedef struct _machine_pin_irq_obj_t { @@ -104,9 +113,60 @@ STATIC const machine_pin_obj_t machine_pin_obj[NUM_BANK0_GPIOS] = { {{&machine_pin_type}, 29}, }; +#if MICROPY_HW_PIN_CYW43_COUNT +#include "lib/cyw43-driver/src/cyw43.h" +#define CYW43_PIN_NAME_PREFIX "WL_GPIO" +STATIC machine_pin_obj_t cyw43_pin_obj[MICROPY_HW_PIN_CYW43_COUNT]; +#endif + +#define LED_PIN_NAME "LED" + +#ifndef MICROPY_HW_PIN_ENABLE_LED_PIN +#if defined(MICROPY_HW_PIN_CYW43_LED_PIN_NUM) || defined(PICO_DEFAULT_LED_PIN) +#define MICROPY_HW_PIN_ENABLE_LED_PIN 1 +#endif +#endif + +#ifdef MICROPY_HW_PIN_ENABLE_LED_PIN +#ifdef MICROPY_HW_PIN_CYW43_LED_PIN_NUM +STATIC machine_pin_obj_t *led_pin_obj = &cyw43_pin_obj[MICROPY_HW_PIN_CYW43_LED_PIN_NUM]; +#elif defined(MICROPY_HW_PIN_LED_PIN_NUM) +STATIC machine_pin_obj_t *led_pin_obj = &machine_pin_obj[MICROPY_HW_PIN_LED_PIN_NUM]; +#elif defined(PICO_DEFAULT_LED_PIN) +STATIC const machine_pin_obj_t *led_pin_obj = &machine_pin_obj[PICO_DEFAULT_LED_PIN]; +#else +#error MICROPY_HW_PIN_ENABLE_LED_PIN defined but there is no LED pin +#endif +#endif + // Mask with "1" indicating that the corresponding pin is in simulated open-drain mode. uint32_t machine_pin_open_drain_mask; +#if MICROPY_HW_PIN_CYW43_COUNT +STATIC inline bool is_cyw43_pin(__unused const machine_pin_obj_t *self) { + return self->is_cyw43; +} +#else +#define is_cyw43_pin(x) false +#endif + +#if MICROPY_HW_PIN_CYW43_COUNT +STATIC inline void update_cyw43_value(__unused machine_pin_obj_t *self, bool value) { + if (value != self->last_output_value || !self->is_output) { + cyw43_gpio_set(&cyw43_state, self->id, value); + } + self->last_output_value = value; +} +#endif + +#if MICROPY_HW_PIN_CYW43_COUNT +STATIC inline bool get_cyw43_value(__unused machine_pin_obj_t *self) { + bool value = false; + cyw43_gpio_get(&cyw43_state, self->id, &value); + return value; +} +#endif + STATIC void gpio_irq(void) { for (int i = 0; i < 4; ++i) { uint32_t intr = iobank0_hw->intr[i]; @@ -129,15 +189,24 @@ STATIC void gpio_irq(void) { void machine_pin_init(void) { memset(MP_STATE_PORT(machine_pin_irq_obj), 0, sizeof(MP_STATE_PORT(machine_pin_irq_obj))); - irq_set_exclusive_handler(IO_IRQ_BANK0, gpio_irq); + irq_add_shared_handler(IO_IRQ_BANK0, gpio_irq, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY); irq_set_enabled(IO_IRQ_BANK0, true); + #if MICROPY_HW_PIN_CYW43_COUNT + for (uint i = 0; i < count_of(cyw43_pin_obj); i++) { + cyw43_pin_obj[i].id = i; + cyw43_pin_obj[i].base.type = &machine_pin_type; + cyw43_pin_obj[i].is_cyw43 = true; + } + #endif } void machine_pin_deinit(void) { for (int i = 0; i < NUM_BANK0_GPIOS; ++i) { + if (MICROPY_HW_PIN_RESERVED(i)) { + continue; + } gpio_set_irq_enabled(i, GPIO_IRQ_ALL, false); } - irq_set_enabled(IO_IRQ_BANK0, false); irq_remove_handler(IO_IRQ_BANK0, gpio_irq); } @@ -145,45 +214,112 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin machine_pin_obj_t *self = self_in; uint funcsel = GPIO_GET_FUNCSEL(self->id); qstr mode_qst; - if (funcsel == GPIO_FUNC_SIO) { - if (GPIO_IS_OPEN_DRAIN(self->id)) { - mode_qst = MP_QSTR_OPEN_DRAIN; - } else if (GPIO_IS_OUT(self->id)) { - mode_qst = MP_QSTR_OUT; + if (!is_cyw43_pin(self)) { + if (funcsel == GPIO_FUNC_SIO) { + if (GPIO_IS_OPEN_DRAIN(self->id)) { + mode_qst = MP_QSTR_OPEN_DRAIN; + } else if (GPIO_IS_OUT(self->id)) { + mode_qst = MP_QSTR_OUT; + } else { + mode_qst = MP_QSTR_IN; + } } else { - mode_qst = MP_QSTR_IN; + mode_qst = MP_QSTR_ALT; + } + mp_printf(print, "Pin(%u, mode=%q", self->id, mode_qst); + bool pull_up = false; + if (GPIO_IS_PULL_UP(self->id)) { + mp_printf(print, ", pull=%q", MP_QSTR_PULL_UP); + pull_up = true; + } + if (GPIO_IS_PULL_DOWN(self->id)) { + if (pull_up) { + mp_printf(print, "|%q", MP_QSTR_PULL_DOWN); + } else { + mp_printf(print, ", pull=%q", MP_QSTR_PULL_DOWN); + } + } + if (funcsel != GPIO_FUNC_SIO) { + mp_printf(print, ", alt=%u", funcsel); } } else { - mode_qst = MP_QSTR_ALT; - } - mp_printf(print, "Pin(%u, mode=%q", self->id, mode_qst); - bool pull_up = false; - if (GPIO_IS_PULL_UP(self->id)) { - mp_printf(print, ", pull=%q", MP_QSTR_PULL_UP); - pull_up = true; - } - if (GPIO_IS_PULL_DOWN(self->id)) { - if (pull_up) { - mp_printf(print, "|%q", MP_QSTR_PULL_DOWN); - } else { - mp_printf(print, ", pull=%q", MP_QSTR_PULL_DOWN); - } - } - if (funcsel != GPIO_FUNC_SIO) { - mp_printf(print, ", alt=%u", funcsel); + #if MICROPY_HW_PIN_CYW43_COUNT + mode_qst = self->is_output ? MP_QSTR_OUT : MP_QSTR_IN; + mp_printf(print, "Pin(%s%u, mode=%q", CYW43_PIN_NAME_PREFIX, self->id, mode_qst); + #endif } mp_printf(print, ")"); } +enum { + ARG_mode, ARG_pull, ARG_value, ARG_alt +}; +static const mp_arg_t allowed_args[] = { + {MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, + {MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, + {MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, + {MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = GPIO_FUNC_SIO}}, +}; + +#if MICROPY_HW_PIN_CYW43_COUNT // pin.init(mode, pull=None, *, value=None, alt=FUNC_SIO) +STATIC mp_obj_t machine_pin_cyw43_obj_init_helper(machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if (args[ARG_pull].u_obj != mp_const_none) { + int pull = mp_obj_get_int(args[ARG_pull].u_obj); + if (pull) { + mp_raise_ValueError("Pulls are not supported for this pin"); + } + } + + if (args[ARG_alt].u_int != GPIO_FUNC_SIO) { + mp_raise_ValueError("Alternate functions are not supported for this pin"); + } + + int value = -1; + if (args[ARG_value].u_obj != mp_const_none) { + value = mp_obj_is_true(args[ARG_value].u_obj); + } + + if (args[ARG_mode].u_obj != mp_const_none) { + mp_int_t mode = mp_obj_get_int(args[ARG_mode].u_obj); + if (mode == GPIO_MODE_IN) { + if (self->is_output) { + // todo need to disable output + } + self->is_output = false; + } else if (mode == GPIO_MODE_OUT) { + if (!self->is_output) { + // todo need to enable output + // for now we just set the value + if (value == -1) { + value = self->last_output_value; + } + self->last_output_value = !self->last_output_value; // defeat shortcircuit + update_cyw43_value(self, value); + self->is_output = true; + } + } else { + mp_raise_ValueError("only Pin.OUT and Pin.IN are supported for this pin"); + } + } + + if (value != -1) { + if (self->is_output) { + update_cyw43_value(self, value); + } else { + // figure if you pass a value to IN it should still remember it (this is what regular GPIO does) + self->last_output_value = value; + } + } + + return mp_const_none; +} +#endif + STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_mode, ARG_pull, ARG_value, ARG_alt }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, - { MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, - { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, - { MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = GPIO_FUNC_SIO}}, - }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -216,7 +352,6 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_ pull = mp_obj_get_int(args[ARG_pull].u_obj); } gpio_set_pulls(self->id, pull & GPIO_PULL_UP, pull & GPIO_PULL_DOWN); - return mp_const_none; } @@ -224,21 +359,57 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_ mp_obj_t mp_pin_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 the wanted pin object - int wanted_pin = mp_obj_get_int(args[0]); - if (!(0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj))) { - mp_raise_ValueError("invalid pin"); - } - const machine_pin_obj_t *self = &machine_pin_obj[wanted_pin]; + const machine_pin_obj_t *self = NULL; + if (mp_obj_is_str(args[0])) { + const char *name = mp_obj_str_get_str(args[0]); + #if MICROPY_HW_PIN_ENABLE_LED_PIN + if (!strcmp(name, LED_PIN_NAME)) { + self = led_pin_obj; + } + #endif + #if MICROPY_HW_PIN_CYW43_COUNT + static_assert(MICROPY_HW_PIN_CYW43_COUNT < 10, ""); // makes parsing name easy! + if (!self && !strncmp(name, CYW43_PIN_NAME_PREFIX, strlen(CYW43_PIN_NAME_PREFIX)) && strlen(name) == strlen(CYW43_PIN_NAME_PREFIX) + 1) { + int num = name[strlen(CYW43_PIN_NAME_PREFIX)] - '0'; + if (num < MICROPY_HW_PIN_CYW43_COUNT) { + self = &cyw43_pin_obj[num]; + } + } + #endif + if (!self) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Unknown named pin \"%s\""), name); + } + } + if (!self) { + // get the wanted pin object + int wanted_pin = mp_obj_get_int(args[0]); + if (!(0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj))) { + mp_raise_ValueError("invalid pin"); + } + self = &machine_pin_obj[wanted_pin]; + } + // note we have different init args based on the type of pin. so Pin("LED", Pin.OUT) may not always make sense + if (!is_cyw43_pin(self)) { + if (n_args > 1 || n_kw > 0) { + // pin mode given, so configure this GPIO + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + machine_pin_obj_init_helper(self, n_args - 1, args + 1, &kw_args); + } + return MP_OBJ_FROM_PTR(self); + } + #if MICROPY_HW_PIN_CYW43_COUNT if (n_args > 1 || n_kw > 0) { // pin mode given, so configure this GPIO mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - machine_pin_obj_init_helper(self, n_args - 1, args + 1, &kw_args); + // The regular Pins are const, but the CYW43 pins are mutable. + machine_pin_obj_t *mutable_self = (machine_pin_obj_t *)self; + machine_pin_cyw43_obj_init_helper(mutable_self, n_args - 1, args + 1, &kw_args); } - return MP_OBJ_FROM_PTR(self); + #endif } // fast method for getting/setting pin value @@ -247,23 +418,39 @@ STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c machine_pin_obj_t *self = self_in; if (n_args == 0) { // get pin - return MP_OBJ_NEW_SMALL_INT(gpio_get(self->id)); + if (!is_cyw43_pin(self)) { + return MP_OBJ_NEW_SMALL_INT(gpio_get(self->id)); + } + #if MICROPY_HW_PIN_CYW43_COUNT + return MP_OBJ_NEW_SMALL_INT(get_cyw43_value(self)); + #endif } else { // set pin bool value = mp_obj_is_true(args[0]); - if (GPIO_IS_OPEN_DRAIN(self->id)) { - MP_STATIC_ASSERT(GPIO_IN == 0 && GPIO_OUT == 1); - gpio_set_dir(self->id, 1 - value); - } else { - gpio_put(self->id, value); + if (!is_cyw43_pin(self)) { + if (GPIO_IS_OPEN_DRAIN(self->id)) { + MP_STATIC_ASSERT(GPIO_IN == 0 && GPIO_OUT == 1); + gpio_set_dir(self->id, 1 - value); + } else { + gpio_put(self->id, value); + } + return mp_const_none; } - return mp_const_none; + #if MICROPY_HW_PIN_CYW43_COUNT + update_cyw43_value(self, value); + #endif } + return mp_const_none; } // pin.init(mode, pull) STATIC mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); + if (!is_cyw43_pin(args[0])) { + return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); + } + #if MICROPY_HW_PIN_CYW43_COUNT + return machine_pin_cyw43_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); + #endif } MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init); @@ -276,40 +463,59 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_ // pin.low() STATIC mp_obj_t machine_pin_low(mp_obj_t self_in) { machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (GPIO_IS_OPEN_DRAIN(self->id)) { - gpio_set_dir(self->id, GPIO_OUT); - } else { - gpio_clr_mask(1u << self->id); + if (!is_cyw43_pin(self)) { + if (GPIO_IS_OPEN_DRAIN(self->id)) { + gpio_set_dir(self->id, GPIO_OUT); + } else { + gpio_clr_mask(1u << self->id); + } + return mp_const_none; } + #if MICROPY_HW_PIN_CYW43_COUNT + update_cyw43_value(self, 0); return mp_const_none; + #endif } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_low_obj, machine_pin_low); // pin.high() STATIC mp_obj_t machine_pin_high(mp_obj_t self_in) { machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (GPIO_IS_OPEN_DRAIN(self->id)) { - gpio_set_dir(self->id, GPIO_IN); - } else { - gpio_set_mask(1u << self->id); + if (!is_cyw43_pin(self)) { + if (GPIO_IS_OPEN_DRAIN(self->id)) { + gpio_set_dir(self->id, GPIO_IN); + } else { + gpio_set_mask(1u << self->id); + } + return mp_const_none; } + #if MICROPY_HW_PIN_CYW43_COUNT + update_cyw43_value(self, 1); return mp_const_none; + #endif } + STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_high_obj, machine_pin_high); // pin.toggle() STATIC mp_obj_t machine_pin_toggle(mp_obj_t self_in) { machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (GPIO_IS_OPEN_DRAIN(self->id)) { - if (GPIO_IS_OUT(self->id)) { - gpio_set_dir(self->id, GPIO_IN); + if (!is_cyw43_pin(self)) { + if (GPIO_IS_OPEN_DRAIN(self->id)) { + if (GPIO_IS_OUT(self->id)) { + gpio_set_dir(self->id, GPIO_IN); + } else { + gpio_set_dir(self->id, GPIO_OUT); + } } else { - gpio_set_dir(self->id, GPIO_OUT); + gpio_xor_mask(1u << self->id); } - } else { - gpio_xor_mask(1u << self->id); + return mp_const_none; } + #if MICROPY_HW_PIN_CYW43_COUNT + update_cyw43_value(self, self->last_output_value ^ 1); return mp_const_none; + #endif } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_toggle_obj, machine_pin_toggle); @@ -357,6 +563,10 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_ { MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} }, }; machine_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (is_cyw43_pin(self)) { + mp_raise_ValueError(MP_ERROR_TEXT("expecting a regular GPIO Pin")); + } + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -400,16 +610,31 @@ STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, i (void)errcode; machine_pin_obj_t *self = self_in; + if (!is_cyw43_pin(self)) { + switch (request) { + case MP_PIN_READ: { + return gpio_get(self->id); + } + case MP_PIN_WRITE: { + gpio_put(self->id, arg); + return 0; + } + } + return -1; + } + + #if MICROPY_HW_PIN_CYW43_COUNT switch (request) { case MP_PIN_READ: { - return gpio_get(self->id); + return get_cyw43_value(self); } case MP_PIN_WRITE: { - gpio_put(self->id, arg); + update_cyw43_value(self, arg); return 0; } } return -1; + #endif } STATIC const mp_pin_p_t pin_pin_p = { @@ -457,5 +682,8 @@ mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t obj) { mp_raise_ValueError(MP_ERROR_TEXT("expecting a Pin")); } machine_pin_obj_t *pin = MP_OBJ_TO_PTR(obj); + if (is_cyw43_pin(pin)) { + mp_raise_ValueError(MP_ERROR_TEXT("expecting a regular GPIO Pin")); + } return pin->id; } diff --git a/ports/rp2/main.c b/ports/rp2/main.c index da21e0b394..664bb18109 100644 --- a/ports/rp2/main.c +++ b/ports/rp2/main.c @@ -46,12 +46,16 @@ #include "pico/stdlib.h" #include "pico/binary_info.h" +#include "pico/unique_id.h" #include "hardware/rtc.h" #include "hardware/structs/rosc.h" #if MICROPY_PY_LWIP #include "lwip/init.h" #include "lwip/apps/mdns.h" #endif +#if MICROPY_PY_NETWORK_CYW43 +#include "lib/cyw43-driver/src/cyw43.h" +#endif #ifndef MICROPY_GC_HEAP_SIZE #if MICROPY_PY_LWIP @@ -90,6 +94,10 @@ int main(int argc, char **argv) { mp_thread_init(); #endif + #ifndef NDEBUG + stdio_init_all(); + #endif + // Start and initialise the RTC datetime_t t = { .year = 2021, @@ -118,6 +126,27 @@ int main(int argc, char **argv) { #endif #endif + #if MICROPY_PY_NETWORK_CYW43 + { + cyw43_init(&cyw43_state); + cyw43_irq_init(); + cyw43_post_poll_hook(); // enable the irq + uint8_t buf[8]; + memcpy(&buf[0], "PICO", 4); + + // MAC isn't loaded from OTP yet, so use unique id to generate the default AP ssid. + const char hexchr[16] = "0123456789ABCDEF"; + pico_unique_board_id_t pid; + pico_get_unique_board_id(&pid); + buf[4] = hexchr[pid.id[7] >> 4]; + buf[5] = hexchr[pid.id[6] & 0xf]; + buf[6] = hexchr[pid.id[5] >> 4]; + buf[7] = hexchr[pid.id[4] & 0xf]; + cyw43_wifi_ap_set_ssid(&cyw43_state, 8, buf); + cyw43_wifi_ap_set_password(&cyw43_state, 8, (const uint8_t *)"picoW123"); + } + #endif + for (;;) { // Initialise MicroPython runtime. diff --git a/ports/rp2/modrp2.c b/ports/rp2/modrp2.c index 5dc066d651..19c7ad6083 100644 --- a/ports/rp2/modrp2.c +++ b/ports/rp2/modrp2.c @@ -28,6 +28,28 @@ #include "drivers/dht/dht.h" #include "modrp2.h" +#if MICROPY_PY_NETWORK_CYW43 +#include "lib/cyw43-driver/src/cyw43_country.h" + +extern uint32_t cyw43_country_code; + +STATIC mp_obj_t rp2_country(size_t n_args, const mp_obj_t *args) { + if (n_args == 0) { + char code[2] = {cyw43_country_code, cyw43_country_code >> 8}; + return mp_obj_new_str(code, 2); + } else { + size_t len; + const char *str = mp_obj_str_get_data(args[0], &len); + if (len != 2) { + mp_raise_ValueError(NULL); + } + cyw43_country_code = CYW43_COUNTRY(str[0], str[1], 0); + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rp2_country_obj, 0, 1, rp2_country); +#endif + STATIC const mp_rom_map_elem_t rp2_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_rp2) }, { MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&rp2_flash_type) }, @@ -35,6 +57,10 @@ STATIC const mp_rom_map_elem_t rp2_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_StateMachine), MP_ROM_PTR(&rp2_state_machine_type) }, { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) }, + + #if MICROPY_PY_NETWORK_CYW43 + { MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&rp2_country_obj) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(rp2_module_globals, rp2_module_globals_table); diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 62388c6bce..9143b5f6c5 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -154,6 +154,20 @@ struct _mp_bluetooth_nimble_malloc_t; #define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE #endif +#if MICROPY_PY_NETWORK_CYW43 +extern const struct _mp_obj_type_t mp_network_cyw43_type; +#define MICROPY_HW_NIC_CYW43 \ + { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mp_network_cyw43_type) }, \ + { MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(CYW43_LINK_DOWN) }, \ + { MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(CYW43_LINK_JOIN) }, \ + { MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(CYW43_LINK_BADAUTH) }, \ + { MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(CYW43_LINK_NONET) }, \ + { MP_ROM_QSTR(MP_QSTR_STAT_CONNECT_FAIL), MP_ROM_INT(CYW43_LINK_FAIL) }, \ + { MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(CYW43_LINK_UP) }, +#else +#define MICROPY_HW_NIC_CYW43 +#endif + #if MICROPY_PY_NETWORK_NINAW10 // This Network interface requires the extended socket state. #ifndef MICROPY_PY_USOCKET_EXTENDED_STATE @@ -184,6 +198,7 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k; #endif #define MICROPY_PORT_NETWORK_INTERFACES \ + MICROPY_HW_NIC_CYW43 \ MICROPY_HW_NIC_NINAW10 \ MICROPY_HW_NIC_WIZNET5K \ MICROPY_BOARD_NETWORK_INTERFACES \ @@ -258,3 +273,10 @@ typedef intptr_t mp_off_t; extern uint32_t rosc_random_u32(void); extern void lwip_lock_acquire(void); extern void lwip_lock_release(void); + +extern uint32_t cyw43_country_code; +extern void cyw43_irq_init(void); +extern void cyw43_post_poll_hook(void); + +#define CYW43_POST_POLL_HOOK cyw43_post_poll_hook(); +#define MICROPY_CYW43_COUNTRY cyw43_country_code diff --git a/ports/rp2/mphalport.c b/ports/rp2/mphalport.c index 4ed648de07..aec4a96724 100644 --- a/ports/rp2/mphalport.c +++ b/ports/rp2/mphalport.c @@ -35,6 +35,10 @@ #include "hardware/rtc.h" #include "pico/unique_id.h" +#if MICROPY_PY_NETWORK_CYW43 +#include "lib/cyw43-driver/src/cyw43.h" +#endif + #if MICROPY_HW_ENABLE_UART_REPL || MICROPY_HW_ENABLE_USBDEV #ifndef MICROPY_HW_STDIN_BUFFER_LEN @@ -168,6 +172,9 @@ uint64_t mp_hal_time_ns(void) { // Generate a random locally administered MAC address (LAA) void mp_hal_generate_laa_mac(int idx, uint8_t buf[6]) { + #ifndef NDEBUG + printf("Warning: No MAC in OTP, generating MAC from board id\n"); + #endif pico_unique_board_id_t pid; pico_get_unique_board_id(&pid); buf[0] = 0x02; // LAA range @@ -180,5 +187,21 @@ void mp_hal_generate_laa_mac(int idx, uint8_t buf[6]) { // A board can override this if needed MP_WEAK void mp_hal_get_mac(int idx, uint8_t buf[6]) { + #if MICROPY_PY_NETWORK_CYW43 + // The mac should come from cyw43 otp when CYW43_USE_OTP_MAC is defined + // This is loaded into the state after the driver is initialised + // cyw43_hal_generate_laa_mac is only called by the driver to generate a mac if otp is not set + memcpy(buf, cyw43_state.mac, 6); + #else mp_hal_generate_laa_mac(idx, buf); + #endif +} + +void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest) { + static const char hexchr[16] = "0123456789ABCDEF"; + uint8_t mac[6]; + mp_hal_get_mac(idx, mac); + for (; chr_len; ++chr_off, --chr_len) { + *dest++ = hexchr[mac[chr_off >> 1] >> (4 * (1 - (chr_off & 1))) & 0xf]; + } } diff --git a/ports/rp2/mphalport.h b/ports/rp2/mphalport.h index 88eef1308d..88683d9360 100644 --- a/ports/rp2/mphalport.h +++ b/ports/rp2/mphalport.h @@ -30,6 +30,7 @@ #include "pico/time.h" #include "hardware/clocks.h" #include "hardware/structs/systick.h" +#include "RP2040.h" // cmsis, for __WFI #define SYSTICK_MAX (0xffffff) @@ -74,6 +75,11 @@ static inline mp_uint_t mp_hal_get_cpu_freq(void) { #define MP_HAL_PIN_FMT "%u" #define mp_hal_pin_obj_t uint +#define MP_HAL_PIN_MODE_INPUT (GPIO_IN) +#define MP_HAL_PIN_MODE_OUTPUT (GPIO_OUT) +#define MP_HAL_PIN_PULL_NONE (0) +#define MP_HAL_PIN_PULL_UP (1) +#define MP_HAL_PIN_PULL_DOWN (2) extern uint32_t machine_pin_open_drain_mask; @@ -102,6 +108,12 @@ static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) { machine_pin_open_drain_mask |= 1 << pin; } +static inline void mp_hal_pin_config(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, uint32_t alt) { + assert((mode == MP_HAL_PIN_MODE_INPUT || mode == MP_HAL_PIN_MODE_OUTPUT) && alt == 0); + gpio_set_dir(pin, mode); + gpio_set_pulls(pin, pull == MP_HAL_PIN_PULL_UP, pull == MP_HAL_PIN_PULL_DOWN); +} + static inline int mp_hal_pin_read(mp_hal_pin_obj_t pin) { return gpio_get(pin); } @@ -143,6 +155,7 @@ enum { }; void mp_hal_get_mac(int idx, uint8_t buf[6]); +void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest); void mp_hal_generate_laa_mac(int idx, uint8_t buf[6]); #endif // MICROPY_INCLUDED_RP2_MPHALPORT_H diff --git a/ports/rp2/mpnetworkport.c b/ports/rp2/mpnetworkport.c index 2b01b62192..0cd6eb14ce 100644 --- a/ports/rp2/mpnetworkport.c +++ b/ports/rp2/mpnetworkport.c @@ -38,6 +38,41 @@ static alarm_id_t lwip_alarm_id = -1; +#if MICROPY_PY_NETWORK_CYW43 +#include "lib/cyw43-driver/src/cyw43.h" +#include "lib/cyw43-driver/src/cyw43_country.h" +#include "lib/cyw43-driver/src/cyw43_stats.h" +#include "hardware/irq.h" + +#define CYW43_IRQ_LEVEL GPIO_IRQ_LEVEL_HIGH +#define CYW43_SHARED_IRQ_HANDLER_PRIORITY PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY + +uint32_t cyw43_country_code = CYW43_COUNTRY_WORLDWIDE; + +static void gpio_irq_handler(void) { + uint32_t events = gpio_get_irq_event_mask(CYW43_PIN_WL_HOST_WAKE); + if (events & CYW43_IRQ_LEVEL) { + // As we use a high level interrupt, it will go off forever until it's serviced. + // So disable the interrupt until this is done. It's re-enabled again by + // CYW43_POST_POLL_HOOK which is called at the end of cyw43_poll_func. + gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, CYW43_IRQ_LEVEL, false); + pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll); + CYW43_STAT_INC(IRQ_COUNT); + } +} + +void cyw43_irq_init(void) { + gpio_add_raw_irq_handler_with_order_priority(IO_IRQ_BANK0, gpio_irq_handler, CYW43_SHARED_IRQ_HANDLER_PRIORITY); + irq_set_enabled(IO_IRQ_BANK0, true); + NVIC_SetPriority(PendSV_IRQn, PICO_LOWEST_IRQ_PRIORITY); +} + +void cyw43_post_poll_hook(void) { + gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, CYW43_IRQ_LEVEL, true); +} + +#endif + #if MICROPY_PY_NETWORK_WIZNET5K void wiznet5k_poll(void); void wiznet5k_deinit(void); diff --git a/ports/rp2/pendsv.c b/ports/rp2/pendsv.c index 006303d46f..91b133c069 100644 --- a/ports/rp2/pendsv.c +++ b/ports/rp2/pendsv.c @@ -28,6 +28,10 @@ #include "pendsv.h" #include "RP2040.h" +#if MICROPY_PY_NETWORK_CYW43 +#include "lib/cyw43-driver/src/cyw43_stats.h" +#endif + static pendsv_dispatch_t pendsv_dispatch_table[PENDSV_DISPATCH_NUM_SLOTS]; static int pendsv_lock; @@ -54,12 +58,21 @@ void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f) { pendsv_dispatch_table[slot] = f; if (pendsv_lock == 0) { SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; + } else { + #if MICROPY_PY_NETWORK_CYW43 + CYW43_STAT_INC(PENDSV_DISABLED_COUNT); + #endif } } // PendSV interrupt handler to perform background processing. void PendSV_Handler(void) { assert(pendsv_lock == 0); + + #if MICROPY_PY_NETWORK_CYW43 + CYW43_STAT_INC(PENDSV_RUN_COUNT); + #endif + for (size_t i = 0; i < PENDSV_DISPATCH_NUM_SLOTS; ++i) { if (pendsv_dispatch_table[i] != NULL) { pendsv_dispatch_t f = pendsv_dispatch_table[i]; diff --git a/ports/rp2/pendsv.h b/ports/rp2/pendsv.h index 7bb43208ab..1da3d22e53 100644 --- a/ports/rp2/pendsv.h +++ b/ports/rp2/pendsv.h @@ -32,6 +32,9 @@ enum { #if MICROPY_PY_LWIP PENDSV_DISPATCH_LWIP, #endif + #if MICROPY_PY_NETWORK_CYW43 + PENDSV_DISPATCH_CYW43, + #endif #if MICROPY_PY_NETWORK_WIZNET5K PENDSV_DISPATCH_WIZNET, #endif diff --git a/ports/rp2/rp2_pio.c b/ports/rp2/rp2_pio.c index fe09ebe249..9955cc5440 100644 --- a/ports/rp2/rp2_pio.c +++ b/ports/rp2/rp2_pio.c @@ -103,8 +103,13 @@ STATIC void pio1_irq0(void) { void rp2_pio_init(void) { // Reset all PIO instruction memory. + #if MICROPY_PY_NETWORK_CYW43 + // TODO: cannot reset PIO memory when CYW43 driver is enabled and active + // because it uses a PIO for the bus interface. + #else pio_clear_instruction_memory(pio0); pio_clear_instruction_memory(pio1); + #endif // Set up interrupts. memset(MP_STATE_PORT(rp2_pio_irq_obj), 0, sizeof(MP_STATE_PORT(rp2_pio_irq_obj))); From 99c25897783122003550d58f8d31b4a8fecc8611 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jun 2022 16:01:25 +1000 Subject: [PATCH 0088/1041] rp2/boards/PICO_W: Add new Pico W board, an RP2040 with WiFi. Work done in collaboration with Graham Sanderson and Peter Harper. Signed-off-by: Damien George --- ports/rp2/boards/PICO_W/board.json | 21 +++++++++++++++++ ports/rp2/boards/PICO_W/manifest.py | 7 ++++++ ports/rp2/boards/PICO_W/mpconfigboard.cmake | 8 +++++++ ports/rp2/boards/PICO_W/mpconfigboard.h | 26 +++++++++++++++++++++ 4 files changed, 62 insertions(+) create mode 100644 ports/rp2/boards/PICO_W/board.json create mode 100644 ports/rp2/boards/PICO_W/manifest.py create mode 100644 ports/rp2/boards/PICO_W/mpconfigboard.cmake create mode 100644 ports/rp2/boards/PICO_W/mpconfigboard.h diff --git a/ports/rp2/boards/PICO_W/board.json b/ports/rp2/boards/PICO_W/board.json new file mode 100644 index 0000000000..755ba10370 --- /dev/null +++ b/ports/rp2/boards/PICO_W/board.json @@ -0,0 +1,21 @@ +{ + "deploy": [ + "../deploy.md" + ], + "docs": "", + "features": [ + "Breadboard friendly", + "Castellated Pads", + "Micro USB", + "WiFi" + ], + "id": "rp2-pico-w", + "images": [ + "rp2-pico-w.jpg" + ], + "mcu": "rp2040", + "product": "Pico W", + "thumbnail": "", + "url": "https://www.raspberrypi.com/products/raspberry-pi-pico/", + "vendor": "Raspberry Pi" +} diff --git a/ports/rp2/boards/PICO_W/manifest.py b/ports/rp2/boards/PICO_W/manifest.py new file mode 100644 index 0000000000..1953d5cbd0 --- /dev/null +++ b/ports/rp2/boards/PICO_W/manifest.py @@ -0,0 +1,7 @@ +include("../manifest.py") + +freeze("$(MPY_DIR)/tools", "upip.py") +freeze("$(MPY_DIR)/tools", "upip_utarfile.py") + +if os.path.isdir(convert_path("$(MPY_LIB_DIR)")): + freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py") diff --git a/ports/rp2/boards/PICO_W/mpconfigboard.cmake b/ports/rp2/boards/PICO_W/mpconfigboard.cmake new file mode 100644 index 0000000000..d3fbce6993 --- /dev/null +++ b/ports/rp2/boards/PICO_W/mpconfigboard.cmake @@ -0,0 +1,8 @@ +# cmake file for Raspberry Pi Pico W +set(MICROPY_BOARD PICO_W) + +set(MICROPY_PY_LWIP ON) +set(MICROPY_PY_NETWORK_CYW43 ON) + +# Board specific version of the frozen manifest +set(MICROPY_FROZEN_MANIFEST ${CMAKE_SOURCE_DIR}/boards/PICO_W/manifest.py) diff --git a/ports/rp2/boards/PICO_W/mpconfigboard.h b/ports/rp2/boards/PICO_W/mpconfigboard.h new file mode 100644 index 0000000000..f467234fbe --- /dev/null +++ b/ports/rp2/boards/PICO_W/mpconfigboard.h @@ -0,0 +1,26 @@ +// Board and hardware specific configuration +#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico W" + +// todo: We need something to check our binary size +#define MICROPY_HW_FLASH_STORAGE_BYTES (848 * 1024) + +#define MICROPY_PY_NETWORK 1 +#define MICROPY_PY_USOCKET 1 +#define MICROPY_PY_USSL 1 + +// CYW43 driver configuration. +#define CYW43_USE_SPI (1) +#define CYW43_LWIP (1) +#define CYW43_GPIO (1) +#define CYW43_SPI_PIO (1) + +// For debugging mbedtls - also set +// Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose +// #define MODUSSL_MBEDTLS_DEBUG_LEVEL 1 + +#define MICROPY_HW_PIN_CYW43_COUNT CYW43_WL_GPIO_COUNT +#ifdef CYW43_WL_GPIO_LED_PIN +#define MICROPY_HW_PIN_CYW43_LED_PIN_NUM CYW43_WL_GPIO_LED_PIN +#endif + +#define MICROPY_HW_PIN_RESERVED(i) ((i) == CYW43_PIN_WL_HOST_WAKE || (i) == CYW43_PIN_WL_REG_ON) From 6519b1b95e44e471cb6a8ac60c31bfac482f0e5a Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 1 Jul 2022 09:57:13 +1000 Subject: [PATCH 0089/1041] stm32/Makefile: Fix setting of define that enables WIZNET5K driver. Commit 9670a156dabc1c751a6b02ef280daccf5a0ed213 missed one renaming of MICROPY_PY_WIZNET5K to MICROPY_PY_NETWORK_WIZNET5K which prevented the Wiznet interface from being enabled. Signed-off-by: Jim Mussared --- ports/stm32/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 53d1bb4ac4..f1c22c2a9a 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -459,7 +459,7 @@ endif ifneq ($(MICROPY_PY_NETWORK_WIZNET5K),0) WIZNET5K_DIR=drivers/wiznet5k INC += -I$(TOP)/$(WIZNET5K_DIR) -CFLAGS_MOD += -DMICROPY_PY_WIZNET5K=$(MICROPY_PY_NETWORK_WIZNET5K) -D_WIZCHIP_=$(MICROPY_PY_NETWORK_WIZNET5K) +CFLAGS_MOD += -DMICROPY_PY_NETWORK_WIZNET5K=$(MICROPY_PY_NETWORK_WIZNET5K) -D_WIZCHIP_=$(MICROPY_PY_NETWORK_WIZNET5K) ifeq ($(MICROPY_PY_LWIP),1) # When using MACRAW mode (with lwIP), maximum buffer space must be used for the raw socket CFLAGS_MOD += -DWIZCHIP_USE_MAX_BUFFER From 3d76292f37ee099ecf460ed0620360fb87a21fdc Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 5 Jul 2022 09:45:44 +1000 Subject: [PATCH 0090/1041] rp2/boards/GARATRONIC_PYBSTICK26_RP2040: Change pico-sdk board name. This follows a similar renaming in pico-sdk. Signed-off-by: Damien George --- .../rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.cmake b/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.cmake index 9add51a78b..311e114b29 100644 --- a/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.cmake +++ b/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.cmake @@ -1,3 +1,3 @@ # cmake file -set(PICO_BOARD pybstick26_rp2040) +set(PICO_BOARD garatronic_pybstick26_rp2040) From f4e69ab103a650a0737537b3899130089f152ed4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 5 Jul 2022 11:04:20 +1000 Subject: [PATCH 0091/1041] lib/cyw43-driver: Update cyw43-driver to fix ap_auth mode setting. Signed-off-by: Damien George --- lib/cyw43-driver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cyw43-driver b/lib/cyw43-driver index 195dfcc10b..5614e2750e 160000 --- a/lib/cyw43-driver +++ b/lib/cyw43-driver @@ -1 +1 @@ -Subproject commit 195dfcc10bb6f379e3dea45147590db2203d3c7b +Subproject commit 5614e2750e019b0ffa14a50e3c92045b952e2634 From d660a0c3d13a5354c8cb10cff90988cff75a33bb Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 5 Jul 2022 11:05:13 +1000 Subject: [PATCH 0092/1041] extmod/network_cyw43: Add "security" config option to get/set auth mode. Signed-off-by: Damien George --- extmod/network_cyw43.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/extmod/network_cyw43.c b/extmod/network_cyw43.c index 8823e3fa25..c131fbb109 100644 --- a/extmod/network_cyw43.c +++ b/extmod/network_cyw43.c @@ -365,6 +365,11 @@ STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map return mp_obj_new_str((const char *)buf, len); } } + #if MICROPY_PY_NETWORK_CYW43_USE_LIB_DRIVER + case MP_QSTR_security: { + return MP_OBJ_NEW_SMALL_INT(cyw43_wifi_ap_get_auth(self->cyw)); + } + #endif case MP_QSTR_mac: { uint8_t buf[6]; cyw43_wifi_get_mac(self->cyw, self->itf, buf); @@ -421,6 +426,10 @@ STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map } break; } + case MP_QSTR_security: { + cyw43_wifi_ap_set_auth(self->cyw, mp_obj_get_int(e->value)); + break; + } case MP_QSTR_key: case MP_QSTR_password: { size_t len; From 4b9a2abbdec0e905fbc08f247513e43fb6bff39e Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 5 Jul 2022 11:07:16 +1000 Subject: [PATCH 0093/1041] rp2/main: Set default AP auth mode to WPA2_AES_PSK. Signed-off-by: Damien George --- ports/rp2/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/rp2/main.c b/ports/rp2/main.c index 664bb18109..d976464de1 100644 --- a/ports/rp2/main.c +++ b/ports/rp2/main.c @@ -143,6 +143,7 @@ int main(int argc, char **argv) { buf[6] = hexchr[pid.id[5] >> 4]; buf[7] = hexchr[pid.id[4] & 0xf]; cyw43_wifi_ap_set_ssid(&cyw43_state, 8, buf); + cyw43_wifi_ap_set_auth(&cyw43_state, CYW43_AUTH_WPA2_AES_PSK); cyw43_wifi_ap_set_password(&cyw43_state, 8, (const uint8_t *)"picoW123"); } #endif From 85be3d3da889af76219c8bbfff041e8a4faab0c8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 5 Jul 2022 16:11:42 +1000 Subject: [PATCH 0094/1041] rp2/mpconfigport: Factor core event handling to EVENT_POLL_HOOK_FAST. Signed-off-by: Damien George --- ports/rp2/mpconfigport.h | 9 +++++++-- ports/rp2/mphalport.c | 3 +-- ports/rp2/rp2_pio.c | 6 ++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 9143b5f6c5..53437d6c98 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -248,12 +248,17 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k; #define MICROPY_HW_USBDEV_TASK_HOOK #endif -#define MICROPY_EVENT_POLL_HOOK \ +#define MICROPY_EVENT_POLL_HOOK_FAST \ do { \ + MICROPY_HW_USBDEV_TASK_HOOK \ extern void mp_handle_pending(bool); \ mp_handle_pending(true); \ + } while (0) + +#define MICROPY_EVENT_POLL_HOOK \ + do { \ + MICROPY_EVENT_POLL_HOOK_FAST; \ best_effort_wfe_or_timeout(make_timeout_time_ms(1)); \ - MICROPY_HW_USBDEV_TASK_HOOK \ } while (0); #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1)) diff --git a/ports/rp2/mphalport.c b/ports/rp2/mphalport.c index aec4a96724..d3824d8f91 100644 --- a/ports/rp2/mphalport.c +++ b/ports/rp2/mphalport.c @@ -157,9 +157,8 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { void mp_hal_delay_ms(mp_uint_t ms) { absolute_time_t t = make_timeout_time_ms(ms); while (!time_reached(t)) { - mp_handle_pending(true); + MICROPY_EVENT_POLL_HOOK_FAST; best_effort_wfe_or_timeout(t); - MICROPY_HW_USBDEV_TASK_HOOK } } diff --git a/ports/rp2/rp2_pio.c b/ports/rp2/rp2_pio.c index 9955cc5440..9900616966 100644 --- a/ports/rp2/rp2_pio.c +++ b/ports/rp2/rp2_pio.c @@ -657,8 +657,7 @@ STATIC mp_obj_t rp2_state_machine_get(size_t n_args, const mp_obj_t *args) { for (;;) { while (pio_sm_is_rx_fifo_empty(self->pio, self->sm)) { // This delay must be fast. - mp_handle_pending(true); - MICROPY_HW_USBDEV_TASK_HOOK + MICROPY_EVENT_POLL_HOOK_FAST; } uint32_t value = pio_sm_get(self->pio, self->sm) >> shift; if (dest == NULL) { @@ -716,8 +715,7 @@ STATIC mp_obj_t rp2_state_machine_put(size_t n_args, const mp_obj_t *args) { } while (pio_sm_is_tx_fifo_full(self->pio, self->sm)) { // This delay must be fast. - mp_handle_pending(true); - MICROPY_HW_USBDEV_TASK_HOOK + MICROPY_EVENT_POLL_HOOK_FAST; } pio_sm_put(self->pio, self->sm, value << shift); } From 651b3704845bff116334993d2a4752d78d23a068 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 4 Jul 2022 11:14:47 +1000 Subject: [PATCH 0095/1041] rp2/Makefile: Regenerate cmake if generated Makefile missing. `CMakeCache.txt` can exist even if cmake failed. Use `Makefile` instead. Signed-off-by: Jim Mussared --- ports/rp2/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/rp2/Makefile b/ports/rp2/Makefile index 87c1d650e0..6f8c621c2a 100644 --- a/ports/rp2/Makefile +++ b/ports/rp2/Makefile @@ -23,7 +23,7 @@ CMAKE_ARGS += -DCMAKE_BUILD_TYPE=Debug endif all: - [ -e $(BUILD)/CMakeCache.txt ] || cmake -S . -B $(BUILD) -DPICO_BUILD_DOCS=0 ${CMAKE_ARGS} + [ -e $(BUILD)/Makefile ] || cmake -S . -B $(BUILD) -DPICO_BUILD_DOCS=0 ${CMAKE_ARGS} $(MAKE) $(MAKESILENT) -C $(BUILD) clean: From 5f4143dd40ceb120db3edd3e4446f01b4240313d Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 4 Jul 2022 11:16:20 +1000 Subject: [PATCH 0096/1041] rp2/CMakeLists: Give error if required submodules are missing. Ensure that nimble and cyw43-driver are initialised when the board requires it. Also make these work with `make submodules`. Signed-off-by: Jim Mussared --- ports/rp2/CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 9185c7d649..198512f885 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -206,6 +206,11 @@ if(MICROPY_PY_BLUETOOTH) endif() if(MICROPY_BLUETOOTH_NIMBLE) + string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/mynewt-nimble) + if(NOT (${ECHO_SUBMODULES}) AND NOT EXISTS ${MICROPY_DIR}/lib/mynewt-nimble/nimble/host/include/host/ble_hs.h) + message(FATAL_ERROR " mynewt-nimble not initialized.\n Run 'make BOARD=${MICROPY_BOARD} submodules'") + endif() + list(APPEND MICROPY_SOURCE_PORT mpnimbleport.c) target_compile_definitions(${MICROPY_TARGET} PRIVATE MICROPY_BLUETOOTH_NIMBLE=1 @@ -223,6 +228,9 @@ endif() if (MICROPY_PY_NETWORK_CYW43) string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/cyw43-driver) + if((NOT (${ECHO_SUBMODULES})) AND NOT EXISTS ${MICROPY_DIR}/lib/cyw43-driver/src/cyw43.h) + message(FATAL_ERROR " cyw43-driver not initialized.\n Run 'make BOARD=${MICROPY_BOARD} submodules'") + endif() target_compile_definitions(${MICROPY_TARGET} PRIVATE MICROPY_PY_NETWORK_CYW43=1 From 11ef618bbc8b7d9afba5e8ab85e82e2a7b9326b6 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 4 Jul 2022 11:21:58 +1000 Subject: [PATCH 0097/1041] rp2/CMakeLists: Don't override cyw43-driver unless necessary. This supresses a warning from pico-sdk when the board isn't using this driver. Signed-off-by: Jim Mussared --- ports/rp2/CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 198512f885..6314bfb44d 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -16,8 +16,6 @@ endif() # Use the local tinyusb instead of the one in pico-sdk set(PICO_TINYUSB_PATH ${MICROPY_DIR}/lib/tinyusb) -# Use the local cyw43_driver instead of the one in pico-sdk -set(PICO_CYW43_DRIVER_PATH ${MICROPY_DIR}/lib/cyw43-driver) # Use the local lwip instead of the one in pico-sdk set(PICO_LWIP_PATH ${MICROPY_DIR}/lib/lwip) @@ -51,6 +49,11 @@ endif() # A board may also have enabled additional components. set(MICROPY_SSL_MBEDTLS ON) +# Use the local cyw43_driver instead of the one in pico-sdk +if (MICROPY_PY_NETWORK_CYW43) + set(PICO_CYW43_DRIVER_PATH ${MICROPY_DIR}/lib/cyw43-driver) +endif() + # Include component cmake fragments include(${MICROPY_DIR}/py/py.cmake) include(${MICROPY_DIR}/extmod/extmod.cmake) From 2efaebc8995d1d73dd6f0d3af448b385b0fa38c8 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 4 Jul 2022 11:35:16 +1000 Subject: [PATCH 0098/1041] rp2/boards/ARDUINO_NANO_RP2040_CONNECT: Add urequests module. Signed-off-by: Jim Mussared --- ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py index 1becb3dfe1..0448aa89a1 100644 --- a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py +++ b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py @@ -8,3 +8,5 @@ include( l2cap=True, security=True, ) +if os.path.isdir(convert_path("$(MPY_LIB_DIR)")): + freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py") From 1ea82b6dcc7dd5f0ad051db414ff91d8f04d20e0 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Tue, 28 Jun 2022 16:38:45 +0300 Subject: [PATCH 0099/1041] esp32,esp8266: Rename WLAN dhcp_hostname config to hostname. But retain old name for backwards compatibility. --- docs/library/network.WLAN.rst | 2 +- ports/esp32/network_wlan.c | 2 ++ ports/esp8266/modnetwork.c | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/library/network.WLAN.rst b/docs/library/network.WLAN.rst index bc416d1c2e..c673194700 100644 --- a/docs/library/network.WLAN.rst +++ b/docs/library/network.WLAN.rst @@ -130,7 +130,7 @@ Methods hidden Whether SSID is hidden (boolean) security Security protocol supported (enumeration, see module constants) key Access key (string) - dhcp_hostname The DHCP hostname to use + hostname The hostname that will be sent to DHCP (STA interfaces) and mDNS (if supported, both STA and AP) reconnects Number of reconnect attempts to make (integer, 0=none, -1=unlimited) txpower Maximum transmit power in dBm (integer or float) ============= =========== diff --git a/ports/esp32/network_wlan.c b/ports/esp32/network_wlan.c index 48b398c8f0..9b2200e4ff 100644 --- a/ports/esp32/network_wlan.c +++ b/ports/esp32/network_wlan.c @@ -452,6 +452,7 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_ cfg.ap.channel = mp_obj_get_int(kwargs->table[i].value); break; } + case MP_QSTR_hostname: case MP_QSTR_dhcp_hostname: { const char *s = mp_obj_str_get_str(kwargs->table[i].value); esp_exceptions(tcpip_adapter_set_hostname(self->if_id, s)); @@ -538,6 +539,7 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_ req_if = WIFI_IF_AP; val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel); break; + case MP_QSTR_hostname: case MP_QSTR_dhcp_hostname: { const char *s; esp_exceptions(tcpip_adapter_get_hostname(self->if_id, &s)); diff --git a/ports/esp8266/modnetwork.c b/ports/esp8266/modnetwork.c index e32a0ff0c9..dbc12f74d4 100644 --- a/ports/esp8266/modnetwork.c +++ b/ports/esp8266/modnetwork.c @@ -397,6 +397,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs cfg.ap.channel = mp_obj_get_int(kwargs->table[i].value); break; } + case MP_QSTR_hostname: case MP_QSTR_dhcp_hostname: { req_if = STATION_IF; if (self->if_id == STATION_IF) { @@ -461,6 +462,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs req_if = SOFTAP_IF; val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel); break; + case MP_QSTR_hostname: case MP_QSTR_dhcp_hostname: { req_if = STATION_IF; char *s = wifi_station_get_hostname(); From 5ab7dfe6db96e3cc7f9358b30eb04b27411fcb07 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 30 Jun 2022 19:02:18 -0500 Subject: [PATCH 0100/1041] unix/moduos: Include errno.h. The file `ports/unix/moduos.c` uses `errno` so it needs to include `errno.h`, otherwise a compiler error can occur. Signed-off-by: David Lechner --- ports/unix/moduos.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/unix/moduos.c b/ports/unix/moduos.c index 848a3612d1..b577dbd297 100644 --- a/ports/unix/moduos.c +++ b/ports/unix/moduos.c @@ -25,6 +25,7 @@ * THE SOFTWARE. */ +#include #include #include From d27e58449b6b0b50ac1e0c78cb9fb189a190c666 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 5 Jul 2022 23:47:54 +1000 Subject: [PATCH 0101/1041] stm32/mboot: Remove redundant code in mboot_state_change function. This code was made redundant in 87fbceef2649b15d40cc8aaf4e5957af537ce9af Signed-off-by: Damien George --- ports/stm32/mboot/mboot.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ports/stm32/mboot/mboot.h b/ports/stm32/mboot/mboot.h index d45f4c1efd..d86fe57303 100644 --- a/ports/stm32/mboot/mboot.h +++ b/ports/stm32/mboot/mboot.h @@ -209,11 +209,7 @@ int mboot_get_reset_mode_default(void); void mboot_state_change_default(mboot_state_t state, uint32_t arg); static inline void mboot_state_change(mboot_state_t state, uint32_t arg) { - #if defined(MBOOT_BOARD_STATE_CHANGE) return MBOOT_BOARD_STATE_CHANGE(state, arg); - #else - return mboot_state_change_default(state, arg); - #endif } #endif // MICROPY_INCLUDED_STM32_MBOOT_MBOOT_H From 07cae9178fd409e8269d55d0b614612a7db49bef Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 2 Jul 2022 14:42:16 -0500 Subject: [PATCH 0102/1041] nrf/Makefile: Drop unused MPY_CROSS and MPY_TOOL variables. These variables are no longer used in the nrf Makefile and can be removed. Signed-off-by: David Lechner --- ports/nrf/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index d022892641..47653ae716 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -61,8 +61,6 @@ include ../../extmod/extmod.mk GIT_SUBMODULES = lib/nrfx lib/tinyusb MICROPY_VFS_FAT ?= 0 -MPY_CROSS = ../../mpy-cross/mpy-cross -MPY_TOOL = ../../tools/mpy-tool.py CROSS_COMPILE ?= arm-none-eabi- From fc6d989f8cca61b33715fcf2e8f1eaa0d0ed67ec Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Tue, 5 Jul 2022 22:13:17 +0200 Subject: [PATCH 0103/1041] drivers/hts221: Add HTS221 humidity sensor driver. --- drivers/hts221/hts221.py | 91 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 drivers/hts221/hts221.py diff --git a/drivers/hts221/hts221.py b/drivers/hts221/hts221.py new file mode 100644 index 0000000000..fec52a7389 --- /dev/null +++ b/drivers/hts221/hts221.py @@ -0,0 +1,91 @@ +""" +The MIT License (MIT) + +Copyright (c) 2013-2022 Ibrahim Abdelkader +Copyright (c) 2013-2022 Kwabena W. Agyeman + +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. + +HTS221 driver driver for MicroPython. +Original source: https://github.com/ControlEverythingCommunity/HTS221/blob/master/Python/HTS221.py + +Example usage: + +import time +import hts221 +from machine import Pin, I2C + +bus = I2C(1, scl=Pin(15), sda=Pin(14)) +hts = hts221.HTS221(bus) + +while (True): + rH = hts.humidity() + temp = hts.temperature() + print ("rH: %.2f%% T: %.2fC" %(rH, temp)) + time.sleep_ms(100) +""" + +import struct + + +class HTS221: + def __init__(self, i2c, data_rate=1, address=0x5F): + self.bus = i2c + self.odr = data_rate + self.slv_addr = address + + # Set configuration register + # Humidity and temperature average configuration + self.bus.writeto_mem(self.slv_addr, 0x10, b"\x1B") + + # Set control register + # PD | BDU | ODR + cfg = 0x80 | 0x04 | (self.odr & 0x3) + self.bus.writeto_mem(self.slv_addr, 0x20, bytes([cfg])) + + # Read Calibration values from non-volatile memory of the device + # Humidity Calibration values + self.H0 = self._read_reg(0x30, 1) / 2 + self.H1 = self._read_reg(0x31, 1) / 2 + self.H2 = self._read_reg(0x36, 2) + self.H3 = self._read_reg(0x3A, 2) + + # Temperature Calibration values + raw = self._read_reg(0x35, 1) + self.T0 = ((raw & 0x03) * 256) + self._read_reg(0x32, 1) + self.T1 = ((raw & 0x0C) * 64) + self._read_reg(0x33, 1) + self.T2 = self._read_reg(0x3C, 2) + self.T3 = self._read_reg(0x3E, 2) + + def _read_reg(self, reg_addr, size): + fmt = "B" if size == 1 else "H" + reg_addr = reg_addr if size == 1 else reg_addr | 0x80 + return struct.unpack(fmt, self.bus.readfrom_mem(self.slv_addr, reg_addr, size))[0] + + def humidity(self): + rH = self._read_reg(0x28, 2) + return (self.H1 - self.H0) * (rH - self.H2) / (self.H3 - self.H2) + self.H0 + + def temperature(self): + temp = self._read_reg(0x2A, 2) + if temp > 32767: + temp -= 65536 + return ((self.T1 - self.T0) / 8.0) * (temp - self.T2) / (self.T3 - self.T2) + ( + self.T0 / 8.0 + ) From 6c07e9eb2701b617534c0a74647b2d1e0c4eff9e Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Tue, 5 Jul 2022 22:14:10 +0200 Subject: [PATCH 0104/1041] drivers/lsm9ds1: Add LSM9DS1 IMU driver. --- drivers/lsm9ds1/lsm9ds1.py | 189 +++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 drivers/lsm9ds1/lsm9ds1.py diff --git a/drivers/lsm9ds1/lsm9ds1.py b/drivers/lsm9ds1/lsm9ds1.py new file mode 100644 index 0000000000..5d9942a7b3 --- /dev/null +++ b/drivers/lsm9ds1/lsm9ds1.py @@ -0,0 +1,189 @@ +""" +The MIT License (MIT) + +Copyright (c) 2013, 2014 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. + + +LSM9DS1 - 9DOF inertial sensor of STMicro driver for MicroPython. +The sensor contains an accelerometer / gyroscope / magnetometer +Uses the internal FIFO to store up to 16 gyro/accel data, use the iter_accel_gyro generator to access it. + +Example usage: + +import time +from lsm9ds1 import LSM9DS1 +from machine import Pin, I2C + +lsm = LSM9DS1(I2C(1, scl=Pin(15), sda=Pin(14))) + +while (True): + #for g,a in lsm.iter_accel_gyro(): print(g,a) # using fifo + print('Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.accel())) + print('Magnetometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.magnet())) + print('Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.gyro())) + print("") + time.sleep_ms(100) +""" +import array + + +_WHO_AM_I = const(0xF) +_CTRL_REG1_G = const(0x10) +_INT_GEN_SRC_G = const(0x14) +_OUT_TEMP = const(0x15) +_OUT_G = const(0x18) +_CTRL_REG4_G = const(0x1E) +_STATUS_REG = const(0x27) +_OUT_XL = const(0x28) +_FIFO_CTRL_REG = const(0x2E) +_FIFO_SRC = const(0x2F) +_OFFSET_REG_X_M = const(0x05) +_CTRL_REG1_M = const(0x20) +_OUT_M = const(0x28) +_SCALE_GYRO = const(((245, 0), (500, 1), (2000, 3))) +_SCALE_ACCEL = const(((2, 0), (4, 2), (8, 3), (16, 1))) + + +class LSM9DS1: + def __init__(self, i2c, address_gyro=0x6B, address_magnet=0x1E): + self.i2c = i2c + self.address_gyro = address_gyro + self.address_magnet = address_magnet + # check id's of accelerometer/gyro and magnetometer + if (self.magent_id() != b"=") or (self.gyro_id() != b"h"): + raise OSError( + "Invalid LSM9DS1 device, using address {}/{}".format(address_gyro, address_magnet) + ) + # allocate scratch buffer for efficient conversions and memread op's + self.scratch = array.array("B", [0, 0, 0, 0, 0, 0]) + self.scratch_int = array.array("h", [0, 0, 0]) + self.init_gyro_accel() + self.init_magnetometer() + + def init_gyro_accel(self, sample_rate=6, scale_gyro=0, scale_accel=0): + """Initalizes Gyro and Accelerator. + sample rate: 0-6 (off, 14.9Hz, 59.5Hz, 119Hz, 238Hz, 476Hz, 952Hz) + scale_gyro: 0-2 (245dps, 500dps, 2000dps ) + scale_accel: 0-3 (+/-2g, +/-4g, +/-8g, +-16g) + """ + assert sample_rate <= 6, "invalid sampling rate: %d" % sample_rate + assert scale_gyro <= 2, "invalid gyro scaling: %d" % scale_gyro + assert scale_accel <= 3, "invalid accelerometer scaling: %d" % scale_accel + + i2c = self.i2c + addr = self.address_gyro + mv = memoryview(self.scratch) + # angular control registers 1-3 / Orientation + mv[0] = ((sample_rate & 0x07) << 5) | ((_SCALE_GYRO[scale_gyro][1] & 0x3) << 3) + mv[1:4] = b"\x00\x00\x00" + i2c.writeto_mem(addr, _CTRL_REG1_G, mv[:5]) + # ctrl4 - enable x,y,z, outputs, no irq latching, no 4D + # ctrl5 - enable all axes, no decimation + # ctrl6 - set scaling and sample rate of accel + # ctrl7,8 - leave at default values + # ctrl9 - FIFO enabled + mv[0] = mv[1] = 0x38 + mv[2] = ((sample_rate & 7) << 5) | ((_SCALE_ACCEL[scale_accel][1] & 0x3) << 3) + mv[3] = 0x00 + mv[4] = 0x4 + mv[5] = 0x2 + i2c.writeto_mem(addr, _CTRL_REG4_G, mv[:6]) + + # fifo: use continous mode (overwrite old data if overflow) + i2c.writeto_mem(addr, _FIFO_CTRL_REG, b"\x00") + i2c.writeto_mem(addr, _FIFO_CTRL_REG, b"\xc0") + + self.scale_gyro = 32768 / _SCALE_GYRO[scale_gyro][0] + self.scale_accel = 32768 / _SCALE_ACCEL[scale_accel][0] + + def init_magnetometer(self, sample_rate=7, scale_magnet=0): + """ + sample rates = 0-7 (0.625, 1.25, 2.5, 5, 10, 20, 40, 80Hz) + scaling = 0-3 (+/-4, +/-8, +/-12, +/-16 Gauss) + """ + assert sample_rate < 8, "invalid sample rate: %d (0-7)" % sample_rate + assert scale_magnet < 4, "invalid scaling: %d (0-3)" % scale_magnet + i2c = self.i2c + addr = self.address_magnet + mv = memoryview(self.scratch) + mv[0] = 0x40 | (sample_rate << 2) # ctrl1: high performance mode + mv[1] = scale_magnet << 5 # ctrl2: scale, normal mode, no reset + mv[2] = 0x00 # ctrl3: continous conversion, no low power, I2C + mv[3] = 0x08 # ctrl4: high performance z-axis + mv[4] = 0x00 # ctr5: no fast read, no block update + i2c.writeto_mem(addr, _CTRL_REG1_M, mv[:5]) + self.scale_factor_magnet = 32768 / ((scale_magnet + 1) * 4) + + def calibrate_magnet(self, offset): + """ + offset is a magnet vecor that will be substracted by the magnetometer + for each measurement. It is written to the magnetometer's offset register + """ + offset = [int(i * self.scale_factor_magnet) for i in offset] + mv = memoryview(self.scratch) + mv[0] = offset[0] & 0xFF + mv[1] = offset[0] >> 8 + mv[2] = offset[1] & 0xFF + mv[3] = offset[1] >> 8 + mv[4] = offset[2] & 0xFF + mv[5] = offset[2] >> 8 + self.i2c.writeto_mem(self.address_magnet, _OFFSET_REG_X_M, mv[:6]) + + def gyro_id(self): + return self.i2c.readfrom_mem(self.address_gyro, _WHO_AM_I, 1) + + def magent_id(self): + return self.i2c.readfrom_mem(self.address_magnet, _WHO_AM_I, 1) + + def magnet(self): + """Returns magnetometer vector in gauss. + raw_values: if True, the non-scaled adc values are returned + """ + mv = memoryview(self.scratch_int) + f = self.scale_factor_magnet + self.i2c.readfrom_mem_into(self.address_magnet, _OUT_M | 0x80, mv) + return (mv[0] / f, mv[1] / f, mv[2] / f) + + def gyro(self): + """Returns gyroscope vector in degrees/sec.""" + mv = memoryview(self.scratch_int) + f = self.scale_gyro + self.i2c.readfrom_mem_into(self.address_gyro, _OUT_G | 0x80, mv) + return (mv[0] / f, mv[1] / f, mv[2] / f) + + def accel(self): + """Returns acceleration vector in gravity units (9.81m/s^2).""" + mv = memoryview(self.scratch_int) + f = self.scale_accel + self.i2c.readfrom_mem_into(self.address_gyro, _OUT_XL | 0x80, mv) + return (mv[0] / f, mv[1] / f, mv[2] / f) + + def iter_accel_gyro(self): + """A generator that returns tuples of (gyro,accelerometer) data from the fifo.""" + while True: + fifo_state = int.from_bytes( + self.i2c.readfrom_mem(self.address_gyro, _FIFO_SRC, 1), "big" + ) + if fifo_state & 0x3F: + # print("Available samples=%d" % (fifo_state & 0x1f)) + yield self.gyro(), self.accel() + else: + break From 7d32b770f284bebe388629b62623262245b6b185 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Tue, 5 Jul 2022 22:14:48 +0200 Subject: [PATCH 0105/1041] drivers/lps22h: Add LPS22HB/HH pressure sensor driver. --- drivers/lps22h/lps22h.py | 117 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 drivers/lps22h/lps22h.py diff --git a/drivers/lps22h/lps22h.py b/drivers/lps22h/lps22h.py new file mode 100644 index 0000000000..8d90b29178 --- /dev/null +++ b/drivers/lps22h/lps22h.py @@ -0,0 +1,117 @@ +""" +The MIT License (MIT) + +Copyright (c) 2016-2019 shaoziyang +Copyright (c) 2022 Ibrahim Abdelkader + +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. + +LPS22HB/HH pressure sensor driver for MicroPython. + +Example usage: + +import time +from lps22h import LPS22H +from machine import Pin, I2C + +bus = I2C(1, scl=Pin(15), sda=Pin(14)) +lps = LPS22H(bus, oneshot=False) + +while (True): + print("Pressure: %.2f hPa Temperature: %.2f C"%(lps.pressure(), lps.temperature())) + time.sleep_ms(10) +""" +import machine + +_LPS22_CTRL_REG1 = const(0x10) +_LPS22_CTRL_REG2 = const(0x11) +_LPS22_STATUS = const(0x27) +_LPS22_TEMP_OUT_L = const(0x2B) +_LPS22_PRESS_OUT_XL = const(0x28) +_LPS22_PRESS_OUT_L = const(0x29) + + +class LPS22H: + def __init__(self, i2c, address=0x5C, oneshot=False): + self.i2c = i2c + self.addr = address + self.oneshot = oneshot + self.buf = bytearray(1) + + if hasattr(machine, "idle"): + self._go_idle = machine.idle() + else: + import time + + self._go_idle = lambda: time.sleep_ms(1) + + # ODR=1 EN_LPFP=1 BDU=1 + self._write_reg(_LPS22_CTRL_REG1, 0x1A) + self.set_oneshot_mode(self.oneshot) + + def _int16(self, d): + return d if d < 0x8000 else d - 0x10000 + + def _write_reg(self, reg, dat): + self.buf[0] = dat + self.i2c.writeto_mem(self.addr, reg, self.buf) + + def _read_reg(self, reg, width=8): + self.i2c.readfrom_mem_into(self.addr, reg, self.buf) + val = self.buf[0] + if width == 16: + val |= self._read_reg(reg + 1) << 8 + return val + + def _tigger_oneshot(self, b): + if self.oneshot: + self._write_reg(_LPS22_CTRL_REG2, self._read_reg(_LPS22_CTRL_REG2) | 0x01) + self._read_reg(0x28 + b * 2) + while True: + if self._read_reg(_LPS22_STATUS) & b: + return + self._go_idle() + + def set_oneshot_mode(self, oneshot): + self._read_reg(_LPS22_CTRL_REG1) + self.oneshot = oneshot + if oneshot: + self.buf[0] &= 0x0F + else: + self.buf[0] |= 0x10 + self._write_reg(_LPS22_CTRL_REG1, self.buf[0]) + + def pressure(self): + if self.oneshot: + self._tigger_oneshot(1) + return ( + self._read_reg(_LPS22_PRESS_OUT_XL) + self._read_reg(_LPS22_PRESS_OUT_L, 16) * 256 + ) / 4096 + + def temperature(self): + if self.oneshot: + self._tigger_oneshot(2) + return self._int16(self._read_reg(_LPS22_TEMP_OUT_L, 16)) / 100 + + def altitude(self): + return ( + (((1013.25 / self.pressure()) ** (1 / 5.257)) - 1.0) + * (self.temperature() + 273.15) + / 0.0065 + ) From 5c31a6c0235b25dd2199825e378f4e18f8db1bc0 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Thu, 21 Apr 2022 11:49:12 +0200 Subject: [PATCH 0106/1041] nrf/boards/arduino_nano_33_ble: Add Arduino Nano 33 BLE sense board. --- .../boards/arduino_nano_33_ble_sense/board.c | 67 +++++++++++++++++ .../arduino_nano_33_ble_sense/board.json | 25 +++++++ .../arduino_nano_33_ble_sense/deploy.md | 23 ++++++ .../arduino_nano_33_ble_sense/manifest.py | 4 + .../arduino_nano_33_ble_sense/mpconfigboard.h | 75 +++++++++++++++++++ .../mpconfigboard.mk | 12 +++ .../nano_bootloader.ld | 1 + .../boards/arduino_nano_33_ble_sense/pins.csv | 50 +++++++++++++ 8 files changed, 257 insertions(+) create mode 100644 ports/nrf/boards/arduino_nano_33_ble_sense/board.c create mode 100644 ports/nrf/boards/arduino_nano_33_ble_sense/board.json create mode 100644 ports/nrf/boards/arduino_nano_33_ble_sense/deploy.md create mode 100644 ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py create mode 100644 ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.h create mode 100644 ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.mk create mode 100644 ports/nrf/boards/arduino_nano_33_ble_sense/nano_bootloader.ld create mode 100644 ports/nrf/boards/arduino_nano_33_ble_sense/pins.csv diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/board.c b/ports/nrf/boards/arduino_nano_33_ble_sense/board.c new file mode 100644 index 0000000000..954639756b --- /dev/null +++ b/ports/nrf/boards/arduino_nano_33_ble_sense/board.c @@ -0,0 +1,67 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Arduino SA + * + * 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 "nrf.h" +#include "nrf_gpio.h" +#include "nrf_rtc.h" + +#define PIN_ENABLE_SENSORS_3V3 (22u) +#define PIN_ENABLE_I2C_PULLUP (32u) +#define DFU_MAGIC_SERIAL_ONLY_RESET (0xb0) + +void NANO33_board_early_init(void) { + // Errata Nano33BLE - I2C pullup is on SWO line, need to disable TRACE + // was being enabled by nrfx_clock_anomaly_132 + CoreDebug->DEMCR = 0; + NRF_CLOCK->TRACECONFIG = 0; + + // Bootloader enables interrupt on COMPARE[0], which we don't handle + // Disable it here to avoid getting stuck when OVERFLOW irq is triggered + nrf_rtc_event_disable(NRF_RTC1, NRF_RTC_INT_COMPARE0_MASK); + nrf_rtc_int_disable(NRF_RTC1, NRF_RTC_INT_COMPARE0_MASK); + + // Always enable I2C pullup and power on startup + // Change for maximum powersave + nrf_gpio_cfg_output(PIN_ENABLE_SENSORS_3V3); + nrf_gpio_cfg_output(PIN_ENABLE_I2C_PULLUP); + + nrf_gpio_pin_set(PIN_ENABLE_SENSORS_3V3); + nrf_gpio_pin_set(PIN_ENABLE_I2C_PULLUP); +} + +void NANO33_board_deinit(void) { + nrf_gpio_cfg_output(PIN_ENABLE_SENSORS_3V3); + nrf_gpio_cfg_output(PIN_ENABLE_I2C_PULLUP); + + nrf_gpio_pin_clear(PIN_ENABLE_SENSORS_3V3); + nrf_gpio_pin_clear(PIN_ENABLE_I2C_PULLUP); +} + +void NANO33_board_enter_bootloader(void) { + __disable_irq(); + NRF_POWER->GPREGRET = DFU_MAGIC_SERIAL_ONLY_RESET; + NVIC_SystemReset(); +} diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/board.json b/ports/nrf/boards/arduino_nano_33_ble_sense/board.json new file mode 100644 index 0000000000..9488c75f84 --- /dev/null +++ b/ports/nrf/boards/arduino_nano_33_ble_sense/board.json @@ -0,0 +1,25 @@ +{ + "deploy": [ + "./deploy.md" + ], + "docs": "", + "features": [ + "Bluetooth 5.0", + "IMU LSM9DS1", + "Humidity sensor HTS221", + "Pressure sensor LPS22H", + "Proximity, Light, RGB sensor APDS-9960", + "Microphone MPM3610", + "Crypto IC ARM CC310", + "USB-MICRO", + "Breadboard Friendly" + ], + "images": [ + "ABX00031_01.iso_998x749.jpg" + ], + "mcu": "nRF52840", + "product": "Arduino Nano 33 BLE Sense", + "thumbnail": "", + "url": "https://store.arduino.cc/products/arduino-nano-33-ble-sense", + "vendor": "Arduino" +} diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/deploy.md b/ports/nrf/boards/arduino_nano_33_ble_sense/deploy.md new file mode 100644 index 0000000000..a2d08f2c81 --- /dev/null +++ b/ports/nrf/boards/arduino_nano_33_ble_sense/deploy.md @@ -0,0 +1,23 @@ +### Update the bootloader + +Before deploying any firmware, make sure you have the updated Arduino Nano 33 BLE bootloader, which relocates the bootloader so the softdevice doesn't overwrite it. Please see: + +https://docs.arduino.cc/tutorials/nano-33-ble/getting-started-omv + +### Via Arduino bootloader and BOSSA + +Download BOSSA from https://github.com/shumatech/BOSSA/ and double tap reset button to enter the Arduino bootloader + +```bash +bossac -e -w --offset=0x16000 --port=ttyACM0 -i -d -U -R build-arduino_nano_33_ble_sense-s140/firmware.bin +``` + +Alternatively, a Linux binary can be found here: https://github.com/openmv/openmv/blob/master/tools/bossac + +### Via nrfprog + +This board can also be programmed via nrfjprog (with Jlink for example), from MicroPython source repository: + +```bash +make -j8 BOARD=arduino_nano_33_ble_sense SD=s140 deploy +``` diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py b/ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py new file mode 100644 index 0000000000..dbc8104dc2 --- /dev/null +++ b/ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py @@ -0,0 +1,4 @@ +include("$(PORT_DIR)/modules/manifest.py") +freeze("$(MPY_DIR)/drivers/hts221", "hts221.py") +freeze("$(MPY_DIR)/drivers/lps22h", "lps22h.py") +freeze("$(MPY_DIR)/drivers/lsm9ds1", "lsm9ds1.py") diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.h b/ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.h new file mode 100644 index 0000000000..4a16b6110b --- /dev/null +++ b/ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.h @@ -0,0 +1,75 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2022 Arduino SA + */ + +#define MICROPY_HW_BOARD_NAME "Arduino Nano 33 BLE Sense" +#define MICROPY_HW_MCU_NAME "NRF52840" + +#define MICROPY_MBFS (1) + +#define MICROPY_BOARD_EARLY_INIT NANO33_board_early_init +#define MICROPY_BOARD_DEINIT NANO33_board_deinit +#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) NANO33_board_enter_bootloader() + +#define MICROPY_PY_MACHINE_UART (1) +#define MICROPY_PY_MACHINE_HW_PWM (1) +#define MICROPY_PY_MACHINE_HW_SPI (1) +#define MICROPY_PY_MACHINE_TIMER (1) +#define MICROPY_PY_MACHINE_RTCOUNTER (1) +#define MICROPY_PY_MACHINE_I2C (1) +#define MICROPY_PY_MACHINE_ADC (1) +#define MICROPY_PY_MACHINE_TEMP (1) + +#define MICROPY_HW_USB_CDC (1) +#define MICROPY_HW_HAS_LED (1) +#define MICROPY_HW_HAS_SWITCH (0) +#define MICROPY_HW_HAS_FLASH (0) +#define MICROPY_HW_HAS_SDCARD (0) +#define MICROPY_HW_HAS_MMA7660 (0) +#define MICROPY_HW_HAS_LIS3DSH (0) +#define MICROPY_HW_HAS_LCD (0) +#define MICROPY_HW_ENABLE_RNG (1) +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_TIMER (0) +#define MICROPY_HW_ENABLE_SERVO (0) +#define MICROPY_HW_ENABLE_DAC (0) +#define MICROPY_HW_ENABLE_CAN (0) + +// LEDs config +#define MICROPY_HW_LED_COUNT (4) // 3 RGB + 1 Yellow +#define MICROPY_HW_LED_PULLUP (1) // RGB LED is active low +#define MICROPY_HW_LED4_PULLUP (0) // Yellow is active high +#define MICROPY_HW_LED1 (24) // RED +#define MICROPY_HW_LED2 (16) // GREEN +#define MICROPY_HW_LED3 (6) // BLUE +#define MICROPY_HW_LED4 (13) // Yellow +#define HELP_TEXT_BOARD_LED "1,2,3,4" + +// UART config +#define MICROPY_HW_UART1_TX (32 + 3) +#define MICROPY_HW_UART1_RX (32 + 10) +// #define MICROPY_HW_UART1_CTS (7) +// #define MICROPY_HW_UART1_RTS (5) +// #define MICROPY_HW_UART1_HWFC (1) + +// SPI0 config +#define MICROPY_HW_SPI0_NAME "SPI0" +#define MICROPY_HW_SPI0_SCK (13) +#define MICROPY_HW_SPI0_MOSI (32 + 1) +#define MICROPY_HW_SPI0_MISO (32 + 8) + +// PWM config +#define MICROPY_HW_PWM0_NAME "PWM0" +#define MICROPY_HW_PWM1_NAME "PWM1" +#define MICROPY_HW_PWM2_NAME "PWM2" +#define MICROPY_HW_PWM3_NAME "PWM3" + +#define MICROPY_HW_USB_VID (0x2341) +#define MICROPY_HW_USB_PID (0x025A) +#define MICROPY_HW_USB_CDC_1200BPS_TOUCH (1) + +void NANO33_board_early_init(void); +void NANO33_board_deinit(void); +void NANO33_board_enter_bootloader(void); diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.mk b/ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.mk new file mode 100644 index 0000000000..cb2ff5c6b8 --- /dev/null +++ b/ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.mk @@ -0,0 +1,12 @@ +MCU_SERIES = m4 +MCU_VARIANT = nrf52 +MCU_SUB_VARIANT = nrf52840 +SOFTDEV_VERSION = 6.1.1 +SD=s140 + +LD_FILES += boards/arduino_nano_33_ble_sense/nano_bootloader.ld boards/nrf52840_1M_256k.ld + +NRF_DEFINES += -DNRF52840_XXAA + +MICROPY_VFS_LFS2 = 1 +FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/nano_bootloader.ld b/ports/nrf/boards/arduino_nano_33_ble_sense/nano_bootloader.ld new file mode 100644 index 0000000000..209a1d447a --- /dev/null +++ b/ports/nrf/boards/arduino_nano_33_ble_sense/nano_bootloader.ld @@ -0,0 +1 @@ +_flash_start = 0xe0000; diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/pins.csv b/ports/nrf/boards/arduino_nano_33_ble_sense/pins.csv new file mode 100644 index 0000000000..9d931634f6 --- /dev/null +++ b/ports/nrf/boards/arduino_nano_33_ble_sense/pins.csv @@ -0,0 +1,50 @@ +P0,P0 +P1,P1 +P2,P2,ADC0_IN0 +P3,P3,ADC0_IN1 +P4,P4,ADC0_IN2 +P5,P5,ADC0_IN3 +P6,P6 +P7,P7 +P8,P8 +P9,P9 +P10,P10 +P11,P11 +P12,P12 +P13,P13 +P14,P14 +P15,P15 +P16,P16 +P17,P17 +P18,P18 +P19,P19 +P20,P20 +P21,P21 +P22,P22 +P23,P23 +P24,P24 +P25,P25 +P26,P26 +P27,P27 +P28,P28,ADC0_IN4 +P29,P29,ADC0_IN5 +P30,P30,ADC0_IN6 +P31,P31,ADC0_IN7 +P32,P32 +P33,P33 +P34,P34 +P35,P35 +P36,P36 +P37,P37 +P38,P38 +P39,P39 +P40,P40 +P41,P41 +P42,P42 +P43,P43 +P44,P44 +P45,P45 +P46,P46 +P47,P47 +I2C_SCL,P2 +I2C_SDA,P31 From 6753c5331832e8741e416f9c13e1abb9dbbb33ad Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Thu, 7 Jul 2022 16:56:45 +0200 Subject: [PATCH 0107/1041] nrf/modmachine: Add machine.idle() function. This improves the compatibility of the nrf port machine module with common drivers, by adding a machine.idle() alias for lightsleep. --- ports/nrf/modules/machine/modmachine.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/nrf/modules/machine/modmachine.c b/ports/nrf/modules/machine/modmachine.c index af659521e0..d322e45067 100644 --- a/ports/nrf/modules/machine/modmachine.c +++ b/ports/nrf/modules/machine/modmachine.c @@ -206,6 +206,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, + { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) }, From 474c47d5958f2a445cd28654297d418f7cc15400 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Thu, 7 Jul 2022 17:00:09 +0200 Subject: [PATCH 0108/1041] drivers/lps22h: Use machine.idle for power saving. All machine modules should have an idle function. --- drivers/lps22h/lps22h.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/lps22h/lps22h.py b/drivers/lps22h/lps22h.py index 8d90b29178..ca29efce2d 100644 --- a/drivers/lps22h/lps22h.py +++ b/drivers/lps22h/lps22h.py @@ -53,14 +53,6 @@ class LPS22H: self.addr = address self.oneshot = oneshot self.buf = bytearray(1) - - if hasattr(machine, "idle"): - self._go_idle = machine.idle() - else: - import time - - self._go_idle = lambda: time.sleep_ms(1) - # ODR=1 EN_LPFP=1 BDU=1 self._write_reg(_LPS22_CTRL_REG1, 0x1A) self.set_oneshot_mode(self.oneshot) @@ -86,7 +78,7 @@ class LPS22H: while True: if self._read_reg(_LPS22_STATUS) & b: return - self._go_idle() + machine.idle() def set_oneshot_mode(self, oneshot): self._read_reg(_LPS22_CTRL_REG1) From 7e5137e0ae6a393571c94427c2d168202941002f Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 8 Jul 2022 22:26:41 +1000 Subject: [PATCH 0109/1041] tools/pyboard.py: Add verbose option to filesystem_command. Signed-off-by: Damien George --- tools/pyboard.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/pyboard.py b/tools/pyboard.py index a9a4cbff87..7d0ab6bcd7 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -558,7 +558,7 @@ def execfile(filename, device="/dev/ttyACM0", baudrate=115200, user="micro", pas pyb.close() -def filesystem_command(pyb, args, progress_callback=None): +def filesystem_command(pyb, args, progress_callback=None, verbose=False): def fname_remote(src): if src.startswith(":"): src = src[1:] @@ -590,7 +590,8 @@ def filesystem_command(pyb, args, progress_callback=None): for src in srcs: src = fname_remote(src) dest2 = fname_cp_dest(src, dest) - print(fmt % (src, dest2)) + if verbose: + print(fmt % (src, dest2)) op(src, dest2, progress_callback=progress_callback) else: op = { @@ -604,7 +605,8 @@ def filesystem_command(pyb, args, progress_callback=None): args = [""] for src in args: src = fname_remote(src) - print("%s :%s" % (cmd, src)) + if verbose: + print("%s :%s" % (cmd, src)) op(src) except PyboardError as er: print(str(er.args[2], "ascii")) @@ -756,7 +758,7 @@ def main(): # do filesystem commands, if given if args.filesystem: - filesystem_command(pyb, args.files) + filesystem_command(pyb, args.files, verbose=True) del args.files[:] # run the command, if given From 80bc9b3dee310de86c6ca88db0edf55d8337f2c1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 8 Jul 2022 22:28:26 +1000 Subject: [PATCH 0110/1041] tools/mpremote: Don't be verbose when using cat command. Fixes issue #8828. Signed-off-by: Damien George --- tools/mpremote/mpremote/main.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/mpremote/mpremote/main.py b/tools/mpremote/mpremote/main.py index 4d74743aa3..e0266fd719 100644 --- a/tools/mpremote/mpremote/main.py +++ b/tools/mpremote/mpremote/main.py @@ -308,6 +308,9 @@ def do_filesystem(pyb, args): else: files.append(os.path.split(path)) + # Don't be verbose when using cat, so output can be redirected to something. + verbose = args[0] != "cat" + if args[0] == "cp" and args[1] == "-r": args.pop(0) args.pop(0) @@ -329,9 +332,10 @@ def do_filesystem(pyb, args): pyb, ["cp", "/".join((dir, file)), ":" + dir + "/"], progress_callback=show_progress_bar, + verbose=verbose, ) else: - pyboard.filesystem_command(pyb, args, progress_callback=show_progress_bar) + pyboard.filesystem_command(pyb, args, progress_callback=show_progress_bar, verbose=verbose) args.clear() From d7a162516e0a85ae9aa571813bb78428db56a93e Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 8 Jul 2022 22:46:51 +1000 Subject: [PATCH 0111/1041] esp32/modmachine: Fix machine.freq to allow maximum 160MHz on ESP32-C3. Fixes issue #8824. Signed-off-by: Damien George --- ports/esp32/modmachine.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index db77becf87..a70f2fbedb 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -82,8 +82,16 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { } else { // set mp_int_t freq = mp_obj_get_int(args[0]) / 1000000; - if (freq != 20 && freq != 40 && freq != 80 && freq != 160 && freq != 240) { + if (freq != 20 && freq != 40 && freq != 80 && freq != 160 + #if !CONFIG_IDF_TARGET_ESP32C3 + && freq != 240 + #endif + ) { + #if CONFIG_IDF_TARGET_ESP32C3 + mp_raise_ValueError(MP_ERROR_TEXT("frequency must be 20MHz, 40MHz, 80Mhz or 160MHz")); + #else mp_raise_ValueError(MP_ERROR_TEXT("frequency must be 20MHz, 40MHz, 80Mhz, 160MHz or 240MHz")); + #endif } #if CONFIG_IDF_TARGET_ESP32 esp_pm_config_esp32_t pm; From 9f8087b448890417d5aa86551957a2100616bb8e Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 8 Jul 2022 23:04:01 +1000 Subject: [PATCH 0112/1041] esp8266/boards: Enable reverse-special-methods on GENERIC board. It increases the firmware size by 292 bytes. Addresses issue #5897. Signed-off-by: Damien George --- ports/esp8266/boards/GENERIC_1M/mpconfigboard.h | 1 + ports/esp8266/boards/GENERIC_512K/mpconfigboard.h | 1 + ports/esp8266/mpconfigport.h | 1 - 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h b/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h index 10e8adcda7..cf5127686c 100644 --- a/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h +++ b/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h @@ -12,5 +12,6 @@ #define MICROPY_VFS (1) #define MICROPY_PY_FSTRINGS (0) +#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0) #define MICROPY_PY_UASYNCIO (0) #define MICROPY_PY_UCRYPTOLIB (1) diff --git a/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h b/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h index ef37e22fb6..b0adb7081c 100644 --- a/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h +++ b/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h @@ -6,6 +6,7 @@ #define MICROPY_PY_FSTRINGS (0) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (0) #define MICROPY_PY_ALL_SPECIAL_METHODS (0) +#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0) #define MICROPY_PY_SYS_STDIO_BUFFER (0) #define MICROPY_PY_UASYNCIO (0) #define MICROPY_PY_URE_SUB (0) diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index c78ae3ce0b..7727f7845a 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -26,7 +26,6 @@ #define MICROPY_PY_BUILTINS_STR_PARTITION (0) #define MICROPY_PY_BUILTINS_STR_SPLITLINES (0) #define MICROPY_PY_BUILTINS_SLICE_INDICES (0) -#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0) #define MICROPY_PY_BUILTINS_COMPILE (0) #define MICROPY_PY_BUILTINS_EXECFILE (0) #define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (0) From 9af6a275dd2bbb8a815e27e1e61c3f4547a44da0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 6 Jul 2022 21:26:42 +1000 Subject: [PATCH 0113/1041] stm32/boardctrl: Allow boards to override fatal-error handler. To override it a board must define MICROPY_BOARD_FATAL_ERROR to a function that takes a string message and does not return. Signed-off-by: Damien George --- ports/stm32/boardctrl.c | 22 ++++++++++++++++++++++ ports/stm32/boardctrl.h | 5 +++++ ports/stm32/main.c | 26 +++----------------------- ports/stm32/modmachine.c | 3 +-- ports/stm32/pybthread.c | 7 +++---- ports/stm32/sdram.c | 9 ++++----- ports/stm32/stm32_it.c | 9 ++++----- ports/stm32/system_stm32.c | 17 ++++++++--------- ports/stm32/uart.c | 4 +--- 9 files changed, 51 insertions(+), 51 deletions(-) diff --git a/ports/stm32/boardctrl.c b/ports/stm32/boardctrl.c index 02a3759991..406a983814 100644 --- a/ports/stm32/boardctrl.c +++ b/ports/stm32/boardctrl.c @@ -24,6 +24,8 @@ * THE SOFTWARE. */ +#include + #include "py/runtime.h" #include "py/objstr.h" #include "py/mphal.h" @@ -33,6 +35,26 @@ #include "led.h" #include "usrsw.h" +NORETURN void boardctrl_fatal_error(const char *msg) { + for (volatile uint delay = 0; delay < 10000000; delay++) { + } + led_state(1, 1); + led_state(2, 1); + led_state(3, 1); + led_state(4, 1); + mp_hal_stdout_tx_strn("\nFATAL ERROR:\n", 14); + mp_hal_stdout_tx_strn(msg, strlen(msg)); + for (uint i = 0;;) { + led_toggle(((i++) & 3) + 1); + for (volatile uint delay = 0; delay < 10000000; delay++) { + } + if (i >= 16) { + // to conserve power + __WFI(); + } + } +} + STATIC void flash_error(int n) { for (int i = 0; i < n; i++) { led_state(PYB_LED_RED, 1); diff --git a/ports/stm32/boardctrl.h b/ports/stm32/boardctrl.h index afd4ab8510..8f4ce30eff 100644 --- a/ports/stm32/boardctrl.h +++ b/ports/stm32/boardctrl.h @@ -33,6 +33,10 @@ #define MICROPY_BOARD_PENDSV_ENTRIES #endif +#ifndef MICROPY_BOARD_FATAL_ERROR +#define MICROPY_BOARD_FATAL_ERROR boardctrl_fatal_error +#endif + #ifndef MICROPY_BOARD_STARTUP #define MICROPY_BOARD_STARTUP powerctrl_check_enter_bootloader #endif @@ -110,6 +114,7 @@ typedef struct _boardctrl_state_t { bool log_soft_reset; } boardctrl_state_t; +NORETURN void boardctrl_fatal_error(const char *msg); void boardctrl_maybe_enter_mboot(size_t n_args, const void *args); void boardctrl_before_soft_reset_loop(boardctrl_state_t *state); void boardctrl_top_soft_reset_loop(boardctrl_state_t *state); diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 875584be8a..54d9b05be1 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -97,41 +97,21 @@ STATIC pyb_uart_obj_t pyb_uart_repl_obj; STATIC uint8_t pyb_uart_repl_rxbuf[MICROPY_HW_UART_REPL_RXBUF]; #endif -void NORETURN __fatal_error(const char *msg) { - for (volatile uint delay = 0; delay < 10000000; delay++) { - } - led_state(1, 1); - led_state(2, 1); - led_state(3, 1); - led_state(4, 1); - mp_hal_stdout_tx_strn("\nFATAL ERROR:\n", 14); - mp_hal_stdout_tx_strn(msg, strlen(msg)); - for (uint i = 0;;) { - led_toggle(((i++) & 3) + 1); - for (volatile uint delay = 0; delay < 10000000; delay++) { - } - if (i >= 16) { - // to conserve power - __WFI(); - } - } -} - void nlr_jump_fail(void *val) { printf("FATAL: uncaught exception %p\n", val); mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(val)); - __fatal_error(""); + MICROPY_BOARD_FATAL_ERROR(""); } void abort(void) { - __fatal_error("abort"); + MICROPY_BOARD_FATAL_ERROR("abort"); } #ifndef NDEBUG void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { (void)func; printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); - __fatal_error(""); + MICROPY_BOARD_FATAL_ERROR(""); } #endif diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index 34e78d2616..acedac7a59 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -339,8 +339,7 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { if (ret == -MP_EINVAL) { mp_raise_ValueError(MP_ERROR_TEXT("invalid freq")); } else if (ret < 0) { - void NORETURN __fatal_error(const char *msg); - __fatal_error("can't change freq"); + MICROPY_BOARD_FATAL_ERROR("can't change freq"); } return mp_const_none; #endif diff --git a/ports/stm32/pybthread.c b/ports/stm32/pybthread.c index 603bc2e4ec..3af0112fad 100644 --- a/ports/stm32/pybthread.c +++ b/ports/stm32/pybthread.c @@ -28,6 +28,7 @@ #include #include "py/obj.h" +#include "boardctrl.h" #include "gccollect.h" #include "irq.h" #include "pybthread.h" @@ -42,8 +43,6 @@ #define RAISE_IRQ_PRI() raise_irq_pri(IRQ_PRI_PENDSV) #define RESTORE_IRQ_PRI(state) restore_irq_pri(state) -extern void __fatal_error(const char *); - volatile int pyb_thread_enabled; pyb_thread_t *volatile pyb_thread_all; pyb_thread_t *volatile pyb_thread_cur; @@ -57,7 +56,7 @@ static inline void pyb_thread_add_to_runable(pyb_thread_t *thread) { static inline void pyb_thread_remove_from_runable(pyb_thread_t *thread) { if (thread->run_next == thread) { - __fatal_error("deadlock"); + MICROPY_BOARD_FATAL_ERROR("deadlock"); } thread->run_prev->run_next = thread->run_next; thread->run_next->run_prev = thread->run_prev; @@ -112,7 +111,7 @@ STATIC void pyb_thread_terminate(void) { SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; enable_irq(irq_state); // should not return - __fatal_error("could not terminate"); + MICROPY_BOARD_FATAL_ERROR("could not terminate"); } uint32_t pyb_thread_new(pyb_thread_t *thread, void *stack, size_t stack_len, void *entry, void *arg) { diff --git a/ports/stm32/sdram.c b/ports/stm32/sdram.c index 4ca79f270c..65a949770e 100644 --- a/ports/stm32/sdram.c +++ b/ports/stm32/sdram.c @@ -50,7 +50,6 @@ #ifdef FMC_SDRAM_BANK static void sdram_init_seq(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *command); -extern void __fatal_error(const char *msg); bool sdram_init(void) { SDRAM_HandleTypeDef hsdram; @@ -325,7 +324,7 @@ bool __attribute__((optimize("Os"))) sdram_test(bool exhaustive) { snprintf(error_buffer, sizeof(error_buffer), "Data bus test failed at 0x%p expected 0x%x found 0x%lx", &mem_base[0], (1 << i), ((volatile uint32_t *)mem_base)[0]); - __fatal_error(error_buffer); + MICROPY_BOARD_FATAL_ERROR(error_buffer); #endif return false; } @@ -340,7 +339,7 @@ bool __attribute__((optimize("Os"))) sdram_test(bool exhaustive) { snprintf(error_buffer, sizeof(error_buffer), "Address bus test failed at 0x%p expected 0x%x found 0x%x", &mem_base[i], pattern, mem_base[i]); - __fatal_error(error_buffer); + MICROPY_BOARD_FATAL_ERROR(error_buffer); #endif return false; } @@ -355,7 +354,7 @@ bool __attribute__((optimize("Os"))) sdram_test(bool exhaustive) { snprintf(error_buffer, sizeof(error_buffer), "Address bus overlap at 0x%p expected 0x%x found 0x%x", &mem_base[i], pattern, mem_base[i]); - __fatal_error(error_buffer); + MICROPY_BOARD_FATAL_ERROR(error_buffer); #endif return false; } @@ -376,7 +375,7 @@ bool __attribute__((optimize("Os"))) sdram_test(bool exhaustive) { snprintf(error_buffer, sizeof(error_buffer), "Address bus slow test failed at 0x%p expected 0x%x found 0x%x", &mem_base[i], ((i % 2) ? pattern : antipattern), mem_base[i]); - __fatal_error(error_buffer); + MICROPY_BOARD_FATAL_ERROR(error_buffer); #endif return false; } diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index 55c772efb4..2f89f67deb 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -83,7 +83,6 @@ #include "i2c.h" #include "usb.h" -extern void __fatal_error(const char *); #if defined(MICROPY_HW_USB_FS) extern PCD_HandleTypeDef pcd_fs_handle; #endif @@ -192,7 +191,7 @@ void HardFault_C_Handler(ExceptionRegisters_t *regs) { /* Go to infinite loop when Hard Fault exception occurs */ while (1) { - __fatal_error("HardFault"); + MICROPY_BOARD_FATAL_ERROR("HardFault"); } } @@ -246,7 +245,7 @@ void NMI_Handler(void) { void MemManage_Handler(void) { /* Go to infinite loop when Memory Manage exception occurs */ while (1) { - __fatal_error("MemManage"); + MICROPY_BOARD_FATAL_ERROR("MemManage"); } } @@ -258,7 +257,7 @@ void MemManage_Handler(void) { void BusFault_Handler(void) { /* Go to infinite loop when Bus Fault exception occurs */ while (1) { - __fatal_error("BusFault"); + MICROPY_BOARD_FATAL_ERROR("BusFault"); } } @@ -270,7 +269,7 @@ void BusFault_Handler(void) { void UsageFault_Handler(void) { /* Go to infinite loop when Usage Fault exception occurs */ while (1) { - __fatal_error("UsageFault"); + MICROPY_BOARD_FATAL_ERROR("UsageFault"); } } diff --git a/ports/stm32/system_stm32.c b/ports/stm32/system_stm32.c index e67c32738c..08f071cd27 100644 --- a/ports/stm32/system_stm32.c +++ b/ports/stm32/system_stm32.c @@ -76,12 +76,11 @@ */ #include "py/mphal.h" +#include "boardctrl.h" #include "powerctrl.h" #if defined(STM32F4) || defined(STM32F7) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) -void __fatal_error(const char *msg); - /** * @brief System Clock Configuration * @@ -390,7 +389,7 @@ MP_WEAK void SystemClock_Config(void) { #endif if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - __fatal_error("HAL_RCC_OscConfig"); + MICROPY_BOARD_FATAL_ERROR("HAL_RCC_OscConfig"); } #if defined(MICROPY_HW_CLK_PLL2M) @@ -478,20 +477,20 @@ MP_WEAK void SystemClock_Config(void) { #endif if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { - __fatal_error("HAL_RCCEx_PeriphCLKConfig"); + MICROPY_BOARD_FATAL_ERROR("HAL_RCCEx_PeriphCLKConfig"); } #endif // defined(STM32H7) #if defined(STM32F7) /* Activate the OverDrive to reach the 200 MHz Frequency */ if (HAL_PWREx_EnableOverDrive() != HAL_OK) { - __fatal_error("HAL_PWREx_EnableOverDrive"); + MICROPY_BOARD_FATAL_ERROR("HAL_PWREx_EnableOverDrive"); } #endif #if defined(STM32G4) if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_8) != HAL_OK) { - __fatal_error("HAL_RCC_ClockConfig"); + MICROPY_BOARD_FATAL_ERROR("HAL_RCC_ClockConfig"); } PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC12 @@ -503,14 +502,14 @@ MP_WEAK void SystemClock_Config(void) { PeriphClkInitStruct.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK; PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { - __fatal_error("HAL_RCCEx_PeriphCLKConfig"); + MICROPY_BOARD_FATAL_ERROR("HAL_RCCEx_PeriphCLKConfig"); } #else uint32_t vco_out = RCC_OscInitStruct.PLL.PLLN * (MICROPY_HW_CLK_VALUE / 1000000) / RCC_OscInitStruct.PLL.PLLM; uint32_t sysclk_mhz = vco_out / RCC_OscInitStruct.PLL.PLLP; bool need_pll48 = vco_out % 48 != 0; if (powerctrl_rcc_clock_config_pll(&RCC_ClkInitStruct, sysclk_mhz, need_pll48) != 0) { - __fatal_error("HAL_RCC_ClockConfig"); + MICROPY_BOARD_FATAL_ERROR("HAL_RCC_ClockConfig"); } #endif @@ -572,7 +571,7 @@ MP_WEAK void SystemClock_Config(void) { | RCC_PLLSAI1_ADC1CLK; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { - __fatal_error("HAL_RCCEx_PeriphCLKConfig"); + MICROPY_BOARD_FATAL_ERROR("HAL_RCCEx_PeriphCLKConfig"); } __PWR_CLK_ENABLE(); diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index adcbe88368..34d8246d5f 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -112,8 +112,6 @@ #endif -extern void NORETURN __fatal_error(const char *msg); - typedef struct _pyb_uart_irq_map_t { uint16_t irq_en; uint16_t flag; @@ -152,7 +150,7 @@ void uart_init0(void) { RCC_PeriphClkInit.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2; RCC_PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1; if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit) != HAL_OK) { - __fatal_error("HAL_RCCEx_PeriphCLKConfig"); + MICROPY_BOARD_FATAL_ERROR("HAL_RCCEx_PeriphCLKConfig"); } #endif } From 1329155b969386623200feff776e87336bf8e2e7 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 11 Jul 2022 14:47:46 +1000 Subject: [PATCH 0114/1041] stm32/sdram: Include boardctrl.h for fatal-error handler. Signed-off-by: Damien George --- ports/stm32/sdram.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/stm32/sdram.c b/ports/stm32/sdram.c index 65a949770e..a94b802ea4 100644 --- a/ports/stm32/sdram.c +++ b/ports/stm32/sdram.c @@ -11,6 +11,7 @@ #include #include "py/runtime.h" #include "py/mphal.h" +#include "boardctrl.h" #include "pin.h" #include "pin_static_af.h" #include "mpu.h" From 8db99f11a7da84e29c2e9b37e9f224ab424d73e1 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 1 Jul 2022 11:22:24 +1000 Subject: [PATCH 0115/1041] py/scheduler: De-inline and fix race with pending exception / scheduler. The optimisation that allows a single check in the VM for either a pending exception or non-empty scheduler queue doesn't work when threading is enabled, as one thread can clear the sched_state if it has no pending exception, meaning the thread with the pending exception will never see it. This removes that optimisation for threaded builds. Also fixes a race in non-scheduler builds where get-and-clear of the pending exception is not protected by the atomic section. Also removes the bulk of the inlining of pending exceptions and scheduler handling from the VM. This just costs code size and complexity at no performance benefit. Signed-off-by: Jim Mussared --- py/runtime.h | 1 - py/scheduler.c | 85 ++++++++++++++++++++++++++++---------------------- py/vm.c | 50 ++++++++++++++--------------- 3 files changed, 70 insertions(+), 66 deletions(-) diff --git a/py/runtime.h b/py/runtime.h index 4393fbfa82..779b66f2bd 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -76,7 +76,6 @@ void mp_deinit(void); void mp_sched_exception(mp_obj_t exc); void mp_sched_keyboard_interrupt(void); void mp_handle_pending(bool raise_exc); -void mp_handle_pending_tail(mp_uint_t atomic_state); #if MICROPY_ENABLE_SCHEDULER void mp_sched_lock(void); diff --git a/py/scheduler.c b/py/scheduler.c index 3966da2975..e8ad4e4f17 100644 --- a/py/scheduler.c +++ b/py/scheduler.c @@ -32,7 +32,11 @@ // sources such as interrupts and UNIX signal handlers). void MICROPY_WRAP_MP_SCHED_EXCEPTION(mp_sched_exception)(mp_obj_t exc) { MP_STATE_MAIN_THREAD(mp_pending_exception) = exc; - #if MICROPY_ENABLE_SCHEDULER + + #if MICROPY_ENABLE_SCHEDULER && !MICROPY_PY_THREAD + // Optimisation for the case where we have scheduler but no threading. + // Allows the VM to do a single check to exclude both pending exception + // and queued tasks. if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) { MP_STATE_VM(sched_state) = MP_SCHED_PENDING; } @@ -62,33 +66,17 @@ static inline bool mp_sched_empty(void) { return mp_sched_num_pending() == 0; } -// A variant of this is inlined in the VM at the pending exception check -void mp_handle_pending(bool raise_exc) { - if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { - mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); - // Re-check state is still pending now that we're in the atomic section. - if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { - mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception); - if (obj != MP_OBJ_NULL) { - MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL; - if (!mp_sched_num_pending()) { - MP_STATE_VM(sched_state) = MP_SCHED_IDLE; - } - if (raise_exc) { - MICROPY_END_ATOMIC_SECTION(atomic_state); - nlr_raise(obj); - } - } - mp_handle_pending_tail(atomic_state); - } else { - MICROPY_END_ATOMIC_SECTION(atomic_state); - } +static inline void mp_sched_run_pending(void) { + mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); + if (MP_STATE_VM(sched_state) != MP_SCHED_PENDING) { + // Something else (e.g. hard IRQ) locked the scheduler while we + // acquired the lock. + MICROPY_END_ATOMIC_SECTION(atomic_state); + return; } -} -// This function should only be called by mp_handle_pending, -// or by the VM's inlined version of that function. -void mp_handle_pending_tail(mp_uint_t atomic_state) { + // Equivalent to mp_sched_lock(), but we're already in the atomic + // section and know that we're pending. MP_STATE_VM(sched_state) = MP_SCHED_LOCKED; #if MICROPY_SCHEDULER_STATIC_NODES @@ -118,14 +106,21 @@ void mp_handle_pending_tail(mp_uint_t atomic_state) { MICROPY_END_ATOMIC_SECTION(atomic_state); } + // Restore MP_STATE_VM(sched_state) to idle (or pending if there are still + // tasks in the queue). mp_sched_unlock(); } +// Locking the scheduler prevents tasks from executing (does not prevent new +// tasks from being added). We lock the scheduler while executing scheduled +// tasks and also in hard interrupts or GC finalisers. void mp_sched_lock(void) { mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); if (MP_STATE_VM(sched_state) < 0) { + // Already locked, increment lock (recursive lock). --MP_STATE_VM(sched_state); } else { + // Pending or idle. MP_STATE_VM(sched_state) = MP_SCHED_LOCKED; } MICROPY_END_ATOMIC_SECTION(atomic_state); @@ -135,12 +130,17 @@ void mp_sched_unlock(void) { mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); assert(MP_STATE_VM(sched_state) < 0); if (++MP_STATE_VM(sched_state) == 0) { - // vm became unlocked - if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL - #if MICROPY_SCHEDULER_STATIC_NODES - || MP_STATE_VM(sched_head) != NULL + // Scheduler became unlocked. Check if there are still tasks in the + // queue and set sched_state accordingly. + if ( + #if !MICROPY_PY_THREAD + // See optimisation in mp_sched_exception. + MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL || #endif - || mp_sched_num_pending()) { + #if MICROPY_SCHEDULER_STATIC_NODES + MP_STATE_VM(sched_head) != NULL || + #endif + mp_sched_num_pending()) { MP_STATE_VM(sched_state) = MP_SCHED_PENDING; } else { MP_STATE_VM(sched_state) = MP_SCHED_IDLE; @@ -196,17 +196,26 @@ bool mp_sched_schedule_node(mp_sched_node_t *node, mp_sched_callback_t callback) } #endif -#else // MICROPY_ENABLE_SCHEDULER +#endif // MICROPY_ENABLE_SCHEDULER -// A variant of this is inlined in the VM at the pending exception check +// Called periodically from the VM or from "waiting" code (e.g. sleep) to +// process background tasks and pending exceptions (e.g. KeyboardInterrupt). void mp_handle_pending(bool raise_exc) { if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) { + mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception); - MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL; - if (raise_exc) { - nlr_raise(obj); + if (obj != MP_OBJ_NULL) { + MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL; + if (raise_exc) { + MICROPY_END_ATOMIC_SECTION(atomic_state); + nlr_raise(obj); + } } + MICROPY_END_ATOMIC_SECTION(atomic_state); } + #if MICROPY_ENABLE_SCHEDULER + if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { + mp_sched_run_pending(); + } + #endif } - -#endif // MICROPY_ENABLE_SCHEDULER diff --git a/py/vm.c b/py/vm.c index 5a624e91f3..ce1e293186 100644 --- a/py/vm.c +++ b/py/vm.c @@ -1295,41 +1295,37 @@ yield: #endif pending_exception_check: + // We've just done a branch, use this as a convenient point to + // run periodic code/checks and/or bounce the GIL.. i.e. + // not _every_ instruction but on average a branch should + // occur every few instructions. MICROPY_VM_HOOK_LOOP + // Check for pending exceptions or scheduled tasks to run. + // Note: it's safe to just call mp_handle_pending(true), but + // we can inline the check for the common case where there is + // neither. + if ( #if MICROPY_ENABLE_SCHEDULER - // This is an inlined variant of mp_handle_pending - if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { - mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); - // Re-check state is still pending now that we're in the atomic section. - if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { - MARK_EXC_IP_SELECTIVE(); - mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception); - if (obj != MP_OBJ_NULL) { - MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL; - if (!mp_sched_num_pending()) { - MP_STATE_VM(sched_state) = MP_SCHED_IDLE; - } - MICROPY_END_ATOMIC_SECTION(atomic_state); - RAISE(obj); - } - mp_handle_pending_tail(atomic_state); - } else { - MICROPY_END_ATOMIC_SECTION(atomic_state); - } - } + #if MICROPY_PY_THREAD + // Scheduler + threading: Scheduler and pending exceptions are independent, check both. + MP_STATE_VM(sched_state) == MP_SCHED_PENDING || MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL #else - // This is an inlined variant of mp_handle_pending - if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) { - MARK_EXC_IP_SELECTIVE(); - mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception); - MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL; - RAISE(obj); - } + // Scheduler + non-threading: Optimisation: pending exception sets sched_state, only check sched_state. + MP_STATE_VM(sched_state) == MP_SCHED_PENDING #endif + #else + // No scheduler: Just check pending exception. + MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL + #endif + ) { + MARK_EXC_IP_SELECTIVE(); + mp_handle_pending(true); + } #if MICROPY_PY_THREAD_GIL #if MICROPY_PY_THREAD_GIL_VM_DIVISOR + // Don't bounce the GIL too frequently (default every 32 branches). if (--gil_divisor == 0) #endif { From 158f1794e87e7860f500622762ec14403ac32f03 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 6 Jul 2022 16:03:16 +1000 Subject: [PATCH 0116/1041] py/vm: Document internal SELECTIVE_EXC_IP option. Signed-off-by: Jim Mussared --- py/vm.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/py/vm.c b/py/vm.c index ce1e293186..d70ae39dc9 100644 --- a/py/vm.c +++ b/py/vm.c @@ -202,14 +202,30 @@ // MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp // MP_VM_RETURN_EXCEPTION, exception in state[0] mp_vm_return_kind_t MICROPY_WRAP_MP_EXECUTE_BYTECODE(mp_execute_bytecode)(mp_code_state_t *code_state, volatile mp_obj_t inject_exc) { + #define SELECTIVE_EXC_IP (0) +// When disabled, code_state->ip is updated unconditionally during op +// dispatch, and this is subsequently used in the exception handler +// (either NLR jump or direct RAISE). This is good for code size because it +// happens in a single place but is more work than necessary, as many opcodes +// cannot raise. Enabling SELECTIVE_EXC_IP means that code_state->ip +// is "selectively" updated only during handling of opcodes that might raise. +// This costs about 360 bytes on PYBV11 for a 1-3% performance gain (e.g. 3% +// in bm_fft.py). On rp2040, there is zero code size diff for a 0-1% gain. +// (Both with computed goto enabled). #if SELECTIVE_EXC_IP -#define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } /* stores ip 1 byte past last opcode */ +// Note: Because ip has already been advanced by one byte in the dispatch, the +// value of ip here is one byte past the last opcode. +#define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } +// No need to update in dispatch. #define MARK_EXC_IP_GLOBAL() #else #define MARK_EXC_IP_SELECTIVE() -#define MARK_EXC_IP_GLOBAL() { code_state->ip = ip; } /* stores ip pointing to last opcode */ +// Immediately before dispatch, save the current ip, which will be the opcode +// about to be dispatched. +#define MARK_EXC_IP_GLOBAL() { code_state->ip = ip; } #endif + #if MICROPY_OPT_COMPUTED_GOTO #include "py/vmentrytable.h" #define DISPATCH() do { \ From daff597753e699bb9f485e69dea98f58b0c1432d Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 29 Jun 2022 14:40:41 +1000 Subject: [PATCH 0117/1041] rp2: Run USB stack task exclusively from core 0. The goal is to avoid a situation where core 1 is shut down while holding the tinyusb spinlock, which could happen during soft reset if mp_thread_deinit is called while core1 is running tud_task(). This also fixes a latent race where the two cores are competing to decrement and compare `vm_hook_divisor` with no mem fence or atomic protection -- only core0 will now do this. Signed-off-by: Jim Mussared --- ports/rp2/mpconfigport.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 53437d6c98..ef1e600824 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -238,7 +238,7 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k; #define MICROPY_HW_USBDEV_TASK_HOOK extern void tud_task(void); tud_task(); #define MICROPY_VM_HOOK_COUNT (10) #define MICROPY_VM_HOOK_INIT static uint vm_hook_divisor = MICROPY_VM_HOOK_COUNT; -#define MICROPY_VM_HOOK_POLL if (--vm_hook_divisor == 0) { \ +#define MICROPY_VM_HOOK_POLL if (get_core_num() == 0 && --vm_hook_divisor == 0) { \ vm_hook_divisor = MICROPY_VM_HOOK_COUNT; \ MICROPY_HW_USBDEV_TASK_HOOK \ } @@ -250,7 +250,7 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k; #define MICROPY_EVENT_POLL_HOOK_FAST \ do { \ - MICROPY_HW_USBDEV_TASK_HOOK \ + if (get_core_num() == 0) { MICROPY_HW_USBDEV_TASK_HOOK } \ extern void mp_handle_pending(bool); \ mp_handle_pending(true); \ } while (0) From 662dc8602bf0ab99332748d178b0e950189df9e7 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 30 Jun 2022 11:42:20 +1000 Subject: [PATCH 0118/1041] rp2: Make atomic sections suspend the other core (if active). When a flash write/erase is in progress, we need to ensure that the other core cannot be using XIP. This also implements MICROPY_BEGIN_ATOMIC_SECTION as a full mutex, which is necessary as it's used to syncronise access to things like the scheduler queue. Signed-off-by: Jim Mussared --- ports/rp2/mpconfigport.h | 9 ++++++--- ports/rp2/mpthreadport.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index ef1e600824..d022c7a289 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -30,6 +30,7 @@ #include "hardware/spi.h" #include "hardware/sync.h" #include "pico/binary_info.h" +#include "pico/multicore.h" #include "mpconfigboard.h" #if MICROPY_HW_USB_MSC #include "hardware/flash.h" @@ -225,9 +226,11 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k; // Miscellaneous settings -// TODO need to look and see if these could/should be spinlock/mutex -#define MICROPY_BEGIN_ATOMIC_SECTION() save_and_disable_interrupts() -#define MICROPY_END_ATOMIC_SECTION(state) restore_interrupts(state) +// Entering a critical section. +extern uint32_t mp_thread_begin_atomic_section(void); +extern void mp_thread_end_atomic_section(uint32_t); +#define MICROPY_BEGIN_ATOMIC_SECTION() mp_thread_begin_atomic_section() +#define MICROPY_END_ATOMIC_SECTION(state) mp_thread_end_atomic_section(state) // Prevent the "lwIP task" from running when unsafe to do so. #define MICROPY_PY_LWIP_ENTER lwip_lock_acquire(); diff --git a/ports/rp2/mpthreadport.c b/ports/rp2/mpthreadport.c index 187f74bb57..252f7b01fa 100644 --- a/ports/rp2/mpthreadport.c +++ b/ports/rp2/mpthreadport.c @@ -36,16 +36,52 @@ extern uint8_t __StackTop, __StackBottom; void *core_state[2]; +// This will be non-NULL while Python code is execting. STATIC void *(*core1_entry)(void *) = NULL; + STATIC void *core1_arg = NULL; STATIC uint32_t *core1_stack = NULL; STATIC size_t core1_stack_num_words = 0; +// Thread mutex. +STATIC mp_thread_mutex_t atomic_mutex; + +uint32_t mp_thread_begin_atomic_section(void) { + if (core1_entry) { + // When both cores are executing, we also need to provide + // full mutual exclusion. + mp_thread_mutex_lock(&atomic_mutex, 1); + // In case this atomic section is for flash access, then + // suspend the other core. + multicore_lockout_start_blocking(); + } + + return save_and_disable_interrupts(); +} + +void mp_thread_end_atomic_section(uint32_t state) { + restore_interrupts(state); + + if (core1_entry) { + multicore_lockout_end_blocking(); + mp_thread_mutex_unlock(&atomic_mutex); + } +} + +// Initialise threading support. void mp_thread_init(void) { + assert(get_core_num() == 0); + + mp_thread_mutex_init(&atomic_mutex); + + // Allow MICROPY_BEGIN_ATOMIC_SECTION to be invoked from core1. + multicore_lockout_victim_init(); + mp_thread_set_state(&mp_state_ctx.thread); core1_entry = NULL; } +// Shutdown threading support -- stops the second thread. void mp_thread_deinit(void) { assert(get_core_num() == 0); // Must ensure that core1 is not currently holding the GC lock, otherwise @@ -69,9 +105,13 @@ void mp_thread_gc_others(void) { } STATIC void core1_entry_wrapper(void) { + // Allow MICROPY_BEGIN_ATOMIC_SECTION to be invoked from core0. + multicore_lockout_victim_init(); + if (core1_entry) { core1_entry(core1_arg); } + core1_entry = NULL; // returning from here will loop the core forever (WFI) } From c5563aa024c60c6da1ebe79e97f2307b49999499 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 11 Jul 2022 10:45:04 +1000 Subject: [PATCH 0119/1041] rp2/mpconfigport: Make networking options consistent across boards. Enable the same set of networking features on boards with wifi/ethernet. Signed-off-by: Jim Mussared --- .../mpconfigboard.h | 7 +----- ports/rp2/boards/PICO_W/mpconfigboard.h | 3 +-- .../boards/W5100S_EVB_PICO/mpconfigboard.h | 4 +--- ports/rp2/mpconfigport.h | 22 +++++++++++++++++++ 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h index 3f18596155..87b9187659 100644 --- a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h +++ b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h @@ -4,13 +4,8 @@ #define MICROPY_HW_BOARD_NAME "Arduino Nano RP2040 Connect" #define MICROPY_HW_FLASH_STORAGE_BYTES (8 * 1024 * 1024) -// Enable networking and sockets. +// Enable networking. #define MICROPY_PY_NETWORK (1) -#define MICROPY_PY_USOCKET (1) -#define MICROPY_PY_WEBREPL (1) -#define MICROPY_PY_UWEBSOCKET (1) -#define MICROPY_PY_UHASHLIB_SHA1 (1) -#define MICROPY_PY_OS_DUPTERM (1) // Disable internal error numbers. #define MICROPY_USE_INTERNAL_ERRNO (0) diff --git a/ports/rp2/boards/PICO_W/mpconfigboard.h b/ports/rp2/boards/PICO_W/mpconfigboard.h index f467234fbe..43a9fbafa7 100644 --- a/ports/rp2/boards/PICO_W/mpconfigboard.h +++ b/ports/rp2/boards/PICO_W/mpconfigboard.h @@ -4,9 +4,8 @@ // todo: We need something to check our binary size #define MICROPY_HW_FLASH_STORAGE_BYTES (848 * 1024) +// Enable networking. #define MICROPY_PY_NETWORK 1 -#define MICROPY_PY_USOCKET 1 -#define MICROPY_PY_USSL 1 // CYW43 driver configuration. #define CYW43_USE_SPI (1) diff --git a/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.h b/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.h index 3816e40138..ca2f7d0cea 100644 --- a/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.h +++ b/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.h @@ -4,10 +4,8 @@ #define MICROPY_HW_BOARD_NAME "W5100S-EVB-Pico" #define MICROPY_HW_FLASH_STORAGE_BYTES (1408 * 1024) -// Enable networking and sockets. +// Enable networking. #define MICROPY_PY_NETWORK (1) -#define MICROPY_PY_USOCKET (1) -#define MICROPY_PY_USSL (1) // Wiznet HW config. #define MICROPY_HW_WIZNET_SPI_ID (0) diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index d022c7a289..1a63476c7c 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -155,6 +155,28 @@ struct _mp_bluetooth_nimble_malloc_t; #define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE #endif +// By default networking should include sockets, ssl, websockets, webrepl, dupterm. +#if MICROPY_PY_NETWORK +#ifndef MICROPY_PY_USOCKET +#define MICROPY_PY_USOCKET (1) +#endif +#ifndef MICROPY_PY_USSL +#define MICROPY_PY_USSL (1) +#endif +#ifndef MICROPY_PY_UWEBSOCKET +#define MICROPY_PY_UWEBSOCKET (1) +#endif +#ifndef MICROPY_PY_UHASHLIB_SHA1 +#define MICROPY_PY_UHASHLIB_SHA1 (1) +#endif +#ifndef MICROPY_PY_WEBREPL +#define MICROPY_PY_WEBREPL (1) +#endif +#ifndef MICROPY_PY_OS_DUPTERM +#define MICROPY_PY_OS_DUPTERM (1) +#endif +#endif + #if MICROPY_PY_NETWORK_CYW43 extern const struct _mp_obj_type_t mp_network_cyw43_type; #define MICROPY_HW_NIC_CYW43 \ From 9f0f7e34c7fa718c9d40897f2ba6ffabc62a1480 Mon Sep 17 00:00:00 2001 From: Peter Harper Date: Thu, 30 Jun 2022 15:35:23 +0100 Subject: [PATCH 0120/1041] rp2/mphalport: Fix missing storage_read_blocks symbol in debug build. When building `make BOARD=PICO_W DEBUG=1` the cyw43-driver requires storage_read_blocks(). Signed-off-by: Peter Harper --- ports/rp2/mphalport.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ports/rp2/mphalport.c b/ports/rp2/mphalport.c index d3824d8f91..63ff76f5d9 100644 --- a/ports/rp2/mphalport.c +++ b/ports/rp2/mphalport.c @@ -204,3 +204,8 @@ void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest) { *dest++ = hexchr[mac[chr_off >> 1] >> (4 * (1 - (chr_off & 1))) & 0xf]; } } + +// Shouldn't be used, needed by cyw43-driver in debug build. +uint32_t storage_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { + panic_unsupported(); +} From e1282556e82ed470941a845af447065502a2c5ad Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 7 Jul 2022 16:35:45 +0100 Subject: [PATCH 0121/1041] shared/netutils/dhcpserver: Match default DNS to server IP. Change the default DNS to match the gateway IP of a board running in access point mode (or otherwise acting as a "server"). This fixes the rather meaningless use of "8.8.8.8" as the default DNS server address offered up to access point clients via the DHCP server. Since most devices wont be able to proxy access to the real "8.8.8.8". It allows for a DNS responder to run and provide a catchall response for captive portal functionality, or just a quality-of-life response to a friendly URL for access-point based configuration and other applications. Signed-off-by: Phil Howard --- shared/netutils/dhcpserver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/netutils/dhcpserver.c b/shared/netutils/dhcpserver.c index 9db42b3fd9..ea5718d114 100644 --- a/shared/netutils/dhcpserver.c +++ b/shared/netutils/dhcpserver.c @@ -65,7 +65,7 @@ #define PORT_DHCP_SERVER (67) #define PORT_DHCP_CLIENT (68) -#define DEFAULT_DNS MAKE_IP4(8, 8, 8, 8) +#define DEFAULT_DNS MAKE_IP4(192, 168, 4, 1) #define DEFAULT_LEASE_TIME_S (24 * 60 * 60) // in seconds #define MAC_LEN (6) From 9714a0ead5c74649d676986836ee27fb418aac9e Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 9 Jul 2022 00:05:59 +1000 Subject: [PATCH 0122/1041] py/emitnative: Fix STORE_ATTR viper code-gen when value is not a pyobj. There was a missing call to MP_F_CONVERT_NATIVE_TO_OBJ. Signed-off-by: Jim Mussared --- py/emitnative.c | 14 ++++++++++--- tests/micropython/viper_storeattr.py | 25 ++++++++++++++++++++++++ tests/micropython/viper_storeattr.py.exp | 4 ++++ 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 tests/micropython/viper_storeattr.py create mode 100644 tests/micropython/viper_storeattr.py.exp diff --git a/py/emitnative.c b/py/emitnative.c index 957e713fdd..7e98ba1556 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -1683,10 +1683,18 @@ STATIC void emit_native_store_global(emit_t *emit, qstr qst, int kind) { } STATIC void emit_native_store_attr(emit_t *emit, qstr qst) { - vtype_kind_t vtype_base, vtype_val; - emit_pre_pop_reg_reg(emit, &vtype_base, REG_ARG_1, &vtype_val, REG_ARG_3); // arg1 = base, arg3 = value + vtype_kind_t vtype_base; + vtype_kind_t vtype_val = peek_vtype(emit, 1); + if (vtype_val == VTYPE_PYOBJ) { + emit_pre_pop_reg_reg(emit, &vtype_base, REG_ARG_1, &vtype_val, REG_ARG_3); // arg1 = base, arg3 = value + } else { + emit_access_stack(emit, 2, &vtype_val, REG_ARG_1); // arg1 = value + emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, vtype_val, REG_ARG_2); // arg2 = type + ASM_MOV_REG_REG(emit->as, REG_ARG_3, REG_RET); // arg3 = value (converted) + emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base + adjust_stack(emit, -1); // pop value + } assert(vtype_base == VTYPE_PYOBJ); - assert(vtype_val == VTYPE_PYOBJ); emit_call_with_qstr_arg(emit, MP_F_STORE_ATTR, qst, REG_ARG_2); // arg2 = attribute name emit_post(emit); } diff --git a/tests/micropython/viper_storeattr.py b/tests/micropython/viper_storeattr.py new file mode 100644 index 0000000000..65f68b6e22 --- /dev/null +++ b/tests/micropython/viper_storeattr.py @@ -0,0 +1,25 @@ +# test storing an attribute with a value of different viper types + + +class X: + def __str__(self): + return "X" + + +x = X() + + +@micropython.viper +def a(): + x.i0 = 0 + x.i7 = 7 + x.s = "hello" + x.o = x + + +a() + +print(x.i0) +print(x.i7) +print(x.s) +print(x.o) diff --git a/tests/micropython/viper_storeattr.py.exp b/tests/micropython/viper_storeattr.py.exp new file mode 100644 index 0000000000..8e6a6cfda9 --- /dev/null +++ b/tests/micropython/viper_storeattr.py.exp @@ -0,0 +1,4 @@ +0 +7 +hello +X From 093c4b6b2681951a277c71453598a9e0e2a82f52 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 10 Feb 2022 13:15:14 -0600 Subject: [PATCH 0123/1041] unix/main: Restore tty settings on nlr_jump_fail(). Since nlr_jump_fail() exits the process, it can leave the terminal in raw mode which means characters are not echoed. Fix this by restoring the original terminal mode. Signed-off-by: David Lechner --- ports/unix/main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ports/unix/main.c b/ports/unix/main.c index 0e00db7fa2..e7048dd712 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -737,6 +737,9 @@ MP_NOINLINE int main_(int argc, char **argv) { } void nlr_jump_fail(void *val) { + #if MICROPY_USE_READLINE == 1 + mp_hal_stdio_mode_orig(); + #endif fprintf(stderr, "FATAL: uncaught NLR %p\n", val); exit(1); } From d84220b8c62003b4714e0fa514a46ff5139148dc Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 21 Jun 2022 18:11:19 +1000 Subject: [PATCH 0124/1041] py/vm: Remove check for ip being NULL when handling StopIteration. This check for code_state->ip being NULL was added in a7c02c4538bb2b986efb1999e00da4d76345767d with a commit message that "When generator raises exception, it is automatically terminated (by setting its code_state.ip to 0)". It was also added without any tests to test for this particular case. (The commit did mention that CPython's test_pep380.py triggered a bug, but upon re-running this test it did not show any need for this NULL check of code_state->ip.) It is true that generators that have completed (either by running to their end or raising an exception) set "code_state.ip = 0". But there is an explicit check at the start of mp_obj_gen_resume() to return immediately for any attempt to resume an already-stopped generator. So the VM can never execute a generator with NULL ip (and this was true at the time of the above-referenced commit). Furthermore, the other parts of the VM just before and after this piece of code do require (or at least assume) code_state->ip is non-NULL. Signed-off-by: Damien George --- py/vm.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/py/vm.c b/py/vm.c index d70ae39dc9..9157fc7d1e 100644 --- a/py/vm.c +++ b/py/vm.c @@ -1375,22 +1375,20 @@ exception_handler: #endif if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) { - if (code_state->ip) { - // check if it's a StopIteration within a for block - if (*code_state->ip == MP_BC_FOR_ITER) { - const byte *ip = code_state->ip + 1; - DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward - code_state->ip = ip + ulab; // jump to after for-block - code_state->sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator - goto outer_dispatch_loop; // continue with dispatch loop - } else if (*code_state->ip == MP_BC_YIELD_FROM) { - // StopIteration inside yield from call means return a value of - // yield from, so inject exception's value as yield from's result - // (Instead of stack pop then push we just replace exhausted gen with value) - *code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val)); - code_state->ip++; // yield from is over, move to next instruction - goto outer_dispatch_loop; // continue with dispatch loop - } + // check if it's a StopIteration within a for block + if (*code_state->ip == MP_BC_FOR_ITER) { + const byte *ip = code_state->ip + 1; + DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward + code_state->ip = ip + ulab; // jump to after for-block + code_state->sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator + goto outer_dispatch_loop; // continue with dispatch loop + } else if (*code_state->ip == MP_BC_YIELD_FROM) { + // StopIteration inside yield from call means return a value of + // yield from, so inject exception's value as yield from's result + // (Instead of stack pop then push we just replace exhausted gen with value) + *code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val)); + code_state->ip++; // yield from is over, move to next instruction + goto outer_dispatch_loop; // continue with dispatch loop } } From 893a5c83412d75c1da8c429d4809650660c2ee94 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 12 Jul 2022 22:41:10 +1000 Subject: [PATCH 0125/1041] py/vm: In YIELD_FROM opcode, expand helper macros and remove them. The GENERATOR_EXIT_IF_NEEDED macro is only used once and it's easier to read and understand the code if this macro body is written in the code. Then the comment just before it makes more sense. Signed-off-by: Damien George --- py/vm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/py/vm.c b/py/vm.c index 9157fc7d1e..80e271845f 100644 --- a/py/vm.c +++ b/py/vm.c @@ -1188,9 +1188,6 @@ yield: ENTRY(MP_BC_YIELD_FROM): { MARK_EXC_IP_SELECTIVE(); -//#define EXC_MATCH(exc, type) mp_obj_is_type(exc, type) -#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type) -#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { mp_obj_t raise_t = mp_make_raise_obj(t); RAISE(raise_t); } mp_vm_return_kind_t ret_kind; mp_obj_t send_value = POP(); mp_obj_t t_exc = MP_OBJ_NULL; @@ -1214,11 +1211,14 @@ yield: SET_TOP(ret_value); // If we injected GeneratorExit downstream, then even // if it was swallowed, we re-raise GeneratorExit - GENERATOR_EXIT_IF_NEEDED(t_exc); + if (t_exc != MP_OBJ_NULL && mp_obj_exception_match(t_exc, MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { + mp_obj_t raise_t = mp_make_raise_obj(t_exc); + RAISE(raise_t); + } DISPATCH(); } else { assert(ret_kind == MP_VM_RETURN_EXCEPTION); - assert(!EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))); + assert(!mp_obj_exception_match(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))); // Pop exhausted gen sp--; RAISE(ret_value); From b878fc042f6441d4a10af6f6cee897330f89d8d9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 12 Jul 2022 22:46:35 +1000 Subject: [PATCH 0126/1041] py/vm: Consistently indent #if guards to match the code they surround. Signed-off-by: Damien George --- py/vm.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/py/vm.c b/py/vm.c index 80e271845f..9273dda02e 100644 --- a/py/vm.c +++ b/py/vm.c @@ -307,14 +307,14 @@ outer_dispatch_loop: // loop to execute byte code for (;;) { dispatch_loop: -#if MICROPY_OPT_COMPUTED_GOTO + #if MICROPY_OPT_COMPUTED_GOTO DISPATCH(); -#else + #else TRACE(ip); MARK_EXC_IP_GLOBAL(); TRACE_TICK(ip, sp, false); switch (*ip++) { -#endif + #endif ENTRY(MP_BC_LOAD_CONST_FALSE): PUSH(mp_const_false); @@ -831,7 +831,7 @@ unwind_jump:; mp_obj_dict_store(sp[0], sp[2], sp[1]); DISPATCH(); -#if MICROPY_PY_BUILTINS_SET + #if MICROPY_PY_BUILTINS_SET ENTRY(MP_BC_BUILD_SET): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; @@ -839,9 +839,9 @@ unwind_jump:; SET_TOP(mp_obj_new_set(unum, sp)); DISPATCH(); } -#endif + #endif -#if MICROPY_PY_BUILTINS_SLICE + #if MICROPY_PY_BUILTINS_SLICE ENTRY(MP_BC_BUILD_SLICE): { MARK_EXC_IP_SELECTIVE(); mp_obj_t step = mp_const_none; @@ -854,7 +854,7 @@ unwind_jump:; SET_TOP(mp_obj_new_slice(start, stop, step)); DISPATCH(); } -#endif + #endif ENTRY(MP_BC_STORE_COMP): { MARK_EXC_IP_SELECTIVE(); @@ -1248,7 +1248,7 @@ yield: mp_import_all(POP()); DISPATCH(); -#if MICROPY_OPT_COMPUTED_GOTO + #if MICROPY_OPT_COMPUTED_GOTO ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI): PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - MP_BC_LOAD_CONST_SMALL_INT_MULTI_EXCESS)); DISPATCH(); @@ -1276,7 +1276,7 @@ yield: ENTRY_DEFAULT: MARK_EXC_IP_SELECTIVE(); -#else + #else ENTRY_DEFAULT: if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + MP_BC_LOAD_CONST_SMALL_INT_MULTI_NUM) { PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - MP_BC_LOAD_CONST_SMALL_INT_MULTI_EXCESS)); @@ -1296,9 +1296,8 @@ yield: SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs)); DISPATCH(); } else -#endif + #endif // MICROPY_OPT_COMPUTED_GOTO { - mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, MP_ERROR_TEXT("opcode")); nlr_pop(); code_state->state[0] = obj; @@ -1306,9 +1305,9 @@ yield: return MP_VM_RETURN_EXCEPTION; } -#if !MICROPY_OPT_COMPUTED_GOTO + #if !MICROPY_OPT_COMPUTED_GOTO } // switch -#endif + #endif pending_exception_check: // We've just done a branch, use this as a convenient point to From 74794d42b8870d9f3990b18816aedce85402e106 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 12 Jul 2022 21:26:31 +1000 Subject: [PATCH 0127/1041] rp2/CMakeLists: Use armv6m mpy-cross arch for rp2. Commit 0e28a1f0e5e229f14b199a30d1796770b232f5a1 made it possible to set -march=armv6m. It needs to be used when freezing for rp2. Signed-off-by: Jim Mussared --- ports/rp2/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 6314bfb44d..202261f9c1 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -323,7 +323,7 @@ list(APPEND MICROPY_SOURCE_QSTR ) # Define mpy-cross flags -set(MICROPY_CROSS_FLAGS -march=armv7m) +set(MICROPY_CROSS_FLAGS -march=armv6m) # Set the frozen manifest file if (MICROPY_USER_FROZEN_MANIFEST) From 2076f2efccfd86977f63de15958c142365c31f3b Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Tue, 12 Jul 2022 22:48:39 +0200 Subject: [PATCH 0128/1041] tools/autobuild: Add nrf port to autobuild scripts. --- tools/autobuild/autobuild.sh | 2 ++ tools/autobuild/build-boards.sh | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/tools/autobuild/autobuild.sh b/tools/autobuild/autobuild.sh index 569f729d1f..2094601516 100755 --- a/tools/autobuild/autobuild.sh +++ b/tools/autobuild/autobuild.sh @@ -74,6 +74,8 @@ cd ../esp32 (source ${IDF_PATH_V44}/export.sh && build_esp32_boards ${FW_TAG} ${LOCAL_FIRMWARE}) cd ../mimxrt build_mimxrt_boards ${FW_TAG} ${LOCAL_FIRMWARE} +cd ../nrf +build_nrf_boards ${FW_TAG} ${LOCAL_FIRMWARE} cd ../renesas-ra build_renesas_ra_boards ${FW_TAG} ${LOCAL_FIRMWARE} cd ../rp2 diff --git a/tools/autobuild/build-boards.sh b/tools/autobuild/build-boards.sh index 9caadc1b07..b3d2f8c4c5 100755 --- a/tools/autobuild/build-boards.sh +++ b/tools/autobuild/build-boards.sh @@ -103,6 +103,10 @@ function build_mimxrt_boards { build_boards modmimxrt.c $1 $2 bin hex } +function build_nrf_boards { + build_boards nrfx_glue.h $1 $2 bin hex +} + function build_renesas_ra_boards { build_boards ra_it.c $1 $2 hex } From 5bf3765631e645412dbd62a616cfdadeca5ea0c3 Mon Sep 17 00:00:00 2001 From: Lars Haulin Date: Fri, 8 Jul 2022 17:48:40 +0200 Subject: [PATCH 0129/1041] py/objnamedtuple: Fix segfault with empty namedtuple. The empty tuple is usually a constant object, but named tuples must be allocated to allow modification. Added explicit allocation to fix this. Also added a regression test to verify creating an empty named tuple works. Fixes issue #7870. Signed-off-by: Lars Haulin --- py/objnamedtuple.c | 7 ++++--- tests/basics/namedtuple1.py | 5 +++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index 214cad2572..b212993506 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -108,9 +108,10 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args, #endif } - // Create a tuple and set the type to this namedtuple - mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(num_fields, NULL)); - tuple->base.type = type_in; + // Create a namedtuple with explicit malloc. Calling mp_obj_new_tuple + // with num_fields=0 returns a read-only object. + mp_obj_tuple_t *tuple = mp_obj_malloc_var(mp_obj_tuple_t, mp_obj_t, num_fields, type_in); + tuple->len = num_fields; // Copy the positional args into the first slots of the namedtuple memcpy(&tuple->items[0], args, sizeof(mp_obj_t) * n_args); diff --git a/tests/basics/namedtuple1.py b/tests/basics/namedtuple1.py index 47c0360eb9..e8247e4d6e 100644 --- a/tests/basics/namedtuple1.py +++ b/tests/basics/namedtuple1.py @@ -85,3 +85,8 @@ print(t.foo, t.bar) # Not implemented so far #T2 = namedtuple("TupComma", "foo,bar") #t = T2(1, 2) + +# Creating an empty namedtuple should not segfault +T5 = namedtuple("TupEmpty", []) +t = T5() +print(t) From 262f4a48554358d3d5866ddbcc23169ffb202f68 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Thu, 14 Jul 2022 21:10:58 +0200 Subject: [PATCH 0130/1041] nrf/mpconfigport: Remove obsolete module declarations. External module declarations are no longer used/needed after the introduction of MP_REGISTER_MODULE. --- ports/nrf/mpconfigport.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 243c30809a..dc7c3b1ea4 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -295,14 +295,6 @@ typedef int mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size typedef long mp_off_t; -// extra built in modules to add to the list of known ones -extern const struct _mp_obj_module_t board_module; -extern const struct _mp_obj_module_t nrf_module; -extern const struct _mp_obj_module_t mp_module_utime; -extern const struct _mp_obj_module_t mp_module_uos; -extern const struct _mp_obj_module_t mp_module_ubluepy; -extern const struct _mp_obj_module_t music_module; - #if BOARD_SPECIFIC_MODULES #include "boardmodules.h" #endif // BOARD_SPECIFIC_MODULES @@ -314,7 +306,6 @@ extern const struct _mp_obj_module_t music_module; // extra constants #define MICROPY_PORT_CONSTANTS \ - { MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&board_module) }, \ { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&mp_module_machine) }, \ #define MP_STATE_PORT MP_STATE_VM From 30c7f1790b26b3b156d3143d30c37bd4c992a810 Mon Sep 17 00:00:00 2001 From: Stuart Langridge Date: Thu, 27 Jan 2022 16:56:58 +0000 Subject: [PATCH 0131/1041] nrf/drivers/bluetooth: Handle PHY_UPDATE messages, used in Bluetooth 5. Some devices, such as the LightBlue BTLE app on iOS, try to use Bluetooth 5 when connecting to a device. This means that they will send a BLE_GAP_EVT_PHY_UPDATE_REQUEST message to shift to a new physical layer. If this event isn't handled, LightBlue (and likely other Bluetooth 5.0 central devices) will try to connect and then fail, staying in "Connecting..." state forever. This message should be replied to with sd_ble_gap_phy_update, as documented in drivers/bluetooth/s140_nrf52_6.1.1/s140_nrf52_6.1.1_API/include/ble_gap.h. This commit handles the event. LightBlue can now successfully connect to a BTLE device on a P10059 nRF52840 dongle running MicroPython. Two other related events have logging added in case they are needed in the future. --- ports/nrf/drivers/bluetooth/ble_drv.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ports/nrf/drivers/bluetooth/ble_drv.c b/ports/nrf/drivers/bluetooth/ble_drv.c index 0040580933..173d3eda01 100644 --- a/ports/nrf/drivers/bluetooth/ble_drv.c +++ b/ports/nrf/drivers/bluetooth/ble_drv.c @@ -1136,6 +1136,24 @@ static void ble_evt_handler(ble_evt_t * p_ble_evt) { sd_ble_gap_data_length_update(p_ble_evt->evt.gap_evt.conn_handle, NULL, NULL); break; + case BLE_GAP_EVT_PHY_UPDATE_REQUEST: + BLE_DRIVER_LOG("BLE_GAP_EVT_PHY_UPDATE_REQUEST\n"); + ble_gap_phys_t const phys = + { + BLE_GAP_PHY_AUTO, + BLE_GAP_PHY_AUTO, + }; + sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys); + break; + + case BLE_GAP_EVT_PHY_UPDATE: + BLE_DRIVER_LOG("BLE_GAP_EVT_PHY_UPDATE -- unhandled!\n"); + break; + + case BLE_GAP_EVT_DATA_LENGTH_UPDATE: + BLE_DRIVER_LOG("BLE_GAP_EVT_DATA_LENGTH_UPDATE -- unhandled!\n"); + break; + #endif // (BLUETOOTH_SD == 132) || (BLUETOOTH_SD == 140) default: From 60539ea162a15d38d974ee58f7c5430c565cf0eb Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 7 Jul 2022 21:19:28 +0200 Subject: [PATCH 0132/1041] nrf/drivers/usb: Probe for interrupt char in USB CDC task. And ensure that the input queue is empty when scheduling the interrupt. --- ports/nrf/drivers/bluetooth/ble_uart.c | 2 +- ports/nrf/drivers/usb/usb_cdc.c | 10 +++++++++- ports/nrf/modules/machine/uart.c | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ports/nrf/drivers/bluetooth/ble_uart.c b/ports/nrf/drivers/bluetooth/ble_uart.c index c3712fe8c9..3020f1af62 100644 --- a/ports/nrf/drivers/bluetooth/ble_uart.c +++ b/ports/nrf/drivers/bluetooth/ble_uart.c @@ -193,9 +193,9 @@ STATIC void gatts_event_handler(mp_obj_t self_in, uint16_t event_id, uint16_t at for (uint16_t i = 0; i < length; i++) { #if MICROPY_KBD_EXCEPTION if (data[i] == mp_interrupt_char) { - mp_sched_keyboard_interrupt(); m_rx_ring_buffer.start = 0; m_rx_ring_buffer.end = 0; + mp_sched_keyboard_interrupt(); } else #endif { diff --git a/ports/nrf/drivers/usb/usb_cdc.c b/ports/nrf/drivers/usb/usb_cdc.c index a1d411a256..eda933b89f 100644 --- a/ports/nrf/drivers/usb/usb_cdc.c +++ b/ports/nrf/drivers/usb/usb_cdc.c @@ -35,6 +35,8 @@ #include "nrfx_uart.h" #include "py/ringbuf.h" #include "py/stream.h" +#include "py/runtime.h" +#include "shared/runtime/interrupt_char.h" #ifdef BLUETOOTH_SD #include "nrf_sdm.h" @@ -127,7 +129,13 @@ static void cdc_task(void) int c; uint32_t count = tud_cdc_read(&c, 1); (void)count; - ringbuf_put((ringbuf_t*)&rx_ringbuf, c); + if (c == mp_interrupt_char) { + rx_ringbuf.iget = 0; + rx_ringbuf.iput = 0; + mp_sched_keyboard_interrupt(); + } else { + ringbuf_put((ringbuf_t*)&rx_ringbuf, c); + } } int chars = 0; diff --git a/ports/nrf/modules/machine/uart.c b/ports/nrf/modules/machine/uart.c index 2cc421aa1f..e8c82e57dd 100644 --- a/ports/nrf/modules/machine/uart.c +++ b/ports/nrf/modules/machine/uart.c @@ -128,6 +128,8 @@ STATIC void uart_event_handler(nrfx_uart_event_t const *p_event, void *p_context nrfx_uart_rx(self->p_uart, &self->buf->rx_buf[0], 1); #if !MICROPY_PY_BLE_NUS && MICROPY_KBD_EXCEPTION if (chr == mp_interrupt_char) { + self->buf->rx_ringbuf.iget = 0; + self->buf->rx_ringbuf.iput = 0; mp_sched_keyboard_interrupt(); } else #endif From c985a0b5148cf51c400a53b692f570daf89d9810 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 8 Jul 2022 14:26:53 +0200 Subject: [PATCH 0133/1041] nrf/drivers/usb: Add a tud_cdc_rx_cb() callback to check interrupt char. --- ports/nrf/drivers/usb/usb_cdc.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/ports/nrf/drivers/usb/usb_cdc.c b/ports/nrf/drivers/usb/usb_cdc.c index eda933b89f..06071fe119 100644 --- a/ports/nrf/drivers/usb/usb_cdc.c +++ b/ports/nrf/drivers/usb/usb_cdc.c @@ -46,7 +46,7 @@ extern void tusb_hal_nrf_power_event(uint32_t event); -static void cdc_task(void); +static void cdc_task(bool tx); static uint8_t rx_ringbuf_array[1024]; static uint8_t tx_ringbuf_array[1024]; @@ -121,7 +121,7 @@ static int cdc_tx_char(void) { return ringbuf_get((ringbuf_t*)&tx_ringbuf); } -static void cdc_task(void) +static void cdc_task(bool tx) { if ( tud_cdc_connected() ) { // connected and there are data available @@ -138,24 +138,30 @@ static void cdc_task(void) } } - int chars = 0; - while (cdc_tx_any()) { - if (chars < 64) { - tud_cdc_write_char(cdc_tx_char()); - chars++; - } else { - chars = 0; - tud_cdc_write_flush(); + if (tx) { + int chars = 0; + while (cdc_tx_any()) { + if (chars < 64) { + tud_cdc_write_char(cdc_tx_char()); + chars++; + } else { + chars = 0; + tud_cdc_write_flush(); + } } - } - tud_cdc_write_flush(); + tud_cdc_write_flush(); + } } } static void usb_cdc_loop(void) { tud_task(); - cdc_task(); + cdc_task(true); +} + +void tud_cdc_rx_cb(uint8_t itf) { + cdc_task(false); } int usb_cdc_init(void) From be6f0f3b3b99820d8aef835a8c2af1a1baaed049 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 9 Jul 2022 08:54:29 +0200 Subject: [PATCH 0134/1041] nrf/mpconfigport: Call tud_task() in MICROPY_EVENT_POLL_HOOK. So that the interrupt character can interrupt a long-running loop, like a sleep. --- ports/nrf/mpconfigport.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index dc7c3b1ea4..0698a52cef 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -346,8 +346,15 @@ typedef long mp_off_t; /* micro:bit root pointers */ \ void *async_data[2]; \ +#if MICROPY_HW_USB_CDC +#define MICROPY_HW_USBDEV_TASK_HOOK extern void tud_task(void); tud_task(); +#else +#define MICROPY_HW_USBDEV_TASK_HOOK ; +#endif + #define MICROPY_EVENT_POLL_HOOK \ do { \ + MICROPY_HW_USBDEV_TASK_HOOK \ extern void mp_handle_pending(bool); \ mp_handle_pending(true); \ __WFI(); \ From cca2305211688df0e13a14f67f1eaf67d9cb267e Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 12 Jul 2022 22:51:32 +0200 Subject: [PATCH 0135/1041] nrf/drivers/usb: Fix reading of a single USB CDC character. --- ports/nrf/drivers/usb/usb_cdc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ports/nrf/drivers/usb/usb_cdc.c b/ports/nrf/drivers/usb/usb_cdc.c index 06071fe119..16d69fff66 100644 --- a/ports/nrf/drivers/usb/usb_cdc.c +++ b/ports/nrf/drivers/usb/usb_cdc.c @@ -126,9 +126,7 @@ static void cdc_task(bool tx) if ( tud_cdc_connected() ) { // connected and there are data available while (tud_cdc_available()) { - int c; - uint32_t count = tud_cdc_read(&c, 1); - (void)count; + int c = tud_cdc_read_char(); if (c == mp_interrupt_char) { rx_ringbuf.iget = 0; rx_ringbuf.iput = 0; From 6670281472aa3c931b08e623488a02c335aeda20 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Sat, 16 Jul 2022 16:47:41 +0300 Subject: [PATCH 0136/1041] py/misc: Add MP_STATIC_ASSERT_NOT_MSC(). To be used in cases where the condition of the assert does not compile under msvc. Signed-off-by: Yonatan Goldschmidt --- py/misc.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/py/misc.h b/py/misc.h index d94afd0b0d..b7b6146abc 100644 --- a/py/misc.h +++ b/py/misc.h @@ -52,6 +52,11 @@ typedef unsigned int uint; // Static assertion macro #define MP_STATIC_ASSERT(cond) ((void)sizeof(char[1 - 2 * !(cond)])) +#if defined(_MSC_VER) +#define MP_STATIC_ASSERT_NOT_MSC(cond) (1) +#else +#define MP_STATIC_ASSERT_NOT_MSC(cond) MP_STATIC_ASSERT(cond) +#endif // Round-up integer division #define MP_CEIL_DIVIDE(a, b) (((a) + (b) - 1) / (b)) From 2a6ba47110be88ff1e1f5abd1bd76c353447884c Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Wed, 22 Jan 2020 13:34:19 +0100 Subject: [PATCH 0137/1041] py/obj: Add static safety checks to mp_obj_is_type(). Commit d96cfd13e3a464862c introduced a regression by breaking existing users of mp_obj_is_type(.., &mp_obj_bool). This function (and associated helpers like mp_obj_is_int()) have some specific nuances, and mistakes like this one can happen again. This commit adds mp_obj_is_exact_type() which behaves like the the old mp_obj_is_type(). The new mp_obj_is_type() has the same prototype but it attempts to statically assert that it's not called with types which should be checked using mp_obj_is_type(). If called with any of these types: int, str, bool, NoneType - it will cause a compilation error. Additional checked types (e.g function types) can be added in the future. Existing users of mp_obj_is_type() with the now "invalid" types, were translated to use mp_obj_is_exact_type(). The use of MP_STATIC_ASSERT() is not bulletproof - usually GCC (and other compilers) can't statically check conditions that are only known during link-time (like variables' addresses comparison). However, in this case, GCC is able to statically detect these conditions, probably because it's the exact same object - `&mp_type_int == &mp_type_int` is detected. Misuses of this function with runtime-chosen types (e.g: `mp_obj_type_t *x = ...; mp_obj_is_type(..., x);` won't be detected. MSC is unable to detect this, so we use MP_STATIC_ASSERT_NOT_MSC(). Compiling with this commit and without the fix for d96cfd13e3a464862c shows that it detects the problem. Signed-off-by: Yonatan Goldschmidt --- py/binary.c | 4 ++-- py/map.c | 2 +- py/obj.c | 8 ++++---- py/obj.h | 22 ++++++++++++++++++---- py/objexcept.c | 2 +- py/objfun.c | 2 +- py/objint.c | 2 +- py/objint_longlong.c | 8 ++++---- py/objint_mpz.c | 10 +++++----- py/objstr.c | 2 +- 10 files changed, 38 insertions(+), 24 deletions(-) diff --git a/py/binary.c b/py/binary.c index 05e658c952..f59e89ca48 100644 --- a/py/binary.c +++ b/py/binary.c @@ -334,7 +334,7 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p #endif default: #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE - if (mp_obj_is_type(val_in, &mp_type_int)) { + if (mp_obj_is_exact_type(val_in, &mp_type_int)) { mp_obj_int_to_bytes_impl(val_in, struct_type == '>', size, p); return; } @@ -371,7 +371,7 @@ void mp_binary_set_val_array(char typecode, void *p, size_t index, mp_obj_t val_ break; default: #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE - if (mp_obj_is_type(val_in, &mp_type_int)) { + if (mp_obj_is_exact_type(val_in, &mp_type_int)) { size_t size = mp_binary_get_size('@', typecode, NULL); mp_obj_int_to_bytes_impl(val_in, MP_ENDIANNESS_BIG, size, (uint8_t *)p + index * size); diff --git a/py/map.c b/py/map.c index b194250cb4..7a6f2233e6 100644 --- a/py/map.c +++ b/py/map.c @@ -174,7 +174,7 @@ mp_map_elem_t *MICROPY_WRAP_MP_MAP_LOOKUP(mp_map_lookup)(mp_map_t * map, mp_obj_ if (compare_only_ptrs) { if (mp_obj_is_qstr(index)) { // Index is a qstr, so can just do ptr comparison. - } else if (mp_obj_is_type(index, &mp_type_str)) { + } else if (mp_obj_is_exact_type(index, &mp_type_str)) { // Index is a non-interned string. // We can either intern the string, or force a full equality comparison. // We chose the latter, since interning costs time and potentially RAM, diff --git a/py/obj.c b/py/obj.c index 024de3c96c..51f6d85def 100644 --- a/py/obj.c +++ b/py/obj.c @@ -304,7 +304,7 @@ mp_int_t mp_obj_get_int(mp_const_obj_t arg) { return 1; } else if (mp_obj_is_small_int(arg)) { return MP_OBJ_SMALL_INT_VALUE(arg); - } else if (mp_obj_is_type(arg, &mp_type_int)) { + } else if (mp_obj_is_exact_type(arg, &mp_type_int)) { return mp_obj_int_get_checked(arg); } else { mp_obj_t res = mp_unary_op(MP_UNARY_OP_INT, (mp_obj_t)arg); @@ -330,7 +330,7 @@ bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value) { *value = 1; } else if (mp_obj_is_small_int(arg)) { *value = MP_OBJ_SMALL_INT_VALUE(arg); - } else if (mp_obj_is_type(arg, &mp_type_int)) { + } else if (mp_obj_is_exact_type(arg, &mp_type_int)) { *value = mp_obj_int_get_checked(arg); } else { return false; @@ -349,7 +349,7 @@ bool mp_obj_get_float_maybe(mp_obj_t arg, mp_float_t *value) { } else if (mp_obj_is_small_int(arg)) { val = (mp_float_t)MP_OBJ_SMALL_INT_VALUE(arg); #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE - } else if (mp_obj_is_type(arg, &mp_type_int)) { + } else if (mp_obj_is_exact_type(arg, &mp_type_int)) { val = mp_obj_int_as_float_impl(arg); #endif } else if (mp_obj_is_float(arg)) { @@ -389,7 +389,7 @@ bool mp_obj_get_complex_maybe(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) *real = (mp_float_t)MP_OBJ_SMALL_INT_VALUE(arg); *imag = 0; #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE - } else if (mp_obj_is_type(arg, &mp_type_int)) { + } else if (mp_obj_is_exact_type(arg, &mp_type_int)) { *real = mp_obj_int_as_float_impl(arg); *imag = 0; #endif diff --git a/py/obj.h b/py/obj.h index 84ca94213c..ea3d2db706 100644 --- a/py/obj.h +++ b/py/obj.h @@ -743,15 +743,29 @@ void *mp_obj_malloc_helper(size_t num_bytes, const mp_obj_type_t *type); // check for more specific object types. // Note: these are kept as macros because inline functions sometimes use much // more code space than the equivalent macros, depending on the compiler. -#define mp_obj_is_type(o, t) (mp_obj_is_obj(o) && (((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type == (t))) // this does not work for checking int, str or fun; use below macros for that +// don't use mp_obj_is_exact_type directly; use mp_obj_is_type which provides additional safety checks. +// use the former only if you need to bypass these checks (because you've already checked everything else) +#define mp_obj_is_exact_type(o, t) (mp_obj_is_obj(o) && (((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type == (t))) + +// Type checks are split to a separate, constant result macro. This is so it doesn't hinder the compilers's +// optimizations (other tricks like using ({ expr; exper; }) or (exp, expr, expr) in mp_obj_is_type() result +// in missed optimizations) +#define mp_type_assert_not_bool_int_str_nonetype(t) ( \ + MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_bool), \ + MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_int), \ + MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_str), \ + MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_NoneType), \ + 1) + +#define mp_obj_is_type(o, t) (mp_type_assert_not_bool_int_str_nonetype(t) && mp_obj_is_exact_type(o, t)) #if MICROPY_OBJ_IMMEDIATE_OBJS // bool's are immediates, not real objects, so test for the 2 possible values. #define mp_obj_is_bool(o) ((o) == mp_const_false || (o) == mp_const_true) #else -#define mp_obj_is_bool(o) mp_obj_is_type(o, &mp_type_bool) +#define mp_obj_is_bool(o) mp_obj_is_exact_type(o, &mp_type_bool) #endif -#define mp_obj_is_int(o) (mp_obj_is_small_int(o) || mp_obj_is_type(o, &mp_type_int)) -#define mp_obj_is_str(o) (mp_obj_is_qstr(o) || mp_obj_is_type(o, &mp_type_str)) +#define mp_obj_is_int(o) (mp_obj_is_small_int(o) || mp_obj_is_exact_type(o, &mp_type_int)) +#define mp_obj_is_str(o) (mp_obj_is_qstr(o) || mp_obj_is_exact_type(o, &mp_type_str)) #define mp_obj_is_str_or_bytes(o) (mp_obj_is_qstr(o) || (mp_obj_is_obj(o) && ((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type->binary_op == mp_obj_str_binary_op)) #define mp_obj_is_dict_or_ordereddict(o) (mp_obj_is_obj(o) && ((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type->make_new == mp_obj_dict_make_new) #define mp_obj_is_fun(o) (mp_obj_is_obj(o) && (((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type->name == MP_QSTR_function)) diff --git a/py/objexcept.c b/py/objexcept.c index dca287bb6e..028b73fd8b 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -122,7 +122,7 @@ STATIC mp_obj_exception_t *get_native_exception(mp_obj_t self_in) { STATIC void decompress_error_text_maybe(mp_obj_exception_t *o) { #if MICROPY_ROM_TEXT_COMPRESSION - if (o->args->len == 1 && mp_obj_is_type(o->args->items[0], &mp_type_str)) { + if (o->args->len == 1 && mp_obj_is_exact_type(o->args->items[0], &mp_type_str)) { mp_obj_str_t *o_str = MP_OBJ_TO_PTR(o->args->items[0]); if (MP_IS_COMPRESSED_ROM_STRING(o_str->data)) { byte *buf = m_new_maybe(byte, MP_MAX_UNCOMPRESSED_TEXT_LEN + 1); diff --git a/py/objfun.c b/py/objfun.c index 37c1eaa549..5fa9d71dda 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -468,7 +468,7 @@ STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { return 0; } else if (obj == mp_const_true) { return 1; - } else if (mp_obj_is_type(obj, &mp_type_int)) { + } else if (mp_obj_is_exact_type(obj, &mp_type_int)) { return mp_obj_int_get_truncated(obj); } else if (mp_obj_is_str(obj)) { // pointer to the string (it's probably constant though!) diff --git a/py/objint.c b/py/objint.c index 5ff5e7de4b..740e7ea948 100644 --- a/py/objint.c +++ b/py/objint.c @@ -232,7 +232,7 @@ char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_co // A small int; get the integer value to format. num = MP_OBJ_SMALL_INT_VALUE(self_in); } else { - assert(mp_obj_is_type(self_in, &mp_type_int)); + assert(mp_obj_is_exact_type(self_in, &mp_type_int)); // Not a small int. #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG const mp_obj_int_t *self = self_in; diff --git a/py/objint_longlong.c b/py/objint_longlong.c index 7fcb5462f8..1c07588367 100644 --- a/py/objint_longlong.c +++ b/py/objint_longlong.c @@ -58,7 +58,7 @@ mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf } void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) { - assert(mp_obj_is_type(self_in, &mp_type_int)); + assert(mp_obj_is_exact_type(self_in, &mp_type_int)); mp_obj_int_t *self = self_in; long long val = self->val; if (big_endian) { @@ -131,13 +131,13 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i if (mp_obj_is_small_int(lhs_in)) { lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs_in); } else { - assert(mp_obj_is_type(lhs_in, &mp_type_int)); + assert(mp_obj_is_exact_type(lhs_in, &mp_type_int)); lhs_val = ((mp_obj_int_t *)lhs_in)->val; } if (mp_obj_is_small_int(rhs_in)) { rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs_in); - } else if (mp_obj_is_type(rhs_in, &mp_type_int)) { + } else if (mp_obj_is_exact_type(rhs_in, &mp_type_int)) { rhs_val = ((mp_obj_int_t *)rhs_in)->val; } else { // delegate to generic function to check for extra cases @@ -284,7 +284,7 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { #if MICROPY_PY_BUILTINS_FLOAT mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in) { - assert(mp_obj_is_type(self_in, &mp_type_int)); + assert(mp_obj_is_exact_type(self_in, &mp_type_int)); mp_obj_int_t *self = self_in; return self->val; } diff --git a/py/objint_mpz.c b/py/objint_mpz.c index cbc4cb75a7..2811bcf2aa 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -91,7 +91,7 @@ mp_obj_int_t *mp_obj_int_new_mpz(void) { // This particular routine should only be called for the mpz representation of the int. char *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma) { - assert(mp_obj_is_type(self_in, &mp_type_int)); + assert(mp_obj_is_exact_type(self_in, &mp_type_int)); const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); size_t needed_size = mp_int_format_size(mpz_max_num_bits(&self->mpz), base, prefix, comma); @@ -113,7 +113,7 @@ mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf } void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) { - assert(mp_obj_is_type(self_in, &mp_type_int)); + assert(mp_obj_is_exact_type(self_in, &mp_type_int)); mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); mpz_as_bytes(&self->mpz, big_endian, len, buf); } @@ -181,7 +181,7 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i mpz_init_fixed_from_int(&z_int, z_int_dig, MPZ_NUM_DIG_FOR_INT, MP_OBJ_SMALL_INT_VALUE(lhs_in)); zlhs = &z_int; } else { - assert(mp_obj_is_type(lhs_in, &mp_type_int)); + assert(mp_obj_is_exact_type(lhs_in, &mp_type_int)); zlhs = &((mp_obj_int_t *)MP_OBJ_TO_PTR(lhs_in))->mpz; } @@ -189,7 +189,7 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i if (mp_obj_is_small_int(rhs_in)) { mpz_init_fixed_from_int(&z_int, z_int_dig, MPZ_NUM_DIG_FOR_INT, MP_OBJ_SMALL_INT_VALUE(rhs_in)); zrhs = &z_int; - } else if (mp_obj_is_type(rhs_in, &mp_type_int)) { + } else if (mp_obj_is_exact_type(rhs_in, &mp_type_int)) { zrhs = &((mp_obj_int_t *)MP_OBJ_TO_PTR(rhs_in))->mpz; #if MICROPY_PY_BUILTINS_FLOAT } else if (mp_obj_is_float(rhs_in)) { @@ -447,7 +447,7 @@ mp_uint_t mp_obj_int_get_uint_checked(mp_const_obj_t self_in) { #if MICROPY_PY_BUILTINS_FLOAT mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in) { - assert(mp_obj_is_type(self_in, &mp_type_int)); + assert(mp_obj_is_exact_type(self_in, &mp_type_int)); mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); return mpz_as_float(&self->mpz); } diff --git a/py/objstr.c b/py/objstr.c index 6e5a316d78..f15a2d9744 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -2144,7 +2144,7 @@ STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in) { qstr mp_obj_str_get_qstr(mp_obj_t self_in) { if (mp_obj_is_qstr(self_in)) { return MP_OBJ_QSTR_VALUE(self_in); - } else if (mp_obj_is_type(self_in, &mp_type_str)) { + } else if (mp_obj_is_exact_type(self_in, &mp_type_str)) { mp_obj_str_t *self = MP_OBJ_TO_PTR(self_in); return qstr_from_strn((char *)self->data, self->len); } else { From a8d78cc39839aaf4a77bef05377c457c7ba75ead Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Wed, 22 Jan 2020 22:21:20 +0100 Subject: [PATCH 0138/1041] py/obj: Add debug-only runtime checks to mp_obj_is_type(). Zero effect on non debug builds, and also usually optimized out even in debug builds as mp_obj_is_type() is called with a compile-time known type. I'm not sure we even have dynamic uses of mp_obj_is_type() at the moment, but if we ever will they will be protected from now on. Signed-off-by: Yonatan Goldschmidt --- py/obj.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/py/obj.h b/py/obj.h index ea3d2db706..c94d09afab 100644 --- a/py/obj.h +++ b/py/obj.h @@ -750,12 +750,12 @@ void *mp_obj_malloc_helper(size_t num_bytes, const mp_obj_type_t *type); // Type checks are split to a separate, constant result macro. This is so it doesn't hinder the compilers's // optimizations (other tricks like using ({ expr; exper; }) or (exp, expr, expr) in mp_obj_is_type() result // in missed optimizations) -#define mp_type_assert_not_bool_int_str_nonetype(t) ( \ - MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_bool), \ - MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_int), \ - MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_str), \ - MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_NoneType), \ - 1) +#define mp_type_assert_not_bool_int_str_nonetype(t) ( \ + MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_bool), assert((t) != &mp_type_bool), \ + MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_int), assert((t) != &mp_type_int), \ + MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_str), assert((t) != &mp_type_str), \ + MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_NoneType), assert((t) != &mp_type_NoneType), \ + 1) #define mp_obj_is_type(o, t) (mp_type_assert_not_bool_int_str_nonetype(t) && mp_obj_is_exact_type(o, t)) #if MICROPY_OBJ_IMMEDIATE_OBJS From fc3d7ae11be11a7f05709ebfd439061fce9ee555 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 12:29:08 -0500 Subject: [PATCH 0139/1041] py/make_root_pointers: Add MP_REGISTER_ROOT_POINTER parser/generator. This adds new compile-time infrastructure to parse source code files for `MP_REGISTER_ROOT_POINTER()` and generates a new `root_pointers.h` header file containing the collected declarations. This works the same as the existing `MP_REGISTER_MODULE()` feature. Signed-off-by: David Lechner --- ports/cc3200/bootmgr/bootloader.mk | 4 +++ ports/stm32/mboot/Makefile | 6 +++- ports/windows/msvc/genhdr.targets | 21 ++++++++++-- py/make_root_pointers.py | 55 ++++++++++++++++++++++++++++++ py/makeqstrdefs.py | 11 ++++-- py/mkrules.cmake | 30 ++++++++++++++++ py/mkrules.mk | 16 +++++++-- py/mpstate.h | 7 ++++ py/obj.h | 11 ++++-- py/py.mk | 5 +++ 10 files changed, 154 insertions(+), 12 deletions(-) create mode 100644 py/make_root_pointers.py diff --git a/ports/cc3200/bootmgr/bootloader.mk b/ports/cc3200/bootmgr/bootloader.mk index e5b817391d..3aeda062ce 100644 --- a/ports/cc3200/bootmgr/bootloader.mk +++ b/ports/cc3200/bootmgr/bootloader.mk @@ -134,3 +134,7 @@ $(HEADER_BUILD)/mpversion.h: | $(HEADER_BUILD) # Create an empty "moduledefs.h" needed by py/mkrules.mk $(HEADER_BUILD)/moduledefs.h: | $(HEADER_BUILD) touch $@ + +# Create an empty "root_pointers.h" needed by py/mkrules.mk +$(HEADER_BUILD)/root_pointers.h: | $(HEADER_BUILD) + touch $@ diff --git a/ports/stm32/mboot/Makefile b/ports/stm32/mboot/Makefile index db39daf882..4c903b4ff6 100755 --- a/ports/stm32/mboot/Makefile +++ b/ports/stm32/mboot/Makefile @@ -213,6 +213,7 @@ PREFIX_FILE = ../boards/stm32f4xx_prefix.c BOARD_PINS = $(BOARD_DIR)/pins.csv HEADER_BUILD = $(BUILD)/genhdr GEN_QSTRDEFS_GENERATED = $(HEADER_BUILD)/qstrdefs.generated.h +GEN_ROOT_POINTERS = $(HEADER_BUILD)/root_pointers.h GEN_PINS_SRC = $(BUILD)/pins_$(BOARD).c GEN_PINS_HDR = $(HEADER_BUILD)/pins.h GEN_PINS_QSTR = $(HEADER_BUILD)/pins_qstr.h @@ -220,7 +221,7 @@ GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h GEN_PINS_AF_DEFS = $(HEADER_BUILD)/pins_af_defs.h GEN_PINS_AF_PY = $(BUILD)/pins_af.py -$(OBJ): $(GEN_QSTRDEFS_GENERATED) $(GEN_PINS_AF_DEFS) +$(OBJ): $(GEN_QSTRDEFS_GENERATED) $(GEN_ROOT_POINTERS) $(GEN_PINS_AF_DEFS) $(HEADER_BUILD): $(MKDIR) -p $(BUILD)/genhdr @@ -228,6 +229,9 @@ $(HEADER_BUILD): $(GEN_QSTRDEFS_GENERATED): | $(HEADER_BUILD) $(Q)echo "// empty" > $@ +$(GEN_ROOT_POINTERS): | $(HEADER_BUILD) + $(Q)echo "// empty" > $@ + $(GEN_PINS_AF_DEFS): $(BOARD_PINS) $(MAKE_PINS) ../$(AF_FILE) $(PREFIX_FILE) | $(HEADER_BUILD) $(ECHO) "GEN $@" $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af ../$(AF_FILE) \ diff --git a/ports/windows/msvc/genhdr.targets b/ports/windows/msvc/genhdr.targets index 84520078f0..11c5eae8ae 100644 --- a/ports/windows/msvc/genhdr.targets +++ b/ports/windows/msvc/genhdr.targets @@ -4,7 +4,7 @@ - + @@ -15,6 +15,7 @@ $(DestDir)qstrdefscollected.h $(DestDir)qstrdefs.generated.h $(DestDir)/moduledefs.collected + $(DestDir)/root_pointers.collected $(MICROPY_CPYTHON3) python cl.exe @@ -45,7 +46,7 @@ using(var outFile = System.IO.File.CreateText(OutputFile)) { foreach(var inFile in InputFiles) foreach(var line in System.IO.File.ReadAllLines(inFile)) - if((line.Contains(".c") && line.StartsWith("#line")) || line.Contains("MP_QSTR")) + if((line.Contains(".c") && line.StartsWith("#line")) || line.Contains("MP_QSTR") || line.Contains("MP_REGISTER")) outFile.WriteLine( line ); } ]]> @@ -114,6 +115,20 @@ using(var outFile = System.IO.File.CreateText(OutputFile)) { + + + + + + + + $(DestDir)root_pointers.h + $(DestFile).tmp + + + + + $(QstrGen).tmp @@ -132,7 +147,7 @@ using(var outFile = System.IO.File.CreateText(OutputFile)) { - + diff --git a/py/make_root_pointers.py b/py/make_root_pointers.py new file mode 100644 index 0000000000..efe398b822 --- /dev/null +++ b/py/make_root_pointers.py @@ -0,0 +1,55 @@ +""" +This pre-processor parses a single file containing a list of +MP_REGISTER_ROOT_POINTER(variable declaration) items. + +These are used to generate a header with the required entries for +"struct _mp_state_vm_t" in py/mpstate.h +""" + +from __future__ import print_function + +import argparse +import io +import re + + +PATTERN = re.compile(r"MP_REGISTER_ROOT_POINTER\((.*?)\);") + + +def find_root_pointer_registrations(filename): + """Find any MP_REGISTER_ROOT_POINTER definitions in the provided file. + + :param str filename: path to file to check + :return: List[variable_declaration] + """ + with io.open(filename, encoding="utf-8") as c_file_obj: + return set(re.findall(PATTERN, c_file_obj.read())) + + +def generate_root_pointer_header(root_pointers): + """Generate header with root pointer entries. + + :param List[variable_declaration] root_pointers: root pointer declarations + :return: None + """ + + # Print header file for all external modules. + print("// Automatically generated by make_root_pointers.py.") + print() + + for item in root_pointers: + print(item, end=";") + print() + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("file", nargs=1, help="file with MP_REGISTER_ROOT_POINTER definitions") + args = parser.parse_args() + + root_pointers = find_root_pointer_registrations(args.file[0]) + generate_root_pointer_header(sorted(root_pointers)) + + +if __name__ == "__main__": + main() diff --git a/py/makeqstrdefs.py b/py/makeqstrdefs.py index 4c416a874a..c445d6d1fe 100644 --- a/py/makeqstrdefs.py +++ b/py/makeqstrdefs.py @@ -24,6 +24,9 @@ _MODE_COMPRESS = "compress" # Extract MP_REGISTER_MODULE(...) macros. _MODE_MODULE = "module" +# Extract MP_REGISTER_ROOT_POINTER(...) macros. +_MODE_ROOT_POINTER = "root_pointer" + def is_c_source(fname): return os.path.splitext(fname)[1] in [".c"] @@ -90,6 +93,8 @@ def process_file(f): re_match = re.compile(r'MP_COMPRESSED_ROM_TEXT\("([^"]*)"\)') elif args.mode == _MODE_MODULE: re_match = re.compile(r"MP_REGISTER_MODULE\(.*?,\s*.*?\);") + elif args.mode == _MODE_ROOT_POINTER: + re_match = re.compile(r"MP_REGISTER_ROOT_POINTER\(.*?\);") output = [] last_fname = None for line in f: @@ -111,7 +116,7 @@ def process_file(f): if args.mode == _MODE_QSTR: name = match.replace("MP_QSTR_", "") output.append("Q(" + name + ")") - elif args.mode in (_MODE_COMPRESS, _MODE_MODULE): + elif args.mode in (_MODE_COMPRESS, _MODE_MODULE, _MODE_ROOT_POINTER): output.append(match) if last_fname: @@ -148,6 +153,8 @@ def cat_together(): mode_full = "Compressed data" elif args.mode == _MODE_MODULE: mode_full = "Module registrations" + elif args.mode == _MODE_ROOT_POINTER: + mode_full = "Root pointer registrations" if old_hash != new_hash: print(mode_full, "updated") try: @@ -208,7 +215,7 @@ if __name__ == "__main__": args.output_dir = sys.argv[4] args.output_file = None if len(sys.argv) == 5 else sys.argv[5] # Unused for command=split - if args.mode not in (_MODE_QSTR, _MODE_COMPRESS, _MODE_MODULE): + if args.mode not in (_MODE_QSTR, _MODE_COMPRESS, _MODE_MODULE, _MODE_ROOT_POINTER): print("error: mode %s unrecognised" % sys.argv[2]) sys.exit(2) diff --git a/py/mkrules.cmake b/py/mkrules.cmake index 4d0bbd22ad..d7be0f934b 100644 --- a/py/mkrules.cmake +++ b/py/mkrules.cmake @@ -11,6 +11,9 @@ set(MICROPY_QSTRDEFS_GENERATED "${MICROPY_GENHDR_DIR}/qstrdefs.generated.h") set(MICROPY_MODULEDEFS_SPLIT "${MICROPY_GENHDR_DIR}/moduledefs.split") set(MICROPY_MODULEDEFS_COLLECTED "${MICROPY_GENHDR_DIR}/moduledefs.collected") set(MICROPY_MODULEDEFS "${MICROPY_GENHDR_DIR}/moduledefs.h") +set(MICROPY_ROOT_POINTERS_SPLIT "${MICROPY_GENHDR_DIR}/root_pointers.split") +set(MICROPY_ROOT_POINTERS_COLLECTED "${MICROPY_GENHDR_DIR}/root_pointers.collected") +set(MICROPY_ROOT_POINTERS "${MICROPY_GENHDR_DIR}/root_pointers.h") # Need to do this before extracting MICROPY_CPP_DEF below. Rest of frozen # manifest handling is at the end of this file. @@ -46,6 +49,7 @@ target_sources(${MICROPY_TARGET} PRIVATE ${MICROPY_MPVERSION} ${MICROPY_QSTRDEFS_GENERATED} ${MICROPY_MODULEDEFS} + ${MICROPY_ROOT_POINTERS} ) # Command to force the build of another command @@ -139,6 +143,31 @@ add_custom_command( DEPENDS ${MICROPY_MODULEDEFS_COLLECTED} ) +# Generate root_pointers.h + +add_custom_command( + OUTPUT ${MICROPY_ROOT_POINTERS_SPLIT} + COMMAND ${Python3_EXECUTABLE} ${MICROPY_PY_DIR}/makeqstrdefs.py split root_pointer ${MICROPY_GENHDR_DIR}/qstr.i.last ${MICROPY_GENHDR_DIR}/root_pointer _ + COMMAND touch ${MICROPY_ROOT_POINTERS_SPLIT} + DEPENDS ${MICROPY_QSTRDEFS_LAST} + VERBATIM + COMMAND_EXPAND_LISTS +) + +add_custom_command( + OUTPUT ${MICROPY_ROOT_POINTERS_COLLECTED} + COMMAND ${Python3_EXECUTABLE} ${MICROPY_PY_DIR}/makeqstrdefs.py cat root_pointer _ ${MICROPY_GENHDR_DIR}/root_pointer ${MICROPY_ROOT_POINTERS_COLLECTED} + DEPENDS ${MICROPY_ROOT_POINTERS_SPLIT} + VERBATIM + COMMAND_EXPAND_LISTS +) + +add_custom_command( + OUTPUT ${MICROPY_ROOT_POINTERS} + COMMAND ${Python3_EXECUTABLE} ${MICROPY_PY_DIR}/make_root_pointers.py ${MICROPY_ROOT_POINTERS_COLLECTED} > ${MICROPY_ROOT_POINTERS} + DEPENDS ${MICROPY_ROOT_POINTERS_COLLECTED} ${MICROPY_PY_DIR}/make_root_pointers.py +) + # Build frozen code if enabled if(MICROPY_FROZEN_MANIFEST) @@ -174,6 +203,7 @@ if(MICROPY_FROZEN_MANIFEST) COMMAND ${Python3_EXECUTABLE} ${MICROPY_DIR}/tools/makemanifest.py -o ${MICROPY_FROZEN_CONTENT} -v "MPY_DIR=${MICROPY_DIR}" -v "MPY_LIB_DIR=${MICROPY_LIB_DIR}" -v "PORT_DIR=${MICROPY_PORT_DIR}" -v "BOARD_DIR=${MICROPY_BOARD_DIR}" -b "${CMAKE_BINARY_DIR}" -f${MICROPY_CROSS_FLAGS} ${MICROPY_FROZEN_MANIFEST} DEPENDS MICROPY_FORCE_BUILD ${MICROPY_QSTRDEFS_GENERATED} + ${MICROPY_ROOT_POINTERS} ${MICROPY_MPYCROSS_DEPENDENCY} VERBATIM ) diff --git a/py/mkrules.mk b/py/mkrules.mk index fa1aad881b..a7c437386f 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -7,8 +7,8 @@ endif # Extra deps that need to happen before object compilation. OBJ_EXTRA_ORDER_DEPS = -# Generate moduledefs.h. -OBJ_EXTRA_ORDER_DEPS += $(HEADER_BUILD)/moduledefs.h +# Generate header files. +OBJ_EXTRA_ORDER_DEPS += $(HEADER_BUILD)/moduledefs.h $(HEADER_BUILD)/root_pointers.h ifeq ($(MICROPY_ROM_TEXT_COMPRESSION),1) # If compression is enabled, trigger the build of compressed.data.h... @@ -126,6 +126,16 @@ $(HEADER_BUILD)/moduledefs.collected: $(HEADER_BUILD)/moduledefs.split $(ECHO) "GEN $@" $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py cat module _ $(HEADER_BUILD)/module $@ +# Module definitions via MP_REGISTER_ROOT_POINTER. +$(HEADER_BUILD)/root_pointers.split: $(HEADER_BUILD)/qstr.i.last + $(ECHO) "GEN $@" + $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py split root_pointer $< $(HEADER_BUILD)/root_pointer _ + $(Q)$(TOUCH) $@ + +$(HEADER_BUILD)/root_pointers.collected: $(HEADER_BUILD)/root_pointers.split + $(ECHO) "GEN $@" + $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py cat root_pointer _ $(HEADER_BUILD)/root_pointer $@ + # Compressed error strings. $(HEADER_BUILD)/compressed.split: $(HEADER_BUILD)/qstr.i.last $(ECHO) "GEN $@" @@ -165,7 +175,7 @@ endif ifneq ($(FROZEN_MANIFEST),) # to build frozen_content.c from a manifest -$(BUILD)/frozen_content.c: FORCE $(BUILD)/genhdr/qstrdefs.generated.h | $(MICROPY_MPYCROSS_DEPENDENCY) +$(BUILD)/frozen_content.c: FORCE $(BUILD)/genhdr/qstrdefs.generated.h $(BUILD)/genhdr/root_pointers.h | $(MICROPY_MPYCROSS_DEPENDENCY) $(Q)$(MAKE_MANIFEST) -o $@ -v "MPY_DIR=$(TOP)" -v "MPY_LIB_DIR=$(MPY_LIB_DIR)" -v "PORT_DIR=$(shell pwd)" -v "BOARD_DIR=$(BOARD_DIR)" -b "$(BUILD)" $(if $(MPY_CROSS_FLAGS),-f"$(MPY_CROSS_FLAGS)",) --mpy-tool-flags="$(MPY_TOOL_FLAGS)" $(FROZEN_MANIFEST) endif diff --git a/py/mpstate.h b/py/mpstate.h index 98aa9a8498..07a4f38609 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -192,6 +192,13 @@ typedef struct _mp_state_vm_t { // include any root pointers defined by a port MICROPY_PORT_ROOT_POINTERS + // Include any root pointers registered with MP_REGISTER_ROOT_POINTER(). + #ifndef NO_QSTR + // Only include root pointer definitions when not doing qstr extraction, because + // the qstr extraction stage also generates the root pointers header file. + #include "genhdr/root_pointers.h" + #endif + // root pointers for extmod #if MICROPY_REPL_EVENT_DRIVEN diff --git a/py/obj.h b/py/obj.h index c94d09afab..7ba4c0a5f2 100644 --- a/py/obj.h +++ b/py/obj.h @@ -416,13 +416,18 @@ typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t; #define MP_DEFINE_CONST_STATICMETHOD_OBJ(obj_name, fun_name) const mp_rom_obj_static_class_method_t obj_name = {{&mp_type_staticmethod}, fun_name} #define MP_DEFINE_CONST_CLASSMETHOD_OBJ(obj_name, fun_name) const mp_rom_obj_static_class_method_t obj_name = {{&mp_type_classmethod}, fun_name} +#ifndef NO_QSTR + // Declare a module as a builtin, processed by makemoduledefs.py // param module_name: MP_QSTR_ // param obj_module: mp_obj_module_t instance - -#ifndef NO_QSTR #define MP_REGISTER_MODULE(module_name, obj_module) -#endif + +// Declare a root pointer (to avoid garbage collection of a global static variable). +// param variable_declaration: a valid C variable declaration +#define MP_REGISTER_ROOT_POINTER(variable_declaration) + +#endif // NO_QSTR // Underlying map/hash table implementation (not dict object or map function) diff --git a/py/py.mk b/py/py.mk index dacfa1bd06..8aac460b47 100644 --- a/py/py.mk +++ b/py/py.mk @@ -218,6 +218,11 @@ $(HEADER_BUILD)/moduledefs.h: $(HEADER_BUILD)/moduledefs.collected @$(ECHO) "GEN $@" $(Q)$(PYTHON) $(PY_SRC)/makemoduledefs.py $< > $@ +# build a list of registered root pointers for py/mpstate.h. +$(HEADER_BUILD)/root_pointers.h: $(HEADER_BUILD)/root_pointers.collected $(PY_SRC)/make_root_pointers.py + @$(ECHO) "GEN $@" + $(Q)$(PYTHON) $(PY_SRC)/make_root_pointers.py $< > $@ + # Standard C functions like memset need to be compiled with special flags so # the compiler does not optimise these functions in terms of themselves. CFLAGS_BUILTIN ?= -ffreestanding -fno-builtin -fno-lto From 81dbea1ce3c27a609a9b27caadd12cceef86a907 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 14:06:10 -0500 Subject: [PATCH 0140/1041] shared/readline: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register the readline_history root pointer array used by shared/readline.c and removes the registration from all mpconfigport.h files. This also required adding a new MICROPY_READLINE_HISTORY_SIZE config option since not all ports used the same sized array. Signed-off-by: David Lechner --- docs/develop/porting.rst | 3 --- examples/embedding/mpconfigport_minimal.h | 2 -- ports/cc3200/mpconfigport.h | 1 - ports/esp32/mpconfigport.h | 1 - ports/esp8266/mpconfigport.h | 1 - ports/javascript/Makefile | 2 +- ports/javascript/mpconfigport.h | 3 --- ports/mimxrt/Makefile | 1 + ports/mimxrt/mpconfigport.h | 1 - ports/minimal/Makefile | 1 + ports/minimal/mpconfigport.h | 3 --- ports/nrf/mpconfigport.h | 1 - ports/pic16bit/mpconfigport.h | 1 - ports/powerpc/Makefile | 2 ++ ports/powerpc/mpconfigport.h | 3 --- ports/renesas-ra/mpconfigport.h | 2 -- ports/rp2/CMakeLists.txt | 1 + ports/rp2/mpconfigport.h | 1 - ports/samd/Makefile | 1 + ports/samd/mpconfigport.h | 3 --- ports/stm32/mpconfigport.h | 2 -- ports/teensy/mpconfigport.h | 1 - ports/unix/mpconfigport.h | 4 +++- ports/windows/mpconfigport.h | 12 ++++++------ ports/zephyr/mpconfigport.h | 1 - ports/zephyr/mpconfigport_minimal.h | 3 --- py/mpconfig.h | 5 +++++ shared/readline/readline.c | 15 ++++++++++----- 28 files changed, 31 insertions(+), 46 deletions(-) diff --git a/docs/develop/porting.rst b/docs/develop/porting.rst index 3d0553205c..0511f5d276 100644 --- a/docs/develop/porting.rst +++ b/docs/develop/porting.rst @@ -174,9 +174,6 @@ The following is an example of an ``mpconfigport.h`` file: #define MP_STATE_PORT MP_STATE_VM - #define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; - This configuration file contains machine-specific configurations including aspects like if different MicroPython features should be enabled e.g. ``#define MICROPY_ENABLE_GC (1)``. Making this Setting ``(0)`` disables the feature. diff --git a/examples/embedding/mpconfigport_minimal.h b/examples/embedding/mpconfigport_minimal.h index 6cc84dcbc1..91b194bc7b 100644 --- a/examples/embedding/mpconfigport_minimal.h +++ b/examples/embedding/mpconfigport_minimal.h @@ -87,8 +87,6 @@ #define MICROPY_PY_UHASHLIB (0) #define MICROPY_PY_UBINASCII (0) -#define MICROPY_PORT_ROOT_POINTERS \ - ////////////////////////////////////////// // Do not change anything beyond this line ////////////////////////////////////////// diff --git a/ports/cc3200/mpconfigport.h b/ports/cc3200/mpconfigport.h index 58ec80a9f5..ce708cb3f4 100644 --- a/ports/cc3200/mpconfigport.h +++ b/ports/cc3200/mpconfigport.h @@ -142,7 +142,6 @@ // vm state and root pointers for the gc #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; \ mp_obj_t mp_const_user_interrupt; \ mp_obj_t machine_config_main; \ mp_obj_list_t pyb_sleep_obj_list; \ diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 1877a01437..a374d81203 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -146,7 +146,6 @@ struct mp_bluetooth_nimble_root_pointers_t; #endif #define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; \ mp_obj_t machine_pin_irq_handler[40]; \ struct _machine_timer_obj_t *machine_timer_obj_head; \ struct _machine_i2s_obj_t *machine_i2s_obj[I2S_NUM_MAX]; \ diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 7727f7845a..3f1db723a5 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -148,7 +148,6 @@ extern const struct _mp_print_t mp_debug_print; #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; \ mp_obj_t pin_irq_handler[16]; \ byte *uart0_rxbuf; \ diff --git a/ports/javascript/Makefile b/ports/javascript/Makefile index aea9d6ec37..046d303336 100644 --- a/ports/javascript/Makefile +++ b/ports/javascript/Makefile @@ -30,7 +30,7 @@ SRC_C = \ mphalport.c \ modutime.c \ -SRC_QSTR += $(SRC_C) +SRC_QSTR += $(SRC_C) $(SRC_SHARED) OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_SHARED:.c=.o)) diff --git a/ports/javascript/mpconfigport.h b/ports/javascript/mpconfigport.h index 4a6cb45883..01a61e391d 100644 --- a/ports/javascript/mpconfigport.h +++ b/ports/javascript/mpconfigport.h @@ -182,6 +182,3 @@ typedef long mp_off_t; #define MICROPY_HW_MCU_NAME "Emscripten" #define MP_STATE_PORT MP_STATE_VM - -#define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index 7ae3f91837..be1c95ba95 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -290,6 +290,7 @@ SRC_QSTR += \ modmimxrt.c \ modutime.c \ pin.c \ + shared/readline/readline.c \ shared/runtime/mpirq.c \ shared/runtime/sys_stdio_mphal.c \ $(GEN_PINS_SRC) diff --git a/ports/mimxrt/mpconfigport.h b/ports/mimxrt/mpconfigport.h index 1dcaccad47..3bff3e474d 100644 --- a/ports/mimxrt/mpconfigport.h +++ b/ports/mimxrt/mpconfigport.h @@ -242,7 +242,6 @@ extern const struct _mp_obj_type_t network_lan_type; #endif #define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; \ struct _machine_timer_obj_t *timer_table[MICROPY_HW_PIT_NUM_CHANNELS]; \ void *machine_pin_irq_objects[MICROPY_HW_NUM_PIN_IRQS]; \ /* list of registered NICs */ \ diff --git a/ports/minimal/Makefile b/ports/minimal/Makefile index fc3730e700..ac74925b57 100644 --- a/ports/minimal/Makefile +++ b/ports/minimal/Makefile @@ -68,6 +68,7 @@ SRC_C += $(SRC_MOD) SRC_CXX += $(SRC_MOD_CXX) +SRC_QSTR += shared/readline/readline.c SRC_QSTR += $(SRC_MOD) $(SRC_MOD_CXX) OBJ += $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) diff --git a/ports/minimal/mpconfigport.h b/ports/minimal/mpconfigport.h index 7d6a3adedc..02312e2e40 100644 --- a/ports/minimal/mpconfigport.h +++ b/ports/minimal/mpconfigport.h @@ -41,6 +41,3 @@ typedef long mp_off_t; #endif #define MP_STATE_PORT MP_STATE_VM - -#define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 0698a52cef..fcbe71c5a0 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -332,7 +332,6 @@ typedef long mp_off_t; #endif #define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; \ mp_obj_t pin_class_mapper; \ mp_obj_t pin_class_map_dict; \ mp_obj_t pin_irq_handlers[NUM_OF_PINS]; \ diff --git a/ports/pic16bit/mpconfigport.h b/ports/pic16bit/mpconfigport.h index e97a465028..e03fb81a6a 100644 --- a/ports/pic16bit/mpconfigport.h +++ b/ports/pic16bit/mpconfigport.h @@ -92,7 +92,6 @@ typedef int mp_off_t; #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ - char *readline_hist[8]; \ mp_obj_t keyboard_interrupt_obj; \ #define MICROPY_MPHALPORT_H "pic16bit_mphal.h" diff --git a/ports/powerpc/Makefile b/ports/powerpc/Makefile index a1e6fa4dac..f1ebd6764c 100644 --- a/ports/powerpc/Makefile +++ b/ports/powerpc/Makefile @@ -42,6 +42,8 @@ SRC_C = \ shared/runtime/stdout_helpers.c \ $(BUILD)/_frozen_mpy.c \ +SRC_QSTR += shared/readline/readline.c + OBJ = $(PY_CORE_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(BUILD)/head.o diff --git a/ports/powerpc/mpconfigport.h b/ports/powerpc/mpconfigport.h index 0b868e3daf..084a461a4a 100644 --- a/ports/powerpc/mpconfigport.h +++ b/ports/powerpc/mpconfigport.h @@ -112,9 +112,6 @@ typedef long mp_off_t; #define MP_STATE_PORT MP_STATE_VM -#define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; - // powerpc64 gcc doesn't seem to define these // These are pointers, so make them 64 bit types typedef long intptr_t; diff --git a/ports/renesas-ra/mpconfigport.h b/ports/renesas-ra/mpconfigport.h index 64caa69fd2..11b106999a 100644 --- a/ports/renesas-ra/mpconfigport.h +++ b/ports/renesas-ra/mpconfigport.h @@ -168,8 +168,6 @@ #endif #define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; \ - \ mp_obj_t pyb_hid_report_desc; \ \ mp_obj_t pyb_config_main; \ diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 202261f9c1..8f7895459e 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -130,6 +130,7 @@ set(MICROPY_SOURCE_PORT set(MICROPY_SOURCE_QSTR ${MICROPY_SOURCE_PY} + ${MICROPY_DIR}/shared/readline/readline.c ${MICROPY_DIR}/shared/runtime/mpirq.c ${MICROPY_DIR}/shared/runtime/sys_stdio_mphal.c ${PROJECT_SOURCE_DIR}/machine_adc.c diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 1a63476c7c..1e85104844 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -231,7 +231,6 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k; #endif #define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; \ void *machine_pin_irq_obj[30]; \ void *rp2_pio_irq_obj[2]; \ void *rp2_state_machine_irq_obj[8]; \ diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 17dd811690..b3d6d8b228 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -127,6 +127,7 @@ SRC_QSTR += \ machine_led.c \ modsamd.c \ samd_flash.c \ + shared/readline/readline.c \ SRC_QSTR += $(SRC_MOD) $(SRC_CXX) diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 1625496a2e..96d34bf4da 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -99,9 +99,6 @@ #define mp_type_fileio mp_type_vfs_lfs1_fileio #define mp_type_textio mp_type_vfs_lfs1_textio -#define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; - #define MP_STATE_PORT MP_STATE_VM // Miscellaneous settings diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index a87fe3768f..4afad339bd 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -258,8 +258,6 @@ struct _mp_bluetooth_btstack_root_pointers_t; #endif #define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; \ - \ mp_obj_t pyb_hid_report_desc; \ \ mp_obj_t pyb_config_main; \ diff --git a/ports/teensy/mpconfigport.h b/ports/teensy/mpconfigport.h index db1f56757a..b870263dfc 100644 --- a/ports/teensy/mpconfigport.h +++ b/ports/teensy/mpconfigport.h @@ -42,7 +42,6 @@ extern const struct _mp_obj_module_t pyb_module; #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; \ mp_obj_t pin_class_mapper; \ mp_obj_t pin_class_map_dict; \ struct _pyb_uart_obj_t *pyb_stdio_uart; \ diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 232bfb857c..4594b8be9d 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -129,6 +129,9 @@ #define MICROPY_READER_POSIX (1) #define MICROPY_READER_VFS (1) #define MICROPY_USE_READLINE_HISTORY (1) +#ifndef MICROPY_READLINE_HISTORY_SIZE +#define MICROPY_READLINE_HISTORY_SIZE 50 +#endif #define MICROPY_HELPER_LEXER_UNIX (1) #ifndef MICROPY_FLOAT_IMPL #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) @@ -302,7 +305,6 @@ struct _mp_bluetooth_nimble_malloc_t; #endif #define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[50]; \ void *mmap_region_head; \ MICROPY_BLUETOOTH_ROOT_POINTERS \ diff --git a/ports/windows/mpconfigport.h b/ports/windows/mpconfigport.h index 47292b3bb6..39f8c0059c 100644 --- a/ports/windows/mpconfigport.h +++ b/ports/windows/mpconfigport.h @@ -33,6 +33,12 @@ #ifndef MICROPY_USE_READLINE #define MICROPY_USE_READLINE (1) #endif +#ifndef MICROPY_USE_READLINE_HISTORY +#define MICROPY_USE_READLINE_HISTORY (1) +#endif +#ifndef MICROPY_READLINE_HISTORY_SIZE +#define MICROPY_READLINE_HISTORY_SIZE (50) +#endif #define MICROPY_ALLOC_PATH_MAX (260) // see minwindef.h for msvc or limits.h for mingw #define MICROPY_PERSISTENT_CODE_LOAD (1) @@ -52,7 +58,6 @@ #define MICROPY_DEBUG_PRINTERS (1) #define MICROPY_READER_POSIX (1) #define MICROPY_READER_VFS (1) -#define MICROPY_USE_READLINE_HISTORY (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_REPL_EMACS_KEYS (1) #define MICROPY_REPL_AUTO_INDENT (1) @@ -210,11 +215,6 @@ typedef long long mp_off_t; typedef long mp_off_t; #endif -#if MICROPY_USE_READLINE == 1 -#define MICROPY_PORT_ROOT_POINTERS \ - char *readline_hist[50]; -#endif - #define MP_STATE_PORT MP_STATE_VM #define MICROPY_MPHALPORT_H "windows_mphal.h" diff --git a/ports/zephyr/mpconfigport.h b/ports/zephyr/mpconfigport.h index 26610ccced..1be755baab 100644 --- a/ports/zephyr/mpconfigport.h +++ b/ports/zephyr/mpconfigport.h @@ -134,7 +134,6 @@ typedef long mp_off_t; #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; \ void *machine_pin_irq_list; /* Linked list of pin irq objects */ \ struct _mp_bluetooth_zephyr_root_pointers_t *bluetooth_zephyr_root_pointers; diff --git a/ports/zephyr/mpconfigport_minimal.h b/ports/zephyr/mpconfigport_minimal.h index f0e57d7566..e819d5cf41 100644 --- a/ports/zephyr/mpconfigport_minimal.h +++ b/ports/zephyr/mpconfigport_minimal.h @@ -83,6 +83,3 @@ typedef unsigned mp_uint_t; // must be pointer size typedef long mp_off_t; #define MP_STATE_PORT MP_STATE_VM - -#define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; diff --git a/py/mpconfig.h b/py/mpconfig.h index d70d39ae97..adaa3ec1fb 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -699,6 +699,11 @@ #define MICROPY_REPL_EVENT_DRIVEN (0) #endif +// The number of items to keep in the readline history. +#ifndef MICROPY_READLINE_HISTORY_SIZE +#define MICROPY_READLINE_HISTORY_SIZE (8) +#endif + // Whether to include lexer helper function for unix #ifndef MICROPY_HELPER_LEXER_UNIX #define MICROPY_HELPER_LEXER_UNIX (0) diff --git a/shared/readline/readline.c b/shared/readline/readline.c index 9b8961712d..b85bbd5bea 100644 --- a/shared/readline/readline.c +++ b/shared/readline/readline.c @@ -40,16 +40,19 @@ #define DEBUG_printf(...) (void)0 #endif -#define READLINE_HIST_SIZE (MP_ARRAY_SIZE(MP_STATE_PORT(readline_hist))) - // flags for readline_t.auto_indent_state #define AUTO_INDENT_ENABLED (0x01) #define AUTO_INDENT_JUST_ADDED (0x02) enum { ESEQ_NONE, ESEQ_ESC, ESEQ_ESC_BRACKET, ESEQ_ESC_BRACKET_DIGIT, ESEQ_ESC_O }; +#ifdef _MSC_VER +// work around MSVC compiler bug: https://stackoverflow.com/q/62259834/1976323 +#pragma warning(disable : 4090) +#endif + void readline_init0(void) { - memset(MP_STATE_PORT(readline_hist), 0, READLINE_HIST_SIZE * sizeof(const char*)); + memset(MP_STATE_PORT(readline_hist), 0, MICROPY_READLINE_HISTORY_SIZE * sizeof(const char*)); } STATIC char *str_dup_maybe(const char *str) { @@ -334,7 +337,7 @@ backward_kill_word: up_arrow_key: #endif // up arrow - if (rl.hist_cur + 1 < (int)READLINE_HIST_SIZE && MP_STATE_PORT(readline_hist)[rl.hist_cur + 1] != NULL) { + if (rl.hist_cur + 1 < MICROPY_READLINE_HISTORY_SIZE && MP_STATE_PORT(readline_hist)[rl.hist_cur + 1] != NULL) { // increase hist num rl.hist_cur += 1; // set line to history @@ -570,10 +573,12 @@ void readline_push_history(const char *line) { // so update the history char *most_recent_hist = str_dup_maybe(line); if (most_recent_hist != NULL) { - for (int i = READLINE_HIST_SIZE - 1; i > 0; i--) { + for (int i = MICROPY_READLINE_HISTORY_SIZE - 1; i > 0; i--) { MP_STATE_PORT(readline_hist)[i] = MP_STATE_PORT(readline_hist)[i - 1]; } MP_STATE_PORT(readline_hist)[0] = most_recent_hist; } } } + +MP_REGISTER_ROOT_POINTER(const char *readline_hist[MICROPY_READLINE_HISTORY_SIZE]); From e5631d959517fcdd8752c60a1c5d07e8e86fbfa5 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 14:10:39 -0500 Subject: [PATCH 0141/1041] unix/alloc: Use MP_REGISTER_ROOT_POINTER() for mmap_region_head. This uses MP_REGISTER_ROOT_POINTER() to register mmap_region_head and removes the same from mpconfigport.h. Signed-off-by: David Lechner --- ports/unix/alloc.c | 2 ++ ports/unix/mpconfigport.h | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ports/unix/alloc.c b/ports/unix/alloc.c index 7fe7b4dba4..e9cf521583 100644 --- a/ports/unix/alloc.c +++ b/ports/unix/alloc.c @@ -104,4 +104,6 @@ void ffi_closure_free(void *ptr) { } #endif +MP_REGISTER_ROOT_POINTER(void *mmap_region_head); + #endif // MICROPY_EMIT_NATIVE || (MICROPY_PY_FFI && MICROPY_FORCE_PLAT_ALLOC_EXEC) diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 4594b8be9d..eb2da23938 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -305,7 +305,6 @@ struct _mp_bluetooth_nimble_malloc_t; #endif #define MICROPY_PORT_ROOT_POINTERS \ - void *mmap_region_head; \ MICROPY_BLUETOOTH_ROOT_POINTERS \ // We need to provide a declaration/definition of alloca() From ac86e8449afebdef38b02af7acfc0ed535db9d94 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 15:37:12 -0500 Subject: [PATCH 0142/1041] drivers/ninaw10/nina_wifi_bsp: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register mp_wifi_spi, mp_wifi_timer and mp_wifi_sockpoll_list and removes the same from all mpconfigport.h. Signed-off-by: David Lechner --- drivers/ninaw10/nina_wifi_bsp.c | 4 ++++ ports/rp2/mpconfigport.h | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/ninaw10/nina_wifi_bsp.c b/drivers/ninaw10/nina_wifi_bsp.c index a65ef7fd86..d11e139705 100644 --- a/drivers/ninaw10/nina_wifi_bsp.c +++ b/drivers/ninaw10/nina_wifi_bsp.c @@ -150,4 +150,8 @@ int nina_bsp_spi_transfer(const uint8_t *tx_buf, uint8_t *rx_buf, uint32_t size) return 0; } +MP_REGISTER_ROOT_POINTER(struct _machine_spi_obj_t *mp_wifi_spi); +MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *mp_wifi_timer); +MP_REGISTER_ROOT_POINTER(struct _mp_obj_list_t *mp_wifi_sockpoll_list); + #endif // MICROPY_PY_NETWORK_NINAW10 diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 1e85104844..87bddbeb77 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -197,12 +197,10 @@ extern const struct _mp_obj_type_t mp_network_cyw43_type; #define MICROPY_PY_USOCKET_EXTENDED_STATE (1) #endif // It also requires an additional root pointer for the SPI object. -#define MICROPY_PORT_ROOT_POINTER_NINAW10 struct _machine_spi_obj_t *mp_wifi_spi; struct _machine_timer_obj_t *mp_wifi_timer; struct _mp_obj_list_t *mp_wifi_sockpoll_list; extern const struct _mod_network_nic_type_t mod_network_nic_type_nina; #define MICROPY_HW_NIC_NINAW10 { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mod_network_nic_type_nina) }, #else #define MICROPY_HW_NIC_NINAW10 -#define MICROPY_PORT_ROOT_POINTER_NINAW10 #endif #if MICROPY_PY_NETWORK_WIZNET5K @@ -239,7 +237,6 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k; void *machine_i2s_obj[2]; \ NETWORK_ROOT_POINTERS \ MICROPY_BOARD_ROOT_POINTERS \ - MICROPY_PORT_ROOT_POINTER_NINAW10 \ MICROPY_PORT_ROOT_POINTER_BLUETOOTH \ MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE \ From 8fa6191f955c81678ac4ec3b45f92a72c641f0b1 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 14:18:09 -0500 Subject: [PATCH 0143/1041] extmod/btstack: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register bluetooth_btstack_root_pointers and removes the same from all mpconfigport.h. Signed-off-by: David Lechner --- extmod/btstack/modbluetooth_btstack.c | 2 ++ ports/stm32/mpconfigport.h | 8 -------- ports/unix/mpconfigport.h | 4 ---- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c index e56e488b1c..c07cc8c10c 100644 --- a/extmod/btstack/modbluetooth_btstack.c +++ b/extmod/btstack/modbluetooth_btstack.c @@ -1460,4 +1460,6 @@ int mp_bluetooth_l2cap_recvinto(uint16_t conn_handle, uint16_t cid, uint8_t *buf #endif // MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS +MP_REGISTER_ROOT_POINTER(struct _mp_bluetooth_btstack_root_pointers_t *bluetooth_btstack_root_pointers); + #endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 4afad339bd..9c719b8d06 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -246,13 +246,6 @@ struct _mp_bluetooth_nimble_malloc_t; #define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE #endif -#if MICROPY_BLUETOOTH_BTSTACK -struct _mp_bluetooth_btstack_root_pointers_t; -#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_BTSTACK struct _mp_bluetooth_btstack_root_pointers_t *bluetooth_btstack_root_pointers; -#else -#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_BTSTACK -#endif - #ifndef MICROPY_BOARD_ROOT_POINTERS #define MICROPY_BOARD_ROOT_POINTERS #endif @@ -292,7 +285,6 @@ struct _mp_bluetooth_btstack_root_pointers_t; \ /* root pointers for sub-systems */ \ MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE \ - MICROPY_PORT_ROOT_POINTER_BLUETOOTH_BTSTACK \ \ /* root pointers defined by a board */ \ MICROPY_BOARD_ROOT_POINTERS \ diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index eb2da23938..e020e54bf5 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -291,10 +291,6 @@ static inline unsigned long mp_urandom_seed_init(void) { #define MP_STATE_PORT MP_STATE_VM #if MICROPY_PY_BLUETOOTH -#if MICROPY_BLUETOOTH_BTSTACK -struct _mp_bluetooth_btstack_root_pointers_t; -#define MICROPY_BLUETOOTH_ROOT_POINTERS struct _mp_bluetooth_btstack_root_pointers_t *bluetooth_btstack_root_pointers; -#endif #if MICROPY_BLUETOOTH_NIMBLE struct _mp_bluetooth_nimble_root_pointers_t; struct _mp_bluetooth_nimble_malloc_t; From e531b72b56cfac9a309f79cd242070d675d6ee0e Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 14:24:16 -0500 Subject: [PATCH 0144/1041] extmod/nimble: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register bluetooth_nimble_memory and bluetooth_nimble_root_pointers and removes the same from all mpconfigport.h. Signed-off-by: David Lechner --- extmod/nimble/modbluetooth_nimble.c | 5 +++++ ports/esp32/mpconfigport.h | 8 -------- ports/rp2/mpconfigport.h | 9 --------- ports/stm32/mpconfigport.h | 11 ----------- ports/unix/mpconfigport.h | 13 ------------- 5 files changed, 5 insertions(+), 41 deletions(-) diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c index fce99bcdf5..c26c09e61a 100644 --- a/extmod/nimble/modbluetooth_nimble.c +++ b/extmod/nimble/modbluetooth_nimble.c @@ -1966,4 +1966,9 @@ STATIC int ble_secret_store_delete(int obj_type, const union ble_store_key *key) #endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING +#if !MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY +MP_REGISTER_ROOT_POINTER(struct _mp_bluetooth_nimble_malloc_t *bluetooth_nimble_memory); +#endif +MP_REGISTER_ROOT_POINTER(struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers); + #endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index a374d81203..7cfce49d37 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -138,19 +138,11 @@ struct _machine_timer_obj_t; -#if MICROPY_BLUETOOTH_NIMBLE -struct mp_bluetooth_nimble_root_pointers_t; -#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers; -#else -#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE -#endif - #define MICROPY_PORT_ROOT_POINTERS \ mp_obj_t machine_pin_irq_handler[40]; \ struct _machine_timer_obj_t *machine_timer_obj_head; \ struct _machine_i2s_obj_t *machine_i2s_obj[I2S_NUM_MAX]; \ mp_obj_t native_code_pointers; \ - MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE // type definitions for the specific machine diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 87bddbeb77..8b7cb7ca42 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -147,14 +147,6 @@ #define MICROPY_PORT_ROOT_POINTER_BLUETOOTH #endif -#if MICROPY_BLUETOOTH_NIMBLE -struct _mp_bluetooth_nimble_root_pointers_t; -struct _mp_bluetooth_nimble_malloc_t; -#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE struct _mp_bluetooth_nimble_malloc_t *bluetooth_nimble_memory; struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers; -#else -#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE -#endif - // By default networking should include sockets, ssl, websockets, webrepl, dupterm. #if MICROPY_PY_NETWORK #ifndef MICROPY_PY_USOCKET @@ -238,7 +230,6 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k; NETWORK_ROOT_POINTERS \ MICROPY_BOARD_ROOT_POINTERS \ MICROPY_PORT_ROOT_POINTER_BLUETOOTH \ - MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE \ #define MP_STATE_PORT MP_STATE_VM diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 9c719b8d06..bf7183a81d 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -238,14 +238,6 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_cc3k; #define MP_STATE_PORT MP_STATE_VM -#if MICROPY_BLUETOOTH_NIMBLE -struct _mp_bluetooth_nimble_root_pointers_t; -struct _mp_bluetooth_nimble_malloc_t; -#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE struct _mp_bluetooth_nimble_malloc_t *bluetooth_nimble_memory; struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers; -#else -#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE -#endif - #ifndef MICROPY_BOARD_ROOT_POINTERS #define MICROPY_BOARD_ROOT_POINTERS #endif @@ -283,9 +275,6 @@ struct _mp_bluetooth_nimble_malloc_t; /* list of registered NICs */ \ mp_obj_list_t mod_network_nic_list; \ \ - /* root pointers for sub-systems */ \ - MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE \ - \ /* root pointers defined by a board */ \ MICROPY_BOARD_ROOT_POINTERS \ diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index e020e54bf5..97846f81f0 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -290,19 +290,6 @@ static inline unsigned long mp_urandom_seed_init(void) { #define MP_STATE_PORT MP_STATE_VM -#if MICROPY_PY_BLUETOOTH -#if MICROPY_BLUETOOTH_NIMBLE -struct _mp_bluetooth_nimble_root_pointers_t; -struct _mp_bluetooth_nimble_malloc_t; -#define MICROPY_BLUETOOTH_ROOT_POINTERS struct _mp_bluetooth_nimble_malloc_t *bluetooth_nimble_memory; struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers; -#endif -#else -#define MICROPY_BLUETOOTH_ROOT_POINTERS -#endif - -#define MICROPY_PORT_ROOT_POINTERS \ - MICROPY_BLUETOOTH_ROOT_POINTERS \ - // We need to provide a declaration/definition of alloca() // unless support for it is disabled. #if !defined(MICROPY_NO_ALLOCA) || MICROPY_NO_ALLOCA == 0 From a3703584fea25854616265c9accc2aab70cf2c97 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 15:01:38 -0500 Subject: [PATCH 0145/1041] extmod/modnetwork: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register mod_network_nic_list and removes the same from all mpconfigport.h. Signed-off-by: David Lechner --- extmod/modnetwork.c | 2 ++ ports/mimxrt/mpconfigport.h | 2 -- ports/renesas-ra/mpconfigport.h | 3 --- ports/rp2/mpconfigport.h | 7 ------- ports/stm32/mpconfigport.h | 3 --- 5 files changed, 2 insertions(+), 15 deletions(-) diff --git a/extmod/modnetwork.c b/extmod/modnetwork.c index e05bfdb11d..b698ee4cf4 100644 --- a/extmod/modnetwork.c +++ b/extmod/modnetwork.c @@ -163,4 +163,6 @@ mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_o #endif +MP_REGISTER_ROOT_POINTER(mp_obj_list_t mod_network_nic_list); + #endif // MICROPY_PY_NETWORK diff --git a/ports/mimxrt/mpconfigport.h b/ports/mimxrt/mpconfigport.h index 3bff3e474d..0603d82166 100644 --- a/ports/mimxrt/mpconfigport.h +++ b/ports/mimxrt/mpconfigport.h @@ -244,8 +244,6 @@ extern const struct _mp_obj_type_t network_lan_type; #define MICROPY_PORT_ROOT_POINTERS \ struct _machine_timer_obj_t *timer_table[MICROPY_HW_PIT_NUM_CHANNELS]; \ void *machine_pin_irq_objects[MICROPY_HW_NUM_PIN_IRQS]; \ - /* list of registered NICs */ \ - mp_obj_list_t mod_network_nic_list; \ /* root pointers defined by a board */ \ MICROPY_BOARD_ROOT_POINTERS \ diff --git a/ports/renesas-ra/mpconfigport.h b/ports/renesas-ra/mpconfigport.h index 11b106999a..badcce8e6f 100644 --- a/ports/renesas-ra/mpconfigport.h +++ b/ports/renesas-ra/mpconfigport.h @@ -185,9 +185,6 @@ /* pointers to all UART objects (if they have been created) */ \ struct _machine_uart_obj_t *machine_uart_obj_all[MICROPY_HW_MAX_UART + MICROPY_HW_MAX_LPUART]; \ \ - /* list of registered NICs */ \ - /* mp_obj_list_t mod_network_nic_list; */ \ - \ /* root pointers for sub-systems */ \ \ /* root pointers defined by a board */ \ diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 8b7cb7ca42..182a3db02d 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -135,12 +135,6 @@ #define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) #endif -#if MICROPY_PY_NETWORK -#define NETWORK_ROOT_POINTERS mp_obj_list_t mod_network_nic_list; -#else -#define NETWORK_ROOT_POINTERS -#endif - #if MICROPY_PY_BLUETOOTH #define MICROPY_PORT_ROOT_POINTER_BLUETOOTH struct _machine_uart_obj_t *mp_bthci_uart; #else @@ -227,7 +221,6 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k; void *rp2_uart_rx_buffer[2]; \ void *rp2_uart_tx_buffer[2]; \ void *machine_i2s_obj[2]; \ - NETWORK_ROOT_POINTERS \ MICROPY_BOARD_ROOT_POINTERS \ MICROPY_PORT_ROOT_POINTER_BLUETOOTH \ diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index bf7183a81d..83986296c9 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -272,9 +272,6 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_cc3k; /* USB_VCP IRQ callbacks (if they have been set) */ \ mp_obj_t pyb_usb_vcp_irq[MICROPY_HW_USB_CDC_NUM]; \ \ - /* list of registered NICs */ \ - mp_obj_list_t mod_network_nic_list; \ - \ /* root pointers defined by a board */ \ MICROPY_BOARD_ROOT_POINTERS \ From 095ad87adf934511e9aaa0beb6f2ae1accc262a7 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 14:26:38 -0500 Subject: [PATCH 0146/1041] cc3200/mpconfigport: Remove mp_const_user_interrupt. mp_const_user_interrupt was listed as a root pointer but not used anywhere in the code base, so it can be removed. Signed-off-by: David Lechner --- ports/cc3200/mpconfigport.h | 1 - 1 file changed, 1 deletion(-) diff --git a/ports/cc3200/mpconfigport.h b/ports/cc3200/mpconfigport.h index ce708cb3f4..a9daca88b5 100644 --- a/ports/cc3200/mpconfigport.h +++ b/ports/cc3200/mpconfigport.h @@ -142,7 +142,6 @@ // vm state and root pointers for the gc #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ - mp_obj_t mp_const_user_interrupt; \ mp_obj_t machine_config_main; \ mp_obj_list_t pyb_sleep_obj_list; \ mp_obj_list_t mp_irq_obj_list; \ From 226e969ad339678404a4ad9153cf9a40a31fc1da Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 14:28:58 -0500 Subject: [PATCH 0147/1041] cc3200: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register all port-specific root pointers for the cc3200 port. Signed-off-by: David Lechner --- ports/cc3200/application.mk | 2 +- ports/cc3200/hal/cc3200_hal.c | 2 ++ ports/cc3200/misc/mpirq.c | 1 + ports/cc3200/mods/modmachine.c | 1 + ports/cc3200/mods/pybsleep.c | 1 + ports/cc3200/mods/pybtimer.c | 1 + ports/cc3200/mods/pybuart.c | 2 ++ ports/cc3200/mpconfigport.h | 9 --------- 8 files changed, 9 insertions(+), 10 deletions(-) diff --git a/ports/cc3200/application.mk b/ports/cc3200/application.mk index 25a9925ea0..428367d66a 100644 --- a/ports/cc3200/application.mk +++ b/ports/cc3200/application.mk @@ -166,7 +166,7 @@ OBJ += $(BUILD)/shared/runtime/gchelper_m3.o OBJ += $(BUILD)/pins.o # List of sources for qstr extraction -SRC_QSTR += $(APP_MODS_SRC_C) $(APP_MISC_SRC_C) $(APP_STM_SRC_C) $(APP_SHARED_SRC_C) +SRC_QSTR += $(APP_MODS_SRC_C) $(APP_MISC_SRC_C) $(APP_STM_SRC_C) $(APP_SHARED_SRC_C) $(APP_HAL_SRC_C) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR SRC_QSTR_AUTO_DEPS += diff --git a/ports/cc3200/hal/cc3200_hal.c b/ports/cc3200/hal/cc3200_hal.c index 3a35e39e1f..4694235eeb 100644 --- a/ports/cc3200/hal/cc3200_hal.c +++ b/ports/cc3200/hal/cc3200_hal.c @@ -195,3 +195,5 @@ static void hal_TickInit (void) { MAP_SysTickEnable(); } #endif + +MP_REGISTER_ROOT_POINTER(struct _os_term_dup_obj_t *os_term_dup_obj); diff --git a/ports/cc3200/misc/mpirq.c b/ports/cc3200/misc/mpirq.c index de30ebc499..eb93e5eef0 100644 --- a/ports/cc3200/misc/mpirq.c +++ b/ports/cc3200/misc/mpirq.c @@ -197,3 +197,4 @@ const mp_obj_type_t mp_irq_type = { .locals_dict = (mp_obj_t)&mp_irq_locals_dict, }; +MP_REGISTER_ROOT_POINTER(mp_obj_list_t mp_irq_obj_list); diff --git a/ports/cc3200/mods/modmachine.c b/ports/cc3200/mods/modmachine.c index 782ccc55a1..3e483e0a23 100644 --- a/ports/cc3200/mods/modmachine.c +++ b/ports/cc3200/mods/modmachine.c @@ -215,3 +215,4 @@ const mp_obj_module_t mp_module_machine = { }; MP_REGISTER_MODULE(MP_QSTR_umachine, mp_module_machine); +MP_REGISTER_ROOT_POINTER(mp_obj_t machine_config_main); diff --git a/ports/cc3200/mods/pybsleep.c b/ports/cc3200/mods/pybsleep.c index 2d4b1ca8a9..76fe0849a4 100644 --- a/ports/cc3200/mods/pybsleep.c +++ b/ports/cc3200/mods/pybsleep.c @@ -652,3 +652,4 @@ STATIC bool setup_timer_hibernate_wake (void) { return false; } +MP_REGISTER_ROOT_POINTER(mp_obj_list_t pyb_sleep_obj_list); diff --git a/ports/cc3200/mods/pybtimer.c b/ports/cc3200/mods/pybtimer.c index 55caa6de13..b2725ae166 100644 --- a/ports/cc3200/mods/pybtimer.c +++ b/ports/cc3200/mods/pybtimer.c @@ -728,3 +728,4 @@ STATIC const mp_obj_type_t pyb_timer_channel_type = { .locals_dict = (mp_obj_t)&pyb_timer_channel_locals_dict, }; +MP_REGISTER_ROOT_POINTER(mp_obj_list_t pyb_timer_channel_obj_list); diff --git a/ports/cc3200/mods/pybuart.c b/ports/cc3200/mods/pybuart.c index b8e8cbb682..6e774b70d9 100644 --- a/ports/cc3200/mods/pybuart.c +++ b/ports/cc3200/mods/pybuart.c @@ -666,3 +666,5 @@ const mp_obj_type_t pyb_uart_type = { .protocol = &uart_stream_p, .locals_dict = (mp_obj_t)&pyb_uart_locals_dict, }; + +MP_REGISTER_ROOT_POINTER(struct _pyb_uart_obj_t *pyb_uart_objs[2]); diff --git a/ports/cc3200/mpconfigport.h b/ports/cc3200/mpconfigport.h index a9daca88b5..8059daeec7 100644 --- a/ports/cc3200/mpconfigport.h +++ b/ports/cc3200/mpconfigport.h @@ -139,16 +139,7 @@ #define MICROPY_PORT_CONSTANTS \ { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, \ -// vm state and root pointers for the gc #define MP_STATE_PORT MP_STATE_VM -#define MICROPY_PORT_ROOT_POINTERS \ - mp_obj_t machine_config_main; \ - mp_obj_list_t pyb_sleep_obj_list; \ - mp_obj_list_t mp_irq_obj_list; \ - mp_obj_list_t pyb_timer_channel_obj_list; \ - struct _pyb_uart_obj_t *pyb_uart_objs[2]; \ - struct _os_term_dup_obj_t *os_term_dup_obj; \ - // type definitions for the specific machine #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1)) From b63282c36194b6388e97df66122ac05f973fe7ca Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 14:41:27 -0500 Subject: [PATCH 0148/1041] esp32: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register all root pointers in the esp32 port. Signed-off-by: David Lechner --- ports/esp32/machine_i2s.c | 2 ++ ports/esp32/machine_pin.c | 2 ++ ports/esp32/machine_timer.c | 2 ++ ports/esp32/main.c | 2 ++ ports/esp32/mpconfigport.h | 8 -------- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ports/esp32/machine_i2s.c b/ports/esp32/machine_i2s.c index 8832ad5e90..933e68684b 100644 --- a/ports/esp32/machine_i2s.c +++ b/ports/esp32/machine_i2s.c @@ -840,4 +840,6 @@ const mp_obj_type_t machine_i2s_type = { .locals_dict = (mp_obj_dict_t *)&machine_i2s_locals_dict, }; +MP_REGISTER_ROOT_POINTER(struct _machine_i2s_obj_t *machine_i2s_obj[I2S_NUM_MAX]); + #endif // MICROPY_PY_MACHINE_I2S diff --git a/ports/esp32/machine_pin.c b/ports/esp32/machine_pin.c index 865face96f..b575626338 100644 --- a/ports/esp32/machine_pin.c +++ b/ports/esp32/machine_pin.c @@ -729,3 +729,5 @@ STATIC const mp_obj_type_t machine_pin_irq_type = { .call = machine_pin_irq_call, .locals_dict = (mp_obj_dict_t *)&machine_pin_irq_locals_dict, }; + +MP_REGISTER_ROOT_POINTER(mp_obj_t machine_pin_irq_handler[40]); diff --git a/ports/esp32/machine_timer.c b/ports/esp32/machine_timer.c index 100b2aa1fb..8541bcbfdb 100644 --- a/ports/esp32/machine_timer.c +++ b/ports/esp32/machine_timer.c @@ -272,3 +272,5 @@ const mp_obj_type_t machine_timer_type = { .make_new = machine_timer_make_new, .locals_dict = (mp_obj_t)&machine_timer_locals_dict, }; + +MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *machine_timer_obj_head); diff --git a/ports/esp32/main.c b/ports/esp32/main.c index 14b7e14c62..c543c5b645 100644 --- a/ports/esp32/main.c +++ b/ports/esp32/main.c @@ -265,3 +265,5 @@ void *esp_native_code_commit(void *buf, size_t len, void *reloc) { memcpy(p, buf, len); return p; } + +MP_REGISTER_ROOT_POINTER(mp_obj_t native_code_pointers); diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 7cfce49d37..8dc3537e59 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -136,14 +136,6 @@ #define MP_STATE_PORT MP_STATE_VM -struct _machine_timer_obj_t; - -#define MICROPY_PORT_ROOT_POINTERS \ - mp_obj_t machine_pin_irq_handler[40]; \ - struct _machine_timer_obj_t *machine_timer_obj_head; \ - struct _machine_i2s_obj_t *machine_i2s_obj[I2S_NUM_MAX]; \ - mp_obj_t native_code_pointers; \ - // type definitions for the specific machine #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p))) From e2d4db96dac0d8316287e5fc60d3eeb57b28f259 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 14:55:33 -0500 Subject: [PATCH 0149/1041] esp8266: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register all port-specific root pointers in the esp2866 port. Signed-off-by: David Lechner --- ports/esp8266/machine_pin.c | 2 ++ ports/esp8266/machine_uart.c | 2 ++ ports/esp8266/mpconfigport.h | 4 ---- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ports/esp8266/machine_pin.c b/ports/esp8266/machine_pin.c index 419ee87a73..8171b8a8a3 100644 --- a/ports/esp8266/machine_pin.c +++ b/ports/esp8266/machine_pin.c @@ -515,3 +515,5 @@ STATIC const mp_obj_type_t pin_irq_type = { .call = pin_irq_call, .locals_dict = (mp_obj_dict_t *)&pin_irq_locals_dict, }; + +MP_REGISTER_ROOT_POINTER(mp_obj_t pin_irq_handler[16]); diff --git a/ports/esp8266/machine_uart.c b/ports/esp8266/machine_uart.c index b774419d2d..4e88eee162 100644 --- a/ports/esp8266/machine_uart.c +++ b/ports/esp8266/machine_uart.c @@ -329,3 +329,5 @@ const mp_obj_type_t pyb_uart_type = { .protocol = &uart_stream_p, .locals_dict = (mp_obj_dict_t *)&pyb_uart_locals_dict, }; + +MP_REGISTER_ROOT_POINTER(byte * uart0_rxbuf); diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 3f1db723a5..779767311c 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -147,10 +147,6 @@ extern const struct _mp_print_t mp_debug_print; #define MP_STATE_PORT MP_STATE_VM -#define MICROPY_PORT_ROOT_POINTERS \ - mp_obj_t pin_irq_handler[16]; \ - byte *uart0_rxbuf; \ - // We need an implementation of the log2 function which is not a macro #define MP_NEED_LOG2 (1) From a316a8fdb37fa80bce761840133946e827a4d33d Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 14:46:44 -0500 Subject: [PATCH 0150/1041] mimxrt: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register all port-specific root pointers in the mimxrt port. Signed-off-by: David Lechner --- ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h | 3 --- ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h | 3 --- ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h | 3 --- ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h | 3 --- ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h | 3 --- ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h | 3 --- ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h | 4 ---- ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h | 3 --- ports/mimxrt/boards/TEENSY40/mpconfigboard.h | 3 --- ports/mimxrt/boards/TEENSY41/mpconfigboard.h | 3 --- ports/mimxrt/machine_i2s.c | 2 ++ ports/mimxrt/machine_pin.c | 2 ++ ports/mimxrt/machine_timer.c | 2 ++ ports/mimxrt/mpconfigport.h | 2 -- 14 files changed, 6 insertions(+), 33 deletions(-) diff --git a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h index 75fda0cad1..6c9aaff96a 100644 --- a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h @@ -74,6 +74,3 @@ I2S_GPIO(1, WS, TX, GPIO_07, IOMUXC_GPIO_07_SAI1_TX_SYNC), \ I2S_GPIO(1, SD, TX, GPIO_04, IOMUXC_GPIO_04_SAI1_TX_DATA00), \ } - -#define MICROPY_BOARD_ROOT_POINTERS \ - struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM]; diff --git a/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h index 17326cb485..adb97fd24e 100644 --- a/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h @@ -79,6 +79,3 @@ I2S_GPIO(1, WS, TX, GPIO_EMC_27, IOMUXC_GPIO_EMC_27_SAI1_TX_SYNC), \ I2S_GPIO(1, SD, TX, GPIO_EMC_25, IOMUXC_GPIO_EMC_25_SAI1_TX_DATA00), \ } - -#define MICROPY_BOARD_ROOT_POINTERS \ - struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM]; diff --git a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h index 1dfe02b651..762499f6c2 100644 --- a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h @@ -172,6 +172,3 @@ { IOMUXC_GPIO_AD_B0_15_ENET_TDATA01, 0, 0xB0E9u }, \ { IOMUXC_GPIO_EMC_40_ENET_MDIO, 0, 0xB0E9u }, \ { IOMUXC_GPIO_EMC_41_ENET_MDC, 0, 0xB0E9u }, - -#define MICROPY_BOARD_ROOT_POINTERS \ - struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM]; diff --git a/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h index 613095e67f..f2a7b0b78b 100644 --- a/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h @@ -162,6 +162,3 @@ { IOMUXC_GPIO_B1_11_ENET_RX_ER, 0, 0xB0E9u }, \ { IOMUXC_GPIO_EMC_41_ENET_MDIO, 0, 0xB0E9u }, \ { IOMUXC_GPIO_EMC_40_ENET_MDC, 0, 0xB0E9u }, - -#define MICROPY_BOARD_ROOT_POINTERS \ - struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM]; diff --git a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h index a3f0062389..5670902d11 100644 --- a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h @@ -160,6 +160,3 @@ { IOMUXC_GPIO_B1_11_ENET_RX_ER, 0, 0xB0E9u }, \ { IOMUXC_GPIO_EMC_41_ENET_MDIO, 0, 0xB0E9u }, \ { IOMUXC_GPIO_EMC_40_ENET_MDC, 0, 0xB0E9u }, - -#define MICROPY_BOARD_ROOT_POINTERS \ - struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM]; diff --git a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h index fe1fb532b8..0f4eaf246d 100644 --- a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h @@ -160,6 +160,3 @@ { IOMUXC_GPIO_B1_11_ENET_RX_ER, 0, 0xB0E9u }, \ { IOMUXC_GPIO_EMC_41_ENET_MDIO, 0, 0xB0E9u }, \ { IOMUXC_GPIO_EMC_40_ENET_MDC, 0, 0xB0E9u }, - -#define MICROPY_BOARD_ROOT_POINTERS \ - struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM]; diff --git a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h index c30caa0470..8c6d159fb7 100644 --- a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h +++ b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h @@ -80,7 +80,3 @@ I2S_GPIO(3, WS, TX, GPIO_SD_00, IOMUXC_GPIO_SD_00_SAI3_TX_SYNC), /* pin D9 */ \ I2S_GPIO(3, SD, TX, GPIO_SD_02, IOMUXC_GPIO_SD_02_SAI3_TX_DATA) /* pin D11 */ \ } - - -#define MICROPY_BOARD_ROOT_POINTERS \ - struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM]; diff --git a/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h b/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h index a6502d3353..d366b4535d 100644 --- a/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h +++ b/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h @@ -173,6 +173,3 @@ #define MIMXRT_IOMUXC_SEMC_WE IOMUXC_GPIO_EMC_28_SEMC_WE #define MIMXRT_IOMUXC_SEMC_CS0 IOMUXC_GPIO_EMC_29_SEMC_CS0 - -#define MICROPY_BOARD_ROOT_POINTERS \ - struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM]; diff --git a/ports/mimxrt/boards/TEENSY40/mpconfigboard.h b/ports/mimxrt/boards/TEENSY40/mpconfigboard.h index f2ea86bd0e..877573d038 100644 --- a/ports/mimxrt/boards/TEENSY40/mpconfigboard.h +++ b/ports/mimxrt/boards/TEENSY40/mpconfigboard.h @@ -104,6 +104,3 @@ .data2 = { GPIO_SD_B0_04_USDHC1_DATA2 }, \ .data3 = { GPIO_SD_B0_05_USDHC1_DATA3 }, \ } - -#define MICROPY_BOARD_ROOT_POINTERS \ - struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM]; diff --git a/ports/mimxrt/boards/TEENSY41/mpconfigboard.h b/ports/mimxrt/boards/TEENSY41/mpconfigboard.h index 7d75f62f36..3c6a05185d 100644 --- a/ports/mimxrt/boards/TEENSY41/mpconfigboard.h +++ b/ports/mimxrt/boards/TEENSY41/mpconfigboard.h @@ -127,6 +127,3 @@ { IOMUXC_GPIO_B1_11_ENET_RX_ER, 0, 0xB0E9u }, \ { IOMUXC_GPIO_B1_15_ENET_MDIO, 0, 0xB0E9u }, \ { IOMUXC_GPIO_B1_14_ENET_MDC, 0, 0xB0E9u }, - -#define MICROPY_BOARD_ROOT_POINTERS \ - struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM]; diff --git a/ports/mimxrt/machine_i2s.c b/ports/mimxrt/machine_i2s.c index 11a203baea..a5446c7ac3 100644 --- a/ports/mimxrt/machine_i2s.c +++ b/ports/mimxrt/machine_i2s.c @@ -1224,4 +1224,6 @@ const mp_obj_type_t machine_i2s_type = { .locals_dict = (mp_obj_dict_t *)&machine_i2s_locals_dict, }; +MP_REGISTER_ROOT_POINTER(struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM]); + #endif // MICROPY_PY_MACHINE_I2S diff --git a/ports/mimxrt/machine_pin.c b/ports/mimxrt/machine_pin.c index 2424088f02..64066af0e1 100644 --- a/ports/mimxrt/machine_pin.c +++ b/ports/mimxrt/machine_pin.c @@ -469,3 +469,5 @@ STATIC const mp_irq_methods_t machine_pin_irq_methods = { .trigger = machine_pin_irq_trigger, .info = machine_pin_irq_info, }; + +MP_REGISTER_ROOT_POINTER(void *machine_pin_irq_objects[MICROPY_HW_NUM_PIN_IRQS]); diff --git a/ports/mimxrt/machine_timer.c b/ports/mimxrt/machine_timer.c index c47d9dca24..62a560ebbf 100644 --- a/ports/mimxrt/machine_timer.c +++ b/ports/mimxrt/machine_timer.c @@ -218,3 +218,5 @@ const mp_obj_type_t machine_timer_type = { .make_new = machine_timer_make_new, .locals_dict = (mp_obj_dict_t *)&machine_timer_locals_dict, }; + +MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *timer_table[MICROPY_HW_PIT_NUM_CHANNELS]); diff --git a/ports/mimxrt/mpconfigport.h b/ports/mimxrt/mpconfigport.h index 0603d82166..2c7446e360 100644 --- a/ports/mimxrt/mpconfigport.h +++ b/ports/mimxrt/mpconfigport.h @@ -242,8 +242,6 @@ extern const struct _mp_obj_type_t network_lan_type; #endif #define MICROPY_PORT_ROOT_POINTERS \ - struct _machine_timer_obj_t *timer_table[MICROPY_HW_PIT_NUM_CHANNELS]; \ - void *machine_pin_irq_objects[MICROPY_HW_NUM_PIN_IRQS]; \ /* root pointers defined by a board */ \ MICROPY_BOARD_ROOT_POINTERS \ From 8a69c54211663157b68438e4b93d11a064c9078a Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 15:04:40 -0500 Subject: [PATCH 0151/1041] nrf: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register all port-specific root pointers for the nrf port. Signed-off-by: David Lechner --- .../boards/microbit/modules/microbitdisplay.c | 2 ++ ports/nrf/drivers/softpwm.c | 3 ++ ports/nrf/modules/machine/pin.c | 10 ++++++ ports/nrf/modules/music/modmusic.c | 3 +- ports/nrf/mpconfigport.h | 35 ------------------- ports/nrf/mphalport.c | 2 ++ 6 files changed, 19 insertions(+), 36 deletions(-) diff --git a/ports/nrf/boards/microbit/modules/microbitdisplay.c b/ports/nrf/boards/microbit/modules/microbitdisplay.c index a0508886d7..b35703ad6f 100644 --- a/ports/nrf/boards/microbit/modules/microbitdisplay.c +++ b/ports/nrf/boards/microbit/modules/microbitdisplay.c @@ -574,3 +574,5 @@ void microbit_display_init(void) { nrf_gpio_cfg_output(i); } } + +MP_REGISTER_ROOT_POINTER(void *async_data[2]); diff --git a/ports/nrf/drivers/softpwm.c b/ports/nrf/drivers/softpwm.c index 517880c8c9..6acdf7aa76 100644 --- a/ports/nrf/drivers/softpwm.c +++ b/ports/nrf/drivers/softpwm.c @@ -255,4 +255,7 @@ void pwm_release(int32_t pin) { nrf_gpio_pin_clear(pin); } +MP_REGISTER_ROOT_POINTER(const struct _pwm_events *pwm_active_events); +MP_REGISTER_ROOT_POINTER(const struct _pwm_events *pwm_pending_events); + #endif // MICROPY_PY_MACHINE_SOFT_PWM diff --git a/ports/nrf/modules/machine/pin.c b/ports/nrf/modules/machine/pin.c index 170caf6dde..3a45c22d18 100644 --- a/ports/nrf/modules/machine/pin.c +++ b/ports/nrf/modules/machine/pin.c @@ -37,6 +37,12 @@ #include "nrf_gpio.h" #include "nrfx_gpiote.h" +#if defined(NRF52840_XXAA) +#define NUM_OF_PINS 48 +#else +#define NUM_OF_PINS 32 +#endif + extern const pin_obj_t machine_board_pin_obj[]; extern const uint8_t machine_pin_num_of_board_pins; @@ -671,3 +677,7 @@ const mp_obj_type_t pin_af_type = { .print = pin_af_obj_print, .locals_dict = (mp_obj_dict_t*)&pin_af_locals_dict, }; + +MP_REGISTER_ROOT_POINTER(mp_obj_t pin_class_mapper); +MP_REGISTER_ROOT_POINTER(mp_obj_t pin_class_map_dict); +MP_REGISTER_ROOT_POINTER(mp_obj_t pin_irq_handlers[NUM_OF_PINS]); diff --git a/ports/nrf/modules/music/modmusic.c b/ports/nrf/modules/music/modmusic.c index a950b03920..a0ae7f7c8e 100644 --- a/ports/nrf/modules/music/modmusic.c +++ b/ports/nrf/modules/music/modmusic.c @@ -70,7 +70,7 @@ enum { ASYNC_MUSIC_STATE_ARTICULATE, }; -#define music_data MP_STATE_PORT(music_data) +#define music_data MP_STATE_PORT(modmusic_music_data) extern volatile uint32_t ticks; @@ -510,5 +510,6 @@ const mp_obj_module_t music_module = { }; MP_REGISTER_MODULE(MP_QSTR_music, music_module); +MP_REGISTER_ROOT_POINTER(struct _music_data_t *modmusic_music_data); #endif // MICROPY_PY_MUSIC diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index fcbe71c5a0..b3a95614a4 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -310,41 +310,6 @@ typedef long mp_off_t; #define MP_STATE_PORT MP_STATE_VM -#if MICROPY_PY_MUSIC -#define ROOT_POINTERS_MUSIC \ - struct _music_data_t *music_data; -#else -#define ROOT_POINTERS_MUSIC -#endif - -#if MICROPY_PY_MACHINE_SOFT_PWM -#define ROOT_POINTERS_SOFTPWM \ - const struct _pwm_events *pwm_active_events; \ - const struct _pwm_events *pwm_pending_events; -#else -#define ROOT_POINTERS_SOFTPWM -#endif - -#if defined(NRF52840_XXAA) -#define NUM_OF_PINS 48 -#else -#define NUM_OF_PINS 32 -#endif - -#define MICROPY_PORT_ROOT_POINTERS \ - mp_obj_t pin_class_mapper; \ - mp_obj_t pin_class_map_dict; \ - mp_obj_t pin_irq_handlers[NUM_OF_PINS]; \ - \ - /* stdio is repeated on this UART object if it's not null */ \ - struct _machine_hard_uart_obj_t *board_stdio_uart; \ - \ - ROOT_POINTERS_MUSIC \ - ROOT_POINTERS_SOFTPWM \ - \ - /* micro:bit root pointers */ \ - void *async_data[2]; \ - #if MICROPY_HW_USB_CDC #define MICROPY_HW_USBDEV_TASK_HOOK extern void tud_task(void); tud_task(); #else diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index 1b31ad5acc..9405cb2e3a 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -374,3 +374,5 @@ 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); From c09e31dabbac1324b396f47274f83174dc1bfd68 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 15:20:14 -0500 Subject: [PATCH 0152/1041] pic16bit/pic16bit_mphal: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register keyboard_interrupt_obj and removes the same from mpconfigport.h. Signed-off-by: David Lechner --- ports/pic16bit/mpconfigport.h | 3 --- ports/pic16bit/pic16bit_mphal.c | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ports/pic16bit/mpconfigport.h b/ports/pic16bit/mpconfigport.h index e03fb81a6a..f1bfa4cd6f 100644 --- a/ports/pic16bit/mpconfigport.h +++ b/ports/pic16bit/mpconfigport.h @@ -91,9 +91,6 @@ typedef int mp_off_t; #define MP_STATE_PORT MP_STATE_VM -#define MICROPY_PORT_ROOT_POINTERS \ - mp_obj_t keyboard_interrupt_obj; \ - #define MICROPY_MPHALPORT_H "pic16bit_mphal.h" #define MICROPY_HW_BOARD_NAME "dsPICSK" #define MICROPY_HW_MCU_NAME "dsPIC33" diff --git a/ports/pic16bit/pic16bit_mphal.c b/ports/pic16bit/pic16bit_mphal.c index adab381934..48e8af87de 100644 --- a/ports/pic16bit/pic16bit_mphal.c +++ b/ports/pic16bit/pic16bit_mphal.c @@ -86,3 +86,5 @@ void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { uart_tx_char(*str++); } } + +MP_REGISTER_ROOT_POINTER(mp_obj_t keyboard_interrupt_obj); From f8805e24166a61b7a3eab8f049480e942623463f Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 15:22:19 -0500 Subject: [PATCH 0153/1041] renesas-ra/mpconfigport: Drop pyb_hid_report_desc root pointer. pyb_hid_report_desc is not used anywhere in the renesas-ra port (probably was copied from stm32 port). Signed-off-by: David Lechner --- ports/renesas-ra/mpconfigport.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/ports/renesas-ra/mpconfigport.h b/ports/renesas-ra/mpconfigport.h index badcce8e6f..9a8c025590 100644 --- a/ports/renesas-ra/mpconfigport.h +++ b/ports/renesas-ra/mpconfigport.h @@ -168,8 +168,6 @@ #endif #define MICROPY_PORT_ROOT_POINTERS \ - mp_obj_t pyb_hid_report_desc; \ - \ mp_obj_t pyb_config_main; \ \ mp_obj_t pyb_switch_callback; \ From 575fa61c6dc85662ce9ae4d81ef7c5cf740758c8 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 15:24:28 -0500 Subject: [PATCH 0154/1041] renesas-ra: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register all port-specific root pointers in the renesas-ra port. Signed-off-by: David Lechner --- ports/renesas-ra/extint.c | 2 ++ ports/renesas-ra/machine_uart.c | 2 ++ ports/renesas-ra/main.c | 2 ++ ports/renesas-ra/mpconfigport.h | 17 ----------------- ports/renesas-ra/mphalport.c | 2 ++ ports/renesas-ra/timer.c | 2 ++ ports/renesas-ra/usrsw.c | 2 ++ 7 files changed, 12 insertions(+), 17 deletions(-) diff --git a/ports/renesas-ra/extint.c b/ports/renesas-ra/extint.c index 05e99eb655..19caa7a3b3 100644 --- a/ports/renesas-ra/extint.c +++ b/ports/renesas-ra/extint.c @@ -399,3 +399,5 @@ void extint_init0(void) { MP_STATE_PORT(pyb_extint_callback)[i] = mp_const_none; } } + +MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_extint_callback[PYB_EXTI_NUM_VECTORS]); diff --git a/ports/renesas-ra/machine_uart.c b/ports/renesas-ra/machine_uart.c index d71562f201..4b4aa3396b 100644 --- a/ports/renesas-ra/machine_uart.c +++ b/ports/renesas-ra/machine_uart.c @@ -581,3 +581,5 @@ const mp_obj_type_t machine_uart_type = { .protocol = &uart_stream_p, .locals_dict = (mp_obj_dict_t *)&machine_uart_locals_dict, }; + +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/main.c b/ports/renesas-ra/main.c index 6f4584b685..78af1a9639 100644 --- a/ports/renesas-ra/main.c +++ b/ports/renesas-ra/main.c @@ -397,3 +397,5 @@ soft_reset_exit: goto soft_reset; } + +MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_config_main); diff --git a/ports/renesas-ra/mpconfigport.h b/ports/renesas-ra/mpconfigport.h index 9a8c025590..0f1d593033 100644 --- a/ports/renesas-ra/mpconfigport.h +++ b/ports/renesas-ra/mpconfigport.h @@ -168,23 +168,6 @@ #endif #define MICROPY_PORT_ROOT_POINTERS \ - mp_obj_t pyb_config_main; \ - \ - mp_obj_t pyb_switch_callback; \ - \ - mp_obj_t pyb_extint_callback[PYB_EXTI_NUM_VECTORS]; \ - \ - /* pointers to all Timer objects (if they have been created) */ \ - struct _pyb_timer_obj_t *pyb_timer_obj_all[MICROPY_HW_MAX_TIMER]; \ - \ - /* stdio is repeated on this UART object if it's not null */ \ - struct _machine_uart_obj_t *pyb_stdio_uart; \ - \ - /* pointers to all UART objects (if they have been created) */ \ - struct _machine_uart_obj_t *machine_uart_obj_all[MICROPY_HW_MAX_UART + MICROPY_HW_MAX_LPUART]; \ - \ - /* root pointers for sub-systems */ \ - \ /* root pointers defined by a board */ \ MICROPY_BOARD_ROOT_POINTERS \ diff --git a/ports/renesas-ra/mphalport.c b/ports/renesas-ra/mphalport.c index 6a416f431a..6e6a83aa26 100644 --- a/ports/renesas-ra/mphalport.c +++ b/ports/renesas-ra/mphalport.c @@ -118,3 +118,5 @@ void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest) { *dest++ = hexchr[mac[chr_off >> 1] >> (4 * (1 - (chr_off & 1))) & 0xf]; } } + +MP_REGISTER_ROOT_POINTER(struct _machine_uart_obj_t *pyb_stdio_uart); diff --git a/ports/renesas-ra/timer.c b/ports/renesas-ra/timer.c index 93b378ac3f..1ae936525e 100644 --- a/ports/renesas-ra/timer.c +++ b/ports/renesas-ra/timer.c @@ -567,3 +567,5 @@ void timer_irq_handler(void *param) { // } } } + +MP_REGISTER_ROOT_POINTER(struct _pyb_timer_obj_t *pyb_timer_obj_all[MICROPY_HW_MAX_TIMER]); diff --git a/ports/renesas-ra/usrsw.c b/ports/renesas-ra/usrsw.c index b0e2396cde..5e11f48e63 100644 --- a/ports/renesas-ra/usrsw.c +++ b/ports/renesas-ra/usrsw.c @@ -144,4 +144,6 @@ const mp_obj_type_t pyb_switch_type = { .locals_dict = (mp_obj_dict_t *)&pyb_switch_locals_dict, }; +MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_switch_callback); + #endif // MICROPY_HW_HAS_SWITCH From ffa22b8f97dcd4696d1e7628c56f9fe2d93f3049 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 14:47:42 -0500 Subject: [PATCH 0155/1041] rp2: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register all port-specific root pointers in the rp2 port. Signed-off-by: David Lechner --- ports/rp2/machine_i2s.c | 2 ++ ports/rp2/machine_pin.c | 2 ++ ports/rp2/machine_uart.c | 3 +++ ports/rp2/mpbthciport.c | 2 ++ ports/rp2/mpconfigport.h | 13 ------------- ports/rp2/rp2_pio.c | 3 +++ 6 files changed, 12 insertions(+), 13 deletions(-) diff --git a/ports/rp2/machine_i2s.c b/ports/rp2/machine_i2s.c index 988e88d36f..1015ba1017 100644 --- a/ports/rp2/machine_i2s.c +++ b/ports/rp2/machine_i2s.c @@ -1147,3 +1147,5 @@ const mp_obj_type_t machine_i2s_type = { .make_new = machine_i2s_make_new, .locals_dict = (mp_obj_dict_t *)&machine_i2s_locals_dict, }; + +MP_REGISTER_ROOT_POINTER(void *machine_i2s_obj[2]); diff --git a/ports/rp2/machine_pin.c b/ports/rp2/machine_pin.c index a0c5dead90..705f61242c 100644 --- a/ports/rp2/machine_pin.c +++ b/ports/rp2/machine_pin.c @@ -687,3 +687,5 @@ mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t obj) { } return pin->id; } + +MP_REGISTER_ROOT_POINTER(void *machine_pin_irq_obj[30]); diff --git a/ports/rp2/machine_uart.c b/ports/rp2/machine_uart.c index fafa3c1b56..77ccdb5f50 100644 --- a/ports/rp2/machine_uart.c +++ b/ports/rp2/machine_uart.c @@ -562,3 +562,6 @@ const mp_obj_type_t machine_uart_type = { .protocol = &uart_stream_p, .locals_dict = (mp_obj_dict_t *)&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/mpbthciport.c b/ports/rp2/mpbthciport.c index 58639fd5b0..cd41da017a 100644 --- a/ports/rp2/mpbthciport.c +++ b/ports/rp2/mpbthciport.c @@ -197,4 +197,6 @@ MP_WEAK int mp_bluetooth_hci_controller_wakeup(void) { return 0; } +MP_REGISTER_ROOT_POINTER(struct _machine_uart_obj_t *mp_bthci_uart); + #endif // MICROPY_PY_BLUETOOTH diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 182a3db02d..82e8de14db 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -135,12 +135,6 @@ #define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) #endif -#if MICROPY_PY_BLUETOOTH -#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH struct _machine_uart_obj_t *mp_bthci_uart; -#else -#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH -#endif - // By default networking should include sockets, ssl, websockets, webrepl, dupterm. #if MICROPY_PY_NETWORK #ifndef MICROPY_PY_USOCKET @@ -215,14 +209,7 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k; #endif #define MICROPY_PORT_ROOT_POINTERS \ - void *machine_pin_irq_obj[30]; \ - void *rp2_pio_irq_obj[2]; \ - void *rp2_state_machine_irq_obj[8]; \ - void *rp2_uart_rx_buffer[2]; \ - void *rp2_uart_tx_buffer[2]; \ - void *machine_i2s_obj[2]; \ MICROPY_BOARD_ROOT_POINTERS \ - MICROPY_PORT_ROOT_POINTER_BLUETOOTH \ #define MP_STATE_PORT MP_STATE_VM diff --git a/ports/rp2/rp2_pio.c b/ports/rp2/rp2_pio.c index 9900616966..072644eba6 100644 --- a/ports/rp2/rp2_pio.c +++ b/ports/rp2/rp2_pio.c @@ -839,3 +839,6 @@ STATIC const mp_irq_methods_t rp2_state_machine_irq_methods = { .trigger = rp2_state_machine_irq_trigger, .info = rp2_state_machine_irq_info, }; + +MP_REGISTER_ROOT_POINTER(void *rp2_pio_irq_obj[2]); +MP_REGISTER_ROOT_POINTER(void *rp2_state_machine_irq_obj[8]); From 816e4537f27ce6e1737225dbfaece0ec75150913 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 14:48:59 -0500 Subject: [PATCH 0156/1041] stm32: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register all port-specific root pointers in the stm32 port. Signed-off-by: David Lechner --- ports/stm32/extint.c | 2 ++ ports/stm32/machine_i2s.c | 2 ++ ports/stm32/main.c | 2 ++ ports/stm32/mpconfigport.h | 29 ----------------------------- ports/stm32/mphalport.c | 2 ++ ports/stm32/pin.c | 3 +++ ports/stm32/pyb_can.c | 2 ++ ports/stm32/timer.c | 2 ++ ports/stm32/uart.c | 2 ++ ports/stm32/usb.c | 5 +++++ ports/stm32/usrsw.c | 2 ++ 11 files changed, 24 insertions(+), 29 deletions(-) diff --git a/ports/stm32/extint.c b/ports/stm32/extint.c index fd4dca276b..d68275bf19 100644 --- a/ports/stm32/extint.c +++ b/ports/stm32/extint.c @@ -720,3 +720,5 @@ void Handle_EXTI_Irq(uint32_t line) { } } } + +MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_extint_callback[PYB_EXTI_NUM_VECTORS]); diff --git a/ports/stm32/machine_i2s.c b/ports/stm32/machine_i2s.c index a9d0da43d4..4f583a53e8 100644 --- a/ports/stm32/machine_i2s.c +++ b/ports/stm32/machine_i2s.c @@ -1125,4 +1125,6 @@ const mp_obj_type_t machine_i2s_type = { .locals_dict = (mp_obj_dict_t *)&machine_i2s_locals_dict, }; +MP_REGISTER_ROOT_POINTER(struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_MAX_I2S]); + #endif // MICROPY_HW_ENABLE_I2S diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 54d9b05be1..44732cef9e 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -659,3 +659,5 @@ soft_reset_exit: goto soft_reset; } + +MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_config_main); diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 83986296c9..bb73b83371 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -243,35 +243,6 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_cc3k; #endif #define MICROPY_PORT_ROOT_POINTERS \ - mp_obj_t pyb_hid_report_desc; \ - \ - mp_obj_t pyb_config_main; \ - \ - mp_obj_t pyb_switch_callback; \ - \ - mp_obj_t pin_class_mapper; \ - mp_obj_t pin_class_map_dict; \ - \ - mp_obj_t pyb_extint_callback[PYB_EXTI_NUM_VECTORS]; \ - \ - /* pointers to all Timer objects (if they have been created) */ \ - struct _pyb_timer_obj_t *pyb_timer_obj_all[MICROPY_HW_MAX_TIMER]; \ - \ - /* stdio is repeated on this UART object if it's not null */ \ - struct _pyb_uart_obj_t *pyb_stdio_uart; \ - \ - /* pointers to all UART objects (if they have been created) */ \ - struct _pyb_uart_obj_t *pyb_uart_obj_all[MICROPY_HW_MAX_UART + MICROPY_HW_MAX_LPUART]; \ - \ - /* pointers to all CAN objects (if they have been created) */ \ - struct _pyb_can_obj_t *pyb_can_obj_all[MICROPY_HW_MAX_CAN]; \ - \ - /* pointers to all I2S objects (if they have been created) */ \ - struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_MAX_I2S]; \ - \ - /* USB_VCP IRQ callbacks (if they have been set) */ \ - mp_obj_t pyb_usb_vcp_irq[MICROPY_HW_USB_CDC_NUM]; \ - \ /* root pointers defined by a board */ \ MICROPY_BOARD_ROOT_POINTERS \ diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index 477192330b..619bde69bf 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -177,3 +177,5 @@ void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest) { *dest++ = hexchr[mac[chr_off >> 1] >> (4 * (1 - (chr_off & 1))) & 0xf]; } } + +MP_REGISTER_ROOT_POINTER(struct _pyb_uart_obj_t *pyb_stdio_uart); diff --git a/ports/stm32/pin.c b/ports/stm32/pin.c index b490a09b7f..af6bafc43f 100644 --- a/ports/stm32/pin.c +++ b/ports/stm32/pin.c @@ -675,3 +675,6 @@ const mp_obj_type_t pin_af_type = { .print = pin_af_obj_print, .locals_dict = (mp_obj_dict_t *)&pin_af_locals_dict, }; + +MP_REGISTER_ROOT_POINTER(mp_obj_t pin_class_mapper); +MP_REGISTER_ROOT_POINTER(mp_obj_t pin_class_map_dict); diff --git a/ports/stm32/pyb_can.c b/ports/stm32/pyb_can.c index 3fa0f6baea..ff41de3186 100644 --- a/ports/stm32/pyb_can.c +++ b/ports/stm32/pyb_can.c @@ -1081,4 +1081,6 @@ const mp_obj_type_t pyb_can_type = { .locals_dict = (mp_obj_dict_t *)&pyb_can_locals_dict, }; +MP_REGISTER_ROOT_POINTER(struct _pyb_can_obj_t *pyb_can_obj_all[MICROPY_HW_MAX_CAN]); + #endif // MICROPY_HW_ENABLE_CAN diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index 8181885e2e..0cef60cb62 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -1684,3 +1684,5 @@ void timer_irq_handler(uint tim_id) { } } } + +MP_REGISTER_ROOT_POINTER(struct _pyb_timer_obj_t *pyb_timer_obj_all[MICROPY_HW_MAX_TIMER]); diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index 34d8246d5f..cea49f4ba1 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -1202,3 +1202,5 @@ const mp_irq_methods_t uart_irq_methods = { .trigger = uart_irq_trigger, .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]); diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index cf9faed112..2a669b2a28 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -1152,4 +1152,9 @@ void USR_KEYBRD_ProcessData(uint8_t pbuf) { #endif // USE_HOST_MODE +#if MICROPY_HW_USB_HID +MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_hid_report_desc); +#endif +MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_usb_vcp_irq[MICROPY_HW_USB_CDC_NUM]); + #endif // MICROPY_HW_ENABLE_USB diff --git a/ports/stm32/usrsw.c b/ports/stm32/usrsw.c index 596efba053..60aae1c883 100644 --- a/ports/stm32/usrsw.c +++ b/ports/stm32/usrsw.c @@ -143,4 +143,6 @@ const mp_obj_type_t pyb_switch_type = { .locals_dict = (mp_obj_dict_t *)&pyb_switch_locals_dict, }; +MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_switch_callback); + #endif // MICROPY_HW_HAS_SWITCH From 2d8589f1a5a04b9f3f2c96b5f99f9b8e740af594 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 16:02:10 -0500 Subject: [PATCH 0157/1041] teensy/mpconfigport: Drop unused root pointers. pin_class_mapper and pin_class_map_dict are not used in the teensy port and can be removed. Signed-off-by: David Lechner --- ports/teensy/mpconfigport.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/ports/teensy/mpconfigport.h b/ports/teensy/mpconfigport.h index b870263dfc..e57fae15e9 100644 --- a/ports/teensy/mpconfigport.h +++ b/ports/teensy/mpconfigport.h @@ -42,8 +42,6 @@ extern const struct _mp_obj_module_t pyb_module; #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ - mp_obj_t pin_class_mapper; \ - mp_obj_t pin_class_map_dict; \ struct _pyb_uart_obj_t *pyb_stdio_uart; \ // type definitions for the specific machine From 186be074a7e5ac7a78da2fa78aa4cacca7a3fe89 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 15:51:12 -0500 Subject: [PATCH 0158/1041] teensy/teensy_hal: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register pyb_stdio_uart and removes the same from mpconfigport.h. Signed-off-by: David Lechner --- ports/teensy/mpconfigport.h | 3 --- ports/teensy/teensy_hal.c | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ports/teensy/mpconfigport.h b/ports/teensy/mpconfigport.h index e57fae15e9..f67eb66fab 100644 --- a/ports/teensy/mpconfigport.h +++ b/ports/teensy/mpconfigport.h @@ -41,9 +41,6 @@ extern const struct _mp_obj_module_t pyb_module; #define MP_STATE_PORT MP_STATE_VM -#define MICROPY_PORT_ROOT_POINTERS \ - struct _pyb_uart_obj_t *pyb_stdio_uart; \ - // type definitions for the specific machine #define UINT_FMT "%u" diff --git a/ports/teensy/teensy_hal.c b/ports/teensy/teensy_hal.c index 342e7c6501..93103319b5 100644 --- a/ports/teensy/teensy_hal.c +++ b/ports/teensy/teensy_hal.c @@ -77,3 +77,5 @@ void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) { void extint_register_pin(const void *pin, uint32_t mode, int hard_irq, mp_obj_t callback_obj) { mp_raise_NotImplementedError(NULL); } + +MP_REGISTER_ROOT_POINTER(struct _pyb_uart_obj_t *pyb_stdio_uart); From ccda7686a436f4d172325cce1fbf1d49165e31fd Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 15:51:12 -0500 Subject: [PATCH 0159/1041] zephyr: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register port-specific root pointers for the zephyr port. Signed-off-by: David Lechner --- ports/zephyr/machine_pin.c | 3 +++ ports/zephyr/modbluetooth_zephyr.c | 2 ++ ports/zephyr/mpconfigport.h | 4 ---- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ports/zephyr/machine_pin.c b/ports/zephyr/machine_pin.c index dee66a5c69..aa55c04104 100644 --- a/ports/zephyr/machine_pin.c +++ b/ports/zephyr/machine_pin.c @@ -322,4 +322,7 @@ STATIC const mp_irq_methods_t machine_pin_irq_methods = { .info = machine_pin_irq_info, }; +/* Linked list of pin irq objects */ +MP_REGISTER_ROOT_POINTER(void *machine_pin_irq_list); + #endif // MICROPY_PY_MACHINE diff --git a/ports/zephyr/modbluetooth_zephyr.c b/ports/zephyr/modbluetooth_zephyr.c index ba13064f33..4d4b19a1d9 100644 --- a/ports/zephyr/modbluetooth_zephyr.c +++ b/ports/zephyr/modbluetooth_zephyr.c @@ -418,4 +418,6 @@ int mp_bluetooth_gap_peripheral_connect_cancel(void) { #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE +MP_REGISTER_ROOT_POINTER(struct _mp_bluetooth_zephyr_root_pointers_t *bluetooth_zephyr_root_pointers); + #endif // MICROPY_PY_BLUETOOTH diff --git a/ports/zephyr/mpconfigport.h b/ports/zephyr/mpconfigport.h index 1be755baab..586b0ec916 100644 --- a/ports/zephyr/mpconfigport.h +++ b/ports/zephyr/mpconfigport.h @@ -133,10 +133,6 @@ typedef long mp_off_t; #define MP_STATE_PORT MP_STATE_VM -#define MICROPY_PORT_ROOT_POINTERS \ - void *machine_pin_irq_list; /* Linked list of pin irq objects */ \ - struct _mp_bluetooth_zephyr_root_pointers_t *bluetooth_zephyr_root_pointers; - // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, From 7e4b205cb00013b272e4cf9fac128866bf0e1f21 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Jul 2022 16:08:57 -0500 Subject: [PATCH 0160/1041] py/mpstate: Drop MICROPY_PORT_ROOT_POINTERS from mp_state_vm_t. All in-tree uses of MICROPY_PORT_ROOT_POINTERS have been replaced with MP_REGISTER_ROOT_POINTER(), so now we can remove both MICROPY_PORT_ROOT_POINTERS and MICROPY_BOARD_ROOT_POINTERS from the code and remaining config files. Signed-off-by: David Lechner --- ports/mimxrt/mpconfigport.h | 8 -------- ports/renesas-ra/mpconfigport.h | 8 -------- ports/rp2/mpconfigport.h | 7 ------- ports/stm32/mpconfigport.h | 8 -------- ports/unix/variants/minimal/mpconfigvariant.h | 2 -- py/mpconfig.h | 5 ----- py/mpstate.h | 3 --- 7 files changed, 41 deletions(-) diff --git a/ports/mimxrt/mpconfigport.h b/ports/mimxrt/mpconfigport.h index 2c7446e360..676e563c7b 100644 --- a/ports/mimxrt/mpconfigport.h +++ b/ports/mimxrt/mpconfigport.h @@ -237,14 +237,6 @@ extern const struct _mp_obj_type_t network_lan_type; #define MICROPY_HW_PIT_NUM_CHANNELS 3 -#ifndef MICROPY_BOARD_ROOT_POINTERS -#define MICROPY_BOARD_ROOT_POINTERS -#endif - -#define MICROPY_PORT_ROOT_POINTERS \ - /* root pointers defined by a board */ \ - MICROPY_BOARD_ROOT_POINTERS \ - #define MP_STATE_PORT MP_STATE_VM // Miscellaneous settings diff --git a/ports/renesas-ra/mpconfigport.h b/ports/renesas-ra/mpconfigport.h index 0f1d593033..8ecc17fcb4 100644 --- a/ports/renesas-ra/mpconfigport.h +++ b/ports/renesas-ra/mpconfigport.h @@ -163,14 +163,6 @@ #define MP_STATE_PORT MP_STATE_VM -#ifndef MICROPY_BOARD_ROOT_POINTERS -#define MICROPY_BOARD_ROOT_POINTERS -#endif - -#define MICROPY_PORT_ROOT_POINTERS \ - /* root pointers defined by a board */ \ - MICROPY_BOARD_ROOT_POINTERS \ - // type definitions for the specific machine #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((uint32_t)(p) | 1)) diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 82e8de14db..3f332b6a82 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -204,13 +204,6 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k; MICROPY_HW_NIC_WIZNET5K \ MICROPY_BOARD_NETWORK_INTERFACES \ -#ifndef MICROPY_BOARD_ROOT_POINTERS -#define MICROPY_BOARD_ROOT_POINTERS -#endif - -#define MICROPY_PORT_ROOT_POINTERS \ - MICROPY_BOARD_ROOT_POINTERS \ - #define MP_STATE_PORT MP_STATE_VM // Miscellaneous settings diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index bb73b83371..e44fa2260c 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -238,14 +238,6 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_cc3k; #define MP_STATE_PORT MP_STATE_VM -#ifndef MICROPY_BOARD_ROOT_POINTERS -#define MICROPY_BOARD_ROOT_POINTERS -#endif - -#define MICROPY_PORT_ROOT_POINTERS \ - /* root pointers defined by a board */ \ - MICROPY_BOARD_ROOT_POINTERS \ - // type definitions for the specific machine #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((uint32_t)(p) | 1)) diff --git a/ports/unix/variants/minimal/mpconfigvariant.h b/ports/unix/variants/minimal/mpconfigvariant.h index 60d194b6a1..1e378e94d7 100644 --- a/ports/unix/variants/minimal/mpconfigvariant.h +++ b/ports/unix/variants/minimal/mpconfigvariant.h @@ -107,8 +107,6 @@ #define MICROPY_PY_UHASHLIB (0) #define MICROPY_PY_UBINASCII (0) -#define MICROPY_PORT_ROOT_POINTERS \ - #define mp_type_fileio mp_type_vfs_posix_fileio #define mp_type_textio mp_type_vfs_posix_textio diff --git a/py/mpconfig.h b/py/mpconfig.h index adaa3ec1fb..ee0123be34 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -1659,11 +1659,6 @@ typedef double mp_float_t; #define MICROPY_PORT_CONSTANTS #endif -// Any root pointers for GC scanning - see mpstate.c -#ifndef MICROPY_PORT_ROOT_POINTERS -#define MICROPY_PORT_ROOT_POINTERS -#endif - /*****************************************************************************/ /* Hooks for a port to wrap functions with attributes */ diff --git a/py/mpstate.h b/py/mpstate.h index 07a4f38609..b51e72cd84 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -189,9 +189,6 @@ typedef struct _mp_state_vm_t { mp_obj_t track_reloc_code_list; #endif - // include any root pointers defined by a port - MICROPY_PORT_ROOT_POINTERS - // Include any root pointers registered with MP_REGISTER_ROOT_POINTER(). #ifndef NO_QSTR // Only include root pointer definitions when not doing qstr extraction, because From 68f46342aa4c20f263cc688cc86d03d03207921e Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 2 Jul 2022 15:05:41 -0500 Subject: [PATCH 0161/1041] shared/runtime/pyexec: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register repl_line instead of using a conditional inside of mp_state_vm_t. Signed-off-by: David Lechner --- ports/minimal/Makefile | 2 +- ports/powerpc/Makefile | 2 +- py/mpstate.h | 4 ---- shared/runtime/pyexec.c | 2 ++ 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/ports/minimal/Makefile b/ports/minimal/Makefile index ac74925b57..4a17df6803 100644 --- a/ports/minimal/Makefile +++ b/ports/minimal/Makefile @@ -68,7 +68,7 @@ SRC_C += $(SRC_MOD) SRC_CXX += $(SRC_MOD_CXX) -SRC_QSTR += shared/readline/readline.c +SRC_QSTR += shared/readline/readline.c shared/runtime/pyexec.c SRC_QSTR += $(SRC_MOD) $(SRC_MOD_CXX) OBJ += $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) diff --git a/ports/powerpc/Makefile b/ports/powerpc/Makefile index f1ebd6764c..12ae485bb8 100644 --- a/ports/powerpc/Makefile +++ b/ports/powerpc/Makefile @@ -42,7 +42,7 @@ SRC_C = \ shared/runtime/stdout_helpers.c \ $(BUILD)/_frozen_mpy.c \ -SRC_QSTR += shared/readline/readline.c +SRC_QSTR += shared/readline/readline.c shared/runtime/pyexec.c OBJ = $(PY_CORE_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) diff --git a/py/mpstate.h b/py/mpstate.h index b51e72cd84..67146d282b 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -198,10 +198,6 @@ typedef struct _mp_state_vm_t { // root pointers for extmod - #if MICROPY_REPL_EVENT_DRIVEN - vstr_t *repl_line; - #endif - #if MICROPY_PY_OS_DUPTERM mp_obj_t dupterm_objs[MICROPY_PY_OS_DUPTERM]; #endif diff --git a/shared/runtime/pyexec.c b/shared/runtime/pyexec.c index 2763319c01..2c9f1e80ff 100644 --- a/shared/runtime/pyexec.c +++ b/shared/runtime/pyexec.c @@ -488,6 +488,8 @@ int pyexec_event_repl_process_char(int c) { return res; } +MP_REGISTER_ROOT_POINTER(vstr_t * repl_line); + #else // MICROPY_REPL_EVENT_DRIVEN int pyexec_raw_repl(void) { From 631b692177ef1e6ba2832ee224e2680ac9982dbf Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 2 Jul 2022 15:05:41 -0500 Subject: [PATCH 0162/1041] extmod/uos_dupterm: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register dupterm_objs instead of using a conditional inside of mp_state_vm_t. Signed-off-by: David Lechner --- extmod/uos_dupterm.c | 4 +++- py/mpstate.h | 4 ---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/extmod/uos_dupterm.c b/extmod/uos_dupterm.c index e18d133b91..826bf1715d 100644 --- a/extmod/uos_dupterm.c +++ b/extmod/uos_dupterm.c @@ -201,4 +201,6 @@ STATIC mp_obj_t mp_uos_dupterm(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj, 1, 2, mp_uos_dupterm); -#endif +MP_REGISTER_ROOT_POINTER(mp_obj_t dupterm_objs[MICROPY_PY_OS_DUPTERM]); + +#endif // MICROPY_PY_OS_DUPTERM diff --git a/py/mpstate.h b/py/mpstate.h index 67146d282b..53bb882ceb 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -198,10 +198,6 @@ typedef struct _mp_state_vm_t { // root pointers for extmod - #if MICROPY_PY_OS_DUPTERM - mp_obj_t dupterm_objs[MICROPY_PY_OS_DUPTERM]; - #endif - #if MICROPY_PY_LWIP_SLIP mp_obj_t lwip_slip_stream; #endif From d532c55e3b8ee7955bea99fc79ccd74d9a35f757 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 2 Jul 2022 15:05:41 -0500 Subject: [PATCH 0163/1041] extmod/modlwip: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register lwip_slip_stream instead of using a conditional inside of mp_state_vm_t. Signed-off-by: David Lechner --- extmod/modlwip.c | 2 ++ py/mpstate.h | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/extmod/modlwip.c b/extmod/modlwip.c index bbfd3a2253..25669228df 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -1783,4 +1783,6 @@ MP_REGISTER_MODULE(MP_QSTR_lwip, mp_module_lwip); // On LWIP-ports, this is the usocket module (replaces extmod/modusocket.c). MP_REGISTER_MODULE(MP_QSTR_usocket, mp_module_lwip); +MP_REGISTER_ROOT_POINTER(mp_obj_t lwip_slip_stream); + #endif // MICROPY_PY_LWIP diff --git a/py/mpstate.h b/py/mpstate.h index 53bb882ceb..7ad9d6b293 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -198,10 +198,6 @@ typedef struct _mp_state_vm_t { // root pointers for extmod - #if MICROPY_PY_LWIP_SLIP - mp_obj_t lwip_slip_stream; - #endif - #if MICROPY_VFS struct _mp_vfs_mount_t *vfs_cur; struct _mp_vfs_mount_t *vfs_mount_table; From 32e32bd761e91b9aa21f98b4f4fd4d96c723fdb6 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 2 Jul 2022 15:05:41 -0500 Subject: [PATCH 0164/1041] extmod/vfs: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register vfs_cur and vfs_mount_table instead of using a conditional inside of mp_state_vm_t. Signed-off-by: David Lechner --- extmod/vfs.c | 3 +++ py/mpstate.h | 5 ----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/extmod/vfs.c b/extmod/vfs.c index 8bcead190d..2799622b38 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -547,4 +547,7 @@ int mp_vfs_mount_and_chdir_protected(mp_obj_t bdev, mp_obj_t mount_point) { return ret; } +MP_REGISTER_ROOT_POINTER(struct _mp_vfs_mount_t *vfs_cur); +MP_REGISTER_ROOT_POINTER(struct _mp_vfs_mount_t *vfs_mount_table); + #endif // MICROPY_VFS diff --git a/py/mpstate.h b/py/mpstate.h index 7ad9d6b293..784eff0a26 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -198,11 +198,6 @@ typedef struct _mp_state_vm_t { // root pointers for extmod - #if MICROPY_VFS - struct _mp_vfs_mount_t *vfs_cur; - struct _mp_vfs_mount_t *vfs_mount_table; - #endif - #if MICROPY_PY_BLUETOOTH mp_obj_t bluetooth; #endif From 2c728c533059a09635a99facfcce18bda8768497 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 2 Jul 2022 15:05:41 -0500 Subject: [PATCH 0165/1041] extmod/modbluetooth: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register `bluetooth` instead of using a conditional inside of mp_state_vm_t. Signed-off-by: David Lechner --- extmod/modbluetooth.c | 2 ++ py/mpstate.h | 6 ------ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 6bdea1616f..9956671863 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -1675,4 +1675,6 @@ int mp_bluetooth_gatts_db_resize(mp_gatts_db_t db, uint16_t handle, size_t len, return entry ? 0 : MP_EINVAL; } +MP_REGISTER_ROOT_POINTER(mp_obj_t bluetooth); + #endif // MICROPY_PY_BLUETOOTH diff --git a/py/mpstate.h b/py/mpstate.h index 784eff0a26..a268e8685b 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -196,12 +196,6 @@ typedef struct _mp_state_vm_t { #include "genhdr/root_pointers.h" #endif - // root pointers for extmod - - #if MICROPY_PY_BLUETOOTH - mp_obj_t bluetooth; - #endif - // // END ROOT POINTER SECTION //////////////////////////////////////////////////////////// From a98aa66df64e2676a311139f43dee9d13bae2c42 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 2 Jul 2022 15:05:41 -0500 Subject: [PATCH 0166/1041] py/persistentcode: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register track_reloc_code_list instead of using a conditional inside of mp_state_vm_t. Signed-off-by: David Lechner --- py/mpstate.h | 5 ----- py/persistentcode.c | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/py/mpstate.h b/py/mpstate.h index a268e8685b..87d367769e 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -184,11 +184,6 @@ typedef struct _mp_state_vm_t { mp_obj_dict_t *mp_module_builtins_override_dict; #endif - #if MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE - // An mp_obj_list_t that tracks relocated native code to prevent the GC from reclaiming them. - mp_obj_t track_reloc_code_list; - #endif - // Include any root pointers registered with MP_REGISTER_ROOT_POINTER(). #ifndef NO_QSTR // Only include root pointer definitions when not doing qstr extraction, because diff --git a/py/persistentcode.c b/py/persistentcode.c index fbef0b2c0f..a8e7429550 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -644,3 +644,8 @@ void mp_raw_code_save_file(mp_compiled_module_t *cm, const char *filename) { #endif // MICROPY_PERSISTENT_CODE_SAVE_FILE #endif // MICROPY_PERSISTENT_CODE_SAVE + +#if MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE +// An mp_obj_list_t that tracks relocated native code to prevent the GC from reclaiming them. +MP_REGISTER_ROOT_POINTER(mp_obj_t track_reloc_code_list); +#endif From 85b4f36100aceeddd246f8b3a64436adc8dff867 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 2 Jul 2022 15:05:41 -0500 Subject: [PATCH 0167/1041] py/modsys: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register cur_exception, sys_exitfunc, mp_sys_path_obj, mp_sys_argv_obj and sys_mutable instead of using a conditional inside of mp_state_vm_t. Signed-off-by: David Lechner --- py/modsys.c | 20 ++++++++++++++++++++ py/mpstate.h | 22 ---------------------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/py/modsys.c b/py/modsys.c index a090f1212d..56e83029c4 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -286,4 +286,24 @@ const mp_obj_module_t mp_module_sys = { MP_REGISTER_MODULE(MP_QSTR_usys, mp_module_sys); +// If MICROPY_PY_SYS_PATH_ARGV_DEFAULTS is not enabled then these two lists +// must be initialised after the call to mp_init. +MP_REGISTER_ROOT_POINTER(mp_obj_list_t mp_sys_path_obj); +MP_REGISTER_ROOT_POINTER(mp_obj_list_t mp_sys_argv_obj); + +#if MICROPY_PY_SYS_EXC_INFO +// current exception being handled, for sys.exc_info() +MP_REGISTER_ROOT_POINTER(mp_obj_base_t * cur_exception); #endif + +#if MICROPY_PY_SYS_ATEXIT +// exposed through sys.atexit function +MP_REGISTER_ROOT_POINTER(mp_obj_t sys_exitfunc); +#endif + +#if MICROPY_PY_SYS_ATTR_DELEGATION +// Contains mutable sys attributes. +MP_REGISTER_ROOT_POINTER(mp_obj_t sys_mutable[MP_SYS_MUTABLE_NUM]); +#endif + +#endif // MICROPY_PY_SYS diff --git a/py/mpstate.h b/py/mpstate.h index 87d367769e..b7c41c81fc 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -154,31 +154,9 @@ typedef struct _mp_state_vm_t { mp_sched_item_t sched_queue[MICROPY_SCHEDULER_DEPTH]; #endif - // current exception being handled, for sys.exc_info() - #if MICROPY_PY_SYS_EXC_INFO - mp_obj_base_t *cur_exception; - #endif - - #if MICROPY_PY_SYS_ATEXIT - // exposed through sys.atexit function - mp_obj_t sys_exitfunc; - #endif - // dictionary for the __main__ module mp_obj_dict_t dict_main; - #if MICROPY_PY_SYS - // If MICROPY_PY_SYS_PATH_ARGV_DEFAULTS is not enabled then these two lists - // must be initialised after the call to mp_init. - mp_obj_list_t mp_sys_path_obj; - mp_obj_list_t mp_sys_argv_obj; - - #if MICROPY_PY_SYS_ATTR_DELEGATION - // Contains mutable sys attributes. - mp_obj_t sys_mutable[MP_SYS_MUTABLE_NUM]; - #endif - #endif - // dictionary for overridden builtins #if MICROPY_CAN_OVERRIDE_BUILTINS mp_obj_dict_t *mp_module_builtins_override_dict; From a1ef5ac65db8c7509bef5d3db9ba6de9fbb4ef40 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 2 Jul 2022 15:05:41 -0500 Subject: [PATCH 0168/1041] py/scheduler: Use MP_REGISTER_ROOT_POINTER(). This uses MP_REGISTER_ROOT_POINTER() to register sched_queue instead of using a conditional inside of mp_state_vm_t. Signed-off-by: David Lechner --- py/mpstate.h | 4 ---- py/scheduler.c | 2 ++ 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/py/mpstate.h b/py/mpstate.h index b7c41c81fc..1b6e623ca9 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -150,10 +150,6 @@ typedef struct _mp_state_vm_t { // dictionary with loaded modules (may be exposed as sys.modules) mp_obj_dict_t mp_loaded_modules_dict; - #if MICROPY_ENABLE_SCHEDULER - mp_sched_item_t sched_queue[MICROPY_SCHEDULER_DEPTH]; - #endif - // dictionary for the __main__ module mp_obj_dict_t dict_main; diff --git a/py/scheduler.c b/py/scheduler.c index e8ad4e4f17..db090b0991 100644 --- a/py/scheduler.c +++ b/py/scheduler.c @@ -196,6 +196,8 @@ bool mp_sched_schedule_node(mp_sched_node_t *node, mp_sched_callback_t callback) } #endif +MP_REGISTER_ROOT_POINTER(mp_sched_item_t sched_queue[MICROPY_SCHEDULER_DEPTH]); + #endif // MICROPY_ENABLE_SCHEDULER // Called periodically from the VM or from "waiting" code (e.g. sleep) to From 1d23c01dd6d2bcf64dec86ceed77db7ecac8a8d9 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 15 Jul 2022 15:13:42 +1000 Subject: [PATCH 0169/1041] stm32/Makefile: Workaround LTO linker order bug in binutils <2.35. Assembly files with weak symbols need to be linked first to avoid issues with the weak symbols being incorrectly linked instead of strong ones. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83967 and https://bugs.launchpad.net/gcc-arm-embedded/+bug/1747966 This is the workaround suggested in comment 10 of the gcc-arm-embedded bug. Signed-off-by: Angus Gratton --- ports/stm32/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index f1c22c2a9a..bab62eaae9 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -534,6 +534,9 @@ endif endif +# SRC_O should be placed first to work around this LTO bug with binutils <2.35: +# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83967 +OBJ += $(addprefix $(BUILD)/, $(SRC_O)) OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) OBJ += $(LIBM_O) @@ -544,7 +547,6 @@ OBJ += $(addprefix $(BUILD)/, $(HAL_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(USBDEV_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_O)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) OBJ += $(BUILD)/pins_$(BOARD).o From 18ecc29bb8eedcc1f4fd999310467f0942eeaaac Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 17 Jul 2022 00:48:41 +1000 Subject: [PATCH 0170/1041] tests/extmod/ussl_basic: Make test run on axtls and mbedtls. Fixes issue #4364. Signed-off-by: Damien George --- tests/extmod/ussl_basic.py | 51 ++++++++++++++++++++-------------- tests/extmod/ussl_basic.py.exp | 13 +++++---- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/tests/extmod/ussl_basic.py b/tests/extmod/ussl_basic.py index 9e1821dca9..dd3b6f0b91 100644 --- a/tests/extmod/ussl_basic.py +++ b/tests/extmod/ussl_basic.py @@ -7,40 +7,49 @@ except ImportError: print("SKIP") raise SystemExit + +class TestSocket(io.IOBase): + def write(self, buf): + return len(buf) + + def readinto(self, buf): + return 0 + + def ioctl(self, cmd, arg): + print("TestSocket.ioctl", cmd, arg) + return 0 + + def setblocking(self, value): + print("TestSocket.setblocking({})".format(value)) + + # create in client mode try: - ss = ssl.wrap_socket(io.BytesIO(), server_hostname="test.example.com") + ss = ssl.wrap_socket(TestSocket(), server_hostname="test.example.com") except OSError as er: - print("wrap_socket:", repr(er)) + print("OSError: client") # create in server mode (can use this object for further tests) -socket = io.BytesIO() -ss = ssl.wrap_socket(socket, server_side=1) +ss = ssl.wrap_socket(TestSocket(), server_side=1, do_handshake=0) # print print(repr(ss)[:12]) -# setblocking() propagates call to the underlying stream object, and -# io.BytesIO doesn't have setblocking() (in CPython too). -# try: -# ss.setblocking(False) -# except NotImplementedError: -# print('setblocking: NotImplementedError') -# ss.setblocking(True) +# setblocking() propagates call to the underlying stream object +ss.setblocking(False) +ss.setblocking(True) # write -print(ss.write(b"aaaa")) +try: + ss.write(b"aaaa") +except OSError: + pass # read (underlying socket has no data) -print(ss.read(8)) - -# read (underlying socket has data, but it's bad data) -socket.write(b"aaaaaaaaaaaaaaaa") -socket.seek(0) try: ss.read(8) -except OSError as er: - print("read:", repr(er)) +except OSError: + pass # close ss.close() @@ -51,10 +60,10 @@ ss.close() try: ss.read(10) except OSError as er: - print("read:", repr(er)) + print("OSError: read") # write on closed socket try: ss.write(b"aaaa") except OSError as er: - print("write:", repr(er)) + print("OSError: write") diff --git a/tests/extmod/ussl_basic.py.exp b/tests/extmod/ussl_basic.py.exp index eb7df855aa..34355c5183 100644 --- a/tests/extmod/ussl_basic.py.exp +++ b/tests/extmod/ussl_basic.py.exp @@ -1,7 +1,8 @@ -wrap_socket: OSError(-256, 'CONN_LOST') +OSError: client <_SSLSocket -4 -b'' -read: OSError(-261,) -read: OSError(9,) -write: OSError(9,) +TestSocket.setblocking(False) +TestSocket.setblocking(True) +TestSocket.ioctl 4 0 +TestSocket.ioctl 4 0 +OSError: read +OSError: write From e30e7ced6fa73605cd6ea5d943725e69e8501356 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 15 Jul 2022 12:12:57 +1000 Subject: [PATCH 0171/1041] unix/mpconfigport: Make MICROPY_EVENT_POLL_HOOK call usleep directly. So that MICROPY_EVENT_POLL_HOOK can be used without including py/mphal.h. Signed-off-by: Damien George --- ports/unix/mpconfigport.h | 2 +- ports/unix/unix_mphal.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 97846f81f0..6397bcfbf6 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -328,7 +328,7 @@ static inline unsigned long mp_urandom_seed_init(void) { do { \ extern void mp_handle_pending(bool); \ mp_handle_pending(true); \ - mp_hal_delay_us(500); \ + usleep(500); /* equivalent to mp_hal_delay_us(500) */ \ } while (0); #include diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c index 80a7d1c8f6..c224f78700 100644 --- a/ports/unix/unix_mphal.c +++ b/ports/unix/unix_mphal.c @@ -233,7 +233,7 @@ void mp_hal_delay_ms(mp_uint_t ms) { #ifdef MICROPY_EVENT_POLL_HOOK mp_uint_t start = mp_hal_ticks_ms(); while (mp_hal_ticks_ms() - start < ms) { - // MICROPY_EVENT_POLL_HOOK does mp_hal_delay_us(500) (i.e. usleep(500)). + // MICROPY_EVENT_POLL_HOOK does usleep(500). MICROPY_EVENT_POLL_HOOK } #else From 26dec1fafb0c3fb45d9f3e21b98a1bb268008f2f Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 15 Jul 2022 12:27:23 +1000 Subject: [PATCH 0172/1041] unix/mbedtls: Add custom config for mbedtls. Based on existing bare-metal config from stm32. Also uses shorter error messages from lib/mbedtls_errors. Signed-off-by: Damien George --- ports/unix/Makefile | 10 +++ ports/unix/mbedtls/mbedtls_config.h | 94 +++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 ports/unix/mbedtls/mbedtls_config.h diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 1067c9c055..dc44744dae 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -133,6 +133,16 @@ CFLAGS_MOD += -DMICROPY_PY_THREAD=1 -DMICROPY_PY_THREAD_GIL=0 LDFLAGS_MOD += $(LIBPTHREAD) endif +ifeq ($(MICROPY_PY_USSL),1) +ifeq ($(MICROPY_SSL_MBEDTLS),1) +GIT_SUBMODULES += lib/mbedtls +CFLAGS_MOD += -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' +# replace mbedtls' error.c by ours +SRC_MOD := $(filter-out %/mbedtls/library/error.c, $(SRC_MOD)) +LIB_SRC_C += lib/mbedtls_errors/mp_mbedtls_errors.c +endif +endif + # If the variant enables it, enable modbluetooth. ifeq ($(MICROPY_PY_BLUETOOTH),1) diff --git a/ports/unix/mbedtls/mbedtls_config.h b/ports/unix/mbedtls/mbedtls_config.h new file mode 100644 index 0000000000..b119d09092 --- /dev/null +++ b/ports/unix/mbedtls/mbedtls_config.h @@ -0,0 +1,94 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 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. + */ +#ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H +#define MICROPY_INCLUDED_MBEDTLS_CONFIG_H + +// If you want to debug MBEDTLS uncomment the following and +// Pass 3 to mbedtls_debug_set_threshold in socket_new +// #define MBEDTLS_DEBUG_C + +// Set mbedtls configuration +#define MBEDTLS_DEPRECATED_REMOVED +#define MBEDTLS_AES_ROM_TABLES +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_CIPHER_MODE_CTR // needed for MICROPY_PY_UCRYPTOLIB_CTR +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#define MBEDTLS_NO_PLATFORM_ENTROPY +#define MBEDTLS_PKCS1_V15 +#define MBEDTLS_SHA256_SMALLER +#define MBEDTLS_SSL_PROTO_TLS1 +#define MBEDTLS_SSL_PROTO_TLS1_1 +#define MBEDTLS_SSL_PROTO_TLS1_2 +#define MBEDTLS_SSL_SERVER_NAME_INDICATION + +// Use a smaller output buffer to reduce size of SSL context +#define MBEDTLS_SSL_MAX_CONTENT_LEN (16384) +#define MBEDTLS_SSL_IN_CONTENT_LEN (MBEDTLS_SSL_MAX_CONTENT_LEN) +#define MBEDTLS_SSL_OUT_CONTENT_LEN (4096) + +// Enable mbedtls modules +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_ERROR_C +#define MBEDTLS_HAVEGE_C +#define MBEDTLS_MD_C +#define MBEDTLS_MD5_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS5_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_RSA_C +#define MBEDTLS_SHA1_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SHA512_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_TLS_C +#define MBEDTLS_TIMING_C +#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_USE_C + +#include "mbedtls/check_config.h" + +#endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_H */ From 13c78ab6fef333c913d54bafaf628c121fe1e58d Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 15 Jul 2022 12:27:33 +1000 Subject: [PATCH 0173/1041] unix/mpconfigport: Switch ussl from axtls to mbedtls. The reasons to make this switch are: - The axtls library is not being maintained/updated, mbedtls is. - So CI and tests can run against mbedtls, which is now the main TLS library used by the ports (eg stm32, rp2, mimxrt, esp32). Only esp8266 uses axtls. Increases unix standard build on x86-64 by about 89000 bytes. Signed-off-by: Damien George --- ports/unix/mpconfigport.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/unix/mpconfigport.mk b/ports/unix/mpconfigport.mk index 3a66d997b2..fe9eec18dc 100644 --- a/ports/unix/mpconfigport.mk +++ b/ports/unix/mpconfigport.mk @@ -27,10 +27,10 @@ MICROPY_PY_FFI = 1 MICROPY_PY_USSL = 1 # axTLS has minimal size but implements only a subset of modern TLS # functionality, so may have problems with some servers. -MICROPY_SSL_AXTLS = 1 +MICROPY_SSL_AXTLS = 0 # mbedTLS is more up to date and complete implementation, but also # more bloated. -MICROPY_SSL_MBEDTLS = 0 +MICROPY_SSL_MBEDTLS = 1 # jni module requires JVM/JNI MICROPY_PY_JNI = 0 From b87f796ef5c8cd7a02e04052913c67a47d057fc5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 18 Jul 2022 22:44:45 +1000 Subject: [PATCH 0174/1041] unix/Makefile: Only include axtls in GIT_SUBMODULES list when enabled. Signed-off-by: Damien George --- ports/unix/Makefile | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/ports/unix/Makefile b/ports/unix/Makefile index dc44744dae..05b8d9bff6 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -30,7 +30,7 @@ UNAME_S := $(shell uname -s) include $(TOP)/py/py.mk include $(TOP)/extmod/extmod.mk -GIT_SUBMODULES += lib/axtls lib/berkeley-db-1.xx lib/libffi +GIT_SUBMODULES += lib/berkeley-db-1.xx lib/libffi INC += -I. INC += -I$(TOP) @@ -134,6 +134,9 @@ LDFLAGS_MOD += $(LIBPTHREAD) endif ifeq ($(MICROPY_PY_USSL),1) +ifeq ($(MICROPY_SSL_AXTLS),1) +GIT_SUBMODULES += lib/axtls +endif ifeq ($(MICROPY_SSL_MBEDTLS),1) GIT_SUBMODULES += lib/mbedtls CFLAGS_MOD += -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' @@ -325,7 +328,7 @@ else CROSS_COMPILE_HOST = endif -deplibs: libffi axtls +deplibs: libffi libffi: $(BUILD)/lib/libffi/include/ffi.h @@ -339,12 +342,6 @@ $(BUILD)/lib/libffi/include/ffi.h: $(TOP)/lib/libffi/configure $(abspath $(TOP))/lib/libffi/configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out --disable-structs CC="$(CC)" CXX="$(CXX)" LD="$(LD)" CFLAGS="-Os -fomit-frame-pointer -fstrict-aliasing -ffast-math -fno-exceptions"; \ $(MAKE) install-exec-recursive; $(MAKE) -C include install-data-am -axtls: $(TOP)/lib/axtls/README - -$(TOP)/lib/axtls/README: - @echo "You cloned without --recursive, fetching submodules for you." - (cd $(TOP); git submodule update --init --recursive) - PREFIX = /usr/local BINDIR = $(DESTDIR)$(PREFIX)/bin From b89422ceaa8746a9e8441426bb9c0d5eb5a6e040 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 18 Jul 2022 22:55:22 +1000 Subject: [PATCH 0175/1041] extmod: Always use custom mbedtls error message code. All ports that use mbedtls use the custom error messages in mp_mbedtls_errors.c. This commit simplifies the build so that ports don't need to explicitly add this file, it's now used by default when mbedtls is enabled. Signed-off-by: Damien George --- extmod/extmod.cmake | 2 +- extmod/extmod.mk | 2 +- ports/mimxrt/Makefile | 4 +--- ports/rp2/CMakeLists.txt | 7 ------- ports/stm32/Makefile | 3 --- ports/unix/Makefile | 3 --- 6 files changed, 3 insertions(+), 18 deletions(-) diff --git a/extmod/extmod.cmake b/extmod/extmod.cmake index 8fe83a0ada..954bfc7e96 100644 --- a/extmod/extmod.cmake +++ b/extmod/extmod.cmake @@ -114,6 +114,7 @@ if(MICROPY_SSL_MBEDTLS) ) target_sources(micropy_lib_mbedtls INTERFACE + ${MICROPY_DIR}/lib/mbedtls_errors/mp_mbedtls_errors.c ${MICROPY_LIB_MBEDTLS_DIR}/library/aes.c ${MICROPY_LIB_MBEDTLS_DIR}/library/aesni.c ${MICROPY_LIB_MBEDTLS_DIR}/library/arc4.c @@ -141,7 +142,6 @@ if(MICROPY_SSL_MBEDTLS) ${MICROPY_LIB_MBEDTLS_DIR}/library/ecp_curves.c ${MICROPY_LIB_MBEDTLS_DIR}/library/entropy.c ${MICROPY_LIB_MBEDTLS_DIR}/library/entropy_poll.c - ${MICROPY_LIB_MBEDTLS_DIR}/library/error.c ${MICROPY_LIB_MBEDTLS_DIR}/library/gcm.c ${MICROPY_LIB_MBEDTLS_DIR}/library/havege.c ${MICROPY_LIB_MBEDTLS_DIR}/library/hmac_drbg.c diff --git a/extmod/extmod.mk b/extmod/extmod.mk index 93b2a11766..ae3e45bd55 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -119,6 +119,7 @@ SRC_MOD += $(addprefix $(AXTLS_DIR)/,\ else ifeq ($(MICROPY_SSL_MBEDTLS),1) MBEDTLS_DIR = lib/mbedtls CFLAGS_MOD += -DMICROPY_SSL_MBEDTLS=1 -I$(TOP)/$(MBEDTLS_DIR)/include +SRC_MOD += lib/mbedtls_errors/mp_mbedtls_errors.c SRC_MOD += $(addprefix $(MBEDTLS_DIR)/library/,\ aes.c \ aesni.c \ @@ -147,7 +148,6 @@ SRC_MOD += $(addprefix $(MBEDTLS_DIR)/library/,\ ecp_curves.c \ entropy.c \ entropy_poll.c \ - error.c \ gcm.c \ havege.c \ hmac_drbg.c \ diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index be1c95ba95..150727577f 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -96,15 +96,13 @@ SRC_TINYUSB_C += \ # All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP ifeq ($(MICROPY_PY_LWIP),1) -SRC_MOD := $(filter-out %/mbedtls/library/error.c, $(SRC_MOD)) SRC_ETH_C += \ $(MCU_DIR)/drivers/fsl_enet.c \ hal/phy/device/phydp83825/fsl_phydp83825.c \ hal/phy/device/phydp83848/fsl_phydp83848.c \ hal/phy/device/phyksz8081/fsl_phyksz8081.c \ hal/phy/device/phylan8720/fsl_phylan8720.c \ - hal/phy/mdio/enet/fsl_enet_mdio.c \ - lib/mbedtls_errors/mp_mbedtls_errors.c + hal/phy/mdio/enet/fsl_enet_mdio.c endif # NXP SDK sources diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 8f7895459e..f9a9efe62a 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -77,7 +77,6 @@ set(MICROPY_SOURCE_LIB ${MICROPY_DIR}/lib/littlefs/lfs1_util.c ${MICROPY_DIR}/lib/littlefs/lfs2.c ${MICROPY_DIR}/lib/littlefs/lfs2_util.c - ${MICROPY_DIR}/lib/mbedtls_errors/mp_mbedtls_errors.c ${MICROPY_DIR}/lib/oofatfs/ff.c ${MICROPY_DIR}/lib/oofatfs/ffunicode.c ${MICROPY_DIR}/shared/netutils/dhcpserver.c @@ -343,12 +342,6 @@ target_sources(${MICROPY_TARGET} PRIVATE target_link_libraries(${MICROPY_TARGET} micropy_lib_mbedtls) -# Filter out library/error.c as we're using mp_mbedtls_errors.c instead. -set_source_files_properties(${MICROPY_LIB_MBEDTLS_DIR}/library/error.c - TARGET_DIRECTORY micropy_lib_mbedtls - PROPERTIES HEADER_FILE_ONLY ON -) - target_link_libraries(${MICROPY_TARGET} usermod) target_include_directories(${MICROPY_TARGET} PRIVATE diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index bab62eaae9..75a1abeabd 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -499,9 +499,6 @@ endif ifeq ($(MICROPY_SSL_MBEDTLS),1) CFLAGS_MOD += -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' SRC_MOD += mbedtls/mbedtls_port.c -# replace mbedtls' error.c by ours -SRC_MOD := $(filter-out %/mbedtls/library/error.c, $(SRC_MOD)) -LIB_SRC_C += lib/mbedtls_errors/mp_mbedtls_errors.c endif ifeq ($(MICROPY_PY_BLUETOOTH),1) diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 05b8d9bff6..04d2242a27 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -140,9 +140,6 @@ endif ifeq ($(MICROPY_SSL_MBEDTLS),1) GIT_SUBMODULES += lib/mbedtls CFLAGS_MOD += -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' -# replace mbedtls' error.c by ours -SRC_MOD := $(filter-out %/mbedtls/library/error.c, $(SRC_MOD)) -LIB_SRC_C += lib/mbedtls_errors/mp_mbedtls_errors.c endif endif From 5e20dcf925e89c75ad7ba7c947211db6d55a7274 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 18 Jul 2022 23:00:51 +1000 Subject: [PATCH 0176/1041] examples/embedding: Remove obsolete axtls build target. axtls is now built as part of the standard make process, using rules in extmod/extmod.mk. Signed-off-by: Damien George --- examples/embedding/Makefile.upylib | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/examples/embedding/Makefile.upylib b/examples/embedding/Makefile.upylib index 217f2643c9..a8e2b91d56 100644 --- a/examples/embedding/Makefile.upylib +++ b/examples/embedding/Makefile.upylib @@ -172,7 +172,7 @@ else CROSS_COMPILE_HOST = endif -deplibs: libffi axtls +deplibs: libffi # install-exec-recursive & install-data-am targets are used to avoid building # docs and depending on makeinfo @@ -182,13 +182,3 @@ libffi: mkdir -p $(MPTOP)/lib/libffi/build_dir; cd $(MPTOP)/lib/libffi/build_dir; \ ../configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out CC="$(CC)" CXX="$(CXX)" LD="$(LD)"; \ make install-exec-recursive; make -C include install-data-am - -axtls: $(MPTOP)/lib/axtls/README - cd $(MPTOP)/lib/axtls; cp config/upyconfig config/.config - cd $(MPTOP)/lib/axtls; make oldconfig -B - cd $(MPTOP)/lib/axtls; make clean - cd $(MPTOP)/lib/axtls; make all CC="$(CC)" LD="$(LD)" - -$(MPTOP)/lib/axtls/README: - @echo "You cloned without --recursive, fetching submodules for you." - (cd $(MPTOP); git submodule update --init --recursive) From c4adeb2e0873c32a14e49a62023cd99ccdf3d78f Mon Sep 17 00:00:00 2001 From: stijn Date: Thu, 23 Jun 2022 16:01:12 +0200 Subject: [PATCH 0177/1041] windows: Provide a definition for MP_ALWAYSINLINE. --- mpy-cross/mpconfigport.h | 1 + ports/windows/mpconfigport.h | 1 + 2 files changed, 2 insertions(+) diff --git a/mpy-cross/mpconfigport.h b/mpy-cross/mpconfigport.h index 95922d04ff..9d455c0af1 100644 --- a/mpy-cross/mpconfigport.h +++ b/mpy-cross/mpconfigport.h @@ -135,6 +135,7 @@ typedef long mp_off_t; #define MP_ENDIANNESS_LITTLE (1) #define NORETURN __declspec(noreturn) #define MP_NOINLINE __declspec(noinline) +#define MP_ALWAYSINLINE __forceinline #define MP_LIKELY(x) (x) #define MP_UNLIKELY(x) (x) #define MICROPY_PORT_CONSTANTS { MP_ROM_QSTR(MP_QSTR_dummy), MP_ROM_PTR(NULL) } diff --git a/ports/windows/mpconfigport.h b/ports/windows/mpconfigport.h index 39f8c0059c..71814e2147 100644 --- a/ports/windows/mpconfigport.h +++ b/ports/windows/mpconfigport.h @@ -256,6 +256,7 @@ typedef long mp_off_t; #define NORETURN __declspec(noreturn) #define MP_WEAK #define MP_NOINLINE __declspec(noinline) +#define MP_ALWAYSINLINE __forceinline #define MP_LIKELY(x) (x) #define MP_UNLIKELY(x) (x) #define MICROPY_PORT_CONSTANTS { MP_ROM_QSTR(MP_QSTR_dummy), MP_ROM_PTR(NULL) } // can't have zero-sized array From 1f16d682daa822a209127b432097113cfcf308d9 Mon Sep 17 00:00:00 2001 From: stijn Date: Thu, 23 Jun 2022 16:02:59 +0200 Subject: [PATCH 0178/1041] py/misc: Fix msvc compilation with compressed error messages. --- py/misc.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/py/misc.h b/py/misc.h index b7b6146abc..e642598c56 100644 --- a/py/misc.h +++ b/py/misc.h @@ -293,15 +293,16 @@ typedef union _mp_float_union_t { // Force usage of the MP_ERROR_TEXT macro by requiring an opaque type. typedef struct { - #ifdef __clang__ - // Fix "error: empty struct has size 0 in C, size 1 in C++". + #if defined(__clang__) || defined(_MSC_VER) + // Fix "error: empty struct has size 0 in C, size 1 in C++", and the msvc counterpart + // "C requires that a struct or union have at least one member" char dummy; #endif } *mp_rom_error_text_t; #include -inline __attribute__((always_inline)) const char *MP_COMPRESSED_ROM_TEXT(const char *msg) { +inline MP_ALWAYSINLINE const char *MP_COMPRESSED_ROM_TEXT(const char *msg) { // "genhdr/compressed.data.h" contains an invocation of the MP_MATCH_COMPRESSED macro for each compressed string. // The giant if(strcmp) tree is optimized by the compiler, which turns this into a direct return of the compressed data. #define MP_MATCH_COMPRESSED(a, b) if (strcmp(msg, a) == 0) { return b; } else From d05377c060f40c9287804d9cc0897d69eaae11a5 Mon Sep 17 00:00:00 2001 From: stijn Date: Thu, 23 Jun 2022 16:05:08 +0200 Subject: [PATCH 0179/1041] windows/msvc: Support compressed ROM text for error messages. Enable it in the dev variant as well for consistency with the makefile-based dev variant. --- ports/windows/msvc/genhdr.targets | 20 +++++++++++++++++-- .../variants/dev/mpconfigvariant.props | 5 +++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/ports/windows/msvc/genhdr.targets b/ports/windows/msvc/genhdr.targets index 11c5eae8ae..aa796088ef 100644 --- a/ports/windows/msvc/genhdr.targets +++ b/ports/windows/msvc/genhdr.targets @@ -4,7 +4,7 @@ - + @@ -16,6 +16,7 @@ $(DestDir)qstrdefs.generated.h $(DestDir)/moduledefs.collected $(DestDir)/root_pointers.collected + $(DestDir)/compressed.collected $(MICROPY_CPYTHON3) python cl.exe @@ -46,7 +47,8 @@ using(var outFile = System.IO.File.CreateText(OutputFile)) { foreach(var inFile in InputFiles) foreach(var line in System.IO.File.ReadAllLines(inFile)) - if((line.Contains(".c") && line.StartsWith("#line")) || line.Contains("MP_QSTR") || line.Contains("MP_REGISTER")) + if((line.Contains(".c") && line.StartsWith("#line")) || line.Contains("MP_QSTR") || + line.Contains("MP_REGISTER") || line.Contains("MP_COMPRESSED_ROM_TEXT")) outFile.WriteLine( line ); } ]]> @@ -101,6 +103,11 @@ using(var outFile = System.IO.File.CreateText(OutputFile)) { + + + + + @@ -129,6 +136,15 @@ using(var outFile = System.IO.File.CreateText(OutputFile)) { + + + $(DestDir)compressed.data.h + $(DestFile).tmp + + + + + $(QstrGen).tmp diff --git a/ports/windows/variants/dev/mpconfigvariant.props b/ports/windows/variants/dev/mpconfigvariant.props index 5f78d6e62a..0f7abf7815 100644 --- a/ports/windows/variants/dev/mpconfigvariant.props +++ b/ports/windows/variants/dev/mpconfigvariant.props @@ -3,4 +3,9 @@ micropython-dev + + + %(PreprocessorDefinitions);MICROPY_ROM_TEXT_COMPRESSION=1 + + From e82aa2abc46f93abcbed2843c4f23f1838abb844 Mon Sep 17 00:00:00 2001 From: stijn Date: Thu, 14 Jul 2022 15:24:27 +0200 Subject: [PATCH 0180/1041] py/qstr: Make mp_decompress_rom_string decl and def the same. Fixes MSVC warning about mismatching argument types. --- py/qstr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/qstr.h b/py/qstr.h index fa634f90b0..a463b67a18 100644 --- a/py/qstr.h +++ b/py/qstr.h @@ -93,7 +93,7 @@ void qstr_pool_info(size_t *n_pool, size_t *n_qstr, size_t *n_str_data_bytes, si void qstr_dump_data(void); #if MICROPY_ROM_TEXT_COMPRESSION -void mp_decompress_rom_string(byte *dst, mp_rom_error_text_t src); +void mp_decompress_rom_string(byte *dst, const mp_rom_error_text_t src); #define MP_IS_COMPRESSED_ROM_STRING(s) (*(byte *)(s) == 0xff) #endif From c947c2529427fedea2b6d7b1dead8b61f6e8a28d Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 18 Jul 2022 11:40:27 -0500 Subject: [PATCH 0181/1041] unix/Makefile: Only checkout libffi submodule when used. This moves the libffi submodule variable modifier inside of the if statement where it is actually used so that the submodule will only be checked out if it is actually being used. A new DEPLIBS variable is also introduced to prevent building the libffi submodule when not needed. Signed-off-by: David Lechner --- ports/unix/Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 04d2242a27..3b339c3d3f 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -30,7 +30,7 @@ UNAME_S := $(shell uname -s) include $(TOP)/py/py.mk include $(TOP)/extmod/extmod.mk -GIT_SUBMODULES += lib/berkeley-db-1.xx lib/libffi +GIT_SUBMODULES += lib/berkeley-db-1.xx INC += -I. INC += -I$(TOP) @@ -202,6 +202,9 @@ endif ifeq ($(MICROPY_PY_FFI),1) ifeq ($(MICROPY_STANDALONE),1) +# Build libffi from source. +GIT_SUBMODULES += lib/libffi +DEPLIBS += libffi LIBFFI_CFLAGS_MOD := -I$(shell ls -1d $(BUILD)/lib/libffi/out/lib/libffi-*/include) ifeq ($(MICROPY_FORCE_32BIT),1) LIBFFI_LDFLAGS_MOD = $(BUILD)/lib/libffi/out/lib32/libffi.a @@ -209,6 +212,7 @@ LIBFFI_CFLAGS_MOD := -I$(shell ls -1d $(BUILD)/lib/libffi/out/lib/libffi-*/inclu LIBFFI_LDFLAGS_MOD = $(BUILD)/lib/libffi/out/lib/libffi.a endif else +# Use system version of libffi. LIBFFI_CFLAGS_MOD := $(shell pkg-config --cflags libffi) LIBFFI_LDFLAGS_MOD := $(shell pkg-config --libs libffi) endif @@ -325,7 +329,7 @@ else CROSS_COMPILE_HOST = endif -deplibs: libffi +deplibs: $(DEPLIBS) libffi: $(BUILD)/lib/libffi/include/ffi.h From 03fb6718339fb77022a84b25875cc1daf804ac9a Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 7 Feb 2022 13:37:37 -0600 Subject: [PATCH 0182/1041] unix/mpconfigport: Allow overriding MICROPY_EVENT_POLL_HOOK. This allows variants to supply their own `MICROPY_EVENT_POLL_HOOK`. Signed-off-by: David Lechner --- ports/unix/mpconfigport.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 6397bcfbf6..312c0cce8f 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -324,12 +324,14 @@ static inline unsigned long mp_urandom_seed_init(void) { #define MICROPY_END_ATOMIC_SECTION(x) (void)x; mp_thread_unix_end_atomic_section() #endif +#ifndef MICROPY_EVENT_POLL_HOOK #define MICROPY_EVENT_POLL_HOOK \ do { \ extern void mp_handle_pending(bool); \ mp_handle_pending(true); \ usleep(500); /* equivalent to mp_hal_delay_us(500) */ \ } while (0); +#endif #include #define MICROPY_UNIX_MACHINE_IDLE sched_yield(); From d1ef3815e6041c4fd569bb19f88080a0c55b20c6 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 18 Jul 2022 15:36:04 +0200 Subject: [PATCH 0183/1041] lib/tinyusb: Update to the most recent master. --- lib/tinyusb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tinyusb b/lib/tinyusb index 4bfab30c02..868f2bcda0 160000 --- a/lib/tinyusb +++ b/lib/tinyusb @@ -1 +1 @@ -Subproject commit 4bfab30c02279a0530e1a56f4a7c539f2d35a293 +Subproject commit 868f2bcda092b0b8d5f7ac55ffaef2c81316d35e From 80339f1a33faadfe85d0276a2e22701ec9a5b82e Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 18 Jul 2022 15:38:04 +0200 Subject: [PATCH 0184/1041] ports: Adapt mimxrt, nrf and rp2 ports to work with latest TinyUSB. rp2: change tud_task() to tud_task_ext(). mimxrt: use lib/tinyusb/src/portable/chipidea/ci_hs/dcd_ci_hs.c instead of lib/tinyusb/src/portable/nxp/transdimension/dcd_transdimension.c. nrf: add a definition for the changed tud_task(). tud_task() is changed to tud_task_ext(), and the #define for backward compatibility is in src/device/usbd.h. The items I know which are fixed with this version: - Fix for the SAMD USB lock-up. - Support the MIMXRT11XX series of MCUs. - Fix a wrong pin definition for MIMXRT1050_EVKB. Tested with the MIMXRT boards, rp2 Pico, SAMD boards, nrf board. --- ports/mimxrt/Makefile | 2 +- ports/nrf/mpconfigport.h | 1 + ports/rp2/mpconfigport.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index 150727577f..de560bdb66 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -91,7 +91,7 @@ SRC_TINYUSB_C += \ lib/tinyusb/src/common/tusb_fifo.c \ lib/tinyusb/src/device/usbd.c \ lib/tinyusb/src/device/usbd_control.c \ - lib/tinyusb/src/portable/nxp/transdimension/dcd_transdimension.c \ + lib/tinyusb/src/portable/chipidea/ci_hs/dcd_ci_hs.c \ lib/tinyusb/src/tusb.c # All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index b3a95614a4..8a2478d27d 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -311,6 +311,7 @@ typedef long mp_off_t; #define MP_STATE_PORT MP_STATE_VM #if MICROPY_HW_USB_CDC +#include "device/usbd.h" #define MICROPY_HW_USBDEV_TASK_HOOK extern void tud_task(void); tud_task(); #else #define MICROPY_HW_USBDEV_TASK_HOOK ; diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 3f332b6a82..14748a763d 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -220,7 +220,7 @@ extern void mp_thread_end_atomic_section(uint32_t); #define MICROPY_PY_LWIP_EXIT lwip_lock_release(); #if MICROPY_HW_ENABLE_USBDEV -#define MICROPY_HW_USBDEV_TASK_HOOK extern void tud_task(void); tud_task(); +#define MICROPY_HW_USBDEV_TASK_HOOK extern void tud_task_ext(uint32_t, bool); tud_task_ext(0, false); #define MICROPY_VM_HOOK_COUNT (10) #define MICROPY_VM_HOOK_INIT static uint vm_hook_divisor = MICROPY_VM_HOOK_COUNT; #define MICROPY_VM_HOOK_POLL if (get_core_num() == 0 && --vm_hook_divisor == 0) { \ From 2e2202993cc84db022c0e6980b0bd9d3e18cbd7e Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 18 Jul 2022 16:42:32 +0200 Subject: [PATCH 0185/1041] shared/runtime/softtimer: Move softtimer.[ch] to shared/runtime. And change the include lock to the naming scheme of that place. This comes from ports/stm32/softtimer.[ch]. --- shared/runtime/softtimer.c | 148 +++++++++++++++++++++++++++++++++++++ shared/runtime/softtimer.h | 66 +++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 shared/runtime/softtimer.c create mode 100644 shared/runtime/softtimer.h diff --git a/shared/runtime/softtimer.c b/shared/runtime/softtimer.c new file mode 100644 index 0000000000..c9c59cab0e --- /dev/null +++ b/shared/runtime/softtimer.c @@ -0,0 +1,148 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 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 +#include "py/gc.h" +#include "py/mphal.h" +#include "py/runtime.h" +#include "irq.h" +#include "softtimer.h" + +#define TICKS_PERIOD 0x80000000 +#define TICKS_DIFF(t1, t0) ((int32_t)(((t1 - t0 + TICKS_PERIOD / 2) & (TICKS_PERIOD - 1)) - TICKS_PERIOD / 2)) + +extern __IO uint32_t uwTick; + +volatile uint32_t soft_timer_next; + +// Pointer to the pairheap of soft timer objects. +// This may contain bss/data pointers as well as GC-heap pointers, +// and is explicitly GC traced by soft_timer_gc_mark_all(). +STATIC soft_timer_entry_t *soft_timer_heap; + +STATIC int soft_timer_lt(mp_pairheap_t *n1, mp_pairheap_t *n2) { + soft_timer_entry_t *e1 = (soft_timer_entry_t *)n1; + soft_timer_entry_t *e2 = (soft_timer_entry_t *)n2; + return TICKS_DIFF(e1->expiry_ms, e2->expiry_ms) < 0; +} + +STATIC void soft_timer_schedule_systick(uint32_t ticks_ms) { + uint32_t irq_state = disable_irq(); + uint32_t uw_tick = uwTick; + if (TICKS_DIFF(ticks_ms, uw_tick) <= 0) { + soft_timer_next = uw_tick + 1; + } else { + soft_timer_next = ticks_ms; + } + enable_irq(irq_state); +} + +void soft_timer_deinit(void) { + // Pop off all the nodes which are allocated on the GC-heap. + uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); + soft_timer_entry_t *heap_from = soft_timer_heap; + soft_timer_entry_t *heap_to = (soft_timer_entry_t *)mp_pairheap_new(soft_timer_lt); + while (heap_from != NULL) { + soft_timer_entry_t *entry = (soft_timer_entry_t *)mp_pairheap_peek(soft_timer_lt, &heap_from->pairheap); + heap_from = (soft_timer_entry_t *)mp_pairheap_pop(soft_timer_lt, &heap_from->pairheap); + if (!(entry->flags & SOFT_TIMER_FLAG_GC_ALLOCATED)) { + heap_to = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &heap_to->pairheap, &entry->pairheap); + } + } + soft_timer_heap = heap_to; + restore_irq_pri(irq_state); +} + +// Must be executed at IRQ_PRI_PENDSV +void soft_timer_handler(void) { + uint32_t ticks_ms = uwTick; + soft_timer_entry_t *heap = soft_timer_heap; + while (heap != NULL && TICKS_DIFF(heap->expiry_ms, ticks_ms) <= 0) { + soft_timer_entry_t *entry = heap; + heap = (soft_timer_entry_t *)mp_pairheap_pop(soft_timer_lt, &heap->pairheap); + if (entry->flags & SOFT_TIMER_FLAG_PY_CALLBACK) { + mp_sched_schedule(entry->py_callback, MP_OBJ_FROM_PTR(entry)); + } else { + entry->c_callback(entry); + } + if (entry->mode == SOFT_TIMER_MODE_PERIODIC) { + entry->expiry_ms += entry->delta_ms; + heap = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &heap->pairheap, &entry->pairheap); + } + } + soft_timer_heap = heap; + if (heap == NULL) { + // No more timers left, set largest delay possible + soft_timer_next = uwTick; + } else { + // Set soft_timer_next so SysTick calls us back at the correct time + soft_timer_schedule_systick(heap->expiry_ms); + } +} + +void soft_timer_gc_mark_all(void) { + // Mark all soft timer nodes that are allocated on the GC-heap. + // To avoid deep C recursion, pop and recreate the pairheap as nodes are marked. + uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); + soft_timer_entry_t *heap_from = soft_timer_heap; + soft_timer_entry_t *heap_to = (soft_timer_entry_t *)mp_pairheap_new(soft_timer_lt); + while (heap_from != NULL) { + soft_timer_entry_t *entry = (soft_timer_entry_t *)mp_pairheap_peek(soft_timer_lt, &heap_from->pairheap); + heap_from = (soft_timer_entry_t *)mp_pairheap_pop(soft_timer_lt, &heap_from->pairheap); + if (entry->flags & SOFT_TIMER_FLAG_GC_ALLOCATED) { + gc_collect_root((void **)&entry, 1); + } + heap_to = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &heap_to->pairheap, &entry->pairheap); + } + soft_timer_heap = heap_to; + restore_irq_pri(irq_state); +} + +void soft_timer_static_init(soft_timer_entry_t *entry, uint16_t mode, uint32_t delta_ms, void (*cb)(soft_timer_entry_t *)) { + mp_pairheap_init_node(soft_timer_lt, &entry->pairheap); + entry->flags = 0; + entry->mode = mode; + entry->delta_ms = delta_ms; + entry->c_callback = cb; +} + +void soft_timer_insert(soft_timer_entry_t *entry, uint32_t initial_delta_ms) { + mp_pairheap_init_node(soft_timer_lt, &entry->pairheap); + entry->expiry_ms = mp_hal_ticks_ms() + initial_delta_ms; + uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); + soft_timer_heap = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &soft_timer_heap->pairheap, &entry->pairheap); + if (entry == soft_timer_heap) { + // This new timer became the earliest one so set soft_timer_next + soft_timer_schedule_systick(entry->expiry_ms); + } + restore_irq_pri(irq_state); +} + +void soft_timer_remove(soft_timer_entry_t *entry) { + uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); + soft_timer_heap = (soft_timer_entry_t *)mp_pairheap_delete(soft_timer_lt, &soft_timer_heap->pairheap, &entry->pairheap); + restore_irq_pri(irq_state); +} diff --git a/shared/runtime/softtimer.h b/shared/runtime/softtimer.h new file mode 100644 index 0000000000..8603ea13f0 --- /dev/null +++ b/shared/runtime/softtimer.h @@ -0,0 +1,66 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 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. + */ +#ifndef MICROPY_INCLUDED_SHARED_RUNTIME_SOFTTIMER_H +#define MICROPY_INCLUDED_SHARED_RUNTIME_SOFTTIMER_H + +#include "py/pairheap.h" + +#define SOFT_TIMER_FLAG_PY_CALLBACK (1) +#define SOFT_TIMER_FLAG_GC_ALLOCATED (2) + +#define SOFT_TIMER_MODE_ONE_SHOT (1) +#define SOFT_TIMER_MODE_PERIODIC (2) + +typedef struct _soft_timer_entry_t { + mp_pairheap_t pairheap; + uint16_t flags; + uint16_t mode; + uint32_t expiry_ms; + uint32_t delta_ms; // for periodic mode + union { + void (*c_callback)(struct _soft_timer_entry_t *); + mp_obj_t py_callback; + }; +} soft_timer_entry_t; + +extern volatile uint32_t soft_timer_next; + +void soft_timer_deinit(void); +void soft_timer_handler(void); +void soft_timer_gc_mark_all(void); + +void soft_timer_static_init(soft_timer_entry_t *entry, uint16_t mode, uint32_t delta_ms, void (*cb)(soft_timer_entry_t *)); +void soft_timer_insert(soft_timer_entry_t *entry, uint32_t initial_delta_ms); +void soft_timer_remove(soft_timer_entry_t *entry); + +// The timer will be reinserted into the heap so that it is called after initial_delta_ms milliseconds. +// After that, if it's periodic, it will continue to be called every entry->delta_ms milliseconds. +static inline void soft_timer_reinsert(soft_timer_entry_t *entry, uint32_t initial_delta_ms) { + soft_timer_remove(entry); + soft_timer_insert(entry, initial_delta_ms); +} + +#endif // MICROPY_INCLUDED_SHARED_RUNTIME_SOFTTIMER_H From c781899438e3a0c1241ddd0d550555562c2a53d4 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 18 Jul 2022 16:44:31 +0200 Subject: [PATCH 0186/1041] stm32/softtimer: Switch to use softtimer code from shared/runtime. --- ports/stm32/Makefile | 2 +- ports/stm32/gccollect.c | 2 +- ports/stm32/machine_timer.c | 2 +- ports/stm32/main.c | 2 +- ports/stm32/mpbthciport.c | 2 +- ports/stm32/softtimer.c | 148 ------------------------------------ ports/stm32/softtimer.h | 66 ---------------- ports/stm32/systick.c | 2 +- 8 files changed, 6 insertions(+), 220 deletions(-) delete mode 100644 ports/stm32/softtimer.c delete mode 100644 ports/stm32/softtimer.h diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 75a1abeabd..652dff19fe 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -144,6 +144,7 @@ SHARED_SRC_C += $(addprefix shared/,\ runtime/interrupt_char.c \ runtime/mpirq.c \ runtime/pyexec.c \ + runtime/softtimer.c \ runtime/stdout_helpers.c \ runtime/sys_stdio_mphal.c \ timeutils/timeutils.c \ @@ -270,7 +271,6 @@ SRC_C += \ irq.c \ pendsv.c \ systick.c \ - softtimer.c \ powerctrl.c \ powerctrlboot.c \ rfcore.c \ diff --git a/ports/stm32/gccollect.c b/ports/stm32/gccollect.c index bd697a2af3..667bbc4327 100644 --- a/ports/stm32/gccollect.c +++ b/ports/stm32/gccollect.c @@ -31,8 +31,8 @@ #include "py/gc.h" #include "py/mpthread.h" #include "shared/runtime/gchelper.h" +#include "shared/runtime/softtimer.h" #include "gccollect.h" -#include "softtimer.h" #include "systick.h" void gc_collect(void) { diff --git a/ports/stm32/machine_timer.c b/ports/stm32/machine_timer.c index c945322187..c387d35117 100644 --- a/ports/stm32/machine_timer.c +++ b/ports/stm32/machine_timer.c @@ -26,7 +26,7 @@ #include "py/runtime.h" #include "py/mphal.h" -#include "softtimer.h" +#include "shared/runtime/softtimer.h" typedef soft_timer_entry_t machine_timer_obj_t; diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 44732cef9e..c001234704 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -34,6 +34,7 @@ #include "py/mphal.h" #include "shared/readline/readline.h" #include "shared/runtime/pyexec.h" +#include "shared/runtime/softtimer.h" #include "lib/oofatfs/ff.h" #include "lib/littlefs/lfs1.h" #include "lib/littlefs/lfs1_util.h" @@ -65,7 +66,6 @@ #include "gccollect.h" #include "factoryreset.h" #include "modmachine.h" -#include "softtimer.h" #include "i2c.h" #include "spi.h" #include "uart.h" diff --git a/ports/stm32/mpbthciport.c b/ports/stm32/mpbthciport.c index d3ddb40421..d73aa50c37 100644 --- a/ports/stm32/mpbthciport.c +++ b/ports/stm32/mpbthciport.c @@ -29,8 +29,8 @@ #include "py/mphal.h" #include "extmod/mpbthci.h" #include "extmod/modbluetooth.h" +#include "shared/runtime/softtimer.h" #include "mpbthciport.h" -#include "softtimer.h" #include "pendsv.h" #include "shared/runtime/mpirq.h" diff --git a/ports/stm32/softtimer.c b/ports/stm32/softtimer.c deleted file mode 100644 index c9c59cab0e..0000000000 --- a/ports/stm32/softtimer.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 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 -#include "py/gc.h" -#include "py/mphal.h" -#include "py/runtime.h" -#include "irq.h" -#include "softtimer.h" - -#define TICKS_PERIOD 0x80000000 -#define TICKS_DIFF(t1, t0) ((int32_t)(((t1 - t0 + TICKS_PERIOD / 2) & (TICKS_PERIOD - 1)) - TICKS_PERIOD / 2)) - -extern __IO uint32_t uwTick; - -volatile uint32_t soft_timer_next; - -// Pointer to the pairheap of soft timer objects. -// This may contain bss/data pointers as well as GC-heap pointers, -// and is explicitly GC traced by soft_timer_gc_mark_all(). -STATIC soft_timer_entry_t *soft_timer_heap; - -STATIC int soft_timer_lt(mp_pairheap_t *n1, mp_pairheap_t *n2) { - soft_timer_entry_t *e1 = (soft_timer_entry_t *)n1; - soft_timer_entry_t *e2 = (soft_timer_entry_t *)n2; - return TICKS_DIFF(e1->expiry_ms, e2->expiry_ms) < 0; -} - -STATIC void soft_timer_schedule_systick(uint32_t ticks_ms) { - uint32_t irq_state = disable_irq(); - uint32_t uw_tick = uwTick; - if (TICKS_DIFF(ticks_ms, uw_tick) <= 0) { - soft_timer_next = uw_tick + 1; - } else { - soft_timer_next = ticks_ms; - } - enable_irq(irq_state); -} - -void soft_timer_deinit(void) { - // Pop off all the nodes which are allocated on the GC-heap. - uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); - soft_timer_entry_t *heap_from = soft_timer_heap; - soft_timer_entry_t *heap_to = (soft_timer_entry_t *)mp_pairheap_new(soft_timer_lt); - while (heap_from != NULL) { - soft_timer_entry_t *entry = (soft_timer_entry_t *)mp_pairheap_peek(soft_timer_lt, &heap_from->pairheap); - heap_from = (soft_timer_entry_t *)mp_pairheap_pop(soft_timer_lt, &heap_from->pairheap); - if (!(entry->flags & SOFT_TIMER_FLAG_GC_ALLOCATED)) { - heap_to = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &heap_to->pairheap, &entry->pairheap); - } - } - soft_timer_heap = heap_to; - restore_irq_pri(irq_state); -} - -// Must be executed at IRQ_PRI_PENDSV -void soft_timer_handler(void) { - uint32_t ticks_ms = uwTick; - soft_timer_entry_t *heap = soft_timer_heap; - while (heap != NULL && TICKS_DIFF(heap->expiry_ms, ticks_ms) <= 0) { - soft_timer_entry_t *entry = heap; - heap = (soft_timer_entry_t *)mp_pairheap_pop(soft_timer_lt, &heap->pairheap); - if (entry->flags & SOFT_TIMER_FLAG_PY_CALLBACK) { - mp_sched_schedule(entry->py_callback, MP_OBJ_FROM_PTR(entry)); - } else { - entry->c_callback(entry); - } - if (entry->mode == SOFT_TIMER_MODE_PERIODIC) { - entry->expiry_ms += entry->delta_ms; - heap = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &heap->pairheap, &entry->pairheap); - } - } - soft_timer_heap = heap; - if (heap == NULL) { - // No more timers left, set largest delay possible - soft_timer_next = uwTick; - } else { - // Set soft_timer_next so SysTick calls us back at the correct time - soft_timer_schedule_systick(heap->expiry_ms); - } -} - -void soft_timer_gc_mark_all(void) { - // Mark all soft timer nodes that are allocated on the GC-heap. - // To avoid deep C recursion, pop and recreate the pairheap as nodes are marked. - uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); - soft_timer_entry_t *heap_from = soft_timer_heap; - soft_timer_entry_t *heap_to = (soft_timer_entry_t *)mp_pairheap_new(soft_timer_lt); - while (heap_from != NULL) { - soft_timer_entry_t *entry = (soft_timer_entry_t *)mp_pairheap_peek(soft_timer_lt, &heap_from->pairheap); - heap_from = (soft_timer_entry_t *)mp_pairheap_pop(soft_timer_lt, &heap_from->pairheap); - if (entry->flags & SOFT_TIMER_FLAG_GC_ALLOCATED) { - gc_collect_root((void **)&entry, 1); - } - heap_to = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &heap_to->pairheap, &entry->pairheap); - } - soft_timer_heap = heap_to; - restore_irq_pri(irq_state); -} - -void soft_timer_static_init(soft_timer_entry_t *entry, uint16_t mode, uint32_t delta_ms, void (*cb)(soft_timer_entry_t *)) { - mp_pairheap_init_node(soft_timer_lt, &entry->pairheap); - entry->flags = 0; - entry->mode = mode; - entry->delta_ms = delta_ms; - entry->c_callback = cb; -} - -void soft_timer_insert(soft_timer_entry_t *entry, uint32_t initial_delta_ms) { - mp_pairheap_init_node(soft_timer_lt, &entry->pairheap); - entry->expiry_ms = mp_hal_ticks_ms() + initial_delta_ms; - uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); - soft_timer_heap = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &soft_timer_heap->pairheap, &entry->pairheap); - if (entry == soft_timer_heap) { - // This new timer became the earliest one so set soft_timer_next - soft_timer_schedule_systick(entry->expiry_ms); - } - restore_irq_pri(irq_state); -} - -void soft_timer_remove(soft_timer_entry_t *entry) { - uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); - soft_timer_heap = (soft_timer_entry_t *)mp_pairheap_delete(soft_timer_lt, &soft_timer_heap->pairheap, &entry->pairheap); - restore_irq_pri(irq_state); -} diff --git a/ports/stm32/softtimer.h b/ports/stm32/softtimer.h deleted file mode 100644 index 9c14f16d61..0000000000 --- a/ports/stm32/softtimer.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 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. - */ -#ifndef MICROPY_INCLUDED_STM32_SOFTTIMER_H -#define MICROPY_INCLUDED_STM32_SOFTTIMER_H - -#include "py/pairheap.h" - -#define SOFT_TIMER_FLAG_PY_CALLBACK (1) -#define SOFT_TIMER_FLAG_GC_ALLOCATED (2) - -#define SOFT_TIMER_MODE_ONE_SHOT (1) -#define SOFT_TIMER_MODE_PERIODIC (2) - -typedef struct _soft_timer_entry_t { - mp_pairheap_t pairheap; - uint16_t flags; - uint16_t mode; - uint32_t expiry_ms; - uint32_t delta_ms; // for periodic mode - union { - void (*c_callback)(struct _soft_timer_entry_t *); - mp_obj_t py_callback; - }; -} soft_timer_entry_t; - -extern volatile uint32_t soft_timer_next; - -void soft_timer_deinit(void); -void soft_timer_handler(void); -void soft_timer_gc_mark_all(void); - -void soft_timer_static_init(soft_timer_entry_t *entry, uint16_t mode, uint32_t delta_ms, void (*cb)(soft_timer_entry_t *)); -void soft_timer_insert(soft_timer_entry_t *entry, uint32_t initial_delta_ms); -void soft_timer_remove(soft_timer_entry_t *entry); - -// The timer will be reinserted into the heap so that it is called after initial_delta_ms milliseconds. -// After that, if it's periodic, it will continue to be called every entry->delta_ms milliseconds. -static inline void soft_timer_reinsert(soft_timer_entry_t *entry, uint32_t initial_delta_ms) { - soft_timer_remove(entry); - soft_timer_insert(entry, initial_delta_ms); -} - -#endif // MICROPY_INCLUDED_STM32_SOFTTIMER_H diff --git a/ports/stm32/systick.c b/ports/stm32/systick.c index 7d1e318ac0..76944d312a 100644 --- a/ports/stm32/systick.c +++ b/ports/stm32/systick.c @@ -26,10 +26,10 @@ #include "py/runtime.h" #include "py/mphal.h" +#include "shared/runtime/softtimer.h" #include "irq.h" #include "pendsv.h" #include "systick.h" -#include "softtimer.h" #include "pybthread.h" extern __IO uint32_t uwTick; From 678cb5a5857d86b4552554e579ab65317c969aa2 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 18 Jul 2022 16:59:24 +0200 Subject: [PATCH 0187/1041] renesas-ra/softtimer: Switch to use softtimer code from shared/runtime. --- ports/renesas-ra/Makefile | 2 +- ports/renesas-ra/gccollect.c | 2 +- ports/renesas-ra/machine_timer.c | 2 +- ports/renesas-ra/main.c | 2 +- ports/renesas-ra/softtimer.c | 148 ------------------------------- ports/renesas-ra/softtimer.h | 66 -------------- ports/renesas-ra/systick.c | 2 +- 7 files changed, 5 insertions(+), 219 deletions(-) delete mode 100644 ports/renesas-ra/softtimer.c delete mode 100644 ports/renesas-ra/softtimer.h diff --git a/ports/renesas-ra/Makefile b/ports/renesas-ra/Makefile index 832b7db9fa..d326c81e78 100644 --- a/ports/renesas-ra/Makefile +++ b/ports/renesas-ra/Makefile @@ -179,6 +179,7 @@ SHARED_SRC_C += $(addprefix shared/,\ runtime/interrupt_char.c \ runtime/mpirq.c \ runtime/pyexec.c \ + runtime/softtimer.c \ runtime/stdout_helpers.c \ runtime/sys_stdio_mphal.c \ timeutils/timeutils.c \ @@ -297,7 +298,6 @@ SRC_C += \ irq.c \ pendsv.c \ systick.c \ - softtimer.c \ powerctrl.c \ powerctrlboot.c \ pybthread.c \ diff --git a/ports/renesas-ra/gccollect.c b/ports/renesas-ra/gccollect.c index bd697a2af3..667bbc4327 100644 --- a/ports/renesas-ra/gccollect.c +++ b/ports/renesas-ra/gccollect.c @@ -31,8 +31,8 @@ #include "py/gc.h" #include "py/mpthread.h" #include "shared/runtime/gchelper.h" +#include "shared/runtime/softtimer.h" #include "gccollect.h" -#include "softtimer.h" #include "systick.h" void gc_collect(void) { diff --git a/ports/renesas-ra/machine_timer.c b/ports/renesas-ra/machine_timer.c index c945322187..c387d35117 100644 --- a/ports/renesas-ra/machine_timer.c +++ b/ports/renesas-ra/machine_timer.c @@ -26,7 +26,7 @@ #include "py/runtime.h" #include "py/mphal.h" -#include "softtimer.h" +#include "shared/runtime/softtimer.h" typedef soft_timer_entry_t machine_timer_obj_t; diff --git a/ports/renesas-ra/main.c b/ports/renesas-ra/main.c index 78af1a9639..a87ddbd868 100644 --- a/ports/renesas-ra/main.c +++ b/ports/renesas-ra/main.c @@ -35,6 +35,7 @@ #include "py/mphal.h" #include "shared/readline/readline.h" #include "shared/runtime/pyexec.h" +#include "shared/runtime/softtimer.h" #include "lib/oofatfs/ff.h" #include "lib/littlefs/lfs1.h" #include "lib/littlefs/lfs1_util.h" @@ -52,7 +53,6 @@ #include "gccollect.h" #include "factoryreset.h" #include "modmachine.h" -#include "softtimer.h" #include "spi.h" #include "uart.h" #include "timer.h" diff --git a/ports/renesas-ra/softtimer.c b/ports/renesas-ra/softtimer.c deleted file mode 100644 index c9c59cab0e..0000000000 --- a/ports/renesas-ra/softtimer.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 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 -#include "py/gc.h" -#include "py/mphal.h" -#include "py/runtime.h" -#include "irq.h" -#include "softtimer.h" - -#define TICKS_PERIOD 0x80000000 -#define TICKS_DIFF(t1, t0) ((int32_t)(((t1 - t0 + TICKS_PERIOD / 2) & (TICKS_PERIOD - 1)) - TICKS_PERIOD / 2)) - -extern __IO uint32_t uwTick; - -volatile uint32_t soft_timer_next; - -// Pointer to the pairheap of soft timer objects. -// This may contain bss/data pointers as well as GC-heap pointers, -// and is explicitly GC traced by soft_timer_gc_mark_all(). -STATIC soft_timer_entry_t *soft_timer_heap; - -STATIC int soft_timer_lt(mp_pairheap_t *n1, mp_pairheap_t *n2) { - soft_timer_entry_t *e1 = (soft_timer_entry_t *)n1; - soft_timer_entry_t *e2 = (soft_timer_entry_t *)n2; - return TICKS_DIFF(e1->expiry_ms, e2->expiry_ms) < 0; -} - -STATIC void soft_timer_schedule_systick(uint32_t ticks_ms) { - uint32_t irq_state = disable_irq(); - uint32_t uw_tick = uwTick; - if (TICKS_DIFF(ticks_ms, uw_tick) <= 0) { - soft_timer_next = uw_tick + 1; - } else { - soft_timer_next = ticks_ms; - } - enable_irq(irq_state); -} - -void soft_timer_deinit(void) { - // Pop off all the nodes which are allocated on the GC-heap. - uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); - soft_timer_entry_t *heap_from = soft_timer_heap; - soft_timer_entry_t *heap_to = (soft_timer_entry_t *)mp_pairheap_new(soft_timer_lt); - while (heap_from != NULL) { - soft_timer_entry_t *entry = (soft_timer_entry_t *)mp_pairheap_peek(soft_timer_lt, &heap_from->pairheap); - heap_from = (soft_timer_entry_t *)mp_pairheap_pop(soft_timer_lt, &heap_from->pairheap); - if (!(entry->flags & SOFT_TIMER_FLAG_GC_ALLOCATED)) { - heap_to = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &heap_to->pairheap, &entry->pairheap); - } - } - soft_timer_heap = heap_to; - restore_irq_pri(irq_state); -} - -// Must be executed at IRQ_PRI_PENDSV -void soft_timer_handler(void) { - uint32_t ticks_ms = uwTick; - soft_timer_entry_t *heap = soft_timer_heap; - while (heap != NULL && TICKS_DIFF(heap->expiry_ms, ticks_ms) <= 0) { - soft_timer_entry_t *entry = heap; - heap = (soft_timer_entry_t *)mp_pairheap_pop(soft_timer_lt, &heap->pairheap); - if (entry->flags & SOFT_TIMER_FLAG_PY_CALLBACK) { - mp_sched_schedule(entry->py_callback, MP_OBJ_FROM_PTR(entry)); - } else { - entry->c_callback(entry); - } - if (entry->mode == SOFT_TIMER_MODE_PERIODIC) { - entry->expiry_ms += entry->delta_ms; - heap = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &heap->pairheap, &entry->pairheap); - } - } - soft_timer_heap = heap; - if (heap == NULL) { - // No more timers left, set largest delay possible - soft_timer_next = uwTick; - } else { - // Set soft_timer_next so SysTick calls us back at the correct time - soft_timer_schedule_systick(heap->expiry_ms); - } -} - -void soft_timer_gc_mark_all(void) { - // Mark all soft timer nodes that are allocated on the GC-heap. - // To avoid deep C recursion, pop and recreate the pairheap as nodes are marked. - uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); - soft_timer_entry_t *heap_from = soft_timer_heap; - soft_timer_entry_t *heap_to = (soft_timer_entry_t *)mp_pairheap_new(soft_timer_lt); - while (heap_from != NULL) { - soft_timer_entry_t *entry = (soft_timer_entry_t *)mp_pairheap_peek(soft_timer_lt, &heap_from->pairheap); - heap_from = (soft_timer_entry_t *)mp_pairheap_pop(soft_timer_lt, &heap_from->pairheap); - if (entry->flags & SOFT_TIMER_FLAG_GC_ALLOCATED) { - gc_collect_root((void **)&entry, 1); - } - heap_to = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &heap_to->pairheap, &entry->pairheap); - } - soft_timer_heap = heap_to; - restore_irq_pri(irq_state); -} - -void soft_timer_static_init(soft_timer_entry_t *entry, uint16_t mode, uint32_t delta_ms, void (*cb)(soft_timer_entry_t *)) { - mp_pairheap_init_node(soft_timer_lt, &entry->pairheap); - entry->flags = 0; - entry->mode = mode; - entry->delta_ms = delta_ms; - entry->c_callback = cb; -} - -void soft_timer_insert(soft_timer_entry_t *entry, uint32_t initial_delta_ms) { - mp_pairheap_init_node(soft_timer_lt, &entry->pairheap); - entry->expiry_ms = mp_hal_ticks_ms() + initial_delta_ms; - uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); - soft_timer_heap = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &soft_timer_heap->pairheap, &entry->pairheap); - if (entry == soft_timer_heap) { - // This new timer became the earliest one so set soft_timer_next - soft_timer_schedule_systick(entry->expiry_ms); - } - restore_irq_pri(irq_state); -} - -void soft_timer_remove(soft_timer_entry_t *entry) { - uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); - soft_timer_heap = (soft_timer_entry_t *)mp_pairheap_delete(soft_timer_lt, &soft_timer_heap->pairheap, &entry->pairheap); - restore_irq_pri(irq_state); -} diff --git a/ports/renesas-ra/softtimer.h b/ports/renesas-ra/softtimer.h deleted file mode 100644 index aec885c547..0000000000 --- a/ports/renesas-ra/softtimer.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 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. - */ -#ifndef MICROPY_INCLUDED_RENESAS_RA_SOFTTIMER_H -#define MICROPY_INCLUDED_RENESAS_RA_SOFTTIMER_H - -#include "py/pairheap.h" - -#define SOFT_TIMER_FLAG_PY_CALLBACK (1) -#define SOFT_TIMER_FLAG_GC_ALLOCATED (2) - -#define SOFT_TIMER_MODE_ONE_SHOT (1) -#define SOFT_TIMER_MODE_PERIODIC (2) - -typedef struct _soft_timer_entry_t { - mp_pairheap_t pairheap; - uint16_t flags; - uint16_t mode; - uint32_t expiry_ms; - uint32_t delta_ms; // for periodic mode - union { - void (*c_callback)(struct _soft_timer_entry_t *); - mp_obj_t py_callback; - }; -} soft_timer_entry_t; - -extern volatile uint32_t soft_timer_next; - -void soft_timer_deinit(void); -void soft_timer_handler(void); -void soft_timer_gc_mark_all(void); - -void soft_timer_static_init(soft_timer_entry_t *entry, uint16_t mode, uint32_t delta_ms, void (*cb)(soft_timer_entry_t *)); -void soft_timer_insert(soft_timer_entry_t *entry, uint32_t initial_delta_ms); -void soft_timer_remove(soft_timer_entry_t *entry); - -// The timer will be reinserted into the heap so that it is called after initial_delta_ms milliseconds. -// After that, if it's periodic, it will continue to be called every entry->delta_ms milliseconds. -static inline void soft_timer_reinsert(soft_timer_entry_t *entry, uint32_t initial_delta_ms) { - soft_timer_remove(entry); - soft_timer_insert(entry, initial_delta_ms); -} - -#endif // MICROPY_INCLUDED_RENESAS_RA_SOFTTIMER_H diff --git a/ports/renesas-ra/systick.c b/ports/renesas-ra/systick.c index e88166b110..95ca808301 100644 --- a/ports/renesas-ra/systick.c +++ b/ports/renesas-ra/systick.c @@ -27,10 +27,10 @@ #include "py/runtime.h" #include "py/mphal.h" +#include "shared/runtime/softtimer.h" #include "irq.h" #include "pendsv.h" #include "systick.h" -#include "softtimer.h" #include "pybthread.h" #include "hal_data.h" From 93a17b9581418c932d8cb3312040fdbaa04da5e0 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 18 Jul 2022 17:09:04 +0200 Subject: [PATCH 0188/1041] shared/runtime/softtimer: Remove obsolete #include statement. --- shared/runtime/softtimer.c | 1 - 1 file changed, 1 deletion(-) diff --git a/shared/runtime/softtimer.c b/shared/runtime/softtimer.c index c9c59cab0e..8bc9621b3d 100644 --- a/shared/runtime/softtimer.c +++ b/shared/runtime/softtimer.c @@ -28,7 +28,6 @@ #include "py/gc.h" #include "py/mphal.h" #include "py/runtime.h" -#include "irq.h" #include "softtimer.h" #define TICKS_PERIOD 0x80000000 From b41cfea02ab9f566785da5e5e0863d009f3ac527 Mon Sep 17 00:00:00 2001 From: Carlosgg Date: Fri, 28 Jan 2022 04:42:46 +0000 Subject: [PATCH 0189/1041] extmod/modussl_mbedtls: Implement cert_reqs and cadata arguments. Add cert_reqs and cadata keyword-args to ssl.wrap_socket() and ssl.CERT_NONE, ssl.CERT_OPTIONAL, ssl.CERT_REQUIRED constants to allow certificate validation. CPython doesn't accept cadata in ssl.wrap_socket(), but it does in SSLContext.load_verify_locations(), so we use this name to at least match the same name in load_verify_locations(). Add docs for these new arguments, as well as docs for the existing server_hostname argument which is important for certificate validation. Tests are added as well. Signed-off-by: Carlos Gil --- docs/library/ssl.rst | 13 ++- extmod/modussl_mbedtls.c | 22 +++- tests/multi_net/ssl_cert_rsa.py | 152 ++++++++++++++++++++++++++++ tests/multi_net/ssl_cert_rsa.py.exp | 4 + tests/net_inet/ssl_cert.py | 68 +++++++++++++ tests/net_inet/ssl_cert.py.exp | 1 + 6 files changed, 258 insertions(+), 2 deletions(-) create mode 100644 tests/multi_net/ssl_cert_rsa.py create mode 100644 tests/multi_net/ssl_cert_rsa.py.exp create mode 100644 tests/net_inet/ssl_cert.py create mode 100644 tests/net_inet/ssl_cert.py.exp diff --git a/docs/library/ssl.rst b/docs/library/ssl.rst index 4726daa59b..924b03b354 100644 --- a/docs/library/ssl.rst +++ b/docs/library/ssl.rst @@ -13,7 +13,7 @@ facilities for network sockets, both client-side and server-side. Functions --------- -.. function:: ssl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, ca_certs=None, do_handshake=True) +.. function:: ssl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, cadata=None, server_hostname=None, do_handshake=True) Takes a `stream` *sock* (usually socket.socket instance of ``SOCK_STREAM`` type), and returns an instance of ssl.SSLSocket, which wraps the underlying stream in @@ -31,6 +31,17 @@ Functions until it completes. Note that in AXTLS the handshake can be deferred until the first read or write but it then blocks until completion. + - *cert_reqs* determines whether the peer (server or client) must present a valid certificate. + Note that for mbedtls based ports, ``ssl.CERT_NONE`` and ``ssl.CERT_OPTIONAL`` will not + validate any certificate, only ``ssl.CERT_REQUIRED`` will. + + - *cadata* is a bytes object containing the CA certificate chain (in DER format) that will + validate the peer's certificate. Currently only a single DER-encoded certificate is supported. + + - *server_hostname* is for use as a client, and sets the hostname to check against the received + server certificate. It also sets the name for Server Name Indication (SNI), allowing the server + to present the proper certificate. + Depending on the underlying module implementation in a particular :term:`MicroPython port`, some or all keyword arguments above may be not supported. diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c index 44668ae63b..8365c7a4a4 100644 --- a/extmod/modussl_mbedtls.c +++ b/extmod/modussl_mbedtls.c @@ -63,6 +63,8 @@ struct ssl_args { mp_arg_val_t cert; mp_arg_val_t server_side; mp_arg_val_t server_hostname; + mp_arg_val_t cert_reqs; + mp_arg_val_t cadata; mp_arg_val_t do_handshake; }; @@ -191,7 +193,7 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) { goto cleanup; } - mbedtls_ssl_conf_authmode(&o->conf, MBEDTLS_SSL_VERIFY_NONE); + mbedtls_ssl_conf_authmode(&o->conf, args->cert_reqs.u_int); mbedtls_ssl_conf_rng(&o->conf, mbedtls_ctr_drbg_random, &o->ctr_drbg); #ifdef MBEDTLS_DEBUG_C mbedtls_ssl_conf_dbg(&o->conf, mbedtls_debug, NULL); @@ -237,6 +239,19 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) { } } + if (args->cadata.u_obj != mp_const_none) { + size_t cacert_len; + const byte *cacert = (const byte *)mp_obj_str_get_data(args->cadata.u_obj, &cacert_len); + // len should include terminating null + ret = mbedtls_x509_crt_parse(&o->cacert, cacert, cacert_len + 1); + if (ret != 0) { + ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; // use general error for all cert errors + goto cleanup; + } + + mbedtls_ssl_conf_ca_chain(&o->conf, &o->cacert, NULL); + } + if (args->do_handshake.u_bool) { while ((ret = mbedtls_ssl_handshake(&o->ssl)) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { @@ -395,6 +410,8 @@ STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_ { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_cert_reqs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MBEDTLS_SSL_VERIFY_NONE}}, + { MP_QSTR_cadata, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, }; @@ -412,6 +429,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socke STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ussl) }, { MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) }, + { MP_ROM_QSTR(MP_QSTR_CERT_NONE), MP_ROM_INT(MBEDTLS_SSL_VERIFY_NONE) }, + { MP_ROM_QSTR(MP_QSTR_CERT_OPTIONAL), MP_ROM_INT(MBEDTLS_SSL_VERIFY_OPTIONAL) }, + { MP_ROM_QSTR(MP_QSTR_CERT_REQUIRED), MP_ROM_INT(MBEDTLS_SSL_VERIFY_REQUIRED) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table); diff --git a/tests/multi_net/ssl_cert_rsa.py b/tests/multi_net/ssl_cert_rsa.py new file mode 100644 index 0000000000..f0f3a554e8 --- /dev/null +++ b/tests/multi_net/ssl_cert_rsa.py @@ -0,0 +1,152 @@ +# Simple test creating an SSL connection and transferring some data +# This test won't run under CPython because CPython doesn't have key/cert + +try: + import ubinascii as binascii, usocket as socket, ussl as ssl +except ImportError: + print("SKIP") + raise SystemExit + +PORT = 8000 + + +# This self-signed key/cert pair is randomly generated and to be used for +# testing/demonstration only. You should always generate your own key/cert. + +# To generate a new self-signed key/cert pair with openssl do: +# $ openssl req -x509 -newkey rsa:4096 -keyout rsa_key.pem -out rsa_cert.pem -days 365 -node +# +# Convert them to DER format: +# $ openssl rsa -in rsa_key.pem -out rsa_key.der -outform DER +# $ openssl x509 -in rsa_cert.pem -out rsa_key.der -outform DER +# +# Then convert to hex format, eg using binascii.hexlify(data). + +cert = binascii.unhexlify( + b"308205d7308203bfa003020102020900bc63b48a700c3d49300d06092a864886f70d01010b050030" + b"8181310b3009060355040613024155310c300a06035504080c03466f6f310c300a06035504070c03" + b"42617231143012060355040a0c0b4d6963726f507974686f6e310c300a060355040b0c03666f6f31" + b"16301406035504030c0d657370686f6d652e6c6f63616c311a301806092a864886f70d010901160b" + b"666f6f406261722e636f6d301e170d3232303731323138303031335a170d32333037313231383030" + b"31335a308181310b3009060355040613024155310c300a06035504080c03466f6f310c300a060355" + b"04070c0342617231143012060355040a0c0b4d6963726f507974686f6e310c300a060355040b0c03" + b"666f6f3116301406035504030c0d657370686f6d652e6c6f63616c311a301806092a864886f70d01" + b"0901160b666f6f406261722e636f6d30820222300d06092a864886f70d01010105000382020f0030" + b"82020a0282020100ce3c0f730ab34432ce605ab44d4ac0aafd8a6243133eab0dcc9d444ab7d9ff66" + b"a6815a101d2d3cbd72140afc34f8c3caedce16e9528350f3e0e56343f248507d82e41b51abb515cb" + b"f60e5a619f2dbca8684d174c3b0951e2c7ba576c7fb06453a3597755810a6a4c45eb0925c855ab53" + b"7785df46bf29145871330ff0641a101a24f0830c20bae865ba8bb32606caac4555812acf19f59553" + b"349ce70fb7ff63512f0444f8f41b973183eabf9679903087c6cd69dc3adcbe754dd0207ea57c50e9" + b"2d800bce6258d1618bb749d3fc01239b6d1af6d3f9cada3acbb312a1d85a59cfabd28b2e572c56a4" + b"818ce170ca2b781a04749c6239206c64ad9e057484143a4c52bdef6189c46405c1a9642489cb640a" + b"937adfc2687578dfa2b40ebafa05213642a1ccbc265557cd40de53324cff1bfba6f5c215f657b8f9" + b"f2260ab6293625d0e203bba975bc7ac6dff3e604c9b0d2a2a4ba5941c0dc8d2e0e9439c56447b404" + b"8c0e6cfb03517742ff6f7c2140a05954aa1e29247d1ae8bfd7db0db8dd45d095710fb78284ede285" + b"0fc0c21235406af83e6044addf9385316403e2a25442b9ffbfc7b01c6c9292e5a3531e6a48496c01" + b"6de1373334a52f01b7c6a0ece1261936788d2161c53a8985a0946d6d319225b230d96d055ea4692f" + b"eb71fdaf4b775ac9fbc38e1b943e6617cf61d33e930ab288a3ea4730b4f2784a8018e0dfc8a11e73" + b"0203010001a350304e301d0603551d0e04160414bc6048fe3cd278257e8b7c90dedbbce8369b20b8" + b"301f0603551d23041830168014bc6048fe3cd278257e8b7c90dedbbce8369b20b8300c0603551d13" + b"040530030101ff300d06092a864886f70d01010b0500038202010009238354b43379a3d2b56e928c" + b"ac8ea28e2c01cf8148e54c0bbd4055e2e57d578697d1e2c392f1fe3bc9211d4f27ed1be631e7547a" + b"6390d7f121a9e20a195fdda73f755188b16cf39714924a9686dd7cc749421335038c0640c2c6b15d" + b"f44d74d94a97285ee2a7b075ccc9d9d632e2a5906030cf59bde14ab10660b7cf47ec9d7ae2f35963" + b"454f76735a3dac12a4a4c907183e9ccf3e07d59484c182e67edc7c35ce15c7e1072fae8c9965a126" + b"1a1f31147d4af8d1ebf8ee7c142badfe67e31fb324a79a29bc94e89370b70d8cf7cd2b2aa427a49f" + b"77849891e7c4d5911f6fda52733a3c169b0188c2d9918f296dd8e234f8962f0db5e47c6159448045" + b"4e2d9a5850d4c696a0fb3b66534a4591c49dda8cc6f1b0008c625aa5e0091ecfbd51d9715c60b85e" + b"4e89d4a6cfabb2acdf81518eb61403b8f8767c5c00216f730e08f22959dff695a081cc726c4ab35a" + b"e3f6538a231f831a6e91206f3b691a94bdf95343ec02ef7aac42da2a70846cd5f13dd2955a5f1737" + b"a4c3c6c03b041d334c1dadd1e305f07c83b4b4e0509ec1d23e95f820290942eaaf8bea304cd5a505" + b"8fc0d4624ff1ffe1348e7bc54c756a12acb258eb5e7426fb062a82b88ec274c9c13b3eff8b010947" + b"62e166f490cd25b14e762db708785859a337d8fd0008fe602a90e2933cded3359e98ce3fbc041208" + b"66bd4d96d6b6f7f53def854d40021196b7a06b" +) + +key = binascii.unhexlify( + b"308209290201000282020100ce3c0f730ab34432ce605ab44d4ac0aafd8a6243133eab0dcc9d444a" + b"b7d9ff66a6815a101d2d3cbd72140afc34f8c3caedce16e9528350f3e0e56343f248507d82e41b51" + b"abb515cbf60e5a619f2dbca8684d174c3b0951e2c7ba576c7fb06453a3597755810a6a4c45eb0925" + b"c855ab537785df46bf29145871330ff0641a101a24f0830c20bae865ba8bb32606caac4555812acf" + b"19f59553349ce70fb7ff63512f0444f8f41b973183eabf9679903087c6cd69dc3adcbe754dd0207e" + b"a57c50e92d800bce6258d1618bb749d3fc01239b6d1af6d3f9cada3acbb312a1d85a59cfabd28b2e" + b"572c56a4818ce170ca2b781a04749c6239206c64ad9e057484143a4c52bdef6189c46405c1a96424" + b"89cb640a937adfc2687578dfa2b40ebafa05213642a1ccbc265557cd40de53324cff1bfba6f5c215" + b"f657b8f9f2260ab6293625d0e203bba975bc7ac6dff3e604c9b0d2a2a4ba5941c0dc8d2e0e9439c5" + b"6447b4048c0e6cfb03517742ff6f7c2140a05954aa1e29247d1ae8bfd7db0db8dd45d095710fb782" + b"84ede2850fc0c21235406af83e6044addf9385316403e2a25442b9ffbfc7b01c6c9292e5a3531e6a" + b"48496c016de1373334a52f01b7c6a0ece1261936788d2161c53a8985a0946d6d319225b230d96d05" + b"5ea4692feb71fdaf4b775ac9fbc38e1b943e6617cf61d33e930ab288a3ea4730b4f2784a8018e0df" + b"c8a11e73020301000102820201008efa0e8fe81c2e2cb6ed10152dfca4242750581d3e6b54f56524" + b"a6a2d2613cf2727efcec6cfddebd4c285f1148bc2a2936c28919cb0da502dea8c92fe2f9856bee61" + b"ac1aebdac838b5e66f7c7c799df07716f30ef362dbb5485884a180c8ce5539cb1db35699dce5f217" + b"27295d811f1ce7a115111c1823b5c90ce880f5352872a7a76282f6f1fd8a015136ab274c3d30783d" + b"eb6ad7096e33d826eafdf7c70398d5eab4d28f91cd3913c69c7a7ade9ef692b9f8292959be64dec4" + b"6ab2c291b41a6464004b5ddd4b93bfe41b37eedeef4ba2d16dcbb9c28b96f57fb96c20ed4a9471ff" + b"ae643b254f100f8c9702b5f67af6369e8d887f285e5d520c5aa5d3a79e5de96432e6d2e3dea68e58" + b"208c075fb119c6d3d4149b7e1247208d6b337c70272befc41d57f278618f1a82de337173346dc135" + b"4d80a7c9075af99dbb2a14733c06b71600c6677a6bb28c0e4fc63db622228047a2cb7474dc8141c3" + b"5f3a597c3e2bca9911d28eb9fd1a0c915e9f9c1cfd643d4fd8cac867f215380168ec37b8cfa28564" + b"e6288ab04a7d67ca44b4c8375214a7ffaa1e6be92c4b138fcfd6beaba251b31a50a6e2ef241c9554" + b"a1dc710b4acb63e749f5849e53d3f4915c6eb2a9a009bab04e932841ab34ae29eb000a08777d6399" + b"169c2dc3d7952df5bc2d06e90a32139c6a2793d3817e4feadac2ccac554d383a8d41569140c29168" + b"89220d3a5e410282010100fd603d18feef7aac61bda3b674a57ab38748bcde5c3efdba2279638f8e" + b"a413cc26b9dda0375c116a8798a295b2c283aaaad7cca0dbd9bb3322a9a815f6d0aa5fc4f9aff8fb" + b"da8ff914091ede7aefdb07a119c9b2e2b2bda776ac497060b8e88a82eb20c62f26f343566697726e" + b"71aa46fd4efad6f42fc8a478856324d72cbf5eb3918317162d6fc2cfd775969a2077759fa2c8220d" + b"acdc2ebb03ec39feed3f2b415449cbf40a7126bcf01d1068e3a45ec01181f2c68d7e05b4720bfe4a" + b"308e1648123c91214a5f8dfce58727c4cd9396a8b403b733a717449b2f1970db97a3b8467271ffa6" + b"e8c7cc9e2e1c0f789284ae9efe77eaac01131463c9c1329a1ba3530282010100d05ed6ab9b9fbdf7" + b"a0f5f91f68dc3bac5789332d6ece46103fb1ef109fc972fdc99edf3107a23d66d1cdfe6bdddfd1bb" + b"3952ccd10b5c20ad1b3e0aa6a51271ecf3a7ef2a65e029f5d77f238d1235b52a9dca3451c165d70a" + b"99cbaea5c610e5455979696db769191e7cf2db21f641959e4ba1c5c0aae260c724962b6ac2621d92" + b"e9df7adeb82b522d37b42cb454003bbe60d9915bf7737aeccf88c7ed1263a22f431a734e61fe7173" + b"a937ddf76ad2a79994c05238defc15f6846858e9edf27ae2a567c7c5c735ea5d2fbef65a2195bc05" + b"d82cbf06a477b29c84c92e8054c2bb25d8c6f19d43ef5fd1fce13c2cdbc361c39baec37b399200b3" + b"2d4a6798ba0b546102820101008e41492c4e7daff7368d1d6c64034067a94dca5461a0301e201add" + b"2e0d5ccb8cb435685bfa98e362572cf8236a10d191b187a568aee688b6c60050d1bc181d7fd57c86" + b"33195bf5b7576b637c6fb358dae8b52ccc15815affb99e334137dcb91a833475db2f4004164b5d20" + b"2c6c1bbf094a50dc7e70ec9f0ed067bb6944b1e7e3c897aaecfc53984add1c4ff5b525034cf3ca95" + b"e8a09aeba804f1c7e02be391b2bc641166c3e654eef5e72dba37d98f406f3fa520e41f2ea10f5574" + b"ac5984f75145378fefbfac1d07fff3f234fec698d55e746b1da18f6f7de24ec84ed7cb446d428820" + b"bef33c00693e6a0ef114b5d66e9fefa8ee059238df1ac37c87e7841ae7028201000721a7d139c34e" + b"da21cd295894db2cc3aa3f4cdc1a35bf1a2143f2bdabea56202f7d5b802f15b36a4875f76633b2cc" + b"57cf0f71691a2d6e04deb0d1e68031d06a5eb079b406c6944910b60e3e6ec81dca369a4c0e1c4363" + b"07bed9c4c171b4f453da4b187ba3d25a04bc1c07b9f2d6adcb3c256e4238d7049eec36a387c4dd5c" + b"cbc16b5fa62dc175cf8c5f83442cb7d153a3b6ee8daa3b6e929a4bc123f1042df1d6271a992d2b6b" + b"309d33074ac7822c304a72069e61ab590915e10862013dd24cdd825ec8fb17724cfc2c59fc1db825" + b"3641fece0ee9241b9dd5c198f0d575d0b7ebe26b3489b5b09edc3bcd366fd3110e83ce886c383d31" + b"feefe6e302cc2345210282010008f77a33d0081e9be3c1b1ac8b8e0eebb72df2eb69b95d2ed74935" + b"b9dab8e17023cc38465354023c5183b51a6a20288fbb2181172be1c2fdb8b444419454e5b37f7f3b" + b"df11e28cf4746b25534eb62f7e87bbbf28eda37024368b3897fbc661b40a93e04a183db9219c04a8" + b"7643edf5d8b5dbfe3d424e91d558d5e3e2fa02ce1984ee69fb8518470eee2e7db0e1df5ac4571f78" + b"a7a2529bc1fef5e32d46994869a8d8cc47869e174d84e7976be8ebb88f2ccb71a603a8bdb06af3eb" + b"2ddbd62082f40d7987e47f2e321eb5eb2a28fefab263409f89dc97ebc723a1b751418cdd3ea684ba" + b"8b17a330a306a6fbcf51ba83563aed85a4f886fff1a22423748d83798c" +) + +# Server +def instance0(): + multitest.globals(IP=multitest.get_network_ip()) + s = socket.socket() + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.bind(socket.getaddrinfo("0.0.0.0", PORT)[0][-1]) + s.listen(1) + multitest.next() + s2, _ = s.accept() + s2 = ssl.wrap_socket(s2, server_side=True, key=key, cert=cert) + print(s2.read(16)) + s2.write(b"server to client") + s2.close() + s.close() + + +# Client +def instance1(): + multitest.next() + s = socket.socket() + s.connect(socket.getaddrinfo(IP, PORT)[0][-1]) + s = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, cadata=cert) + s.write(b"client to server") + print(s.read(16)) + s.close() diff --git a/tests/multi_net/ssl_cert_rsa.py.exp b/tests/multi_net/ssl_cert_rsa.py.exp new file mode 100644 index 0000000000..909c496d01 --- /dev/null +++ b/tests/multi_net/ssl_cert_rsa.py.exp @@ -0,0 +1,4 @@ +--- instance0 --- +b'client to server' +--- instance1 --- +b'server to client' diff --git a/tests/net_inet/ssl_cert.py b/tests/net_inet/ssl_cert.py new file mode 100644 index 0000000000..d2d437e381 --- /dev/null +++ b/tests/net_inet/ssl_cert.py @@ -0,0 +1,68 @@ +import ubinascii as binascii +import usocket as socket +import ussl as ssl + + +# This certificate was obtained from micropython.org using openssl: +# $ openssl s_client -showcerts -connect micropython.org:443 /dev/null +# The certificate is from Let's Encrypt: +# 1 s:/C=US/O=Let's Encrypt/CN=R3 +# i:/C=US/O=Internet Security Research Group/CN=ISRG Root X1 +# Validity +# Not Before: Sep 4 00:00:00 2020 GMT +# Not After : Sep 15 16:00:00 2025 GMT +# Copy PEM content to a file (certmpy.pem) and convert to DER e.g. +# $ openssl x509 -in certmpy.pem -out certmpy.der -outform DER +# Then convert to hex format, eg using binascii.hexlify(data). + +ca_cert_chain = binascii.unhexlify( + b"30820516308202fea003020102021100912b084acf0c18a753f6d62e25a75f5a300d06092a864886" + b"f70d01010b0500304f310b300906035504061302555331293027060355040a1320496e7465726e65" + b"742053656375726974792052657365617263682047726f7570311530130603550403130c49535247" + b"20526f6f74205831301e170d3230303930343030303030305a170d3235303931353136303030305a" + b"3032310b300906035504061302555331163014060355040a130d4c6574277320456e637279707431" + b"0b300906035504031302523330820122300d06092a864886f70d01010105000382010f003082010a" + b"0282010100bb021528ccf6a094d30f12ec8d5592c3f882f199a67a4288a75d26aab52bb9c54cb1af" + b"8e6bf975c8a3d70f4794145535578c9ea8a23919f5823c42a94e6ef53bc32edb8dc0b05cf35938e7" + b"edcf69f05a0b1bbec094242587fa3771b313e71cace19befdbe43b45524596a9c153ce34c852eeb5" + b"aeed8fde6070e2a554abb66d0e97a540346b2bd3bc66eb66347cfa6b8b8f572999f830175dba726f" + b"fb81c5add286583d17c7e709bbf12bf786dcc1da715dd446e3ccad25c188bc60677566b3f118f7a2" + b"5ce653ff3a88b647a5ff1318ea9809773f9d53f9cf01e5f5a6701714af63a4ff99b3939ddc53a706" + b"fe48851da169ae2575bb13cc5203f5ed51a18bdb150203010001a382010830820104300e0603551d" + b"0f0101ff040403020186301d0603551d250416301406082b0601050507030206082b060105050703" + b"0130120603551d130101ff040830060101ff020100301d0603551d0e04160414142eb317b75856cb" + b"ae500940e61faf9d8b14c2c6301f0603551d2304183016801479b459e67bb6e5e40173800888c81a" + b"58f6e99b6e303206082b0601050507010104263024302206082b060105050730028616687474703a" + b"2f2f78312e692e6c656e63722e6f72672f30270603551d1f0420301e301ca01aa018861668747470" + b"3a2f2f78312e632e6c656e63722e6f72672f30220603551d20041b30193008060667810c01020130" + b"0d060b2b0601040182df13010101300d06092a864886f70d01010b0500038202010085ca4e473ea3" + b"f7854485bcd56778b29863ad754d1e963d336572542d81a0eac3edf820bf5fccb77000b76e3bf65e" + b"94dee4209fa6ef8bb203e7a2b5163c91ceb4ed3902e77c258a47e6656e3f46f4d9f0ce942bee54ce" + b"12bc8c274bb8c1982fa2afcd71914a08b7c8b8237b042d08f908573e83d904330a472178098227c3" + b"2ac89bb9ce5cf264c8c0be79c04f8e6d440c5e92bb2ef78b10e1e81d4429db5920ed63b921f81226" + b"949357a01d6504c10a22ae100d4397a1181f7ee0e08637b55ab1bd30bf876e2b2aff214e1b05c3f5" + b"1897f05eacc3a5b86af02ebc3b33b9ee4bdeccfce4af840b863fc0554336f668e136176a8e99d1ff" + b"a540a734b7c0d063393539756ef2ba76c89302e9a94b6c17ce0c02d9bd81fb9fb768d40665b3823d" + b"7753f88e7903ad0a3107752a43d8559772c4290ef7c45d4ec8ae468430d7f2855f18a179bbe75e70" + b"8b07e18693c3b98fdc6171252aafdfed255052688b92dce5d6b5e3da7dd0876c842131ae82f5fbb9" + b"abc889173de14ce5380ef6bd2bbd968114ebd5db3d20a77e59d3e2f858f95bb848cdfe5c4f1629fe" + b"1e5523afc811b08dea7c9390172ffdaca20947463ff0e9b0b7ff284d6832d6675e1e69a393b8f59d" + b"8b2f0bd25243a66f3257654d3281df3853855d7e5d6629eab8dde495b5cdb5561242cdc44ec62538" + b"44506decce005518fee94964d44eca979cb45bc073a8abb847c2" +) + + +def main(use_stream=True): + s = socket.socket() + ai = socket.getaddrinfo("micropython.org", 443) + addr = ai[0][-1] + s.connect(addr) + s = ssl.wrap_socket( + s, cert_reqs=ssl.CERT_REQUIRED, cadata=ca_cert_chain, server_hostname="micropython.org" + ) + s.write(b"GET / HTTP/1.0\r\n\r\n") + print(s.read(17)) + s.close() + + +main() diff --git a/tests/net_inet/ssl_cert.py.exp b/tests/net_inet/ssl_cert.py.exp new file mode 100644 index 0000000000..fb69ecf1a6 --- /dev/null +++ b/tests/net_inet/ssl_cert.py.exp @@ -0,0 +1 @@ +b'HTTP/1.1 200 OK\r\n' From bdad63eda2ddcf8cc6ac51bb463ecb695f12c86c Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 15 Jul 2022 11:23:23 +1000 Subject: [PATCH 0190/1041] extmod/btstack: Fix descriptor discovery handle range and events. This fixes two problems with the BTstack implementation of descriptor discovery: - The call to gatt_client_discover_characteristic_descriptors needs to have value_handle set to the starting handle (actually characteristic handle) to start the search from. - The BTstack event for a descriptor query result is GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT. With this change the test tests/multi_bluetooth/ble_subscribe.py now passes when BTstack is instance1 (for BTstack to pass as instance0 requires gatts_write to support sending an update on BTstack). Signed-off-by: Damien George --- extmod/btstack/modbluetooth_btstack.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c index c07cc8c10c..d41c671d68 100644 --- a/extmod/btstack/modbluetooth_btstack.c +++ b/extmod/btstack/modbluetooth_btstack.c @@ -451,7 +451,7 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t gatt_event_characteristic_query_result_get_characteristic(packet, &characteristic); mp_obj_bluetooth_uuid_t characteristic_uuid = create_mp_uuid(characteristic.uuid16, characteristic.uuid128); mp_bluetooth_gattc_on_characteristic_result(conn_handle, characteristic.start_handle, characteristic.value_handle, characteristic.properties, &characteristic_uuid); - } else if (event_type == GATT_EVENT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT) { + } else if (event_type == GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT) { DEBUG_printf(" --> gatt descriptor query result\n"); uint16_t conn_handle = gatt_event_all_characteristic_descriptors_query_result_get_handle(packet); gatt_client_characteristic_descriptor_t descriptor; @@ -1358,9 +1358,9 @@ int mp_bluetooth_gattc_discover_descriptors(uint16_t conn_handle, uint16_t start } gatt_client_characteristic_t characteristic = { - // Only start/end handles needed for gatt_client_discover_characteristic_descriptors. - .start_handle = start_handle, - .value_handle = 0, + // Only value/end handles needed for gatt_client_discover_characteristic_descriptors. + .start_handle = 0, + .value_handle = start_handle, .end_handle = end_handle, .properties = 0, .uuid16 = 0, From 768cbea507c57891371a428073df9781d410142e Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Tue, 19 Jul 2022 18:17:55 +0200 Subject: [PATCH 0191/1041] nrf/boards/arduino_nano_33_ble_sense: Update deploy instructions. --- .../boards/arduino_nano_33_ble_sense/deploy.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/deploy.md b/ports/nrf/boards/arduino_nano_33_ble_sense/deploy.md index a2d08f2c81..0d94a537bb 100644 --- a/ports/nrf/boards/arduino_nano_33_ble_sense/deploy.md +++ b/ports/nrf/boards/arduino_nano_33_ble_sense/deploy.md @@ -1,19 +1,23 @@ ### Update the bootloader -Before deploying any firmware, make sure you have the updated Arduino Nano 33 BLE bootloader, which relocates the bootloader so the softdevice doesn't overwrite it. Please see: - -https://docs.arduino.cc/tutorials/nano-33-ble/getting-started-omv +Before deploying any firmware images, make sure the board is running the +updated Arduino Nano 33 BLE bootloader (which is relocated to the end of +the flash), otherwise the bootloader will be overwritten by the softdevice. +For more information on how to update the bootloader, see the +[Getting Started with OpenMV/MicroPython](https://docs.arduino.cc/tutorials/nano-33-ble/getting-started-omv) tutorial. ### Via Arduino bootloader and BOSSA -Download BOSSA from https://github.com/shumatech/BOSSA/ and double tap reset button to enter the Arduino bootloader +Download the latest BOSSA flash programmer from the +[Arduino BOSSA fork](https://github.com/arduino/BOSSA/releases/latest). +Note this version adds support for nRF devices, and must be used with the +Nano 33 BLE. Double tap the reset button to enter the bootloader, and run +the following command: ```bash bossac -e -w --offset=0x16000 --port=ttyACM0 -i -d -U -R build-arduino_nano_33_ble_sense-s140/firmware.bin ``` -Alternatively, a Linux binary can be found here: https://github.com/openmv/openmv/blob/master/tools/bossac - ### Via nrfprog This board can also be programmed via nrfjprog (with Jlink for example), from MicroPython source repository: From 2e2fc8f60f68d03a593286a3e946e12c962c9b0c Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 20 Jul 2022 08:08:24 +0200 Subject: [PATCH 0192/1041] nrf/main: Call usb_cdc_init() before executing boot.py and main.py. Otherwise, there is no USB available when running main.py, and main.py cannot be interrupted with Ctrl-C. --- ports/nrf/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ports/nrf/main.c b/ports/nrf/main.c index 091aa73f45..83466626fc 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -257,16 +257,16 @@ soft_reset: led_state(1, 0); + #if MICROPY_HW_USB_CDC + usb_cdc_init(); + #endif + #if MICROPY_VFS || MICROPY_MBFS || MICROPY_MODULE_FROZEN // run boot.py and main.py if they exist. pyexec_file_if_exists("boot.py"); pyexec_file_if_exists("main.py"); #endif - #if MICROPY_HW_USB_CDC - usb_cdc_init(); - #endif - for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_raw_repl() != 0) { From 8b4298a4bf4c5b6cf56021385661739744f0037c Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 20 Jul 2022 17:16:36 +1000 Subject: [PATCH 0193/1041] rp2/mpbthciport: Remove mp_bthci_uart from set of root pointers. This is a statically-allocated UART (see machine_uart.c), and doesn't contain any heap pointers other than the ringbufs (which are already root pointers), so no need to track it additionally. Saves needing to add mpbthciport.c to the QSTR sources. Signed-off-by: Jim Mussared --- ports/rp2/mpbthciport.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ports/rp2/mpbthciport.c b/ports/rp2/mpbthciport.c index cd41da017a..91c908b164 100644 --- a/ports/rp2/mpbthciport.c +++ b/ports/rp2/mpbthciport.c @@ -100,8 +100,10 @@ int mp_bluetooth_hci_uart_init(uint32_t port, uint32_t baudrate) { MP_OBJ_NEW_QSTR(MP_QSTR_timeout), MP_OBJ_NEW_SMALL_INT(1000), }; + // This is a statically-allocated UART (see machine_uart.c), and doesn't + // contain any heap pointers other than the ringbufs (which are already + // root pointers), so no need to track this as a root pointer. mp_bthci_uart = machine_uart_type.make_new((mp_obj_t)&machine_uart_type, 2, 2, args); - MP_STATE_PORT(mp_bthci_uart) = mp_bthci_uart; // Start the HCI polling to process any initial events/packets. mp_bluetooth_hci_start_polling(); @@ -197,6 +199,4 @@ MP_WEAK int mp_bluetooth_hci_controller_wakeup(void) { return 0; } -MP_REGISTER_ROOT_POINTER(struct _machine_uart_obj_t *mp_bthci_uart); - #endif // MICROPY_PY_BLUETOOTH From a0538270841987b87f44164548d6c2696a05fdee Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 20 Jul 2022 17:17:34 +1000 Subject: [PATCH 0194/1041] extmod/network_ninaw10: Move ninaw10 root pointer registrations here. Originally in drivers/ninaw10/nina_wifi_bsp.c but that isn't a QSTR source. Also remove outdated commment about root pointers in mpconfigport.h. Signed-off-by: Jim Mussared --- drivers/ninaw10/nina_wifi_bsp.c | 4 ---- extmod/network_ninaw10.c | 4 ++++ ports/rp2/mpconfigport.h | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/ninaw10/nina_wifi_bsp.c b/drivers/ninaw10/nina_wifi_bsp.c index d11e139705..a65ef7fd86 100644 --- a/drivers/ninaw10/nina_wifi_bsp.c +++ b/drivers/ninaw10/nina_wifi_bsp.c @@ -150,8 +150,4 @@ int nina_bsp_spi_transfer(const uint8_t *tx_buf, uint8_t *rx_buf, uint32_t size) return 0; } -MP_REGISTER_ROOT_POINTER(struct _machine_spi_obj_t *mp_wifi_spi); -MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *mp_wifi_timer); -MP_REGISTER_ROOT_POINTER(struct _mp_obj_list_t *mp_wifi_sockpoll_list); - #endif // MICROPY_PY_NETWORK_NINAW10 diff --git a/extmod/network_ninaw10.c b/extmod/network_ninaw10.c index 622e29ba68..4014a71c1a 100644 --- a/extmod/network_ninaw10.c +++ b/extmod/network_ninaw10.c @@ -797,4 +797,8 @@ const mod_network_nic_type_t mod_network_nic_type_nina = { .ioctl = network_ninaw10_socket_ioctl, }; +MP_REGISTER_ROOT_POINTER(struct _machine_spi_obj_t *mp_wifi_spi); +MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *mp_wifi_timer); +MP_REGISTER_ROOT_POINTER(struct _mp_obj_list_t *mp_wifi_sockpoll_list); + #endif // #if MICROPY_PY_BLUETOOTH && MICROPY_PY_NETWORK_NINAW10 diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 14748a763d..d07c1015e7 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -176,7 +176,6 @@ extern const struct _mp_obj_type_t mp_network_cyw43_type; #ifndef MICROPY_PY_USOCKET_EXTENDED_STATE #define MICROPY_PY_USOCKET_EXTENDED_STATE (1) #endif -// It also requires an additional root pointer for the SPI object. extern const struct _mod_network_nic_type_t mod_network_nic_type_nina; #define MICROPY_HW_NIC_NINAW10 { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mod_network_nic_type_nina) }, #else From 4cf9928902a1e4bca4edc433eeab6b8fdb1a5245 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 20 Jul 2022 17:30:16 +1000 Subject: [PATCH 0195/1041] cc3200: Fix various array-based compiler warnings. 1. Add -Wno-array-bounds to avoid false positive on gcc 12.1; see related issue #8685. 2. Remove always-true not-NULL-check (Msg.Rsp.Args.Common.Bssid is an array not a pointer). 3. Fix pointer-to-freed-stack in wlan_set_security. Signed-off-by: Jim Mussared --- drivers/cc3100/src/wlan.c | 5 +---- ports/cc3200/Makefile | 3 +++ ports/cc3200/mods/modwlan.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/cc3100/src/wlan.c b/drivers/cc3100/src/wlan.c index 59adf02f02..22be4d7ddf 100644 --- a/drivers/cc3100/src/wlan.c +++ b/drivers/cc3100/src/wlan.c @@ -536,10 +536,7 @@ _i16 sl_WlanProfileGet(const _i16 Index,_i8* pName, _i16 *pNameLen, _u8 *pMacAd *pNameLen = Msg.Rsp.Args.Common.SsidLen; *pPriority = Msg.Rsp.Args.Common.Priority; - if (NULL != Msg.Rsp.Args.Common.Bssid) - { - sl_Memcpy(pMacAddr, Msg.Rsp.Args.Common.Bssid, sizeof(Msg.Rsp.Args.Common.Bssid)); - } + sl_Memcpy(pMacAddr, Msg.Rsp.Args.Common.Bssid, sizeof(Msg.Rsp.Args.Common.Bssid)); sl_Memcpy(pName, EAP_PROFILE_SSID_STRING(&Msg), *pNameLen); diff --git a/ports/cc3200/Makefile b/ports/cc3200/Makefile index 90be4529d8..b880ad646b 100644 --- a/ports/cc3200/Makefile +++ b/ports/cc3200/Makefile @@ -25,6 +25,9 @@ CFLAGS += -g -ffunction-sections -fdata-sections -fno-common -fsigned-char -mno- CFLAGS += -Iboards/$(BOARD) CFLAGS += $(CFLAGS_MOD) +# Workaround gcc 12.1 bug. +CFLAGS += -Wno-array-bounds + LDFLAGS = -Wl,-nostdlib -Wl,--gc-sections -Wl,-Map=$@.map FLASH_SIZE_WIPY = 2M diff --git a/ports/cc3200/mods/modwlan.c b/ports/cc3200/mods/modwlan.c index 920079b589..3b686932e8 100644 --- a/ports/cc3200/mods/modwlan.c +++ b/ports/cc3200/mods/modwlan.c @@ -641,8 +641,8 @@ STATIC void wlan_set_security (uint8_t auth, const char *key, uint8_t len) { if (key != NULL) { memcpy(&wlan_obj.key, key, len); wlan_obj.key[len] = '\0'; + _u8 wep_key[32]; if (auth == SL_SEC_TYPE_WEP) { - _u8 wep_key[32]; wlan_wep_key_unhexlify(key, (char *)&wep_key); key = (const char *)&wep_key; len /= 2; From e05d0a6335be6a45f29f5d987091b858ad378cfa Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 17 Mar 2021 12:34:49 +1100 Subject: [PATCH 0196/1041] extmod/modbluetooth: Add support for running sync irq on system thread. If the Bluetooth stack runs on another OS thread then synchronous BLE irq callbacks, which block the Bluetooth stack until the callback to Python is complete, must coordinate with the main thread and configure the MicroPython thread-local-state. This commit adds MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS_WITH_INTERLOCK which can be enabled if the system has these requirements. Signed-off-by: Damien George --- extmod/modbluetooth.c | 73 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 9956671863..4645ae6c98 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -34,6 +34,7 @@ #include "py/objarray.h" #include "py/qstr.h" #include "py/runtime.h" +#include "py/stackctrl.h" #include "extmod/modbluetooth.h" #include @@ -1135,7 +1136,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluetooth_ble_invoke_irq_obj, bluetooth_ble_inv #if MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS -STATIC mp_obj_t invoke_irq_handler(uint16_t event, +STATIC mp_obj_t invoke_irq_handler_run(uint16_t event, const mp_int_t *numeric, size_t n_unsigned, size_t n_signed, const uint8_t *addr, const mp_obj_bluetooth_uuid_t *uuid, @@ -1185,6 +1186,76 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event, return result; } +#if MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS_WITH_INTERLOCK + +// On some systems the BLE event callbacks may occur on a system thread which is not +// a MicroPython thread. In such cases the callback must set up relevant MicroPython +// state and obtain the GIL, to synchronised with the rest of the runtime. + +#if MICROPY_ENABLE_PYSTACK +#error not supported +#endif + +STATIC mp_obj_t invoke_irq_handler(uint16_t event, + const mp_int_t *numeric, size_t n_unsigned, size_t n_signed, + const uint8_t *addr, + const mp_obj_bluetooth_uuid_t *uuid, + const uint8_t **data, size_t *data_len, size_t n_data) { + + // This code may run on an existing MicroPython thread, or a non-MicroPython thread + // that's not using the mp_thread_get_state() value. In the former case the state + // must be restored once this callback finishes. + mp_state_thread_t *ts_orig = mp_thread_get_state(); + + mp_state_thread_t ts; + if (ts_orig == NULL) { + mp_thread_set_state(&ts); + mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan + mp_stack_set_limit(MICROPY_PY_BLUETOOTH_SYNC_EVENT_STACK_SIZE - 1024); + ts.gc_lock_depth = 0; + ts.mp_pending_exception = MP_OBJ_NULL; + mp_locals_set(mp_state_ctx.thread.dict_locals); // set from the outer context + mp_globals_set(mp_state_ctx.thread.dict_globals); // set from the outer context + MP_THREAD_GIL_ENTER(); + } + + mp_obj_t result = mp_const_none; + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_sched_lock(); + result = invoke_irq_handler_run(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data); + mp_sched_unlock(); + nlr_pop(); + } else { + // Uncaught exception, print it out. + mp_sched_unlock(); + mp_printf(MICROPY_ERROR_PRINTER, "Unhandled exception in IRQ callback handler\n"); + mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(nlr.ret_val)); + } + + if (ts_orig == NULL) { + MP_THREAD_GIL_EXIT(); + mp_thread_set_state(ts_orig); + } + + return result; +} + +#else + +// BLE event callbacks are called directly from the MicroPython runtime, so additional +// synchronisation is not needed, and BLE event handlers can be called directly. + +STATIC mp_obj_t invoke_irq_handler(uint16_t event, + const mp_int_t *numeric, size_t n_unsigned, size_t n_signed, + const uint8_t *addr, + const mp_obj_bluetooth_uuid_t *uuid, + const uint8_t **data, size_t *data_len, size_t n_data) { + return invoke_irq_handler_run(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data); +} + +#endif + #define NULL_NUMERIC NULL #define NULL_ADDR NULL #define NULL_UUID NULL From 5dbb822ca4a809ac5cb4513afb0411b4eb8dc3cf Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 17 Mar 2021 12:35:59 +1100 Subject: [PATCH 0197/1041] esp32/mpconfigport: Enable BLE synchronous events and pairing/bonding. Signed-off-by: Damien George --- ports/esp32/main/CMakeLists.txt | 6 +++++- ports/esp32/mpconfigport.h | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ports/esp32/main/CMakeLists.txt b/ports/esp32/main/CMakeLists.txt index 9ac6537f86..fccfd6b7c7 100644 --- a/ports/esp32/main/CMakeLists.txt +++ b/ports/esp32/main/CMakeLists.txt @@ -198,11 +198,15 @@ target_compile_options(${MICROPY_TARGET} PUBLIC -Wno-missing-field-initializers ) +# Additional include directories needed for private NimBLE headers. +target_include_directories(${MICROPY_TARGET} PUBLIC + ${IDF_PATH}/components/bt/host/nimble/nimble +) + # Add additional extmod and usermod components. target_link_libraries(${MICROPY_TARGET} micropy_extmod_btree) target_link_libraries(${MICROPY_TARGET} usermod) - # Collect all of the include directories and compile definitions for the IDF components. foreach(comp ${IDF_COMPONENTS}) micropy_gather_target_properties(__idf_${comp}) diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 8dc3537e59..dfa577d2bc 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -70,7 +70,11 @@ // extended modules #ifndef MICROPY_PY_BLUETOOTH #define MICROPY_PY_BLUETOOTH (1) +#define MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS (1) +#define MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS_WITH_INTERLOCK (1) +#define MICROPY_PY_BLUETOOTH_SYNC_EVENT_STACK_SIZE (CONFIG_BT_NIMBLE_TASK_STACK_SIZE) #define MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE (1) +#define MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING (1) #define MICROPY_BLUETOOTH_NIMBLE (1) #define MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY (1) #endif From bcc827d695e20b644ff4626bd529e3d8706716d7 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Wed, 24 Jan 2018 02:09:58 +0100 Subject: [PATCH 0198/1041] py/gc: Allow the GC heap to be split over multiple memory areas. This commit adds a new option MICROPY_GC_SPLIT_HEAP (disabled by default) which, when enabled, allows the GC heap to be split over multiple memory areas/regions. The first area is added with gc_init() and subsequent areas can be added with gc_add(). New areas can be added at runtime. Areas are stored internally as a linked list, and calls to gc_alloc() can be satisfied from any area. This feature has the following use-cases (among others): - The ESP32 has a fragmented OS heap, so to use all (or more) of it the GC heap must be split. - Other MCUs may have disjoint RAM regions and are now able to use them all for the GC heap. - The user could explicitly increase the size of the GC heap. - Support a dynamic heap while running on an OS, adding more heap when necessary. --- py/gc.c | 769 +++++++++++++++++++++++++++++--------------------- py/gc.h | 6 + py/mpconfig.h | 5 + py/mpstate.h | 39 ++- 4 files changed, 497 insertions(+), 322 deletions(-) diff --git a/py/gc.c b/py/gc.c index 0c1f3961df..93e83aaad5 100644 --- a/py/gc.c +++ b/py/gc.c @@ -74,17 +74,22 @@ #define ATB_2_IS_FREE(a) (((a) & ATB_MASK_2) == 0) #define ATB_3_IS_FREE(a) (((a) & ATB_MASK_3) == 0) -#define BLOCK_SHIFT(block) (2 * ((block) & (BLOCKS_PER_ATB - 1))) -#define ATB_GET_KIND(block) ((MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] >> BLOCK_SHIFT(block)) & 3) -#define ATB_ANY_TO_FREE(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] &= (~(AT_MARK << BLOCK_SHIFT(block))); } while (0) -#define ATB_FREE_TO_HEAD(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] |= (AT_HEAD << BLOCK_SHIFT(block)); } while (0) -#define ATB_FREE_TO_TAIL(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] |= (AT_TAIL << BLOCK_SHIFT(block)); } while (0) -#define ATB_HEAD_TO_MARK(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] |= (AT_MARK << BLOCK_SHIFT(block)); } while (0) -#define ATB_MARK_TO_HEAD(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] &= (~(AT_TAIL << BLOCK_SHIFT(block))); } while (0) +#if MICROPY_GC_SPLIT_HEAP +#define NEXT_AREA(area) (area->next) +#else +#define NEXT_AREA(area) (NULL) +#endif -#define BLOCK_FROM_PTR(ptr) (((byte *)(ptr) - MP_STATE_MEM(gc_pool_start)) / BYTES_PER_BLOCK) -#define PTR_FROM_BLOCK(block) (((block) * BYTES_PER_BLOCK + (uintptr_t)MP_STATE_MEM(gc_pool_start))) -#define ATB_FROM_BLOCK(bl) ((bl) / BLOCKS_PER_ATB) +#define BLOCK_SHIFT(block) (2 * ((block) & (BLOCKS_PER_ATB - 1))) +#define ATB_GET_KIND(area, block) (((area)->gc_alloc_table_start[(block) / BLOCKS_PER_ATB] >> BLOCK_SHIFT(block)) & 3) +#define ATB_ANY_TO_FREE(area, block) do { area->gc_alloc_table_start[(block) / BLOCKS_PER_ATB] &= (~(AT_MARK << BLOCK_SHIFT(block))); } while (0) +#define ATB_FREE_TO_HEAD(area, block) do { area->gc_alloc_table_start[(block) / BLOCKS_PER_ATB] |= (AT_HEAD << BLOCK_SHIFT(block)); } while (0) +#define ATB_FREE_TO_TAIL(area, block) do { area->gc_alloc_table_start[(block) / BLOCKS_PER_ATB] |= (AT_TAIL << BLOCK_SHIFT(block)); } while (0) +#define ATB_HEAD_TO_MARK(area, block) do { area->gc_alloc_table_start[(block) / BLOCKS_PER_ATB] |= (AT_MARK << BLOCK_SHIFT(block)); } while (0) +#define ATB_MARK_TO_HEAD(area, block) do { area->gc_alloc_table_start[(block) / BLOCKS_PER_ATB] &= (~(AT_TAIL << BLOCK_SHIFT(block))); } while (0) + +#define BLOCK_FROM_PTR(area, ptr) (((byte *)(ptr) - area->gc_pool_start) / BYTES_PER_BLOCK) +#define PTR_FROM_BLOCK(area, block) (((block) * BYTES_PER_BLOCK + (uintptr_t)area->gc_pool_start)) #if MICROPY_ENABLE_FINALISER // FTB = finaliser table byte @@ -92,9 +97,9 @@ #define BLOCKS_PER_FTB (8) -#define FTB_GET(block) ((MP_STATE_MEM(gc_finaliser_table_start)[(block) / BLOCKS_PER_FTB] >> ((block) & 7)) & 1) -#define FTB_SET(block) do { MP_STATE_MEM(gc_finaliser_table_start)[(block) / BLOCKS_PER_FTB] |= (1 << ((block) & 7)); } while (0) -#define FTB_CLEAR(block) do { MP_STATE_MEM(gc_finaliser_table_start)[(block) / BLOCKS_PER_FTB] &= (~(1 << ((block) & 7))); } while (0) +#define FTB_GET(area, block) ((area->gc_finaliser_table_start[(block) / BLOCKS_PER_FTB] >> ((block) & 7)) & 1) +#define FTB_SET(area, block) do { area->gc_finaliser_table_start[(block) / BLOCKS_PER_FTB] |= (1 << ((block) & 7)); } while (0) +#define FTB_CLEAR(area, block) do { area->gc_finaliser_table_start[(block) / BLOCKS_PER_FTB] &= (~(1 << ((block) & 7))); } while (0) #endif #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL @@ -106,11 +111,7 @@ #endif // TODO waste less memory; currently requires that all entries in alloc_table have a corresponding block in pool -void gc_init(void *start, void *end) { - // align end pointer on block boundary - end = (void *)((uintptr_t)end & (~(BYTES_PER_BLOCK - 1))); - DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, (byte *)end - (byte *)start); - +STATIC void gc_setup_area(mp_state_mem_area_t *area, void *start, void *end) { // calculate parameters for GC (T=total, A=alloc table, F=finaliser table, P=pool; all in bytes): // T = A + F + P // F = A * BLOCKS_PER_ATB / BLOCKS_PER_FTB @@ -118,36 +119,52 @@ void gc_init(void *start, void *end) { // => T = A * (1 + BLOCKS_PER_ATB / BLOCKS_PER_FTB + BLOCKS_PER_ATB * BYTES_PER_BLOCK) size_t total_byte_len = (byte *)end - (byte *)start; #if MICROPY_ENABLE_FINALISER - MP_STATE_MEM(gc_alloc_table_byte_len) = total_byte_len * MP_BITS_PER_BYTE / (MP_BITS_PER_BYTE + MP_BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB + MP_BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK); + area->gc_alloc_table_byte_len = total_byte_len * MP_BITS_PER_BYTE / (MP_BITS_PER_BYTE + MP_BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB + MP_BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK); #else - MP_STATE_MEM(gc_alloc_table_byte_len) = total_byte_len / (1 + MP_BITS_PER_BYTE / 2 * BYTES_PER_BLOCK); + area->gc_alloc_table_byte_len = total_byte_len / (1 + MP_BITS_PER_BYTE / 2 * BYTES_PER_BLOCK); #endif - MP_STATE_MEM(gc_alloc_table_start) = (byte *)start; + area->gc_alloc_table_start = (byte *)start; #if MICROPY_ENABLE_FINALISER - size_t gc_finaliser_table_byte_len = (MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB + BLOCKS_PER_FTB - 1) / BLOCKS_PER_FTB; - MP_STATE_MEM(gc_finaliser_table_start) = MP_STATE_MEM(gc_alloc_table_start) + MP_STATE_MEM(gc_alloc_table_byte_len); + size_t gc_finaliser_table_byte_len = (area->gc_alloc_table_byte_len * BLOCKS_PER_ATB + BLOCKS_PER_FTB - 1) / BLOCKS_PER_FTB; + area->gc_finaliser_table_start = area->gc_alloc_table_start + area->gc_alloc_table_byte_len; #endif - size_t gc_pool_block_len = MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; - MP_STATE_MEM(gc_pool_start) = (byte *)end - gc_pool_block_len * BYTES_PER_BLOCK; - MP_STATE_MEM(gc_pool_end) = end; + size_t gc_pool_block_len = area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; + area->gc_pool_start = (byte *)end - gc_pool_block_len * BYTES_PER_BLOCK; + area->gc_pool_end = end; #if MICROPY_ENABLE_FINALISER - assert(MP_STATE_MEM(gc_pool_start) >= MP_STATE_MEM(gc_finaliser_table_start) + gc_finaliser_table_byte_len); + assert(area->gc_pool_start >= area->gc_finaliser_table_start + gc_finaliser_table_byte_len); #endif // clear ATBs - memset(MP_STATE_MEM(gc_alloc_table_start), 0, MP_STATE_MEM(gc_alloc_table_byte_len)); + memset(area->gc_alloc_table_start, 0, area->gc_alloc_table_byte_len); #if MICROPY_ENABLE_FINALISER // clear FTBs - memset(MP_STATE_MEM(gc_finaliser_table_start), 0, gc_finaliser_table_byte_len); + memset(area->gc_finaliser_table_start, 0, gc_finaliser_table_byte_len); #endif + area->gc_last_free_atb_index = 0; + + #if MICROPY_GC_SPLIT_HEAP + area->next = NULL; + #endif +} + +void gc_init(void *start, void *end) { + // align end pointer on block boundary + end = (void *)((uintptr_t)end & (~(BYTES_PER_BLOCK - 1))); + DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, (byte *)end - (byte *)start); + + gc_setup_area(&MP_STATE_MEM(area), start, end); + // set last free ATB index to start of heap - MP_STATE_MEM(gc_last_free_atb_index) = 0; + #if MICROPY_GC_SPLIT_HEAP + MP_STATE_MEM(gc_last_free_area) = &MP_STATE_MEM(area); + #endif // unlock the GC MP_STATE_THREAD(gc_lock_depth) = 0; @@ -173,6 +190,29 @@ void gc_init(void *start, void *end) { DEBUG_printf(" pool at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", MP_STATE_MEM(gc_pool_start), gc_pool_block_len * BYTES_PER_BLOCK, gc_pool_block_len); } +#if MICROPY_GC_SPLIT_HEAP +void gc_add(void *start, void *end) { + // Place the area struct at the start of the area. + mp_state_mem_area_t *area = (mp_state_mem_area_t *)start; + start = (void *)((uintptr_t)start + sizeof(mp_state_mem_area_t)); + + end = (void *)((uintptr_t)end & (~(BYTES_PER_BLOCK - 1))); + DEBUG_printf("Adding GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, (byte *)end - (byte *)start); + + // Init this area + gc_setup_area(area, start, end); + + // Find the last registered area in the linked list + mp_state_mem_area_t *prev_area = &MP_STATE_MEM(area); + while (prev_area->next != NULL) { + prev_area = prev_area->next; + } + + // Add this area to the linked list + prev_area->next = area; +} +#endif + void gc_lock(void) { // This does not need to be atomic or have the GC mutex because: // - each thread has its own gc_lock_depth so there are no races between threads; @@ -190,12 +230,20 @@ bool gc_is_locked(void) { return MP_STATE_THREAD(gc_lock_depth) != 0; } -// ptr should be of type void* -#define VERIFY_PTR(ptr) ( \ - ((uintptr_t)(ptr) & (BYTES_PER_BLOCK - 1)) == 0 /* must be aligned on a block */ \ - && ptr >= (void *)MP_STATE_MEM(gc_pool_start) /* must be above start of pool */ \ - && ptr < (void *)MP_STATE_MEM(gc_pool_end) /* must be below end of pool */ \ - ) +// Returns the area to which this pointer belongs, or NULL if it isn't +// allocated on the GC-managed heap. +STATIC inline mp_state_mem_area_t *gc_get_ptr_area(const void *ptr) { + if (((uintptr_t)(ptr) & (BYTES_PER_BLOCK - 1)) != 0) { // must be aligned on a block + return NULL; + } + for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { + if (ptr >= (void *)area->gc_pool_start // must be above start of pool + && ptr < (void *)area->gc_pool_end) { // must be below end of pool + return area; + } + } + return NULL; +} #ifndef TRACE_MARK #if DEBUG_PRINT @@ -209,45 +257,64 @@ bool gc_is_locked(void) { // children: mark the unmarked child blocks and put those newly marked // blocks on the stack. When all children have been checked, pop off the // topmost block on the stack and repeat with that one. -STATIC void gc_mark_subtree(size_t block) { - // Start with the block passed in the argument. +STATIC void gc_mark_subtree(mp_gc_stack_item_t item) { + // Start with the item passed in the argument. size_t sp = 0; for (;;) { MICROPY_GC_HOOK_LOOP + + #if MICROPY_GC_SPLIT_HEAP + mp_state_mem_area_t *area = item.area; + #else + mp_state_mem_area_t *area = &MP_STATE_MEM(area); + #endif + size_t block = item.block; + // work out number of consecutive blocks in the chain starting with this one size_t n_blocks = 0; do { n_blocks += 1; - } while (ATB_GET_KIND(block + n_blocks) == AT_TAIL); + } while (ATB_GET_KIND(area, block + n_blocks) == AT_TAIL); // check this block's children - void **ptrs = (void **)PTR_FROM_BLOCK(block); + void **ptrs = (void **)PTR_FROM_BLOCK(area, block); for (size_t i = n_blocks * BYTES_PER_BLOCK / sizeof(void *); i > 0; i--, ptrs++) { MICROPY_GC_HOOK_LOOP void *ptr = *ptrs; - if (VERIFY_PTR(ptr)) { - // Mark and push this pointer - size_t childblock = BLOCK_FROM_PTR(ptr); - if (ATB_GET_KIND(childblock) == AT_HEAD) { - // an unmarked head, mark it, and push it on gc stack - TRACE_MARK(childblock, ptr); - ATB_HEAD_TO_MARK(childblock); - if (sp < MICROPY_ALLOC_GC_STACK_SIZE) { - MP_STATE_MEM(gc_stack)[sp++] = childblock; - } else { - MP_STATE_MEM(gc_stack_overflow) = 1; - } - } + // If this is a heap pointer that hasn't been marked, mark it and push + // it's children to the stack. + mp_state_mem_area_t *ptr_area = gc_get_ptr_area(ptr); + if (!ptr_area) { + // Not a heap-allocated pointer (might even be random data). + continue; + } + size_t ptr_block = BLOCK_FROM_PTR(ptr_area, ptr); + if (ATB_GET_KIND(ptr_area, ptr_block) != AT_HEAD) { + // This block is already marked. + continue; + } + // An unmarked head. Mark it, and push it on gc stack. + TRACE_MARK(ptr_block, ptr); + ATB_HEAD_TO_MARK(ptr_area, ptr_block); + if (sp < MICROPY_ALLOC_GC_STACK_SIZE) { + #if MICROPY_GC_SPLIT_HEAP + mp_gc_stack_item_t ptr_item = {ptr_area, ptr_block}; + #else + mp_gc_stack_item_t ptr_item = {ptr_block}; + #endif + MP_STATE_MEM(gc_stack)[sp++] = ptr_item; + } else { + MP_STATE_MEM(gc_stack_overflow) = 1; } } - // Are there any blocks on the stack? + // Are there any items on the stack? if (sp == 0) { break; // No, stack is empty, we're done. } - // pop the next block off the stack - block = MP_STATE_MEM(gc_stack)[--sp]; + // pop the next item off the stack + item = MP_STATE_MEM(gc_stack)[--sp]; } } @@ -256,11 +323,20 @@ STATIC void gc_deal_with_stack_overflow(void) { MP_STATE_MEM(gc_stack_overflow) = 0; // scan entire memory looking for blocks which have been marked but not their children - for (size_t block = 0; block < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; block++) { - MICROPY_GC_HOOK_LOOP - // trace (again) if mark bit set - if (ATB_GET_KIND(block) == AT_MARK) { - gc_mark_subtree(block); + for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { + for (size_t block = 0; block < area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) { + MICROPY_GC_HOOK_LOOP + // trace (again) if mark bit set + if (ATB_GET_KIND(area, block) == AT_MARK) { + #if MICROPY_GC_SPLIT_HEAP + mp_gc_stack_item_t item = {area, block}; + #else + mp_gc_stack_item_t item = {block}; + #endif + // *MP_STATE_MEM(gc_sp)++ = item; + // gc_drain_stack(); + gc_mark_subtree(item); + } } } } @@ -272,53 +348,55 @@ STATIC void gc_sweep(void) { #endif // free unmarked heads and their tails int free_tail = 0; - for (size_t block = 0; block < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; block++) { - MICROPY_GC_HOOK_LOOP - switch (ATB_GET_KIND(block)) { - case AT_HEAD: - #if MICROPY_ENABLE_FINALISER - if (FTB_GET(block)) { - mp_obj_base_t *obj = (mp_obj_base_t *)PTR_FROM_BLOCK(block); - if (obj->type != NULL) { - // if the object has a type then see if it has a __del__ method - mp_obj_t dest[2]; - mp_load_method_maybe(MP_OBJ_FROM_PTR(obj), MP_QSTR___del__, dest); - if (dest[0] != MP_OBJ_NULL) { - // load_method returned a method, execute it in a protected environment - #if MICROPY_ENABLE_SCHEDULER - mp_sched_lock(); - #endif - mp_call_function_1_protected(dest[0], dest[1]); - #if MICROPY_ENABLE_SCHEDULER - mp_sched_unlock(); - #endif + for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { + for (size_t block = 0; block < area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) { + MICROPY_GC_HOOK_LOOP + switch (ATB_GET_KIND(area, block)) { + case AT_HEAD: + #if MICROPY_ENABLE_FINALISER + if (FTB_GET(area, block)) { + mp_obj_base_t *obj = (mp_obj_base_t *)PTR_FROM_BLOCK(area, block); + if (obj->type != NULL) { + // if the object has a type then see if it has a __del__ method + mp_obj_t dest[2]; + mp_load_method_maybe(MP_OBJ_FROM_PTR(obj), MP_QSTR___del__, dest); + if (dest[0] != MP_OBJ_NULL) { + // load_method returned a method, execute it in a protected environment + #if MICROPY_ENABLE_SCHEDULER + mp_sched_lock(); + #endif + mp_call_function_1_protected(dest[0], dest[1]); + #if MICROPY_ENABLE_SCHEDULER + mp_sched_unlock(); + #endif + } } + // clear finaliser flag + FTB_CLEAR(area, block); } - // clear finaliser flag - FTB_CLEAR(block); - } - #endif - free_tail = 1; - DEBUG_printf("gc_sweep(%p)\n", (void *)PTR_FROM_BLOCK(block)); - #if MICROPY_PY_GC_COLLECT_RETVAL - MP_STATE_MEM(gc_collected)++; - #endif - // fall through to free the head - MP_FALLTHROUGH - - case AT_TAIL: - if (free_tail) { - ATB_ANY_TO_FREE(block); - #if CLEAR_ON_SWEEP - memset((void *)PTR_FROM_BLOCK(block), 0, BYTES_PER_BLOCK); #endif - } - break; + free_tail = 1; + DEBUG_printf("gc_sweep(%p)\n", (void *)PTR_FROM_BLOCK(area, block)); + #if MICROPY_PY_GC_COLLECT_RETVAL + MP_STATE_MEM(gc_collected)++; + #endif + // fall through to free the head + MP_FALLTHROUGH - case AT_MARK: - ATB_MARK_TO_HEAD(block); - free_tail = 0; - break; + case AT_TAIL: + if (free_tail) { + ATB_ANY_TO_FREE(area, block); + #if CLEAR_ON_SWEEP + memset((void *)PTR_FROM_BLOCK(area, block), 0, BYTES_PER_BLOCK); + #endif + } + break; + + case AT_MARK: + ATB_MARK_TO_HEAD(area, block); + free_tail = 0; + break; + } } } } @@ -360,13 +438,18 @@ void gc_collect_root(void **ptrs, size_t len) { for (size_t i = 0; i < len; i++) { MICROPY_GC_HOOK_LOOP void *ptr = gc_get_ptr(ptrs, i); - if (VERIFY_PTR(ptr)) { - size_t block = BLOCK_FROM_PTR(ptr); - if (ATB_GET_KIND(block) == AT_HEAD) { + mp_state_mem_area_t *area = gc_get_ptr_area(ptr); + if (area) { + size_t block = BLOCK_FROM_PTR(area, ptr); + if (ATB_GET_KIND(area, block) == AT_HEAD) { // An unmarked head: mark it, and mark all its children - TRACE_MARK(block, ptr); - ATB_HEAD_TO_MARK(block); - gc_mark_subtree(block); + ATB_HEAD_TO_MARK(area, block); + #if MICROPY_GC_SPLIT_HEAP + mp_gc_stack_item_t item = {area, block}; + #else + mp_gc_stack_item_t item = {block}; + #endif + gc_mark_subtree(item); } } } @@ -375,7 +458,12 @@ void gc_collect_root(void **ptrs, size_t len) { void gc_collect_end(void) { gc_deal_with_stack_overflow(); gc_sweep(); - MP_STATE_MEM(gc_last_free_atb_index) = 0; + #if MICROPY_GC_SPLIT_HEAP + MP_STATE_MEM(gc_last_free_area) = &MP_STATE_MEM(area); + #endif + for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { + area->gc_last_free_atb_index = 0; + } MP_STATE_THREAD(gc_lock_depth)--; GC_EXIT(); } @@ -389,59 +477,62 @@ void gc_sweep_all(void) { void gc_info(gc_info_t *info) { GC_ENTER(); - info->total = MP_STATE_MEM(gc_pool_end) - MP_STATE_MEM(gc_pool_start); + info->total = 0; info->used = 0; info->free = 0; info->max_free = 0; info->num_1block = 0; info->num_2block = 0; info->max_block = 0; - bool finish = false; - for (size_t block = 0, len = 0, len_free = 0; !finish;) { - size_t kind = ATB_GET_KIND(block); - switch (kind) { - case AT_FREE: - info->free += 1; - len_free += 1; - len = 0; - break; + for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { + bool finish = false; + info->total += area->gc_pool_end - area->gc_pool_start; + for (size_t block = 0, len = 0, len_free = 0; !finish;) { + size_t kind = ATB_GET_KIND(area, block); + switch (kind) { + case AT_FREE: + info->free += 1; + len_free += 1; + len = 0; + break; - case AT_HEAD: - info->used += 1; - len = 1; - break; + case AT_HEAD: + info->used += 1; + len = 1; + break; - case AT_TAIL: - info->used += 1; - len += 1; - break; + case AT_TAIL: + info->used += 1; + len += 1; + break; - case AT_MARK: - // shouldn't happen - break; - } - - block++; - finish = (block == MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB); - // Get next block type if possible - if (!finish) { - kind = ATB_GET_KIND(block); - } - - if (finish || kind == AT_FREE || kind == AT_HEAD) { - if (len == 1) { - info->num_1block += 1; - } else if (len == 2) { - info->num_2block += 1; + case AT_MARK: + // shouldn't happen + break; } - if (len > info->max_block) { - info->max_block = len; + + block++; + finish = (block == area->gc_alloc_table_byte_len * BLOCKS_PER_ATB); + // Get next block type if possible + if (!finish) { + kind = ATB_GET_KIND(area, block); } - if (finish || kind == AT_HEAD) { - if (len_free > info->max_free) { - info->max_free = len_free; + + if (finish || kind == AT_FREE || kind == AT_HEAD) { + if (len == 1) { + info->num_1block += 1; + } else if (len == 2) { + info->num_2block += 1; + } + if (len > info->max_block) { + info->max_block = len; + } + if (finish || kind == AT_HEAD) { + if (len_free > info->max_free) { + info->max_free = len_free; + } + len_free = 0; } - len_free = 0; } } } @@ -468,6 +559,7 @@ void *gc_alloc(size_t n_bytes, unsigned int alloc_flags) { GC_ENTER(); + mp_state_mem_area_t *area; size_t i; size_t end_block; size_t start_block; @@ -485,16 +577,33 @@ void *gc_alloc(size_t n_bytes, unsigned int alloc_flags) { for (;;) { + #if MICROPY_GC_SPLIT_HEAP + area = MP_STATE_MEM(gc_last_free_area); + #else + area = &MP_STATE_MEM(area); + #endif + // look for a run of n_blocks available blocks - n_free = 0; - for (i = MP_STATE_MEM(gc_last_free_atb_index); i < MP_STATE_MEM(gc_alloc_table_byte_len); i++) { - byte a = MP_STATE_MEM(gc_alloc_table_start)[i]; - // *FORMAT-OFF* - if (ATB_0_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 0; goto found; } } else { n_free = 0; } - if (ATB_1_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 1; goto found; } } else { n_free = 0; } - if (ATB_2_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 2; goto found; } } else { n_free = 0; } - if (ATB_3_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 3; goto found; } } else { n_free = 0; } - // *FORMAT-ON* + for (; area != NULL; area = NEXT_AREA(area), i = 0) { + n_free = 0; + for (i = area->gc_last_free_atb_index; i < area->gc_alloc_table_byte_len; i++) { + byte a = area->gc_alloc_table_start[i]; + // *FORMAT-OFF* + if (ATB_0_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 0; goto found; } } else { n_free = 0; } + if (ATB_1_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 1; goto found; } } else { n_free = 0; } + if (ATB_2_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 2; goto found; } } else { n_free = 0; } + if (ATB_3_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 3; goto found; } } else { n_free = 0; } + // *FORMAT-ON* + } + + // No free blocks found on this heap. Mark this heap as + // filled, so we won't try to find free space here again until + // space is freed. + #if MICROPY_GC_SPLIT_HEAP + if (n_blocks == 1) { + area->gc_last_free_atb_index = (i + 1) / BLOCKS_PER_ATB; // or (size_t)-1 + } + #endif } GC_EXIT(); @@ -520,21 +629,24 @@ found: // before this one. Also, whenever we free or shink a block we must check // if this index needs adjusting (see gc_realloc and gc_free). if (n_free == 1) { - MP_STATE_MEM(gc_last_free_atb_index) = (i + 1) / BLOCKS_PER_ATB; + #if MICROPY_GC_SPLIT_HEAP + MP_STATE_MEM(gc_last_free_area) = area; + #endif + area->gc_last_free_atb_index = (i + 1) / BLOCKS_PER_ATB; } // mark first block as used head - ATB_FREE_TO_HEAD(start_block); + ATB_FREE_TO_HEAD(area, start_block); // mark rest of blocks as used tail // TODO for a run of many blocks can make this more efficient for (size_t bl = start_block + 1; bl <= end_block; bl++) { - ATB_FREE_TO_TAIL(bl); + ATB_FREE_TO_TAIL(area, bl); } // get pointer to first block // we must create this pointer before unlocking the GC so a collection can find it - void *ret_ptr = (void *)(MP_STATE_MEM(gc_pool_start) + start_block * BYTES_PER_BLOCK); + void *ret_ptr = (void *)(area->gc_pool_start + start_block * BYTES_PER_BLOCK); DEBUG_printf("gc_alloc(%p)\n", ret_ptr); #if MICROPY_GC_ALLOC_THRESHOLD @@ -561,7 +673,7 @@ found: ((mp_obj_base_t *)ret_ptr)->type = NULL; // set mp_obj flag only if it has a finaliser GC_ENTER(); - FTB_SET(start_block); + FTB_SET(area, start_block); GC_EXIT(); } #else @@ -598,46 +710,65 @@ void gc_free(void *ptr) { DEBUG_printf("gc_free(%p)\n", ptr); if (ptr == NULL) { + // free(NULL) is a no-op GC_EXIT(); - } else { - // get the GC block number corresponding to this pointer - assert(VERIFY_PTR(ptr)); - size_t block = BLOCK_FROM_PTR(ptr); - assert(ATB_GET_KIND(block) == AT_HEAD); - - #if MICROPY_ENABLE_FINALISER - FTB_CLEAR(block); - #endif - - // set the last_free pointer to this block if it's earlier in the heap - if (block / BLOCKS_PER_ATB < MP_STATE_MEM(gc_last_free_atb_index)) { - MP_STATE_MEM(gc_last_free_atb_index) = block / BLOCKS_PER_ATB; - } - - // free head and all of its tail blocks - do { - ATB_ANY_TO_FREE(block); - block += 1; - } while (ATB_GET_KIND(block) == AT_TAIL); - - GC_EXIT(); - - #if EXTENSIVE_HEAP_PROFILING - gc_dump_alloc_table(); - #endif + return; } + + // get the GC block number corresponding to this pointer + mp_state_mem_area_t *area = gc_get_ptr_area(ptr); + assert(area); + size_t block = BLOCK_FROM_PTR(area, ptr); + assert(ATB_GET_KIND(area, block) == AT_HEAD); + + #if MICROPY_ENABLE_FINALISER + FTB_CLEAR(area, block); + #endif + + #if MICROPY_GC_SPLIT_HEAP + if (MP_STATE_MEM(gc_last_free_area) != area) { + // We freed something but it isn't the current area. Reset the + // last free area to the start for a rescan. Note that this won't + // give much of a performance hit, since areas that are completely + // filled will likely be skipped (the gc_last_free_atb_index + // points to the last block). + // The reason why this is necessary is because it is not possible + // to see which area came first (like it is possible to adjust + // gc_last_free_atb_index based on whether the freed block is + // before the last free block). + MP_STATE_MEM(gc_last_free_area) = &MP_STATE_MEM(area); + } + #endif + + // set the last_free pointer to this block if it's earlier in the heap + if (block / BLOCKS_PER_ATB < area->gc_last_free_atb_index) { + area->gc_last_free_atb_index = block / BLOCKS_PER_ATB; + } + + // free head and all of its tail blocks + do { + ATB_ANY_TO_FREE(area, block); + block += 1; + } while (ATB_GET_KIND(area, block) == AT_TAIL); + + GC_EXIT(); + + #if EXTENSIVE_HEAP_PROFILING + gc_dump_alloc_table(); + #endif } size_t gc_nbytes(const void *ptr) { GC_ENTER(); - if (VERIFY_PTR(ptr)) { - size_t block = BLOCK_FROM_PTR(ptr); - if (ATB_GET_KIND(block) == AT_HEAD) { + mp_state_mem_area_t *area = gc_get_ptr_area(ptr); + if (area) { + size_t block = BLOCK_FROM_PTR(area, ptr); + if (ATB_GET_KIND(area, block) == AT_HEAD) { // work out number of consecutive blocks in the chain starting with this on size_t n_blocks = 0; do { n_blocks += 1; - } while (ATB_GET_KIND(block + n_blocks) == AT_TAIL); + } while (ATB_GET_KIND(area, block + n_blocks) == AT_TAIL); GC_EXIT(); return n_blocks * BYTES_PER_BLOCK; } @@ -698,9 +829,10 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { GC_ENTER(); // get the GC block number corresponding to this pointer - assert(VERIFY_PTR(ptr)); - size_t block = BLOCK_FROM_PTR(ptr); - assert(ATB_GET_KIND(block) == AT_HEAD); + mp_state_mem_area_t *area = gc_get_ptr_area(ptr); + assert(area); + size_t block = BLOCK_FROM_PTR(area, ptr); + assert(ATB_GET_KIND(area, block) == AT_HEAD); // compute number of new blocks that are requested size_t new_blocks = (n_bytes + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK; @@ -713,9 +845,9 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { // efficiently shrink it (see below for shrinking code). size_t n_free = 0; size_t n_blocks = 1; // counting HEAD block - size_t max_block = MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; + size_t max_block = area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; for (size_t bl = block + n_blocks; bl < max_block; bl++) { - byte block_type = ATB_GET_KIND(bl); + byte block_type = ATB_GET_KIND(area, bl); if (block_type == AT_TAIL) { n_blocks++; continue; @@ -741,12 +873,19 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { if (new_blocks < n_blocks) { // free unneeded tail blocks for (size_t bl = block + new_blocks, count = n_blocks - new_blocks; count > 0; bl++, count--) { - ATB_ANY_TO_FREE(bl); + ATB_ANY_TO_FREE(area, bl); } + #if MICROPY_GC_SPLIT_HEAP + if (MP_STATE_MEM(gc_last_free_area) != area) { + // See comment in gc_free. + MP_STATE_MEM(gc_last_free_area) = &MP_STATE_MEM(area); + } + #endif + // set the last_free pointer to end of this block if it's earlier in the heap - if ((block + new_blocks) / BLOCKS_PER_ATB < MP_STATE_MEM(gc_last_free_atb_index)) { - MP_STATE_MEM(gc_last_free_atb_index) = (block + new_blocks) / BLOCKS_PER_ATB; + if ((block + new_blocks) / BLOCKS_PER_ATB < area->gc_last_free_atb_index) { + area->gc_last_free_atb_index = (block + new_blocks) / BLOCKS_PER_ATB; } GC_EXIT(); @@ -762,8 +901,8 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { if (new_blocks <= n_blocks + n_free) { // mark few more blocks as used tail for (size_t bl = block + n_blocks; bl < block + new_blocks; bl++) { - assert(ATB_GET_KIND(bl) == AT_FREE); - ATB_FREE_TO_TAIL(bl); + assert(ATB_GET_KIND(area, bl) == AT_FREE); + ATB_FREE_TO_TAIL(area, bl); } GC_EXIT(); @@ -784,7 +923,7 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { } #if MICROPY_ENABLE_FINALISER - bool ftb_state = FTB_GET(block); + bool ftb_state = FTB_GET(area, block); #else bool ftb_state = false; #endif @@ -823,129 +962,131 @@ void gc_dump_info(void) { void gc_dump_alloc_table(void) { GC_ENTER(); static const size_t DUMP_BYTES_PER_LINE = 64; - #if !EXTENSIVE_HEAP_PROFILING - // When comparing heap output we don't want to print the starting - // pointer of the heap because it changes from run to run. - mp_printf(&mp_plat_print, "GC memory layout; from %p:", MP_STATE_MEM(gc_pool_start)); - #endif - for (size_t bl = 0; bl < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; bl++) { - if (bl % DUMP_BYTES_PER_LINE == 0) { - // a new line of blocks - { - // check if this line contains only free blocks - size_t bl2 = bl; - while (bl2 < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB && ATB_GET_KIND(bl2) == AT_FREE) { - bl2++; - } - if (bl2 - bl >= 2 * DUMP_BYTES_PER_LINE) { - // there are at least 2 lines containing only free blocks, so abbreviate their printing - mp_printf(&mp_plat_print, "\n (%u lines all free)", (uint)(bl2 - bl) / DUMP_BYTES_PER_LINE); - bl = bl2 & (~(DUMP_BYTES_PER_LINE - 1)); - if (bl >= MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB) { - // got to end of heap - break; + for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { + #if !EXTENSIVE_HEAP_PROFILING + // When comparing heap output we don't want to print the starting + // pointer of the heap because it changes from run to run. + mp_printf(&mp_plat_print, "GC memory layout; from %p:", area->gc_pool_start); + #endif + for (size_t bl = 0; bl < area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; bl++) { + if (bl % DUMP_BYTES_PER_LINE == 0) { + // a new line of blocks + { + // check if this line contains only free blocks + size_t bl2 = bl; + while (bl2 < area->gc_alloc_table_byte_len * BLOCKS_PER_ATB && ATB_GET_KIND(area, bl2) == AT_FREE) { + bl2++; + } + if (bl2 - bl >= 2 * DUMP_BYTES_PER_LINE) { + // there are at least 2 lines containing only free blocks, so abbreviate their printing + mp_printf(&mp_plat_print, "\n (%u lines all free)", (uint)(bl2 - bl) / DUMP_BYTES_PER_LINE); + bl = bl2 & (~(DUMP_BYTES_PER_LINE - 1)); + if (bl >= area->gc_alloc_table_byte_len * BLOCKS_PER_ATB) { + // got to end of heap + break; + } } } + // print header for new line of blocks + // (the cast to uint32_t is for 16-bit ports) + // mp_printf(&mp_plat_print, "\n%05x: ", (uint)(PTR_FROM_BLOCK(area, bl) & (uint32_t)0xfffff)); + mp_printf(&mp_plat_print, "\n%05x: ", (uint)((bl * BYTES_PER_BLOCK) & (uint32_t)0xfffff)); } - // print header for new line of blocks - // (the cast to uint32_t is for 16-bit ports) - // mp_printf(&mp_plat_print, "\n%05x: ", (uint)(PTR_FROM_BLOCK(bl) & (uint32_t)0xfffff)); - mp_printf(&mp_plat_print, "\n%05x: ", (uint)((bl * BYTES_PER_BLOCK) & (uint32_t)0xfffff)); - } - int c = ' '; - switch (ATB_GET_KIND(bl)) { - case AT_FREE: - c = '.'; - break; - /* this prints out if the object is reachable from BSS or STACK (for unix only) - case AT_HEAD: { - c = 'h'; - void **ptrs = (void**)(void*)&mp_state_ctx; - mp_uint_t len = offsetof(mp_state_ctx_t, vm.stack_top) / sizeof(mp_uint_t); - for (mp_uint_t i = 0; i < len; i++) { - mp_uint_t ptr = (mp_uint_t)ptrs[i]; - if (VERIFY_PTR(ptr) && BLOCK_FROM_PTR(ptr) == bl) { - c = 'B'; - break; - } - } - if (c == 'h') { - ptrs = (void**)&c; - len = ((mp_uint_t)MP_STATE_THREAD(stack_top) - (mp_uint_t)&c) / sizeof(mp_uint_t); + int c = ' '; + switch (ATB_GET_KIND(area, bl)) { + case AT_FREE: + c = '.'; + break; + /* this prints out if the object is reachable from BSS or STACK (for unix only) + case AT_HEAD: { + c = 'h'; + void **ptrs = (void**)(void*)&mp_state_ctx; + mp_uint_t len = offsetof(mp_state_ctx_t, vm.stack_top) / sizeof(mp_uint_t); for (mp_uint_t i = 0; i < len; i++) { mp_uint_t ptr = (mp_uint_t)ptrs[i]; - if (VERIFY_PTR(ptr) && BLOCK_FROM_PTR(ptr) == bl) { - c = 'S'; + if (gc_get_ptr_area(ptr) && BLOCK_FROM_PTR(ptr) == bl) { + c = 'B'; break; } } - } - break; - } - */ - /* this prints the uPy object type of the head block */ - case AT_HEAD: { - void **ptr = (void **)(MP_STATE_MEM(gc_pool_start) + bl * BYTES_PER_BLOCK); - if (*ptr == &mp_type_tuple) { - c = 'T'; - } else if (*ptr == &mp_type_list) { - c = 'L'; - } else if (*ptr == &mp_type_dict) { - c = 'D'; - } else if (*ptr == &mp_type_str || *ptr == &mp_type_bytes) { - c = 'S'; - } - #if MICROPY_PY_BUILTINS_BYTEARRAY - else if (*ptr == &mp_type_bytearray) { - c = 'A'; - } - #endif - #if MICROPY_PY_ARRAY - else if (*ptr == &mp_type_array) { - c = 'A'; - } - #endif - #if MICROPY_PY_BUILTINS_FLOAT - else if (*ptr == &mp_type_float) { - c = 'F'; - } - #endif - else if (*ptr == &mp_type_fun_bc) { - c = 'B'; - } else if (*ptr == &mp_type_module) { - c = 'M'; - } else { - c = 'h'; - #if 0 - // This code prints "Q" for qstr-pool data, and "q" for qstr-str - // data. It can be useful to see how qstrs are being allocated, - // but is disabled by default because it is very slow. - for (const qstr_pool_t *pool = MP_STATE_VM(last_pool); c == 'h' && pool != NULL; pool = pool->prev) { - if ((const qstr_pool_t *)ptr == pool) { - c = 'Q'; - break; - } - for (const char *const *q = pool->qstrs, *const *q_top = pool->qstrs + pool->len; q < q_top; q++) { - if ((const char *)ptr == *q) { - c = 'q'; + if (c == 'h') { + ptrs = (void**)&c; + len = ((mp_uint_t)MP_STATE_THREAD(stack_top) - (mp_uint_t)&c) / sizeof(mp_uint_t); + for (mp_uint_t i = 0; i < len; i++) { + mp_uint_t ptr = (mp_uint_t)ptrs[i]; + if (gc_get_ptr_area(ptr) && BLOCK_FROM_PTR(ptr) == bl) { + c = 'S'; break; } } } - #endif + break; } - break; + */ + /* this prints the uPy object type of the head block */ + case AT_HEAD: { + void **ptr = (void **)(area->gc_pool_start + bl * BYTES_PER_BLOCK); + if (*ptr == &mp_type_tuple) { + c = 'T'; + } else if (*ptr == &mp_type_list) { + c = 'L'; + } else if (*ptr == &mp_type_dict) { + c = 'D'; + } else if (*ptr == &mp_type_str || *ptr == &mp_type_bytes) { + c = 'S'; + } + #if MICROPY_PY_BUILTINS_BYTEARRAY + else if (*ptr == &mp_type_bytearray) { + c = 'A'; + } + #endif + #if MICROPY_PY_ARRAY + else if (*ptr == &mp_type_array) { + c = 'A'; + } + #endif + #if MICROPY_PY_BUILTINS_FLOAT + else if (*ptr == &mp_type_float) { + c = 'F'; + } + #endif + else if (*ptr == &mp_type_fun_bc) { + c = 'B'; + } else if (*ptr == &mp_type_module) { + c = 'M'; + } else { + c = 'h'; + #if 0 + // This code prints "Q" for qstr-pool data, and "q" for qstr-str + // data. It can be useful to see how qstrs are being allocated, + // but is disabled by default because it is very slow. + for (qstr_pool_t *pool = MP_STATE_VM(last_pool); c == 'h' && pool != NULL; pool = pool->prev) { + if ((qstr_pool_t *)ptr == pool) { + c = 'Q'; + break; + } + for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) { + if ((const byte *)ptr == *q) { + c = 'q'; + break; + } + } + } + #endif + } + break; + } + case AT_TAIL: + c = '='; + break; + case AT_MARK: + c = 'm'; + break; } - case AT_TAIL: - c = '='; - break; - case AT_MARK: - c = 'm'; - break; + mp_printf(&mp_plat_print, "%c", c); } - mp_printf(&mp_plat_print, "%c", c); + mp_print_str(&mp_plat_print, "\n"); } - mp_print_str(&mp_plat_print, "\n"); GC_EXIT(); } diff --git a/py/gc.h b/py/gc.h index 5aef27c006..bb4204b06f 100644 --- a/py/gc.h +++ b/py/gc.h @@ -28,9 +28,15 @@ #include #include +#include "py/mpconfig.h" void gc_init(void *start, void *end); +#if MICROPY_GC_SPLIT_HEAP +// Used to add additional memory areas to the heap. +void gc_add(void *start, void *end); +#endif + // These lock/unlock functions can be nested. // They can be used to prevent the GC from allocating/freeing. void gc_lock(void); diff --git a/py/mpconfig.h b/py/mpconfig.h index ee0123be34..25f37ff8b3 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -606,6 +606,11 @@ #define MICROPY_ENABLE_GC (0) #endif +// Whether the garbage-collected heap can be split over multiple memory areas. +#ifndef MICROPY_GC_SPLIT_HEAP +#define MICROPY_GC_SPLIT_HEAP (0) +#endif + // Hook to run code during time consuming garbage collector operations #ifndef MICROPY_GC_HOOK_LOOP #define MICROPY_GC_HOOK_LOOP diff --git a/py/mpstate.h b/py/mpstate.h index 1b6e623ca9..ea069c24dd 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -71,12 +71,11 @@ typedef struct _mp_sched_item_t { mp_obj_t arg; } mp_sched_item_t; -// This structure hold information about the memory allocation system. -typedef struct _mp_state_mem_t { - #if MICROPY_MEM_STATS - size_t total_bytes_allocated; - size_t current_bytes_allocated; - size_t peak_bytes_allocated; +// This structure holds information about a single contiguous area of +// memory reserved for the memory manager. +typedef struct _mp_state_mem_area_t { + #if MICROPY_GC_SPLIT_HEAP + struct _mp_state_mem_area_t *next; #endif byte *gc_alloc_table_start; @@ -87,8 +86,30 @@ typedef struct _mp_state_mem_t { byte *gc_pool_start; byte *gc_pool_end; + size_t gc_last_free_atb_index; +} mp_state_mem_area_t; + +// This structure holds a single stacked block and the area it is on. Used +// during garbage collection. +typedef struct { + #if MICROPY_GC_SPLIT_HEAP + mp_state_mem_area_t *area; + #endif + size_t block; +} mp_gc_stack_item_t; + +// This structure hold information about the memory allocation system. +typedef struct _mp_state_mem_t { + #if MICROPY_MEM_STATS + size_t total_bytes_allocated; + size_t current_bytes_allocated; + size_t peak_bytes_allocated; + #endif + + mp_state_mem_area_t area; + int gc_stack_overflow; - MICROPY_GC_STACK_ENTRY_TYPE gc_stack[MICROPY_ALLOC_GC_STACK_SIZE]; + mp_gc_stack_item_t gc_stack[MICROPY_ALLOC_GC_STACK_SIZE]; // This variable controls auto garbage collection. If set to 0 then the // GC won't automatically run when gc_alloc can't find enough blocks. But @@ -100,7 +121,9 @@ typedef struct _mp_state_mem_t { size_t gc_alloc_threshold; #endif - size_t gc_last_free_atb_index; + #if MICROPY_GC_SPLIT_HEAP + mp_state_mem_area_t *gc_last_free_area; + #endif #if MICROPY_PY_GC_COLLECT_RETVAL size_t gc_collected; From 4a48531803843f53caf2b535da7ff3bb2a802106 Mon Sep 17 00:00:00 2001 From: Rob Knegjens Date: Tue, 12 Apr 2022 21:26:16 -0700 Subject: [PATCH 0199/1041] py/gc: Reduce code size when MICROPY_GC_SPLIT_HEAP is disabled. Use C macros to reduce the size of firmware images when the GC split-heap feature is disabled. The code size difference of this commit versus HEAD~2 (ie the commit prior to MICROPY_GC_SPLIT_HEAP being introduced) when split-heap is disabled is: bare-arm: +0 +0.000% minimal x86: +0 +0.000% unix x64: -16 -0.003% unix nanbox: -20 -0.004% stm32: -8 -0.002% PYBV10 cc3200: +0 +0.000% esp8266: +8 +0.001% GENERIC esp32: +0 +0.000% GENERIC nrf: -20 -0.011% pca10040 rp2: +0 +0.000% PICO samd: -4 -0.003% ADAFRUIT_ITSYBITSY_M4_EXPRESS The code size difference of this commit versus HEAD~2 split-heap is enabled with MICROPY_GC_MULTIHEAP=1 (but no extra code to add more heaps): unix x64: +1032 +0.197% [incl +544(bss)] esp32: +592 +0.039% GENERIC[incl +16(data) +264(bss)] --- py/gc.c | 119 ++++++++++++++++++++++++++++++++++++--------------- py/mpstate.h | 15 +++---- 2 files changed, 90 insertions(+), 44 deletions(-) diff --git a/py/gc.c b/py/gc.c index 93e83aaad5..120213783b 100644 --- a/py/gc.c +++ b/py/gc.c @@ -230,6 +230,7 @@ bool gc_is_locked(void) { return MP_STATE_THREAD(gc_lock_depth) != 0; } +#if MICROPY_GC_SPLIT_HEAP // Returns the area to which this pointer belongs, or NULL if it isn't // allocated on the GC-managed heap. STATIC inline mp_state_mem_area_t *gc_get_ptr_area(const void *ptr) { @@ -244,6 +245,14 @@ STATIC inline mp_state_mem_area_t *gc_get_ptr_area(const void *ptr) { } return NULL; } +#endif + +// ptr should be of type void* +#define VERIFY_PTR(ptr) ( \ + ((uintptr_t)(ptr) & (BYTES_PER_BLOCK - 1)) == 0 /* must be aligned on a block */ \ + && ptr >= (void *)MP_STATE_MEM(area).gc_pool_start /* must be above start of pool */ \ + && ptr < (void *)MP_STATE_MEM(area).gc_pool_end /* must be below end of pool */ \ + ) #ifndef TRACE_MARK #if DEBUG_PRINT @@ -257,18 +266,20 @@ STATIC inline mp_state_mem_area_t *gc_get_ptr_area(const void *ptr) { // children: mark the unmarked child blocks and put those newly marked // blocks on the stack. When all children have been checked, pop off the // topmost block on the stack and repeat with that one. -STATIC void gc_mark_subtree(mp_gc_stack_item_t item) { - // Start with the item passed in the argument. +#if MICROPY_GC_SPLIT_HEAP +STATIC void gc_mark_subtree(mp_state_mem_area_t *area, size_t block) +#else +STATIC void gc_mark_subtree(size_t block) +#endif +{ + // Start with the block passed in the argument. size_t sp = 0; for (;;) { MICROPY_GC_HOOK_LOOP - #if MICROPY_GC_SPLIT_HEAP - mp_state_mem_area_t *area = item.area; - #else - mp_state_mem_area_t *area = &MP_STATE_MEM(area); + #if !MICROPY_GC_SPLIT_HEAP + mp_state_mem_area_t * area = &MP_STATE_MEM(area); #endif - size_t block = item.block; // work out number of consecutive blocks in the chain starting with this one size_t n_blocks = 0; @@ -283,11 +294,18 @@ STATIC void gc_mark_subtree(mp_gc_stack_item_t item) { void *ptr = *ptrs; // If this is a heap pointer that hasn't been marked, mark it and push // it's children to the stack. + #if MICROPY_GC_SPLIT_HEAP mp_state_mem_area_t *ptr_area = gc_get_ptr_area(ptr); if (!ptr_area) { // Not a heap-allocated pointer (might even be random data). continue; } + #else + if (!VERIFY_PTR(ptr)) { + continue; + } + mp_state_mem_area_t *ptr_area = area; + #endif size_t ptr_block = BLOCK_FROM_PTR(ptr_area, ptr); if (ATB_GET_KIND(ptr_area, ptr_block) != AT_HEAD) { // This block is already marked. @@ -297,24 +315,27 @@ STATIC void gc_mark_subtree(mp_gc_stack_item_t item) { TRACE_MARK(ptr_block, ptr); ATB_HEAD_TO_MARK(ptr_area, ptr_block); if (sp < MICROPY_ALLOC_GC_STACK_SIZE) { + MP_STATE_MEM(gc_block_stack)[sp] = ptr_block; #if MICROPY_GC_SPLIT_HEAP - mp_gc_stack_item_t ptr_item = {ptr_area, ptr_block}; - #else - mp_gc_stack_item_t ptr_item = {ptr_block}; + MP_STATE_MEM(gc_area_stack)[sp] = ptr_area; #endif - MP_STATE_MEM(gc_stack)[sp++] = ptr_item; + sp += 1; } else { MP_STATE_MEM(gc_stack_overflow) = 1; } } - // Are there any items on the stack? + // Are there any blocks on the stack? if (sp == 0) { break; // No, stack is empty, we're done. } - // pop the next item off the stack - item = MP_STATE_MEM(gc_stack)[--sp]; + // pop the next block off the stack + sp -= 1; + block = MP_STATE_MEM(gc_block_stack)[sp]; + #if MICROPY_GC_SPLIT_HEAP + area = MP_STATE_MEM(gc_area_stack)[sp]; + #endif } } @@ -329,13 +350,10 @@ STATIC void gc_deal_with_stack_overflow(void) { // trace (again) if mark bit set if (ATB_GET_KIND(area, block) == AT_MARK) { #if MICROPY_GC_SPLIT_HEAP - mp_gc_stack_item_t item = {area, block}; + gc_mark_subtree(area, block); #else - mp_gc_stack_item_t item = {block}; + gc_mark_subtree(block); #endif - // *MP_STATE_MEM(gc_sp)++ = item; - // gc_drain_stack(); - gc_mark_subtree(item); } } } @@ -435,22 +453,31 @@ static void *gc_get_ptr(void **ptrs, int i) { } void gc_collect_root(void **ptrs, size_t len) { + #if !MICROPY_GC_SPLIT_HEAP + mp_state_mem_area_t *area = &MP_STATE_MEM(area); + #endif for (size_t i = 0; i < len; i++) { MICROPY_GC_HOOK_LOOP void *ptr = gc_get_ptr(ptrs, i); + #if MICROPY_GC_SPLIT_HEAP mp_state_mem_area_t *area = gc_get_ptr_area(ptr); - if (area) { - size_t block = BLOCK_FROM_PTR(area, ptr); - if (ATB_GET_KIND(area, block) == AT_HEAD) { - // An unmarked head: mark it, and mark all its children - ATB_HEAD_TO_MARK(area, block); - #if MICROPY_GC_SPLIT_HEAP - mp_gc_stack_item_t item = {area, block}; - #else - mp_gc_stack_item_t item = {block}; - #endif - gc_mark_subtree(item); - } + if (!area) { + continue; + } + #else + if (!VERIFY_PTR(ptr)) { + continue; + } + #endif + size_t block = BLOCK_FROM_PTR(area, ptr); + if (ATB_GET_KIND(area, block) == AT_HEAD) { + // An unmarked head: mark it, and mark all its children + ATB_HEAD_TO_MARK(area, block); + #if MICROPY_GC_SPLIT_HEAP + gc_mark_subtree(area, block); + #else + gc_mark_subtree(block); + #endif } } } @@ -716,8 +743,15 @@ void gc_free(void *ptr) { } // get the GC block number corresponding to this pointer - mp_state_mem_area_t *area = gc_get_ptr_area(ptr); + mp_state_mem_area_t *area; + #if MICROPY_GC_SPLIT_HEAP + area = gc_get_ptr_area(ptr); assert(area); + #else + assert(VERIFY_PTR(ptr)); + area = &MP_STATE_MEM(area); + #endif + size_t block = BLOCK_FROM_PTR(area, ptr); assert(ATB_GET_KIND(area, block) == AT_HEAD); @@ -760,7 +794,18 @@ void gc_free(void *ptr) { size_t gc_nbytes(const void *ptr) { GC_ENTER(); - mp_state_mem_area_t *area = gc_get_ptr_area(ptr); + + mp_state_mem_area_t *area; + #if MICROPY_GC_SPLIT_HEAP + area = gc_get_ptr_area(ptr); + #else + if (VERIFY_PTR(ptr)) { + area = &MP_STATE_MEM(area); + } else { + area = NULL; + } + #endif + if (area) { size_t block = BLOCK_FROM_PTR(area, ptr); if (ATB_GET_KIND(area, block) == AT_HEAD) { @@ -829,8 +874,14 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { GC_ENTER(); // get the GC block number corresponding to this pointer - mp_state_mem_area_t *area = gc_get_ptr_area(ptr); + mp_state_mem_area_t *area; + #if MICROPY_GC_SPLIT_HEAP + area = gc_get_ptr_area(ptr); assert(area); + #else + assert(VERIFY_PTR(ptr)); + area = &MP_STATE_MEM(area); + #endif size_t block = BLOCK_FROM_PTR(area, ptr); assert(ATB_GET_KIND(area, block) == AT_HEAD); diff --git a/py/mpstate.h b/py/mpstate.h index ea069c24dd..ba47c76482 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -89,15 +89,6 @@ typedef struct _mp_state_mem_area_t { size_t gc_last_free_atb_index; } mp_state_mem_area_t; -// This structure holds a single stacked block and the area it is on. Used -// during garbage collection. -typedef struct { - #if MICROPY_GC_SPLIT_HEAP - mp_state_mem_area_t *area; - #endif - size_t block; -} mp_gc_stack_item_t; - // This structure hold information about the memory allocation system. typedef struct _mp_state_mem_t { #if MICROPY_MEM_STATS @@ -109,7 +100,11 @@ typedef struct _mp_state_mem_t { mp_state_mem_area_t area; int gc_stack_overflow; - mp_gc_stack_item_t gc_stack[MICROPY_ALLOC_GC_STACK_SIZE]; + MICROPY_GC_STACK_ENTRY_TYPE gc_block_stack[MICROPY_ALLOC_GC_STACK_SIZE]; + #if MICROPY_GC_SPLIT_HEAP + // Array that tracks the area for each block on gc_block_stack. + mp_state_mem_area_t *gc_area_stack[MICROPY_ALLOC_GC_STACK_SIZE]; + #endif // This variable controls auto garbage collection. If set to 0 then the // GC won't automatically run when gc_alloc can't find enough blocks. But From d2e4cf00ccec432ccd38adea78099887ac578882 Mon Sep 17 00:00:00 2001 From: Rob Knegjens Date: Wed, 13 Apr 2022 09:52:22 -0700 Subject: [PATCH 0200/1041] unix: Enable MICROPY_GC_SPLIT_HEAP on coverage build. With a new option to evenly split the GC heap over multiple areas. This adds code coverage for gc_add() and code associated with MICROPY_GC_SPLIT_HEAP. --- ports/unix/main.c | 20 +++++++++++++++++++ ports/unix/mpconfigport.h | 4 ++++ .../unix/variants/coverage/mpconfigvariant.h | 2 ++ 3 files changed, 26 insertions(+) diff --git a/ports/unix/main.c b/ports/unix/main.c index e7048dd712..0b27a1f5f5 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -477,8 +477,22 @@ MP_NOINLINE int main_(int argc, char **argv) { pre_process_options(argc, argv); #if MICROPY_ENABLE_GC + #if !MICROPY_GC_SPLIT_HEAP char *heap = malloc(heap_size); gc_init(heap, heap + heap_size); + #else + assert(MICROPY_GC_SPLIT_HEAP_N_HEAPS > 0); + char *heaps[MICROPY_GC_SPLIT_HEAP_N_HEAPS]; + long multi_heap_size = heap_size / MICROPY_GC_SPLIT_HEAP_N_HEAPS; + for (size_t i = 0; i < MICROPY_GC_SPLIT_HEAP_N_HEAPS; i++) { + heaps[i] = malloc(multi_heap_size); + if (i == 0) { + gc_init(heaps[i], heaps[i] + multi_heap_size); + } else { + gc_add(heaps[i], heaps[i] + multi_heap_size); + } + } + #endif #endif #if MICROPY_ENABLE_PYSTACK @@ -729,7 +743,13 @@ MP_NOINLINE int main_(int argc, char **argv) { #if MICROPY_ENABLE_GC && !defined(NDEBUG) // We don't really need to free memory since we are about to exit the // process, but doing so helps to find memory leaks. + #if !MICROPY_GC_SPLIT_HEAP free(heap); + #else + for (size_t i = 0; i < MICROPY_GC_SPLIT_HEAP_N_HEAPS; i++) { + free(heaps[i]); + } + #endif #endif // printf("total bytes = %d\n", m_get_total_bytes_allocated()); diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 312c0cce8f..4252a406ce 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -120,6 +120,10 @@ #define MICROPY_EMIT_ARM (1) #endif #define MICROPY_ENABLE_GC (1) +// Number of heaps to assign if MICROPY_GC_SPLIT_HEAP=1 +#ifndef MICROPY_GC_SPLIT_HEAP_N_HEAPS +#define MICROPY_GC_SPLIT_HEAP_N_HEAPS (1) +#endif #define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1) #define MICROPY_MEM_STATS (1) #define MICROPY_DEBUG_PRINTERS (1) diff --git a/ports/unix/variants/coverage/mpconfigvariant.h b/ports/unix/variants/coverage/mpconfigvariant.h index 30e3a4e5d2..fb70d791ac 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.h +++ b/ports/unix/variants/coverage/mpconfigvariant.h @@ -32,6 +32,8 @@ // Enable additional features. #define MICROPY_DEBUG_PARSE_RULE_NAME (1) +#define MICROPY_GC_SPLIT_HEAP (1) +#define MICROPY_GC_SPLIT_HEAP_N_HEAPS (4) #define MICROPY_TRACKED_ALLOC (1) #define MICROPY_FLOAT_HIGH_QUALITY_HASH (1) #define MICROPY_REPL_EMACS_WORDS_MOVE (1) From 924e55aca18978215209a2ed81a49b0a6bdcaaa7 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 20 Jul 2022 12:09:24 +1000 Subject: [PATCH 0201/1041] extmod/webrepl: Allow the page to run from the device (over HTTP). The device will respond to a non-WS request with a simple page that loads websocket_content.js from a static host (http or https). However, even if the resources are https, the page is still http and therefore allows requesting to a WS (not WSS) websocket on the device. Removed unused client_handshake from websocket_helper, and then merges the remainder of this file (server_handshake) into webrepl.py (to reduce firmware size). Also added the respond-as-HTTP handling to server_handshake. The default HTTP response is a simple page that sets the base URL and then loads webrepl_content.js which document.write's the actual HTML. Signed-off-by: Jim Mussared --- extmod/webrepl/manifest.py | 2 +- extmod/webrepl/webrepl.py | 121 +++++++++++++++++++++++++---- extmod/webrepl/webrepl_setup.py | 1 - extmod/webrepl/websocket_helper.py | 85 -------------------- 4 files changed, 107 insertions(+), 102 deletions(-) delete mode 100644 extmod/webrepl/websocket_helper.py diff --git a/extmod/webrepl/manifest.py b/extmod/webrepl/manifest.py index 6eceb3eeb6..c504c7305c 100644 --- a/extmod/webrepl/manifest.py +++ b/extmod/webrepl/manifest.py @@ -1 +1 @@ -freeze(".", ("webrepl.py", "webrepl_setup.py", "websocket_helper.py")) +freeze(".", ("webrepl.py", "webrepl_setup.py")) diff --git a/extmod/webrepl/webrepl.py b/extmod/webrepl/webrepl.py index 0de813cda1..56767d8b71 100644 --- a/extmod/webrepl/webrepl.py +++ b/extmod/webrepl/webrepl.py @@ -1,14 +1,93 @@ # This module should be imported from REPL, not run from command line. -import socket -import uos +import binascii +import hashlib import network -import uwebsocket -import websocket_helper +import os +import socket +import sys +import websocket import _webrepl listen_s = None client_s = None +DEBUG = 0 + +_DEFAULT_STATIC_HOST = const("https://micropython.org/webrepl/") +static_host = _DEFAULT_STATIC_HOST + + +def server_handshake(cl): + req = cl.makefile("rwb", 0) + # Skip HTTP GET line. + l = req.readline() + if DEBUG: + sys.stdout.write(repr(l)) + + webkey = None + upgrade = False + websocket = False + + while True: + l = req.readline() + if not l: + # EOF in headers. + return False + if l == b"\r\n": + break + if DEBUG: + sys.stdout.write(l) + h, v = [x.strip() for x in l.split(b":", 1)] + if DEBUG: + print((h, v)) + if h == b"Sec-WebSocket-Key": + webkey = v + elif h == b"Connection" and b"Upgrade" in v: + upgrade = True + elif h == b"Upgrade" and v == b"websocket": + websocket = True + + if not (upgrade and websocket and webkey): + return False + + if DEBUG: + print("Sec-WebSocket-Key:", webkey, len(webkey)) + + d = hashlib.sha1(webkey) + d.update(b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11") + respkey = d.digest() + respkey = binascii.b2a_base64(respkey)[:-1] + if DEBUG: + print("respkey:", respkey) + + cl.send( + b"""\ +HTTP/1.1 101 Switching Protocols\r +Upgrade: websocket\r +Connection: Upgrade\r +Sec-WebSocket-Accept: """ + ) + cl.send(respkey) + cl.send("\r\n\r\n") + + return True + + +def send_html(cl): + cl.send( + b"""\ +HTTP/1.0 200 OK\r +\r +\r +\r +""" + ) + cl.close() + def setup_conn(port, accept_handler): global listen_s @@ -25,34 +104,41 @@ def setup_conn(port, accept_handler): for i in (network.AP_IF, network.STA_IF): iface = network.WLAN(i) if iface.active(): - print("WebREPL daemon started on ws://%s:%d" % (iface.ifconfig()[0], port)) + print("WebREPL server started on http://%s:%d/" % (iface.ifconfig()[0], port)) return listen_s def accept_conn(listen_sock): global client_s cl, remote_addr = listen_sock.accept() - prev = uos.dupterm(None) - uos.dupterm(prev) + + if not server_handshake(cl): + send_html(cl) + return False + + prev = os.dupterm(None) + os.dupterm(prev) if prev: print("\nConcurrent WebREPL connection from", remote_addr, "rejected") cl.close() - return + return False print("\nWebREPL connection from:", remote_addr) client_s = cl - websocket_helper.server_handshake(cl) - ws = uwebsocket.websocket(cl, True) + + ws = websocket.websocket(cl, True) ws = _webrepl._webrepl(ws) cl.setblocking(False) # notify REPL on socket incoming data (ESP32/ESP8266-only) - if hasattr(uos, "dupterm_notify"): - cl.setsockopt(socket.SOL_SOCKET, 20, uos.dupterm_notify) - uos.dupterm(ws) + if hasattr(os, "dupterm_notify"): + cl.setsockopt(socket.SOL_SOCKET, 20, os.dupterm_notify) + os.dupterm(ws) + + return True def stop(): global listen_s, client_s - uos.dupterm(None) + os.dupterm(None) if client_s: client_s.close() if listen_s: @@ -60,6 +146,7 @@ def stop(): def start(port=8266, password=None, accept_handler=accept_conn): + global static_host stop() webrepl_pass = password if webrepl_pass is None: @@ -67,6 +154,8 @@ def start(port=8266, password=None, accept_handler=accept_conn): import webrepl_cfg webrepl_pass = webrepl_cfg.PASS + if hasattr(webrepl_cfg, "BASE"): + static_host = webrepl_cfg.BASE except: print("WebREPL is not configured, run 'import webrepl_setup'") @@ -75,7 +164,9 @@ def start(port=8266, password=None, accept_handler=accept_conn): if accept_handler is None: print("Starting webrepl in foreground mode") - accept_conn(s) + # Run accept_conn to serve HTML until we get a websocket connection. + while not accept_conn(s): + pass elif password is None: print("Started webrepl in normal mode") else: diff --git a/extmod/webrepl/webrepl_setup.py b/extmod/webrepl/webrepl_setup.py index ffc9c77fc0..16e5f76e65 100644 --- a/extmod/webrepl/webrepl_setup.py +++ b/extmod/webrepl/webrepl_setup.py @@ -1,6 +1,5 @@ import sys -# import uos as os import os import machine diff --git a/extmod/webrepl/websocket_helper.py b/extmod/webrepl/websocket_helper.py deleted file mode 100644 index 3260acc52f..0000000000 --- a/extmod/webrepl/websocket_helper.py +++ /dev/null @@ -1,85 +0,0 @@ -try: - import usys as sys -except ImportError: - import sys - -try: - import ubinascii as binascii -except: - import binascii -try: - import uhashlib as hashlib -except: - import hashlib - -DEBUG = 0 - - -def server_handshake(sock): - clr = sock.makefile("rwb", 0) - l = clr.readline() - # sys.stdout.write(repr(l)) - - webkey = None - - while 1: - l = clr.readline() - if not l: - raise OSError("EOF in headers") - if l == b"\r\n": - break - # sys.stdout.write(l) - h, v = [x.strip() for x in l.split(b":", 1)] - if DEBUG: - print((h, v)) - if h == b"Sec-WebSocket-Key": - webkey = v - - if not webkey: - raise OSError("Not a websocket request") - - if DEBUG: - print("Sec-WebSocket-Key:", webkey, len(webkey)) - - d = hashlib.sha1(webkey) - d.update(b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11") - respkey = d.digest() - respkey = binascii.b2a_base64(respkey)[:-1] - if DEBUG: - print("respkey:", respkey) - - sock.send( - b"""\ -HTTP/1.1 101 Switching Protocols\r -Upgrade: websocket\r -Connection: Upgrade\r -Sec-WebSocket-Accept: """ - ) - sock.send(respkey) - sock.send("\r\n\r\n") - - -# Very simplified client handshake, works for MicroPython's -# websocket server implementation, but probably not for other -# servers. -def client_handshake(sock): - cl = sock.makefile("rwb", 0) - cl.write( - b"""\ -GET / HTTP/1.1\r -Host: echo.websocket.org\r -Connection: Upgrade\r -Upgrade: websocket\r -Sec-WebSocket-Key: foo\r -\r -""" - ) - l = cl.readline() - # print(l) - while 1: - l = cl.readline() - if l == b"\r\n": - break - - -# sys.stdout.write(l) From f736afb577f91cee2a53a22ea17b61755e3f44fc Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sun, 17 Jul 2022 08:43:33 +1000 Subject: [PATCH 0202/1041] drivers,ports: Fix a few typos in comments. Fixes: - Should read `definitions` rather than `defintions`. - Should read `resolution` rather than `resoultion`. - Should read `inefficient` rather than `inefficent`. - Should read `closed` rather than `closded`. Signed-off-by: Tim Gates --- drivers/cc3000/src/evnt_handler.c | 2 +- ports/mimxrt/hal/flexspi_flash_config.h | 4 ++-- ports/stm32/adc.c | 6 +++--- ports/teensy/core/pins_teensy.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/cc3000/src/evnt_handler.c b/drivers/cc3000/src/evnt_handler.c index 80f34e469b..d430bbfdad 100644 --- a/drivers/cc3000/src/evnt_handler.c +++ b/drivers/cc3000/src/evnt_handler.c @@ -604,7 +604,7 @@ INT32 hci_unsol_event_handler(CHAR *event_hdr) { //data[0] represents the socket id, for which FIN was received by remote. //Upon receiving this event, the user can close the socket, or else the - //socket will be closded after inacvitity timeout (by default 60 seconds) + //socket will be closed after inacvitity timeout (by default 60 seconds) tSLInformation.sWlanCB(event_type, data, 1); } } diff --git a/ports/mimxrt/hal/flexspi_flash_config.h b/ports/mimxrt/hal/flexspi_flash_config.h index 3c21eb609a..80526880be 100644 --- a/ports/mimxrt/hal/flexspi_flash_config.h +++ b/ports/mimxrt/hal/flexspi_flash_config.h @@ -18,7 +18,7 @@ #define FSL_XIP_BOARD_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*@}*/ -/* FLEXSPI memory config block related defintions */ +/* FLEXSPI memory config block related definitions */ #define FLEXSPI_CFG_BLK_TAG (0x42464346UL) // ascii "FCFB" Big Endian #define FLEXSPI_CFG_BLK_VERSION (0x56010400UL) // V1.4.0 #define FLEXSPI_CFG_BLK_SIZE (512) @@ -26,7 +26,7 @@ /* FLEXSPI Feature related definitions */ #define FLEXSPI_FEATURE_HAS_PARALLEL_MODE 1 -/* Lookup table related defintions */ +/* Lookup table related definitions */ #define CMD_INDEX_READ 0 #define CMD_INDEX_READSTATUS 1 #define CMD_INDEX_WRITEENABLE 2 diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index fcc7d51e45..9b7788e59e 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -50,7 +50,7 @@ /// val = adc.read_core_vbat() # read MCU VBAT /// val = adc.read_core_vref() # read MCU VREF -/* ADC defintions */ +/* ADC definitions */ #define ADCx (ADC1) #define PIN_ADC_MASK PIN_ADC1 #define pin_adc_table pin_adc1 @@ -171,8 +171,8 @@ #define EOC_TIMEOUT (10) /* Core temperature sensor definitions */ -#define CORE_TEMP_V25 (943) /* (0.76v/3.3v)*(2^ADC resoultion) */ -#define CORE_TEMP_AVG_SLOPE (3) /* (2.5mv/3.3v)*(2^ADC resoultion) */ +#define CORE_TEMP_V25 (943) /* (0.76v/3.3v)*(2^ADC resolution) */ +#define CORE_TEMP_AVG_SLOPE (3) /* (2.5mv/3.3v)*(2^ADC resolution) */ // scale and calibration values for VBAT and VREF #define ADC_SCALE (ADC_SCALE_V / ((1 << ADC_CAL_BITS) - 1)) diff --git a/ports/teensy/core/pins_teensy.c b/ports/teensy/core/pins_teensy.c index b28f94a9ec..5817121fad 100644 --- a/ports/teensy/core/pins_teensy.c +++ b/ports/teensy/core/pins_teensy.c @@ -181,7 +181,7 @@ void portb_isr(void) void portc_isr(void) { - // TODO: these are inefficent. Use CLZ somehow.... + // TODO: these are inefficient. Use CLZ somehow.... uint32_t isfr = PORTC_ISFR; PORTC_ISFR = isfr; if ((isfr & CORE_PIN9_BITMASK) && intFunc[9]) intFunc[9](); From fa15aed0f718562871288aa174e91507a134db28 Mon Sep 17 00:00:00 2001 From: Andrew Scheller Date: Fri, 22 Jul 2022 17:28:30 +0100 Subject: [PATCH 0203/1041] docs/library/neopixel: Add note that neopixel is included in rp2 builds. --- docs/library/neopixel.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/library/neopixel.rst b/docs/library/neopixel.rst index 1b37f088ba..bc3b4e68a4 100644 --- a/docs/library/neopixel.rst +++ b/docs/library/neopixel.rst @@ -6,7 +6,7 @@ This module provides a driver for WS2818 / NeoPixel LEDs. -.. note:: This module is only included by default on the ESP8266 and ESP32 +.. note:: This module is only included by default on the ESP8266, ESP32 and RP2 ports. On STM32 / Pyboard, you can `download the module `_ and copy it to the filesystem. From 1e87b56219c69306d77a887cac3d29146180f113 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 4 Jul 2022 17:35:46 +1000 Subject: [PATCH 0204/1041] py/obj: Add support for __float__ and __complex__ functions. --- py/obj.c | 15 +++++-- py/objcomplex.c | 4 ++ py/objtype.c | 6 +++ py/runtime.c | 9 ++++ py/runtime0.h | 2 + .../types_float_implicit_conversion.py | 14 +++++++ tests/float/complex_dunder.py | 40 ++++++++++++++++++ tests/float/float_dunder.py | 42 +++++++++++++++++++ tests/run-tests.py | 1 + 9 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 tests/cpydiff/types_float_implicit_conversion.py create mode 100644 tests/float/complex_dunder.py create mode 100644 tests/float/float_dunder.py diff --git a/py/obj.c b/py/obj.c index 51f6d85def..5a05ea58c5 100644 --- a/py/obj.c +++ b/py/obj.c @@ -355,9 +355,13 @@ bool mp_obj_get_float_maybe(mp_obj_t arg, mp_float_t *value) { } else if (mp_obj_is_float(arg)) { val = mp_obj_float_get(arg); } else { - return false; + arg = mp_unary_op(MP_UNARY_OP_FLOAT_MAYBE, (mp_obj_t)arg); + if (arg != MP_OBJ_NULL && mp_obj_is_float(arg)) { + val = mp_obj_float_get(arg); + } else { + return false; + } } - *value = val; return true; } @@ -399,7 +403,12 @@ bool mp_obj_get_complex_maybe(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) } else if (mp_obj_is_type(arg, &mp_type_complex)) { mp_obj_complex_get(arg, real, imag); } else { - return false; + arg = mp_unary_op(MP_UNARY_OP_COMPLEX_MAYBE, (mp_obj_t)arg); + if (arg != MP_OBJ_NULL && mp_obj_is_type(arg, &mp_type_complex)) { + mp_obj_complex_get(arg, real, imag); + } else { + return false; + } } return true; } diff --git a/py/objcomplex.c b/py/objcomplex.c index 157617e156..3c4cb66140 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -88,6 +88,10 @@ STATIC mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, si // a complex, just return it return args[0]; } else { + mp_float_t real, imag; + if (mp_obj_get_complex_maybe(args[0], &real, &imag)) { + return mp_obj_new_complex(real, imag); + } // something else, try to cast it to a complex return mp_obj_new_complex(mp_obj_get_float(args[0]), 0); } diff --git a/py/objtype.c b/py/objtype.c index 37c1e3bd22..fe1918bd37 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -378,6 +378,12 @@ const byte mp_unary_op_method_name[MP_UNARY_OP_NUM_RUNTIME] = { [MP_UNARY_OP_INVERT] = MP_QSTR___invert__, [MP_UNARY_OP_ABS] = MP_QSTR___abs__, #endif + #if MICROPY_PY_BUILTINS_FLOAT + [MP_UNARY_OP_FLOAT_MAYBE] = MP_QSTR___float__, + #if MICROPY_PY_BUILTINS_COMPLEX + [MP_UNARY_OP_COMPLEX_MAYBE] = MP_QSTR___complex__, + #endif + #endif #if MICROPY_PY_SYS_GETSIZEOF [MP_UNARY_OP_SIZEOF] = MP_QSTR___sizeof__, #endif diff --git a/py/runtime.c b/py/runtime.c index e6d8c68070..2c3b3ddde4 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -319,6 +319,15 @@ mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) { // if arg==mp_const_none. return mp_const_true; } + #if MICROPY_PY_BUILTINS_FLOAT + if (op == MP_UNARY_OP_FLOAT_MAYBE + #if MICROPY_PY_BUILTINS_COMPLEX + || op == MP_UNARY_OP_COMPLEX_MAYBE + #endif + ) { + return MP_OBJ_NULL; + } + #endif // With MP_UNARY_OP_INT, mp_unary_op() becomes a fallback for mp_obj_get_int(). // In this case provide a more focused error message to not confuse, e.g. chr(1.0) #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE diff --git a/py/runtime0.h b/py/runtime0.h index e6eeff97d6..c82a4717f4 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -76,6 +76,8 @@ typedef enum { MP_UNARY_OP_HASH, // __hash__; must return a small int MP_UNARY_OP_ABS, // __abs__ MP_UNARY_OP_INT, // __int__ + MP_UNARY_OP_FLOAT_MAYBE, // __float__ + MP_UNARY_OP_COMPLEX_MAYBE, // __complex__ MP_UNARY_OP_SIZEOF, // for sys.getsizeof() } mp_unary_op_t; diff --git a/tests/cpydiff/types_float_implicit_conversion.py b/tests/cpydiff/types_float_implicit_conversion.py new file mode 100644 index 0000000000..8d39a7cd41 --- /dev/null +++ b/tests/cpydiff/types_float_implicit_conversion.py @@ -0,0 +1,14 @@ +""" +categories: Types,float +description: uPy allows implicit conversion of objects in maths operations while CPython does not. +cause: Unknown +workaround: Objects should be wrapped in `float(obj)` for compatibility with CPython. +""" + + +class Test: + def __float__(self): + return 0.5 + + +print(2.0 * Test()) diff --git a/tests/float/complex_dunder.py b/tests/float/complex_dunder.py new file mode 100644 index 0000000000..128dc69293 --- /dev/null +++ b/tests/float/complex_dunder.py @@ -0,0 +1,40 @@ +# test __complex__ function support + + +class TestComplex: + def __complex__(self): + return 1j + 10 + + +class TestStrComplex: + def __complex__(self): + return "a" + + +class TestNonComplex: + def __complex__(self): + return 6 + + +class Test: + pass + + +print(complex(TestComplex())) + +try: + print(complex(TestStrComplex())) +except TypeError: + print("TypeError") + + +try: + print(complex(TestNonComplex())) +except TypeError: + print("TypeError") + + +try: + print(complex(Test())) +except TypeError: + print("TypeError") diff --git a/tests/float/float_dunder.py b/tests/float/float_dunder.py new file mode 100644 index 0000000000..1cd03db524 --- /dev/null +++ b/tests/float/float_dunder.py @@ -0,0 +1,42 @@ +# test __float__ function support + + +class TestFloat: + def __float__(self): + return 10.0 + + +class TestStrFloat: + def __float__(self): + return "a" + + +class TestNonFloat: + def __float__(self): + return 6 + + +class Test: + pass + + +print("%.1f" % float(TestFloat())) +print("%.1f" % TestFloat()) + + +try: + print(float(TestStrFloat())) +except TypeError: + print("TypeError") + + +try: + print(float(TestNonFloat())) +except TypeError: + print("TypeError") + + +try: + print(float(Test())) +except TypeError: + print("TypeError") diff --git a/tests/run-tests.py b/tests/run-tests.py index 2d6dbaaf1c..baab7bdd4a 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -525,6 +525,7 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): skip_tests.add("float/int_big_float.py") skip_tests.add("float/true_value.py") skip_tests.add("float/types.py") + skip_tests.add("float/complex_dunder.py") if not has_coverage: skip_tests.add("cmdline/cmd_parsetree.py") From 4fe3e493b1a62381db15b724f77d565ff2666120 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 25 Jul 2022 15:23:48 +1000 Subject: [PATCH 0205/1041] py/obj: Make mp_obj_get_complex_maybe call mp_obj_get_float_maybe first. This commit simplifies mp_obj_get_complex_maybe() by first calling mp_obj_get_float_maybe() to handle the cases corresponding to floats. Only if that fails does it attempt to extra a full complex number. This reduces code size and also means that mp_obj_get_complex_maybe() now supports user-defined classes defining __float__; in particular this allows user-defined classes to be used as arguments to cmath-module function. Furthermore, complex_make_new() can now be simplified to directly call mp_obj_get_complex(), instead of mp_obj_get_complex_maybe() followed by mp_obj_get_float(). This also improves error messages from complex with an invalid argument, it now raises "can't convert to complex" rather than "can't convert to float". Signed-off-by: Damien George --- py/obj.c | 17 +---------------- py/objcomplex.c | 7 ++----- tests/float/cmath_dunder.py | 21 +++++++++++++++++++++ tests/float/complex_dunder.py | 6 ++++++ tests/float/math_dunder.py | 15 +++++++++++++++ 5 files changed, 45 insertions(+), 21 deletions(-) create mode 100644 tests/float/cmath_dunder.py create mode 100644 tests/float/math_dunder.py diff --git a/py/obj.c b/py/obj.c index 5a05ea58c5..b461fe50aa 100644 --- a/py/obj.c +++ b/py/obj.c @@ -383,22 +383,7 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) { #if MICROPY_PY_BUILTINS_COMPLEX bool mp_obj_get_complex_maybe(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { - if (arg == mp_const_false) { - *real = 0; - *imag = 0; - } else if (arg == mp_const_true) { - *real = 1; - *imag = 0; - } else if (mp_obj_is_small_int(arg)) { - *real = (mp_float_t)MP_OBJ_SMALL_INT_VALUE(arg); - *imag = 0; - #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE - } else if (mp_obj_is_exact_type(arg, &mp_type_int)) { - *real = mp_obj_int_as_float_impl(arg); - *imag = 0; - #endif - } else if (mp_obj_is_float(arg)) { - *real = mp_obj_float_get(arg); + if (mp_obj_get_float_maybe(arg, real)) { *imag = 0; } else if (mp_obj_is_type(arg, &mp_type_complex)) { mp_obj_complex_get(arg, real, imag); diff --git a/py/objcomplex.c b/py/objcomplex.c index 3c4cb66140..4aa598a0bc 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -89,11 +89,8 @@ STATIC mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, si return args[0]; } else { mp_float_t real, imag; - if (mp_obj_get_complex_maybe(args[0], &real, &imag)) { - return mp_obj_new_complex(real, imag); - } - // something else, try to cast it to a complex - return mp_obj_new_complex(mp_obj_get_float(args[0]), 0); + mp_obj_get_complex(args[0], &real, &imag); + return mp_obj_new_complex(real, imag); } case 2: diff --git a/tests/float/cmath_dunder.py b/tests/float/cmath_dunder.py new file mode 100644 index 0000000000..3526341510 --- /dev/null +++ b/tests/float/cmath_dunder.py @@ -0,0 +1,21 @@ +# test that cmath functions support user classes with __float__ and __complex__ + +try: + import cmath +except ImportError: + print("SKIP") + raise SystemExit + + +class TestFloat: + def __float__(self): + return 1.0 + + +class TestComplex: + def __complex__(self): + return 1j + 10 + + +for clas in TestFloat, TestComplex: + print("%.5g" % cmath.phase(clas())) diff --git a/tests/float/complex_dunder.py b/tests/float/complex_dunder.py index 128dc69293..975d829b47 100644 --- a/tests/float/complex_dunder.py +++ b/tests/float/complex_dunder.py @@ -1,6 +1,11 @@ # test __complex__ function support +class TestFloat: + def __float__(self): + return 1.0 + + class TestComplex: def __complex__(self): return 1j + 10 @@ -20,6 +25,7 @@ class Test: pass +print(complex(TestFloat())) print(complex(TestComplex())) try: diff --git a/tests/float/math_dunder.py b/tests/float/math_dunder.py new file mode 100644 index 0000000000..33ea7f7c1c --- /dev/null +++ b/tests/float/math_dunder.py @@ -0,0 +1,15 @@ +# test that math functions support user classes with __float__ + +try: + import math +except ImportError: + print("SKIP") + raise SystemExit + + +class TestFloat: + def __float__(self): + return 1.0 + + +print("%.5g" % math.exp(TestFloat())) From 9fd8250d6962d016942ac48e0d20767124bcd732 Mon Sep 17 00:00:00 2001 From: Peter Harper Date: Thu, 21 Jul 2022 12:04:19 +0100 Subject: [PATCH 0206/1041] lib/cyw43-driver: Update driver to latest version. This version of the driver adds an event hook to call during firmware download, and the ability to query the current power mode. --- lib/cyw43-driver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cyw43-driver b/lib/cyw43-driver index 5614e2750e..2ab6ca93f9 160000 --- a/lib/cyw43-driver +++ b/lib/cyw43-driver @@ -1 +1 @@ -Subproject commit 5614e2750e019b0ffa14a50e3c92045b952e2634 +Subproject commit 2ab6ca93f9cd044bc6f35c1403b1284e4161294a From 33d6994d4c5855228ae423f2d77fb2549db9f854 Mon Sep 17 00:00:00 2001 From: Peter Harper Date: Thu, 14 Jul 2022 18:11:34 +0100 Subject: [PATCH 0207/1041] rp2/cyw43_configport: Set CYW43_EVENT_POLL_HOOK value. This should allow USB to work while we're loading WiFi firmware. Fixes issue #8904. --- ports/rp2/cyw43_configport.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/rp2/cyw43_configport.h b/ports/rp2/cyw43_configport.h index 6173964cb2..aeb220b202 100644 --- a/ports/rp2/cyw43_configport.h +++ b/ports/rp2/cyw43_configport.h @@ -95,4 +95,6 @@ static inline void cyw43_delay_ms(uint32_t ms) { } } +#define CYW43_EVENT_POLL_HOOK MICROPY_EVENT_POLL_HOOK_FAST + #endif // MICROPY_INCLUDED_RP2_CYW43_CONFIGPORT_H From f64862a766bf7c22feb1de75dadc69fb9e1aed4a Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 26 Jul 2022 01:37:03 +1000 Subject: [PATCH 0208/1041] rp2/cyw43_configport: Set CYW43_WIFI_NVRAM_INCLUDE_FILE value. Required for latest cyw43-driver. Signed-off-by: Damien George --- ports/rp2/cyw43_configport.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/rp2/cyw43_configport.h b/ports/rp2/cyw43_configport.h index aeb220b202..b6f5b3cad8 100644 --- a/ports/rp2/cyw43_configport.h +++ b/ports/rp2/cyw43_configport.h @@ -32,6 +32,7 @@ #include "py/mphal.h" #include "pendsv.h" +#define CYW43_WIFI_NVRAM_INCLUDE_FILE "wifi_nvram_43439.h" #define CYW43_IOCTL_TIMEOUT_US (1000000) #define CYW43_SLEEP_MAX (10) #define CYW43_NETUTILS (1) From 0c45a28d24e1a7f9ea5912c928d7b5a860a6514a Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 24 Jul 2022 09:15:38 +0200 Subject: [PATCH 0209/1041] rp2/rp2_pio: Fix StateMachine.restart when PIO program is shared. The state machines were not properly restarted in the case that the same PIO program was shared among multiple StateMachine instances. This is because only the first StateMachine to use the program would set the rp2_state_machine_initial_pc variable. See https://forum.micropython.org/viewtopic.php?f=21&t=12776&p=69464#p69464 --- ports/rp2/rp2_pio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/rp2/rp2_pio.c b/ports/rp2/rp2_pio.c index 072644eba6..eb85eb2248 100644 --- a/ports/rp2/rp2_pio.c +++ b/ports/rp2/rp2_pio.c @@ -469,8 +469,8 @@ STATIC mp_obj_t rp2_state_machine_init_helper(const rp2_state_machine_obj_t *sel if (offset < 0) { rp2_pio_add_program(&rp2_pio_obj[PIO_NUM(self->pio)], args[ARG_prog].u_obj); offset = mp_obj_get_int(prog[PROG_OFFSET_PIO0 + PIO_NUM(self->pio)]); - rp2_state_machine_initial_pc[self->id] = offset; } + rp2_state_machine_initial_pc[self->id] = offset; // Compute the clock divider. uint16_t clkdiv_int; From c0fa903d6b2ed5131ae60f8faff2c6ad5276b3a2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 26 Jul 2022 12:24:50 +1000 Subject: [PATCH 0210/1041] py/compile: Support large integers in inline-asm data directive. Fixes issue #8956. Signed-off-by: Damien George --- py/compile.c | 5 +++-- tests/inlineasm/asmdata.py | 16 ++++++++++++++++ tests/inlineasm/asmdata.py.exp | 5 +++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 tests/inlineasm/asmdata.py create mode 100644 tests/inlineasm/asmdata.py.exp diff --git a/py/compile.c b/py/compile.c index ff3e5ffc6d..8aaf885327 100644 --- a/py/compile.c +++ b/py/compile.c @@ -3286,12 +3286,13 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind if (pass > MP_PASS_SCOPE) { mp_int_t bytesize = MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]); for (uint j = 1; j < n_args; j++) { - if (!MP_PARSE_NODE_IS_SMALL_INT(pn_arg[j])) { + mp_obj_t int_obj; + if (!mp_parse_node_get_int_maybe(pn_arg[j], &int_obj)) { compile_syntax_error(comp, nodes[i], MP_ERROR_TEXT("'data' requires integer arguments")); return; } mp_asm_base_data((mp_asm_base_t *)comp->emit_inline_asm, - bytesize, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[j])); + bytesize, mp_obj_int_get_truncated(int_obj)); } } } else { diff --git a/tests/inlineasm/asmdata.py b/tests/inlineasm/asmdata.py new file mode 100644 index 0000000000..bbd20c9186 --- /dev/null +++ b/tests/inlineasm/asmdata.py @@ -0,0 +1,16 @@ +# test the "data" directive + + +@micropython.asm_thumb +def ret_num(r0) -> uint: + lsl(r0, r0, 2) + mov(r1, pc) + add(r0, r0, r1) + ldr(r0, [r0, 4]) + b(HERE) + data(4, 0x12345678, 0x20000000, 0x40000000, 0x7FFFFFFF + 1, (1 << 32) - 2) + label(HERE) + + +for i in range(5): + print(hex(ret_num(i))) diff --git a/tests/inlineasm/asmdata.py.exp b/tests/inlineasm/asmdata.py.exp new file mode 100644 index 0000000000..502c04f993 --- /dev/null +++ b/tests/inlineasm/asmdata.py.exp @@ -0,0 +1,5 @@ +0x12345678 +0x20000000 +0x40000000 +0x80000000 +0xfffffffe From e65d1e69e88268145ff0e7e73240f028885915be Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 22 Jul 2022 13:53:13 +1000 Subject: [PATCH 0211/1041] py/modio: Remove FileIO and TextIOWrapper from io module. On ports with more than one filesystem, the type will be wrong, for example if using LFS but FAT enabled, then the type will be FAT. So it's not possible to use these classes to identify a file object type. Furthermore, constructing an io.FileIO currently crashes on FAT, and make_new isn't supported on LFS. And the io.TextIOWrapper class does not match CPython at all. Signed-off-by: Jim Mussared --- extmod/vfs.c | 2 +- extmod/vfs_fat_file.c | 149 ++++++++++++++++---------------------- extmod/vfs_posix.c | 2 +- extmod/vfs_posix_file.c | 19 +---- py/modio.c | 9 --- tests/extmod/vfs_posix.py | 4 +- 6 files changed, 69 insertions(+), 116 deletions(-) diff --git a/extmod/vfs.c b/extmod/vfs.c index 2799622b38..be1a82d404 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -312,7 +312,7 @@ mp_obj_t mp_vfs_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) #if MICROPY_VFS_POSIX // If the file is an integer then delegate straight to the POSIX handler if (mp_obj_is_small_int(args[ARG_file].u_obj)) { - return mp_vfs_posix_file_open(&mp_type_textio, args[ARG_file].u_obj, args[ARG_mode].u_obj); + return mp_vfs_posix_file_open(&mp_type_vfs_posix_textio, args[ARG_file].u_obj, args[ARG_mode].u_obj); } #endif diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index 537101d00f..ebf36fc397 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -151,18 +151,67 @@ STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, } } -// Note: encoding is ignored for now; it's also not a valid kwarg for CPython's FileIO, -// but by adding it here we can use one single mp_arg_t array for open() and FileIO's constructor -STATIC const mp_arg_t file_open_args[] = { - { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} }, - { MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_r)} }, - { MP_QSTR_encoding, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} }, -}; -#define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args) +// TODO gc hook to close the file if not already closed -STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_arg_val_t *args) { +STATIC const mp_rom_map_elem_t vfs_fat_rawfile_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, + { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) }, + { 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_close), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) }, + { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&file_obj___exit___obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(vfs_fat_rawfile_locals_dict, vfs_fat_rawfile_locals_dict_table); + +#if MICROPY_PY_IO_FILEIO +STATIC const mp_stream_p_t vfs_fat_fileio_stream_p = { + .read = file_obj_read, + .write = file_obj_write, + .ioctl = file_obj_ioctl, +}; + +const mp_obj_type_t mp_type_vfs_fat_fileio = { + { &mp_type_type }, + .name = MP_QSTR_FileIO, + .print = file_obj_print, + .getiter = mp_identity_getiter, + .iternext = mp_stream_unbuffered_iter, + .protocol = &vfs_fat_fileio_stream_p, + .locals_dict = (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict, +}; +#endif + +STATIC const mp_stream_p_t vfs_fat_textio_stream_p = { + .read = file_obj_read, + .write = file_obj_write, + .ioctl = file_obj_ioctl, + .is_text = true, +}; + +const mp_obj_type_t mp_type_vfs_fat_textio = { + { &mp_type_type }, + .name = MP_QSTR_TextIOWrapper, + .print = file_obj_print, + .getiter = mp_identity_getiter, + .iternext = mp_stream_unbuffered_iter, + .protocol = &vfs_fat_textio_stream_p, + .locals_dict = (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict, +}; + +// Factory function for I/O stream classes +STATIC mp_obj_t fat_vfs_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) { + fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); + + const mp_obj_type_t *type = &mp_type_vfs_fat_textio; int mode = 0; - const char *mode_s = mp_obj_str_get_str(args[1].u_obj); + const char *mode_s = mp_obj_str_get_str(mode_in); // TODO make sure only one of r, w, x, a, and b, t are specified while (*mode_s) { switch (*mode_s++) { @@ -195,9 +244,8 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar pyb_file_obj_t *o = m_new_obj_with_finaliser(pyb_file_obj_t); o->base.type = type; - const char *fname = mp_obj_str_get_str(args[0].u_obj); - assert(vfs != NULL); - FRESULT res = f_open(&vfs->fatfs, &o->fp, fname, mode); + const char *fname = mp_obj_str_get_str(path_in); + FRESULT res = f_open(&self->fatfs, &o->fp, fname, mode); if (res != FR_OK) { m_del_obj(pyb_file_obj_t, o); mp_raise_OSError(fresult_to_errno_table[res]); @@ -210,79 +258,6 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar return MP_OBJ_FROM_PTR(o); } - -STATIC mp_obj_t file_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS]; - mp_arg_parse_all_kw_array(n_args, n_kw, args, FILE_OPEN_NUM_ARGS, file_open_args, arg_vals); - return file_open(NULL, type, arg_vals); -} - -// TODO gc hook to close the file if not already closed - -STATIC const mp_rom_map_elem_t vfs_fat_rawfile_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, - { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, - { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) }, - { 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_close), MP_ROM_PTR(&mp_stream_close_obj) }, - { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) }, - { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, - { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&file_obj___exit___obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(vfs_fat_rawfile_locals_dict, vfs_fat_rawfile_locals_dict_table); - -#if MICROPY_PY_IO_FILEIO -STATIC const mp_stream_p_t vfs_fat_fileio_stream_p = { - .read = file_obj_read, - .write = file_obj_write, - .ioctl = file_obj_ioctl, -}; - -const mp_obj_type_t mp_type_vfs_fat_fileio = { - { &mp_type_type }, - .name = MP_QSTR_FileIO, - .print = file_obj_print, - .make_new = file_obj_make_new, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &vfs_fat_fileio_stream_p, - .locals_dict = (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict, -}; -#endif - -STATIC const mp_stream_p_t vfs_fat_textio_stream_p = { - .read = file_obj_read, - .write = file_obj_write, - .ioctl = file_obj_ioctl, - .is_text = true, -}; - -const mp_obj_type_t mp_type_vfs_fat_textio = { - { &mp_type_type }, - .name = MP_QSTR_TextIOWrapper, - .print = file_obj_print, - .make_new = file_obj_make_new, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &vfs_fat_textio_stream_p, - .locals_dict = (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict, -}; - -// Factory function for I/O stream classes -STATIC mp_obj_t fatfs_builtin_open_self(mp_obj_t self_in, mp_obj_t path, mp_obj_t mode) { - // TODO: analyze buffering args and instantiate appropriate type - fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); - mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS]; - arg_vals[0].u_obj = path; - arg_vals[1].u_obj = mode; - arg_vals[2].u_obj = mp_const_none; - return file_open(self, &mp_type_vfs_fat_textio, arg_vals); -} -MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_open_obj, fatfs_builtin_open_self); +MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_open_obj, fat_vfs_open); #endif // MICROPY_VFS && MICROPY_VFS_FAT diff --git a/extmod/vfs_posix.c b/extmod/vfs_posix.c index 1ada596d13..9b00365817 100644 --- a/extmod/vfs_posix.c +++ b/extmod/vfs_posix.c @@ -138,7 +138,7 @@ STATIC mp_obj_t vfs_posix_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode if (!mp_obj_is_small_int(path_in)) { path_in = vfs_posix_get_path_obj(self, path_in); } - return mp_vfs_posix_file_open(&mp_type_textio, path_in, mode_in); + return mp_vfs_posix_file_open(&mp_type_vfs_posix_textio, path_in, mode_in); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_posix_open_obj, vfs_posix_open); diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index 837c5489b0..795ad7bbd9 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -111,17 +111,6 @@ mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_ return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t vfs_posix_file_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - static const mp_arg_t allowed_args[] = { - { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} }, - { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_r)} }, - }; - - mp_arg_val_t arg_vals[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, arg_vals); - return mp_vfs_posix_file_open(type, arg_vals[0].u_obj, arg_vals[1].u_obj); -} - STATIC mp_obj_t vfs_posix_file_fileno(mp_obj_t self_in) { mp_obj_vfs_posix_file_t *self = MP_OBJ_TO_PTR(self_in); check_fd_is_open(self); @@ -268,7 +257,6 @@ const mp_obj_type_t mp_type_vfs_posix_fileio = { { &mp_type_type }, .name = MP_QSTR_FileIO, .print = vfs_posix_file_print, - .make_new = vfs_posix_file_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &vfs_posix_fileio_stream_p, @@ -287,15 +275,14 @@ const mp_obj_type_t mp_type_vfs_posix_textio = { { &mp_type_type }, .name = MP_QSTR_TextIOWrapper, .print = vfs_posix_file_print, - .make_new = vfs_posix_file_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &vfs_posix_textio_stream_p, .locals_dict = (mp_obj_dict_t *)&vfs_posix_rawfile_locals_dict, }; -const mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_textio}, STDIN_FILENO}; -const mp_obj_vfs_posix_file_t mp_sys_stdout_obj = {{&mp_type_textio}, STDOUT_FILENO}; -const mp_obj_vfs_posix_file_t mp_sys_stderr_obj = {{&mp_type_textio}, STDERR_FILENO}; +const mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_vfs_posix_textio}, STDIN_FILENO}; +const mp_obj_vfs_posix_file_t mp_sys_stdout_obj = {{&mp_type_vfs_posix_textio}, STDOUT_FILENO}; +const mp_obj_vfs_posix_file_t mp_sys_stderr_obj = {{&mp_type_vfs_posix_textio}, STDERR_FILENO}; #endif // MICROPY_VFS_POSIX || MICROPY_VFS_POSIX_FILE diff --git a/py/modio.c b/py/modio.c index 50af0b6a47..d44c1948ab 100644 --- a/py/modio.c +++ b/py/modio.c @@ -37,9 +37,6 @@ #if MICROPY_PY_IO -extern const mp_obj_type_t mp_type_fileio; -extern const mp_obj_type_t mp_type_textio; - #if MICROPY_PY_IO_IOBASE STATIC const mp_obj_type_t mp_type_iobase; @@ -211,12 +208,6 @@ STATIC const mp_rom_map_elem_t mp_module_io_globals_table[] = { #if MICROPY_PY_IO_IOBASE { MP_ROM_QSTR(MP_QSTR_IOBase), MP_ROM_PTR(&mp_type_iobase) }, #endif - #if MICROPY_PY_IO_FILEIO - { MP_ROM_QSTR(MP_QSTR_FileIO), MP_ROM_PTR(&mp_type_fileio) }, - #if MICROPY_CPYTHON_COMPAT - { MP_ROM_QSTR(MP_QSTR_TextIOWrapper), MP_ROM_PTR(&mp_type_textio) }, - #endif - #endif { MP_ROM_QSTR(MP_QSTR_StringIO), MP_ROM_PTR(&mp_type_stringio) }, #if MICROPY_PY_IO_BYTESIO { MP_ROM_QSTR(MP_QSTR_BytesIO), MP_ROM_PTR(&mp_type_bytesio) }, diff --git a/tests/extmod/vfs_posix.py b/tests/extmod/vfs_posix.py index 2a14fc2076..d193236696 100644 --- a/tests/extmod/vfs_posix.py +++ b/tests/extmod/vfs_posix.py @@ -42,8 +42,8 @@ f.close() # close on a closed file should succeed f.close() -# construct a file object using the type constructor, with a raw fileno -f = type(f)(2) +# construct a file object with a raw fileno +f = open(2) print(f) # file read From 092784da1948c6bfb224f8f6c593aff255ab2db0 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 22 Jul 2022 13:53:40 +1000 Subject: [PATCH 0212/1041] ports: Remove unused mp_type_{fileio/textio} macros in mpconfigport.h. Signed-off-by: Jim Mussared --- ports/cc3200/mpconfigport.h | 4 ---- ports/esp32/mpconfigport.h | 2 -- ports/esp8266/mpconfigport.h | 11 ----------- ports/mimxrt/mpconfigport.h | 4 ---- ports/nrf/mpconfigport.h | 17 ----------------- ports/renesas-ra/mpconfigport.h | 12 ------------ ports/rp2/mpconfigport.h | 9 --------- ports/samd/mpconfigport.h | 4 ---- ports/stm32/mpconfigport.h | 12 ------------ ports/unix/mpconfigport.h | 3 --- ports/unix/variants/minimal/mpconfigvariant.h | 3 --- ports/windows/mpconfigport.h | 3 --- 12 files changed, 84 deletions(-) diff --git a/ports/cc3200/mpconfigport.h b/ports/cc3200/mpconfigport.h index 8059daeec7..e81a2fc29b 100644 --- a/ports/cc3200/mpconfigport.h +++ b/ports/cc3200/mpconfigport.h @@ -131,10 +131,6 @@ X(EINVAL) \ X(ETIMEDOUT) \ -// TODO these should be generic, not bound to fatfs -#define mp_type_fileio mp_type_vfs_fat_fileio -#define mp_type_textio mp_type_vfs_fat_textio - // extra constants #define MICROPY_PORT_CONSTANTS \ { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, \ diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index dfa577d2bc..957aa2e93b 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -135,8 +135,6 @@ #define MICROPY_FATFS_RPATH (2) #define MICROPY_FATFS_MAX_SS (4096) #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ -#define mp_type_fileio mp_type_vfs_fat_fileio -#define mp_type_textio mp_type_vfs_fat_textio #define MP_STATE_PORT MP_STATE_VM diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 779767311c..9ff6a34ffd 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -134,17 +134,6 @@ void *esp_native_code_commit(void *, size_t, void *); // printer for debugging output, goes to UART only extern const struct _mp_print_t mp_debug_print; -#if MICROPY_VFS_FAT -#define mp_type_fileio mp_type_vfs_fat_fileio -#define mp_type_textio mp_type_vfs_fat_textio -#elif MICROPY_VFS_LFS1 -#define mp_type_fileio mp_type_vfs_lfs1_fileio -#define mp_type_textio mp_type_vfs_lfs1_textio -#elif MICROPY_VFS_LFS2 -#define mp_type_fileio mp_type_vfs_lfs2_fileio -#define mp_type_textio mp_type_vfs_lfs2_textio -#endif - #define MP_STATE_PORT MP_STATE_VM // We need an implementation of the log2 function which is not a macro diff --git a/ports/mimxrt/mpconfigport.h b/ports/mimxrt/mpconfigport.h index 676e563c7b..00714ca8d0 100644 --- a/ports/mimxrt/mpconfigport.h +++ b/ports/mimxrt/mpconfigport.h @@ -184,10 +184,6 @@ uint32_t trng_random_u32(void); #define MICROPY_PY_PENDSV_REENTER atomic_state = raise_irq_pri(IRQ_PRI_PENDSV); #define MICROPY_PY_PENDSV_EXIT restore_irq_pri(atomic_state); -// Use VfsLfs2's types for fileio/textio -#define mp_type_fileio mp_type_vfs_lfs2_fileio -#define mp_type_textio mp_type_vfs_lfs2_textio - // Hooks to add builtins __attribute__((always_inline)) static inline void enable_irq(uint32_t state) { diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 8a2478d27d..a25ca1ec27 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -133,23 +133,6 @@ #define MICROPY_FATFS_MAX_SS (4096) #endif -#if MICROPY_VFS -// TODO these should be generic, not bound to a particular FS implementation -#if MICROPY_VFS_FAT -#define mp_type_fileio mp_type_vfs_fat_fileio -#define mp_type_textio mp_type_vfs_fat_textio -#elif MICROPY_VFS_LFS1 -#define mp_type_fileio mp_type_vfs_lfs1_fileio -#define mp_type_textio mp_type_vfs_lfs1_textio -#elif MICROPY_VFS_LFS2 -#define mp_type_fileio mp_type_vfs_lfs2_fileio -#define mp_type_textio mp_type_vfs_lfs2_textio -#endif -#else // !MICROPY_VFS_FAT -#define mp_type_fileio fatfs_type_fileio -#define mp_type_textio fatfs_type_textio -#endif - // Use port specific uos module rather than extmod variant. #define MICROPY_PY_UOS (0) diff --git a/ports/renesas-ra/mpconfigport.h b/ports/renesas-ra/mpconfigport.h index 8ecc17fcb4..65b194274a 100644 --- a/ports/renesas-ra/mpconfigport.h +++ b/ports/renesas-ra/mpconfigport.h @@ -137,18 +137,6 @@ #define MICROPY_FATFS_RPATH (2) #define MICROPY_FATFS_MULTI_PARTITION (1) -// TODO these should be generic, not bound to a particular FS implementation -#if MICROPY_VFS_FAT -#define mp_type_fileio mp_type_vfs_fat_fileio -#define mp_type_textio mp_type_vfs_fat_textio -#elif MICROPY_VFS_LFS1 -#define mp_type_fileio mp_type_vfs_lfs1_fileio -#define mp_type_textio mp_type_vfs_lfs1_textio -#elif MICROPY_VFS_LFS2 -#define mp_type_fileio mp_type_vfs_lfs2_fileio -#define mp_type_textio mp_type_vfs_lfs2_textio -#endif - #if MICROPY_PY_MACHINE #define MACHINE_BUILTIN_MODULE_CONSTANTS \ { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, \ diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index d07c1015e7..a3725789f0 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -122,15 +122,6 @@ #define MICROPY_FATFS_MAX_SS (FLASH_SECTOR_SIZE) #endif -#if MICROPY_VFS_FAT && MICROPY_HW_USB_MSC -#define mp_type_fileio mp_type_vfs_fat_fileio -#define mp_type_textio mp_type_vfs_fat_textio -#elif MICROPY_VFS_LFS2 -// Use VfsLfs2's types for fileio/textio -#define mp_type_fileio mp_type_vfs_lfs2_fileio -#define mp_type_textio mp_type_vfs_lfs2_textio -#endif - #ifndef MICROPY_BOARD_ENTER_BOOTLOADER #define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) #endif diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 96d34bf4da..24b9cbfe19 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -95,10 +95,6 @@ #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_UASYNCIO (1) -// Use VfsLfs's types for fileio/textio -#define mp_type_fileio mp_type_vfs_lfs1_fileio -#define mp_type_textio mp_type_vfs_lfs1_textio - #define MP_STATE_PORT MP_STATE_VM // Miscellaneous settings diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index e44fa2260c..e06e32c0d2 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -151,18 +151,6 @@ #define MICROPY_FATFS_RPATH (2) #define MICROPY_FATFS_MULTI_PARTITION (1) -// TODO these should be generic, not bound to a particular FS implementation -#if MICROPY_VFS_FAT -#define mp_type_fileio mp_type_vfs_fat_fileio -#define mp_type_textio mp_type_vfs_fat_textio -#elif MICROPY_VFS_LFS1 -#define mp_type_fileio mp_type_vfs_lfs1_fileio -#define mp_type_textio mp_type_vfs_lfs1_textio -#elif MICROPY_VFS_LFS2 -#define mp_type_fileio mp_type_vfs_lfs2_fileio -#define mp_type_textio mp_type_vfs_lfs2_textio -#endif - #if MICROPY_PY_PYB extern const struct _mp_obj_module_t pyb_module; #define PYB_BUILTIN_MODULE_CONSTANTS \ diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 4252a406ce..ed4c71097f 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -224,9 +224,6 @@ extern const struct _mp_print_t mp_stderr_print; #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256) #define MICROPY_ASYNC_KBD_INTR (1) -#define mp_type_fileio mp_type_vfs_posix_fileio -#define mp_type_textio mp_type_vfs_posix_textio - // type definitions for the specific machine // For size_t and ssize_t diff --git a/ports/unix/variants/minimal/mpconfigvariant.h b/ports/unix/variants/minimal/mpconfigvariant.h index 1e378e94d7..d6e5fc4726 100644 --- a/ports/unix/variants/minimal/mpconfigvariant.h +++ b/ports/unix/variants/minimal/mpconfigvariant.h @@ -107,9 +107,6 @@ #define MICROPY_PY_UHASHLIB (0) #define MICROPY_PY_UBINASCII (0) -#define mp_type_fileio mp_type_vfs_posix_fileio -#define mp_type_textio mp_type_vfs_posix_textio - ////////////////////////////////////////// // Do not change anything beyond this line ////////////////////////////////////////// diff --git a/ports/windows/mpconfigport.h b/ports/windows/mpconfigport.h index 71814e2147..5f8ad983ad 100644 --- a/ports/windows/mpconfigport.h +++ b/ports/windows/mpconfigport.h @@ -176,9 +176,6 @@ extern const struct _mp_print_t mp_stderr_print; #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256) #define MICROPY_KBD_EXCEPTION (1) -#define mp_type_fileio mp_type_vfs_posix_fileio -#define mp_type_textio mp_type_vfs_posix_textio - #define MICROPY_PORT_INIT_FUNC init() #define MICROPY_PORT_DEINIT_FUNC deinit() From b22abcdbbedb0f7583b19031fd65e19b3883671d Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 21 Jul 2022 09:54:02 +1000 Subject: [PATCH 0213/1041] extmod/uasyncio: Handle gather with no awaitables. This previously resulted in gather() yielding but with no way to be resumed. Signed-off-by: Jim Mussared --- extmod/uasyncio/funcs.py | 3 +++ tests/extmod/uasyncio_gather.py | 5 +++++ tests/extmod/uasyncio_gather.py.exp | 2 ++ 3 files changed, 10 insertions(+) diff --git a/extmod/uasyncio/funcs.py b/extmod/uasyncio/funcs.py index a1d38fbcbf..96883e4fe1 100644 --- a/extmod/uasyncio/funcs.py +++ b/extmod/uasyncio/funcs.py @@ -62,6 +62,9 @@ class _Remove: async def gather(*aws, return_exceptions=False): + if not aws: + return [] + def done(t, er): # Sub-task "t" has finished, with exception "er". nonlocal state diff --git a/tests/extmod/uasyncio_gather.py b/tests/extmod/uasyncio_gather.py index c081221c9f..af6ea555ab 100644 --- a/tests/extmod/uasyncio_gather.py +++ b/tests/extmod/uasyncio_gather.py @@ -53,6 +53,11 @@ async def main(): print("====") + # Gather with no awaitables + print(await asyncio.gather()) + + print("====") + # Test return_exceptions, where one task is cancelled and the other finishes normally tasks = [asyncio.create_task(task(1)), asyncio.create_task(task(2))] tasks[0].cancel() diff --git a/tests/extmod/uasyncio_gather.py.exp b/tests/extmod/uasyncio_gather.py.exp index a5ea47ab50..371d1ae60d 100644 --- a/tests/extmod/uasyncio_gather.py.exp +++ b/tests/extmod/uasyncio_gather.py.exp @@ -9,6 +9,8 @@ Task C: Compute factorial(4)... Task C: factorial(4) = 24 [2, 6, 24] ==== +[] +==== start 2 end 2 [CancelledError(), 2] From f9cbe6bc47dd4f5b8e85178caecd6f0de22b4c34 Mon Sep 17 00:00:00 2001 From: Dan Ellis Date: Tue, 12 Jul 2022 09:48:38 -0400 Subject: [PATCH 0214/1041] py/formatfloat: Format all whole-number floats exactly. Formerly, py/formatfloat would print whole numbers inaccurately with nonzero digits beyond the decimal place. This resulted from its strategy of successive scaling of the argument by 0.1 which cannot be exactly represented in floating point. The change in this commit avoids scaling until the value is smaller than 1, so all whole numbers print with zero fractional part. Fixes issue #4212. Signed-off-by: Dan Ellis dan.ellis@gmail.com --- py/formatfloat.c | 156 +++++++++++++------- tests/float/float_format_ftoe.py | 4 + tests/float/float_format_ftoe.py.exp | 1 + tests/float/float_format_ints.py | 31 ++++ tests/float/float_format_ints_doubleprec.py | 15 ++ tests/run-tests.py | 1 + tools/tinytest-codegen.py | 1 + 7 files changed, 154 insertions(+), 55 deletions(-) create mode 100644 tests/float/float_format_ftoe.py create mode 100644 tests/float/float_format_ftoe.py.exp create mode 100644 tests/float/float_format_ints.py create mode 100644 tests/float/float_format_ints_doubleprec.py diff --git a/py/formatfloat.c b/py/formatfloat.c index 9d28b2317d..357b73ace3 100644 --- a/py/formatfloat.c +++ b/py/formatfloat.c @@ -25,6 +25,7 @@ */ #include "py/mpconfig.h" +#include "py/misc.h" #if MICROPY_FLOAT_IMPL != MICROPY_FLOAT_IMPL_NONE #include @@ -96,7 +97,16 @@ static inline int fp_isless1(float x) { #define fp_iszero(x) (x == 0) #define fp_isless1(x) (x < 1.0) -#endif +#endif // MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT/DOUBLE + +static inline int fp_ge_eps(FPTYPE x, FPTYPE y) { + mp_float_union_t fb_y = {y}; + // Back off 2 eps. + // This is valid for almost all values, but in practice + // it's only used when y = 1eX for X>=0. + fb_y.i -= 2; + return x >= fb_y.f; +} static const FPTYPE g_pos_pow[] = { #if FPDECEXP > 32 @@ -173,6 +183,7 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch int num_digits = 0; const FPTYPE *pos_pow = g_pos_pow; const FPTYPE *neg_pow = g_neg_pow; + int signed_e = 0; if (fp_iszero(f)) { e = 0; @@ -192,31 +203,24 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch } } } else if (fp_isless1(f)) { - // We need to figure out what an integer digit will be used - // in case 'f' is used (or we revert other format to it below). - // As we just tested number to be <1, this is obviously 0, - // but we can round it up to 1 below. - char first_dig = '0'; - if (f >= FPROUND_TO_ONE) { - first_dig = '1'; - } - + FPTYPE f_mod = f; // Build negative exponent for (e = 0, e1 = FPDECEXP; e1; e1 >>= 1, pos_pow++, neg_pow++) { - if (*neg_pow > f) { + if (*neg_pow > f_mod) { e += e1; - f *= *pos_pow; + f_mod *= *pos_pow; } } + char e_sign_char = '-'; - if (fp_isless1(f) && f >= FPROUND_TO_ONE) { - f = FPCONST(1.0); + if (fp_isless1(f_mod) && f_mod >= FPROUND_TO_ONE) { + f_mod = FPCONST(1.0); if (e == 0) { e_sign_char = '+'; } - } else if (fp_isless1(f)) { + } else if (fp_isless1(f_mod)) { e++; - f *= FPCONST(10.0); + f_mod *= FPCONST(10.0); } // If the user specified 'g' format, and e is <= 4, then we'll switch @@ -224,8 +228,7 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch if (fmt == 'f' || (fmt == 'g' && e <= 4)) { fmt = 'f'; - dec = -1; - *s++ = first_dig; + dec = 0; if (org_fmt == 'g') { prec += (e - 1); @@ -237,13 +240,8 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch } num_digits = prec; - if (num_digits) { - *s++ = '.'; - while (--e && num_digits) { - *s++ = '0'; - num_digits--; - } - } + signed_e = 0; + ++num_digits; } else { // For e & g formats, we'll be printing the exponent, so set the // sign. @@ -256,22 +254,29 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch prec++; } } + signed_e = -e; } } else { - // Build positive exponent - for (e = 0, e1 = FPDECEXP; e1; e1 >>= 1, pos_pow++, neg_pow++) { - if (*pos_pow <= f) { + // Build positive exponent. + // We don't modify f at this point to avoid innaccuracies from + // scaling it. Instead, we find the product of powers of 10 + // that is not greater than it, and use that to start the + // mantissa. + FPTYPE u_base = FPCONST(1.0); + for (e = 0, e1 = FPDECEXP; e1; e1 >>= 1, pos_pow++) { + FPTYPE next_u = u_base * *pos_pow; + // fp_ge_eps performs "f >= (next_u - 2eps)" so that if, for + // numerical reasons, f is very close to a power of ten but + // not strictly equal, we still treat it as that power of 10. + // The comparison was failing for maybe 10% of 1eX values, but + // although rounding fixed many of them, there were still some + // rendering as 9.99999998e(X-1). + if (fp_ge_eps(f, next_u)) { + u_base = next_u; e += e1; - f *= *neg_pow; } } - // It can be that f was right on the edge of an entry in pos_pow needs to be reduced - if ((int)f >= 10) { - e += 1; - f *= FPCONST(0.1); - } - // If the user specified fixed format (fmt == 'f') and e makes the // number too big to fit into the available buffer, then we'll // switch to the 'e' format. @@ -310,15 +315,15 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch } else { e_sign = '+'; } + signed_e = e; } if (prec < 0) { // This can happen when the prec is trimmed to prevent buffer overflow prec = 0; } - // We now have num.f as a floating point number between >= 1 and < 10 - // (or equal to zero), and e contains the absolute value of the power of - // 10 exponent. and (dec + 1) == the number of dgits before the decimal. + // At this point e contains the absolute value of the power of 10 exponent. + // (dec + 1) == the number of dgits before the decimal. // For e, prec is # digits after the decimal // For f, prec is # digits after the decimal @@ -336,25 +341,63 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch num_digits = prec; } - // Print the digits of the mantissa - for (int i = 0; i < num_digits; ++i, --dec) { - int32_t d = (int32_t)f; - if (d < 0) { - *s++ = '0'; - } else { - *s++ = '0' + d; + if (signed_e < 0) { + // The algorithm below treats numbers smaller than 1 by scaling them + // repeatedly by 10 to bring the new digit to the top. Our input number + // was smaller than 1, so scale it up to be 1 <= f < 10. + FPTYPE u_base = FPCONST(1.0); + const FPTYPE *pow_u = g_pos_pow; + for (int m = FPDECEXP; m; m >>= 1, pow_u++) { + if (m & e) { + u_base *= *pow_u; + } } - if (dec == 0 && prec > 0) { - *s++ = '.'; - } - f -= (FPTYPE)d; - f *= FPCONST(10.0); + f *= u_base; } - // Round - // If we print non-exponential format (i.e. 'f'), but a digit we're going - // to round by (e) is too far away, then there's nothing to round. - if ((org_fmt != 'f' || e <= num_digits) && f >= FPCONST(5.0)) { + int d = 0; + int num_digits_left = num_digits; + for (int digit_index = signed_e; num_digits_left >= 0; --digit_index) { + FPTYPE u_base = FPCONST(1.0); + if (digit_index > 0) { + // Generate 10^digit_index for positive digit_index. + const FPTYPE *pow_u = g_pos_pow; + int target_index = digit_index; + for (int m = FPDECEXP; m; m >>= 1, pow_u++) { + if (m & target_index) { + u_base *= *pow_u; + } + } + } + for (d = 0; d < 9; ++d) { + // This is essentially "if (f < u_base)", but with 2eps margin + // so that if f is just a tiny bit smaller, we treat it as + // equal (and accept the additional digit value). + if (!fp_ge_eps(f, u_base)) { + break; + } + f -= u_base; + } + // We calculate one more digit than we display, to use in rounding + // below. So only emit the digit if it's one that we display. + if (num_digits_left > 0) { + // Emit this number (the leading digit). + *s++ = '0' + d; + if (dec == 0 && prec > 0) { + *s++ = '.'; + } + } + --dec; + --num_digits_left; + if (digit_index <= 0) { + // Once we get below 1.0, we scale up f instead of calculting + // negative powers of 10 in u_base. This provides better + // renditions of exact decimals like 1/16 etc. + f *= FPCONST(10.0); + } + } + // Rounding. If the next digit to print is >= 5, round up. + if (d >= 5) { char *rs = s; rs--; while (1) { @@ -394,7 +437,10 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch } } else { // Need at extra digit at the end to make room for the leading '1' - s++; + // but if we're at the buffer size limit, just drop the final digit. + if ((size_t)(s + 1 - buf) < buf_size) { + s++; + } } char *ss = s; while (ss > rs) { diff --git a/tests/float/float_format_ftoe.py b/tests/float/float_format_ftoe.py new file mode 100644 index 0000000000..bc4e5a4a53 --- /dev/null +++ b/tests/float/float_format_ftoe.py @@ -0,0 +1,4 @@ +# check a case where rounding was suppressed inappropriately when "f" was +# promoted to "e" for large numbers. +v = 8.888e32 +print("%.2f" % v) # '%.2f' format with e32 becomes '%.2e', expect 8.89e+32. diff --git a/tests/float/float_format_ftoe.py.exp b/tests/float/float_format_ftoe.py.exp new file mode 100644 index 0000000000..f8b1deb3ec --- /dev/null +++ b/tests/float/float_format_ftoe.py.exp @@ -0,0 +1 @@ +8.89e+32 diff --git a/tests/float/float_format_ints.py b/tests/float/float_format_ints.py new file mode 100644 index 0000000000..0bf4baf12d --- /dev/null +++ b/tests/float/float_format_ints.py @@ -0,0 +1,31 @@ +# Test that integers format to exact values. + +for b in [13, 123, 457, 23456]: + for r in range(1, 10): + e_fmt = "{:." + str(r) + "e}" + f_fmt = "{:." + str(r) + "f}" + g_fmt = "{:." + str(r) + "g}" + for e in range(0, 5): + f = b * (10**e) + title = str(b) + " x 10^" + str(e) + print(title, "with format", e_fmt, "gives", e_fmt.format(f)) + print(title, "with format", f_fmt, "gives", f_fmt.format(f)) + print(title, "with format", g_fmt, "gives", g_fmt.format(f)) + +# Check that powers of 10 (that fit in float32) format correctly. +for i in range(31): + # It works to 12 digits on all platforms *except* qemu-arm, where + # 10^11 comes out as 10000000820 or something. + print("{:.7g}".format(float("1e" + str(i)))) + +# 16777215 is 2^24 - 1, the largest integer that can be completely held +# in a float32. +print("{:f}".format(16777215)) +# 4294967040 = 16777215 * 128 is the largest integer that is exactly +# represented by a float32 and that will also fit within a (signed) int32. +# The upper bound of our integer-handling code is actually double this, +# but that constant might cause trouble on systems using 32 bit ints. +print("{:f}".format(2147483520)) +# Very large positive integers can be a test for precision and resolution. +# This is a weird way to represent 1e38 (largest power of 10 for float32). +print("{:.6e}".format(float("9" * 30 + "e8"))) diff --git a/tests/float/float_format_ints_doubleprec.py b/tests/float/float_format_ints_doubleprec.py new file mode 100644 index 0000000000..57899d6d65 --- /dev/null +++ b/tests/float/float_format_ints_doubleprec.py @@ -0,0 +1,15 @@ +# Test formatting of very large ints. +# Relies on double-precision floats. + +import array +import sys + +# Challenging way to express 1e200 and 1e100. +print("{:.12e}".format(float("9" * 400 + "e-200"))) +print("{:.12e}".format(float("9" * 400 + "e-300"))) + +# These correspond to the binary representation of 1e200 in float64s: +v1 = 0x54B249AD2594C37D # 1e100 +v2 = 0x6974E718D7D7625A # 1e200 +print("{:.12e}".format(array.array("d", v1.to_bytes(8, sys.byteorder))[0])) +print("{:.12e}".format(array.array("d", v2.to_bytes(8, sys.byteorder))[0])) diff --git a/tests/run-tests.py b/tests/run-tests.py index baab7bdd4a..2745ee1393 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -516,6 +516,7 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): if upy_float_precision < 64: skip_tests.add("float/float_divmod.py") # tested by float/float_divmod_relaxed.py instead skip_tests.add("float/float2int_doubleprec_intbig.py") + skip_tests.add("float/float_format_ints_doubleprec.py") skip_tests.add("float/float_parse_doubleprec.py") if not has_complex: diff --git a/tools/tinytest-codegen.py b/tools/tinytest-codegen.py index f1169a34d4..feda75f283 100755 --- a/tools/tinytest-codegen.py +++ b/tools/tinytest-codegen.py @@ -79,6 +79,7 @@ exclude_tests = ( "float/float_divmod.py", # requires double precision floating point to work "float/float2int_doubleprec_intbig.py", + "float/float_format_ints_doubleprec.py", "float/float_parse_doubleprec.py", # inline asm FP tests (require Cortex-M4) "inlineasm/asmfpaddsub.py", From 1230d86dca414baec926b2268156d241346efd66 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 27 Jul 2022 11:37:53 +1000 Subject: [PATCH 0215/1041] py/builtinimport: Remove duplicate static function argument. context==mc in all cases where this function was being called. Signed-off-by: Angus Gratton --- py/builtinimport.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/py/builtinimport.c b/py/builtinimport.c index cd9636ccdc..36cdac0767 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -159,7 +159,7 @@ STATIC void do_load_from_lexer(mp_module_context_t *context, mp_lexer_t *lex) { #endif #if (MICROPY_HAS_FILE_READER && MICROPY_PERSISTENT_CODE_LOAD) || MICROPY_MODULE_FROZEN_MPY -STATIC void do_execute_raw_code(mp_module_context_t *context, const mp_raw_code_t *rc, const mp_module_context_t *mc, const char *source_name) { +STATIC void do_execute_raw_code(const mp_module_context_t *context, const mp_raw_code_t *rc, const char *source_name) { (void)source_name; #if MICROPY_PY___FILE__ @@ -179,7 +179,7 @@ STATIC void do_execute_raw_code(mp_module_context_t *context, const mp_raw_code_ nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { - mp_obj_t module_fun = mp_make_function_from_raw_code(rc, mc, NULL); + mp_obj_t module_fun = mp_make_function_from_raw_code(rc, context, NULL); mp_call_function_0(module_fun); // finish nlr block, restore context @@ -224,7 +224,7 @@ STATIC void do_load(mp_module_context_t *module_obj, vstr_t *file) { if (frozen_type == MP_FROZEN_MPY) { const mp_frozen_module_t *frozen = modref; module_obj->constants = frozen->constants; - do_execute_raw_code(module_obj, frozen->rc, module_obj, file_str + frozen_path_prefix_len); + do_execute_raw_code(module_obj, frozen->rc, file_str + frozen_path_prefix_len); return; } #endif @@ -237,7 +237,7 @@ STATIC void do_load(mp_module_context_t *module_obj, vstr_t *file) { #if MICROPY_HAS_FILE_READER && MICROPY_PERSISTENT_CODE_LOAD if (file_str[file->len - 3] == 'm') { mp_compiled_module_t cm = mp_raw_code_load_file(file_str, module_obj); - do_execute_raw_code(module_obj, cm.rc, cm.context, file_str); + do_execute_raw_code(cm.context, cm.rc, file_str); return; } #endif From 45ab801c300d605db96229f6e0626ebe2801f24d Mon Sep 17 00:00:00 2001 From: Peter Harper Date: Tue, 26 Jul 2022 15:56:07 +0100 Subject: [PATCH 0216/1041] rp2/cyw43_configport: Add event hook into cyw43_delay_ms. Still see some USB issues apparently caused by delays loading wifi firmware. cyw43_delay_ms is used to wait in the driver, so we should call the event hook in there. Fixes #8963. --- ports/rp2/cyw43_configport.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/rp2/cyw43_configport.h b/ports/rp2/cyw43_configport.h index b6f5b3cad8..a5ce8a9e74 100644 --- a/ports/rp2/cyw43_configport.h +++ b/ports/rp2/cyw43_configport.h @@ -93,6 +93,7 @@ static inline void cyw43_delay_ms(uint32_t ms) { int32_t start = mp_hal_ticks_us(); while (mp_hal_ticks_us() - start < us) { __WFI(); + MICROPY_EVENT_POLL_HOOK_FAST; } } From 3c32ca6e77143704ac08d5694b7260781f127c3d Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 15 Apr 2022 12:04:01 -0500 Subject: [PATCH 0217/1041] unix/unix_mphal: Allow overriding hal time functions. This adds #ifdefs around each of the mp_hal_* time functions for the unix port. This allows variants to override individual functions as needed. Signed-off-by: David Lechner --- ports/unix/unix_mphal.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c index c224f78700..6f2def8903 100644 --- a/ports/unix/unix_mphal.c +++ b/ports/unix/unix_mphal.c @@ -199,6 +199,7 @@ void mp_hal_stdout_tx_str(const char *str) { mp_hal_stdout_tx_strn(str, strlen(str)); } +#ifndef mp_hal_ticks_ms mp_uint_t mp_hal_ticks_ms(void) { #if (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(_POSIX_MONOTONIC_CLOCK) struct timespec tv; @@ -210,7 +211,9 @@ mp_uint_t mp_hal_ticks_ms(void) { return tv.tv_sec * 1000 + tv.tv_usec / 1000; #endif } +#endif +#ifndef mp_hal_ticks_us mp_uint_t mp_hal_ticks_us(void) { #if (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(_POSIX_MONOTONIC_CLOCK) struct timespec tv; @@ -222,13 +225,17 @@ mp_uint_t mp_hal_ticks_us(void) { return tv.tv_sec * 1000000 + tv.tv_usec; #endif } +#endif +#ifndef mp_hal_time_ns uint64_t mp_hal_time_ns(void) { struct timeval tv; gettimeofday(&tv, NULL); return (uint64_t)tv.tv_sec * 1000000000ULL + (uint64_t)tv.tv_usec * 1000ULL; } +#endif +#ifndef mp_hal_delay_ms void mp_hal_delay_ms(mp_uint_t ms) { #ifdef MICROPY_EVENT_POLL_HOOK mp_uint_t start = mp_hal_ticks_ms(); @@ -242,6 +249,7 @@ void mp_hal_delay_ms(mp_uint_t ms) { usleep(ms * 1000); #endif } +#endif void mp_hal_get_random(size_t n, void *buf) { #ifdef _HAVE_GETRANDOM From fdfe4eca745dce5f20fb65a3c197006b9053999a Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 28 Jul 2022 17:56:27 +1000 Subject: [PATCH 0218/1041] ports: Always include debug information in the ELF. For bare metal ARM & xtensa targets, passing -g will make the ELF file larger but doesn't change the binary size. However, this means tools like gdb, addr2line, etc can extract source-level information from the ELF. Also standardise -ggdb to -g, these produce the exact same ELF file on arm-none-eabi-gcc and will use DWARF format for all these ports. --- ports/esp8266/Makefile | 2 +- ports/mimxrt/Makefile | 3 ++- ports/minimal/Makefile | 3 ++- ports/nrf/Makefile | 5 +++-- ports/renesas-ra/Makefile | 3 ++- ports/samd/Makefile | 3 ++- ports/stm32/Makefile | 3 ++- ports/teensy/Makefile | 3 ++- 8 files changed, 16 insertions(+), 9 deletions(-) diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index f70fbd2284..52ba18d7d8 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -68,8 +68,8 @@ LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) LIBS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc # Debugging/Optimization +CFLAGS += -g # always include debug info in the ELF ifeq ($(DEBUG), 1) -CFLAGS += -g COPT = -O0 else CFLAGS += -fdata-sections -ffunction-sections diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index de560bdb66..13b766eb3c 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -297,8 +297,9 @@ SRC_QSTR += \ # Compiler Flags # ============================================================================= +CFLAGS += -g # always include debug info in the ELF ifeq ($(DEBUG),1) -CFLAGS += -Og -ggdb +CFLAGS += -Og else CFLAGS += -Os -DNDEBUG endif diff --git a/ports/minimal/Makefile b/ports/minimal/Makefile index 4a17df6803..169132a1a2 100644 --- a/ports/minimal/Makefile +++ b/ports/minimal/Makefile @@ -34,8 +34,9 @@ endif CSUPEROPT = -Os # save some code space # Tune for Debugging or Optimization +CFLAGS += -g # always include debug info in the ELF ifeq ($(DEBUG), 1) -CFLAGS += -O0 -ggdb +CFLAGS += -O0 else CFLAGS += -Os -DNDEBUG CFLAGS += -fdata-sections -ffunction-sections diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 47653ae716..0586524ba6 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -124,7 +124,7 @@ endif CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES)) -CFLAGS += $(INC) -Wall -Werror -g -ansi -std=c11 -nostdlib $(COPT) $(NRF_DEFINES) $(CFLAGS_MOD) $(CFLAGS_EXTRA) +CFLAGS += $(INC) -Wall -Werror -ansi -std=c11 -nostdlib $(COPT) $(NRF_DEFINES) $(CFLAGS_MOD) $(CFLAGS_EXTRA) CFLAGS += -fno-strict-aliasing CFLAGS += -Iboards/$(BOARD) CFLAGS += -DNRF5_HAL_H='<$(MCU_VARIANT)_hal.h>' @@ -138,9 +138,10 @@ LDFLAGS += -Wl,'--defsym=_fs_size=$(FS_SIZE)' endif #Debugging/Optimization +CFLAGS += -g # always include debug info in the ELF ifeq ($(DEBUG), 1) #ASMFLAGS += -g -gtabs+ -CFLAGS += -O0 -ggdb +CFLAGS += -O0 LDFLAGS += -O0 else CFLAGS += -Os -DNDEBUG diff --git a/ports/renesas-ra/Makefile b/ports/renesas-ra/Makefile index d326c81e78..92d8be0692 100644 --- a/ports/renesas-ra/Makefile +++ b/ports/renesas-ra/Makefile @@ -148,8 +148,9 @@ CFLAGS += -fdata-sections -ffunction-sections LDFLAGS += --gc-sections # Debugging/Optimization +CFLAGS += -g # always include debug info in the ELF ifeq ($(DEBUG), 1) -CFLAGS += -g -DPENDSV_DEBUG +CFLAGS += -DPENDSV_DEBUG #COPT = -Og COPT = -Os # Disable text compression in debug builds diff --git a/ports/samd/Makefile b/ports/samd/Makefile index b3d6d8b228..7091365f49 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -57,8 +57,9 @@ LDFLAGS += $(LDFLAGS_MOD) LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) # Tune for Debugging or Optimization +CFLAGS += -g # always include debug info in the ELF ifeq ($(DEBUG),1) -CFLAGS += -O0 -ggdb +CFLAGS += -O0 else CFLAGS += -Os -DNDEBUG LDFLAGS += --gc-sections diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 652dff19fe..657524798c 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -114,8 +114,9 @@ $(BUILD)/stm32_it.o $(BUILD)/pendsv.o: CFLAGS += -fno-lto endif # Debugging/Optimization +CFLAGS += -g # always include debug info in the ELF ifeq ($(DEBUG), 1) -CFLAGS += -g -DPENDSV_DEBUG +CFLAGS += -DPENDSV_DEBUG COPT ?= -Og # Disable text compression in debug builds MICROPY_ROM_TEXT_COMPRESSION = 0 diff --git a/ports/teensy/Makefile b/ports/teensy/Makefile index 745f530d7a..d7161fcbbc 100644 --- a/ports/teensy/Makefile +++ b/ports/teensy/Makefile @@ -105,8 +105,9 @@ LIBS += -L $(dir $(LIBC_FILE_NAME)) -lc LIBS += -L $(dir $(LIBGCC_FILE_NAME)) -lgcc #Debugging/Optimization +CFLAGS += -g # always include debug info in the ELF ifdef DEBUG -CFLAGS += -Og -ggdb +CFLAGS += -Og else CFLAGS += -Os #-DNDEBUG endif From fe5598452dd82ab24cf19221777b901a6decccdd Mon Sep 17 00:00:00 2001 From: Peter Hinch Date: Wed, 27 Jul 2022 18:19:42 +0100 Subject: [PATCH 0219/1041] docs/library/time: Provide more info about which epoch is used. Some embedded targets use 1970 epoch. --- docs/library/time.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/library/time.rst b/docs/library/time.rst index 6ca172f221..3ab5caf248 100644 --- a/docs/library/time.rst +++ b/docs/library/time.rst @@ -10,8 +10,8 @@ The ``time`` module provides functions for getting the current time and date, measuring time intervals, and for delays. **Time Epoch**: Unix port uses standard for POSIX systems epoch of -1970-01-01 00:00:00 UTC. However, embedded ports use epoch of -2000-01-01 00:00:00 UTC. +1970-01-01 00:00:00 UTC. However, some embedded ports use epoch of +2000-01-01 00:00:00 UTC. Epoch year may be determined with ``gmtime(0)[0]``. **Maintaining actual calendar date/time**: This requires a Real Time Clock (RTC). On systems with underlying OS (including some From e168d47424eefc15ab74c3c15e363d02deb46fba Mon Sep 17 00:00:00 2001 From: chrismas9 Date: Sun, 26 Jun 2022 22:59:09 +1000 Subject: [PATCH 0220/1041] docs/library/pyb.Pin: Fix out-of-context paragraphs, and AF_PP typo. Remove out of context callback paragraph, it was part of the wipy docs. And move the paragraph about PULL_UP/PULL_DOWN resistor values to within the init() method docs. Also fix pull-pull -> push-pull. Signed-off-by: Chris Mason --- docs/library/pyb.Pin.rst | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/docs/library/pyb.Pin.rst b/docs/library/pyb.Pin.rst index d13cb9741c..292758c11c 100644 --- a/docs/library/pyb.Pin.rst +++ b/docs/library/pyb.Pin.rst @@ -58,16 +58,6 @@ an ordinal pin number: You can set ``pyb.Pin.debug(True)`` to get some debug information about how a particular object gets mapped to a pin. -When a pin has the ``Pin.PULL_UP`` or ``Pin.PULL_DOWN`` pull-mode enabled, -that pin has an effective 40k Ohm resistor pulling it to 3V3 or GND -respectively (except pin Y5 which has 11k Ohm resistors). - -Now every time a falling edge is seen on the gpio pin, the callback will be -executed. Caution: mechanical push buttons have "bounce" and pushing or -releasing a switch will often generate multiple edges. -See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed -explanation, along with various techniques for debouncing. - All pin objects go through the pin mapper to come up with one of the gpio pins. @@ -107,7 +97,7 @@ Methods - ``Pin.IN`` - configure the pin for input; - ``Pin.OUT_PP`` - configure the pin for output, with push-pull control; - ``Pin.OUT_OD`` - configure the pin for output, with open-drain control; - - ``Pin.AF_PP`` - configure the pin for alternate function, pull-pull; + - ``Pin.AF_PP`` - configure the pin for alternate function, push-pull; - ``Pin.AF_OD`` - configure the pin for alternate function, open-drain; - ``Pin.ANALOG`` - configure the pin for analog. @@ -117,6 +107,10 @@ Methods - ``Pin.PULL_UP`` - enable the pull-up resistor; - ``Pin.PULL_DOWN`` - enable the pull-down resistor. + When a pin has the ``Pin.PULL_UP`` or ``Pin.PULL_DOWN`` pull-mode enabled, + that pin has an effective 40k Ohm resistor pulling it to 3V3 or GND + respectively (except pin Y5 which has 11k Ohm resistors). + - *value* if not None will set the port output value before enabling the pin. - *alt* can be used when mode is ``Pin.AF_PP`` or ``Pin.AF_OD`` to set the From 33ea400ce849777617bf1e8f44b10928530b64b9 Mon Sep 17 00:00:00 2001 From: chrismas9 Date: Sun, 26 Jun 2022 23:30:37 +1000 Subject: [PATCH 0221/1041] docs/library/pyb.Pin: Add Pin.ALT constant. Some Pin alternate functions are inputs, for example, timer capture and break inputs. In Pyb.Pin the only way to set alt mode is with Pin.AF_PP or Pin.AF_OD. It is not intuitive to use an output mode to configure an input. Pin.ALT is used in the machine.Pin class and works in pyb.Pin. The examples are changed to use Pin.ALT because TIM2_CH3 can be a capture input or pulse output. Signed-off-by: Chris Mason --- docs/library/pyb.Pin.rst | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/library/pyb.Pin.rst b/docs/library/pyb.Pin.rst index 292758c11c..b93924508b 100644 --- a/docs/library/pyb.Pin.rst +++ b/docs/library/pyb.Pin.rst @@ -97,6 +97,7 @@ Methods - ``Pin.IN`` - configure the pin for input; - ``Pin.OUT_PP`` - configure the pin for output, with push-pull control; - ``Pin.OUT_OD`` - configure the pin for output, with open-drain control; + - ``Pin.ALT`` - configure the pin for alternate function, input or output; - ``Pin.AF_PP`` - configure the pin for alternate function, push-pull; - ``Pin.AF_OD`` - configure the pin for alternate function, open-drain; - ``Pin.ANALOG`` - configure the pin for analog. @@ -113,8 +114,8 @@ Methods - *value* if not None will set the port output value before enabling the pin. - - *alt* can be used when mode is ``Pin.AF_PP`` or ``Pin.AF_OD`` to set the - index or name of one of the alternate functions associated with a pin. + - *alt* can be used when mode is ``Pin.ALT`` , ``Pin.AF_PP`` or ``Pin.AF_OD`` to + set the index or name of one of the alternate functions associated with a pin. This arg was previously called *af* which can still be used if needed. Returns: ``None``. @@ -177,6 +178,10 @@ Methods Constants --------- +.. data:: Pin.ALT + + initialise the pin to alternate-function mode for input or output + .. data:: Pin.AF_OD initialise the pin to alternate-function mode with an open-drain drive @@ -237,11 +242,11 @@ control is desired. To configure X3 to expose TIM2_CH3, you could use:: - pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, alt=pyb.Pin.AF1_TIM2) + pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.ALT, alt=pyb.Pin.AF1_TIM2) or:: - pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, alt=1) + pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.ALT, alt=1) Methods ------- From c038ea0cc68bff18ce9ac338a283d2dd4cf29f1e Mon Sep 17 00:00:00 2001 From: chrismas9 Date: Sun, 26 Jun 2022 23:54:37 +1000 Subject: [PATCH 0222/1041] docs/library/pyb.Timer: Document how to use BKIN pin with example. Document how to connect the Timer block BRK_IN to a physical Pin alternate function. Add an example of PWM Motor drive using complementary outputs with dead time and break input to kill the PWM and generate a callback. Signed-off-by: Chris Mason --- docs/library/pyb.Timer.rst | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/library/pyb.Timer.rst b/docs/library/pyb.Timer.rst index 53213666ba..1749efce2d 100644 --- a/docs/library/pyb.Timer.rst +++ b/docs/library/pyb.Timer.rst @@ -111,7 +111,9 @@ Methods the PWM when the ``BRK_IN`` input is asserted. The value of this argument determines if break is enabled and what the polarity is, and can be one of ``Timer.BRK_OFF``, ``Timer.BRK_LOW`` or - ``Timer.BRK_HIGH``. + ``Timer.BRK_HIGH``. To select the ``BRK_IN`` pin construct a Pin object with + ``mode=Pin.ALT, alt=Pin.AFn_TIMx``. The pin's GPIO input features are + available in alt mode - ``pull=`` , ``value()`` and ``irq()``. You must either specify freq or both of period and prescaler. @@ -204,6 +206,17 @@ Methods ch2 = timer.channel(2, pyb.Timer.PWM, pin=pyb.Pin.board.X2, pulse_width=8000) ch3 = timer.channel(3, pyb.Timer.PWM, pin=pyb.Pin.board.X3, pulse_width=16000) + PWM Motor Example with complementary outputs, dead time, break input and break callback:: + + from pyb import Timer + from machine import Pin # machine.Pin supports alt mode and irq on the same pin. + pin_t8_1 = Pin(Pin.board.Y1, mode=Pin.ALT, af=Pin.AF3_TIM8) # Pin PC6, TIM8_CH1 + pin_t8_1n = Pin(Pin.board.X8, mode=Pin.ALT, af=Pin.AF3_TIM8) # Pin PA7, TIM8_CH1N + pin_bkin = Pin(Pin.board.X7, mode=Pin.ALT, af=Pin.AF3_TIM8) # Pin PA6, TIM8_BKIN + pin_bkin.irq(handler=break_callabck, trigger=Pin.IRQ_FALLING) + timer = pyb.Timer(8, freq=1000, deadtime=1008, brk=Timer.BRK_LOW) + ch1 = timer.channel(1, pyb.Timer.PWM, pulse_width_percent=30) + .. method:: Timer.counter([value]) Get or set the timer counter. From 963e599ec0d253534eb835ade7020e8ac3d7919b Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 29 Jul 2022 12:06:08 +1000 Subject: [PATCH 0223/1041] tests/cpydiff: Fix formatting of code snippet to use double quotes. Signed-off-by: Damien George --- tests/cpydiff/types_float_implicit_conversion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cpydiff/types_float_implicit_conversion.py b/tests/cpydiff/types_float_implicit_conversion.py index 8d39a7cd41..3726839fac 100644 --- a/tests/cpydiff/types_float_implicit_conversion.py +++ b/tests/cpydiff/types_float_implicit_conversion.py @@ -2,7 +2,7 @@ categories: Types,float description: uPy allows implicit conversion of objects in maths operations while CPython does not. cause: Unknown -workaround: Objects should be wrapped in `float(obj)` for compatibility with CPython. +workaround: Objects should be wrapped in ``float(obj)`` for compatibility with CPython. """ From 9a1b7d8448346b353e3aa7ae11ff2b441b6d5313 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 8 Jul 2022 14:32:12 +1000 Subject: [PATCH 0224/1041] lib/micropython-lib: Add micropython-lib as a submodule. Several boards now depend on libraries from micropython-lib. Rather than expecting micropython-lib to be available as a sibling of the micropython repo, instead make it a submodule. Signed-off-by: Jim Mussared --- .gitmodules | 3 +++ lib/micropython-lib | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/micropython-lib diff --git a/.gitmodules b/.gitmodules index 3d1e2fea74..3c47b5959a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -53,3 +53,6 @@ [submodule "lib/cyw43-driver"] path = lib/cyw43-driver url = https://github.com/georgerobotics/cyw43-driver.git +[submodule "lib/micropython-lib"] + path = lib/micropython-lib + url = https://github.com/micropython/micropython-lib.git diff --git a/lib/micropython-lib b/lib/micropython-lib new file mode 160000 index 0000000000..70e422dc2e --- /dev/null +++ b/lib/micropython-lib @@ -0,0 +1 @@ +Subproject commit 70e422dc2e885bbaafe6eb7e3d81118e17d4b555 From be83c08f463c75bb52619ea4f35b5256fc479158 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 8 Jul 2022 14:59:33 +1000 Subject: [PATCH 0225/1041] ports: Always append to GIT_SUBMODULES. Avoids overwriting submodules required by base makefiles. Signed-off-by: Jim Mussared --- ports/esp32/Makefile | 2 +- ports/esp8266/Makefile | 2 +- ports/mimxrt/Makefile | 2 +- ports/nrf/Makefile | 2 +- ports/samd/Makefile | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index c8ca9262c8..88f946fa98 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -14,7 +14,7 @@ BAUD ?= 460800 PYTHON ?= python3 -GIT_SUBMODULES = lib/berkeley-db-1.xx +GIT_SUBMODULES += lib/berkeley-db-1.xx .PHONY: all clean deploy erase submodules FORCE diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index 52ba18d7d8..c027f690fb 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -32,7 +32,7 @@ FROZEN_MANIFEST ?= boards/manifest.py include $(TOP)/py/py.mk include $(TOP)/extmod/extmod.mk -GIT_SUBMODULES = lib/axtls lib/berkeley-db-1.xx +GIT_SUBMODULES += lib/axtls lib/berkeley-db-1.xx FWBIN = $(BUILD)/firmware-combined.bin PORT ?= /dev/ttyACM0 diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index 13b766eb3c..6312ecdd8f 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -7,7 +7,7 @@ BOARD_DIR ?= boards/$(BOARD) BUILD ?= build-$(BOARD) PORT ?= /dev/ttyACM0 CROSS_COMPILE ?= arm-none-eabi- -GIT_SUBMODULES = lib/tinyusb lib/nxp_driver lib/lwip lib/mbedtls +GIT_SUBMODULES += lib/tinyusb lib/nxp_driver lib/lwip lib/mbedtls # MicroPython feature configurations FROZEN_MANIFEST ?= boards/manifest.py diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 0586524ba6..23be4430f3 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -58,7 +58,7 @@ FROZEN_MANIFEST ?= modules/manifest.py include ../../py/py.mk include ../../extmod/extmod.mk -GIT_SUBMODULES = lib/nrfx lib/tinyusb +GIT_SUBMODULES += lib/nrfx lib/tinyusb MICROPY_VFS_FAT ?= 0 diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 7091365f49..aed8637abc 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -24,7 +24,7 @@ FROZEN_MANIFEST ?= boards/manifest.py include $(TOP)/py/py.mk include $(TOP)/extmod/extmod.mk -GIT_SUBMODULES = lib/asf4 lib/tinyusb +GIT_SUBMODULES += lib/asf4 lib/tinyusb INC += -I. INC += -I$(TOP) From 9a7ac41be61a4d80234ac91c97ee5f099af29626 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 8 Jul 2022 15:26:06 +1000 Subject: [PATCH 0226/1041] rp2/Makefile: Always use cmake to discover submodules. Used to be special-cased for Pico, but now everything depends on micropython-lib if it's using a frozen manifest. Signed-off-by: Jim Mussared --- ports/rp2/CMakeLists.txt | 11 +++++++++-- ports/rp2/Makefile | 15 ++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index f9a9efe62a..f5bd61c44e 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -54,6 +54,10 @@ if (MICROPY_PY_NETWORK_CYW43) set(PICO_CYW43_DRIVER_PATH ${MICROPY_DIR}/lib/cyw43-driver) endif() +# Necessary submodules for all boards. +string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/mbedtls) +string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/tinyusb) + # Include component cmake fragments include(${MICROPY_DIR}/py/py.cmake) include(${MICROPY_DIR}/extmod/extmod.cmake) @@ -278,6 +282,11 @@ if (MICROPY_PY_NETWORK_NINAW10) endif() if (MICROPY_PY_NETWORK_WIZNET5K) + string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/wiznet5k) + if((NOT (${ECHO_SUBMODULES})) AND NOT EXISTS ${MICROPY_DIR}/lib/wiznet5k/README.md) + message(FATAL_ERROR " wiznet5k not initialized.\n Run 'make BOARD=${MICROPY_BOARD} submodules'") + endif() + target_compile_definitions(${MICROPY_TARGET} PRIVATE MICROPY_PY_NETWORK_WIZNET5K=1 WIZCHIP_PREFIXED_EXPORTS=1 @@ -312,8 +321,6 @@ if (MICROPY_PY_NETWORK_WIZNET5K) list(APPEND MICROPY_SOURCE_EXTMOD ${MICROPY_DIR}/extmod/network_wiznet5k.c ) - - string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/wiznet5k) endif() # Add qstr sources for extmod and usermod, in case they are modified by components above. diff --git a/ports/rp2/Makefile b/ports/rp2/Makefile index 6f8c621c2a..6d2fc00964 100644 --- a/ports/rp2/Makefile +++ b/ports/rp2/Makefile @@ -29,17 +29,10 @@ all: clean: $(RM) -rf $(BUILD) -GIT_SUBMODULES += lib/mbedtls lib/tinyusb - +# First ensure that pico-sdk is initialised, then use cmake to pick everything +# else (including board-specific dependencies). submodules: - # lib/pico-sdk is required for the cmake build to function (as used for boards other than PICO below) $(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="lib/pico-sdk" submodules -ifeq ($(BOARD),PICO) - # Run the standard submodules target with minimum required submodules above - $(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="$(GIT_SUBMODULES)" submodules -else - # Run submodules task through cmake interface to pick up any board specific dependencies. - GIT_SUBMODULES=$$(cmake -B $(BUILD)/submodules -DECHO_SUBMODULES=1 -DGIT_SUBMODULES="$(GIT_SUBMODULES)" ${CMAKE_ARGS} -S . 2>&1 | \ - grep 'GIT_SUBMODULES=' | cut -d= -f2); \ + GIT_SUBMODULES=$$(cmake -B $(BUILD)/submodules -DECHO_SUBMODULES=1 ${CMAKE_ARGS} -S . 2>&1 | \ + grep '^GIT_SUBMODULES=' | cut -d= -f2); \ $(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="$${GIT_SUBMODULES}" submodules -endif From 19f5da9e1bf23821095da2252c2f3c2381f2fe21 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 8 Jul 2022 15:26:52 +1000 Subject: [PATCH 0227/1041] esp32/Makefile: Force micropython-lib as a required submodule. Also use mkrules.mk's submodule target rather than duplicating the call to `submodule sync`. Until we can find a way to use idf.py/cmake to discover submodules we have no way to discover optional or board-specific submodules so need to err on the side of including everything. Signed-off-by: Jim Mussared --- ports/esp32/Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 88f946fa98..b7d804d073 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -14,7 +14,11 @@ BAUD ?= 460800 PYTHON ?= python3 -GIT_SUBMODULES += lib/berkeley-db-1.xx +# Would be good to use cmake to discover submodules (see how rp2/Makefile does +# it), but on ESP32 the same trick doesn't work because "idf.py build" fails +# on berkeley-db dependency before printing out the submodule list. +# For now just force the submodule dependencies here. +GIT_SUBMODULES += lib/berkeley-db-1.xx lib/micropython-lib .PHONY: all clean deploy erase submodules FORCE @@ -52,4 +56,4 @@ erase: idf.py $(IDFPY_FLAGS) -p $(PORT) -b $(BAUD) erase_flash submodules: - git submodule update --init $(addprefix ../../,$(GIT_SUBMODULES)) + $(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="$(GIT_SUBMODULES)" submodules From 58bed5ec14a2575fd53ca1822be80860f7e3023a Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 8 Jul 2022 15:27:23 +1000 Subject: [PATCH 0228/1041] tools/ci.sh: Initialise submodules for more ports. Signed-off-by: Jim Mussared --- tools/ci.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/ci.sh b/tools/ci.sh index 6c3914b144..7e2479e43d 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -245,8 +245,10 @@ function ci_qemu_arm_setup { function ci_qemu_arm_build { make ${MAKEOPTS} -C mpy-cross + make ${MAKEOPTS} -C ports/qemu-arm submodules make ${MAKEOPTS} -C ports/qemu-arm CFLAGS_EXTRA=-DMP_ENDIANNESS_BIG=1 make ${MAKEOPTS} -C ports/qemu-arm clean + make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test submodules make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test test make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test clean make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test BOARD=sabrelite test @@ -354,6 +356,7 @@ function ci_teensy_setup { } function ci_teensy_build { + make ${MAKEOPTS} -C ports/teensy submodules make ${MAKEOPTS} -C ports/teensy } @@ -577,6 +580,7 @@ function ci_unix_float_clang_run_tests { function ci_unix_settrace_build { make ${MAKEOPTS} -C mpy-cross + make ${MAKEOPTS} -C ports/unix submodules make ${MAKEOPTS} -C ports/unix "${CI_UNIX_OPTS_SYS_SETTRACE[@]}" } @@ -586,6 +590,7 @@ function ci_unix_settrace_run_tests { function ci_unix_settrace_stackless_build { make ${MAKEOPTS} -C mpy-cross + make ${MAKEOPTS} -C ports/unix submodules make ${MAKEOPTS} -C ports/unix "${CI_UNIX_OPTS_SYS_SETTRACE_STACKLESS[@]}" } @@ -661,6 +666,7 @@ function ci_windows_setup { function ci_windows_build { make ${MAKEOPTS} -C mpy-cross + make ${MAKEOPTS} -C ports/windows submodules make ${MAKEOPTS} -C ports/windows CROSS_COMPILE=i686-w64-mingw32- } From 579f330508e4ba46f4a71193582c36bdf7aa56bd Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 8 Jul 2022 15:00:33 +1000 Subject: [PATCH 0229/1041] py/mkenv.mk: Use micropython-lib from submodule by default. Also adds micropython-lib to 'make submodules' when using a frozen manifest (for make and cmake). Signed-off-by: Jim Mussared --- ports/windows/.appveyor.yml | 4 ++++ ports/windows/msvc/genhdr.targets | 2 +- py/mkenv.mk | 3 ++- py/mkrules.cmake | 7 ++++++- py/mkrules.mk | 7 +++++++ 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/ports/windows/.appveyor.yml b/ports/windows/.appveyor.yml index d7192236df..110511fe22 100644 --- a/ports/windows/.appveyor.yml +++ b/ports/windows/.appveyor.yml @@ -74,6 +74,10 @@ after_test: throw "$env:MSYSTEM mpy_cross build exited with code $LASTEXITCODE" } cd (Join-Path $env:APPVEYOR_BUILD_FOLDER 'ports/windows') + C:\msys64\usr\bin\bash.exe -l -c "make -B VARIANT=$($env:PyVariant) submodules" + if ($LASTEXITCODE -ne 0) { + throw "$env:MSYSTEM build exited with code $LASTEXITCODE" + } C:\msys64\usr\bin\bash.exe -l -c "make -B -j4 V=1 MICROPY_MPYCROSS=../../mpy-cross/mpy-cross.exe VARIANT=$($env:PyVariant)" if ($LASTEXITCODE -ne 0) { throw "$env:MSYSTEM build exited with code $LASTEXITCODE" diff --git a/ports/windows/msvc/genhdr.targets b/ports/windows/msvc/genhdr.targets index aa796088ef..308a6a1f5f 100644 --- a/ports/windows/msvc/genhdr.targets +++ b/ports/windows/msvc/genhdr.targets @@ -170,7 +170,7 @@ using(var outFile = System.IO.File.CreateText(OutputFile)) { MICROPY_MODULE_FROZEN_MPY=1;MICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool;%(PreprocessorDefinitions) - + diff --git a/py/mkenv.mk b/py/mkenv.mk index 2b247974b6..cc04a8c0b3 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -57,7 +57,8 @@ MAKE_MANIFEST = $(PYTHON) $(TOP)/tools/makemanifest.py MAKE_FROZEN = $(PYTHON) $(TOP)/tools/make-frozen.py MPY_TOOL = $(PYTHON) $(TOP)/tools/mpy-tool.py -MPY_LIB_DIR = $(TOP)/../micropython-lib +MPY_LIB_SUBMODULE_DIR = $(TOP)/lib/micropython-lib +MPY_LIB_DIR = $(MPY_LIB_SUBMODULE_DIR) ifeq ($(MICROPY_MPYCROSS),) MICROPY_MPYCROSS = $(TOP)/mpy-cross/mpy-cross diff --git a/py/mkrules.cmake b/py/mkrules.cmake index d7be0f934b..2f168ede6f 100644 --- a/py/mkrules.cmake +++ b/py/mkrules.cmake @@ -180,7 +180,12 @@ if(MICROPY_FROZEN_MANIFEST) # Note: target_compile_definitions already added earlier. if(NOT MICROPY_LIB_DIR) - set(MICROPY_LIB_DIR ${MICROPY_DIR}/../micropython-lib) + string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/micropython-lib) + set(MICROPY_LIB_DIR ${MICROPY_DIR}/lib/micropython-lib) + endif() + + if(NOT (${ECHO_SUBMODULES}) AND NOT EXISTS ${MICROPY_LIB_DIR}/README.md) + message(FATAL_ERROR " micropython-lib not initialized.\n Run 'make BOARD=${MICROPY_BOARD} submodules'") endif() # If MICROPY_MPYCROSS is not explicitly defined in the environment (which diff --git a/py/mkrules.mk b/py/mkrules.mk index a7c437386f..41ec4b0641 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -174,8 +174,15 @@ $(error Support for FROZEN_MPY_DIR was removed. Please use manifest.py instead, endif ifneq ($(FROZEN_MANIFEST),) +# If we're using the default submodule path for micropython-lib, then make +# sure it's included in "make submodules". +ifeq ($(MPY_LIB_DIR),$(MPY_LIB_SUBMODULE_DIR)) +GIT_SUBMODULES += lib/micropython-lib +endif + # to build frozen_content.c from a manifest $(BUILD)/frozen_content.c: FORCE $(BUILD)/genhdr/qstrdefs.generated.h $(BUILD)/genhdr/root_pointers.h | $(MICROPY_MPYCROSS_DEPENDENCY) + $(Q)test -e "$(MPY_LIB_DIR)/README.md" || (echo "Error: micropython-lib not initialized. Run 'make submodules'"; false) $(Q)$(MAKE_MANIFEST) -o $@ -v "MPY_DIR=$(TOP)" -v "MPY_LIB_DIR=$(MPY_LIB_DIR)" -v "PORT_DIR=$(shell pwd)" -v "BOARD_DIR=$(BOARD_DIR)" -b "$(BUILD)" $(if $(MPY_CROSS_FLAGS),-f"$(MPY_CROSS_FLAGS)",) --mpy-tool-flags="$(MPY_TOOL_FLAGS)" $(FROZEN_MANIFEST) endif From 6152bbe3dd82fb7dc1b063e24c19a42af03bf321 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 28 Jul 2022 19:25:59 -0500 Subject: [PATCH 0230/1041] stm32/boards/LEGO_HUB_NO6: Fix typo in README. This fixes a typo in the build directory path. Signed-off-by: David Lechner --- ports/stm32/boards/LEGO_HUB_NO6/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/LEGO_HUB_NO6/README.md b/ports/stm32/boards/LEGO_HUB_NO6/README.md index 376d0f2b0e..cc67b6a4bb 100644 --- a/ports/stm32/boards/LEGO_HUB_NO6/README.md +++ b/ports/stm32/boards/LEGO_HUB_NO6/README.md @@ -112,8 +112,8 @@ To use this feature, build the firmware (see above for details) then gzip it and copy the resulting file to the Hub (eg using mpremote): $ make BOARD=LEGO_HUB_NO6 - $ gzip boards/LEGO_HUB_NO6/firmware.dfu - $ mpremote cp boards/LEGO_HUB_NO6/firmware.dfu.gz : + $ gzip build-LEGO_HUB_NO6/firmware.dfu + $ mpremote cp build-LEGO_HUB_NO6/firmware.dfu.gz : Then get a REPL on the Hub and execute: From 7cc6df3303f467e218a6ac4f12924eac0ed15045 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 29 Jul 2022 13:58:33 -0500 Subject: [PATCH 0231/1041] stm32/boards/LEGO_HUB_NO6: Use named pins. This changes all uses of pins to use the alias names of the pins. This makes the code easier to understand and will also allow sharing more code with LEGO_HUB_NO7. Signed-off-by: David Lechner --- ports/stm32/boards/LEGO_HUB_NO6/appupdate.py | 9 +++- ports/stm32/boards/LEGO_HUB_NO6/board_init.c | 2 +- ports/stm32/boards/LEGO_HUB_NO6/hub_display.c | 30 ++++++------ .../stm32/boards/LEGO_HUB_NO6/mpconfigboard.h | 49 +++++++++---------- ports/stm32/boards/LEGO_HUB_NO6/pins.csv | 8 +-- 5 files changed, 51 insertions(+), 47 deletions(-) diff --git a/ports/stm32/boards/LEGO_HUB_NO6/appupdate.py b/ports/stm32/boards/LEGO_HUB_NO6/appupdate.py index 65954454a5..0927f16111 100644 --- a/ports/stm32/boards/LEGO_HUB_NO6/appupdate.py +++ b/ports/stm32/boards/LEGO_HUB_NO6/appupdate.py @@ -23,8 +23,13 @@ def update_app(filename): key = struct.pack("CCR2 = 2; tim->EGR = 1; // UG - mp_hal_pin_config(pin_B15, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 9); + mp_hal_pin_config(pyb_pin_TLC_GS_CLK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 9); } static void hub_display_spi_init(void) { @@ -93,9 +93,9 @@ static void hub_display_spi_init(void) { spi->CR1 = SPI_CR1_SSM | SPI_CR1_SSI | 0 << SPI_CR1_BR_Pos | SPI_CR1_MSTR; spi->CR1 |= SPI_CR1_SPE; - mp_hal_pin_config(pin_A5, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 5); - mp_hal_pin_config(pin_A6, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 5); - mp_hal_pin_config(pin_A7, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 5); + mp_hal_pin_config(pyb_pin_TLC_SCLK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 5); + mp_hal_pin_config(pyb_pin_TLC_SOUT, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 5); + mp_hal_pin_config(pyb_pin_TLC_SIN, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 5); } static void hub_display_spi_write(uint8_t value) { @@ -123,9 +123,9 @@ static void hub_display_latch_ctrl(uint8_t dc, uint32_t mc, uint32_t bc, uint8_t for (int i = 0; i < 42; ++i) { hub_display_spi_write(dc); } - mp_hal_pin_high(pin_A15); + mp_hal_pin_high(pyb_pin_TLC_LAT); mp_hal_delay_us(1); - mp_hal_pin_low(pin_A15); + mp_hal_pin_low(pyb_pin_TLC_LAT); } void hub_display_set(uint8_t led, uint16_t value) { @@ -142,17 +142,17 @@ void hub_display_update(void) { for (int i = 0; i < 96; ++i) { hub_display_spi_write(hub_display_gs_state[95 - i]); } - mp_hal_pin_high(pin_A15); + mp_hal_pin_high(pyb_pin_TLC_LAT); mp_hal_delay_us(1); - mp_hal_pin_low(pin_A15); + mp_hal_pin_low(pyb_pin_TLC_LAT); } void hub_display_on(void) { if (hub_display_init) { return; } - mp_hal_pin_output(pin_A15); - mp_hal_pin_low(pin_A15); + mp_hal_pin_output(pyb_pin_TLC_LAT); + mp_hal_pin_low(pyb_pin_TLC_LAT); hub_display_spi_init(); for (int i = 0; i < 2; ++i) { hub_display_latch_ctrl(0xff, 0, 0x1fffff, 0x11); @@ -171,10 +171,10 @@ void hub_display_off(void) { __HAL_RCC_SPI1_CLK_DISABLE(); __HAL_RCC_SPI1_FORCE_RESET(); __HAL_RCC_SPI1_RELEASE_RESET(); - mp_hal_pin_config(pin_A5, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); - mp_hal_pin_config(pin_A6, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); - mp_hal_pin_config(pin_A7, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); - mp_hal_pin_config(pin_A15, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); - mp_hal_pin_config(pin_B15, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); + mp_hal_pin_config(pyb_pin_TLC_SCLK, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); + mp_hal_pin_config(pyb_pin_TLC_SOUT, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); + mp_hal_pin_config(pyb_pin_TLC_SIN, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); + mp_hal_pin_config(pyb_pin_TLC_LAT, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); + mp_hal_pin_config(pyb_pin_TLC_GS_CLK, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); hub_display_init = false; } diff --git a/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h b/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h index cab46fa02d..7f0b1fbe45 100644 --- a/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h +++ b/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h @@ -34,41 +34,40 @@ // UART buses // Bluetooth HCI -#define MICROPY_HW_UART2_CTS (pin_D3) -#define MICROPY_HW_UART2_RTS (pin_D4) -#define MICROPY_HW_UART2_TX (pin_D5) -#define MICROPY_HW_UART2_RX (pin_D6) +#define MICROPY_HW_UART2_CTS (pyb_pin_BT_CTS) +#define MICROPY_HW_UART2_RTS (pyb_pin_BT_RTS) +#define MICROPY_HW_UART2_TX (pyb_pin_BT_TX) +#define MICROPY_HW_UART2_RX (pyb_pin_BT_RX) // Port B -#define MICROPY_HW_UART4_TX (pin_D1) -#define MICROPY_HW_UART4_RX (pin_D0) +#define MICROPY_HW_UART4_TX (pyb_pin_PORTB_TX) +#define MICROPY_HW_UART4_RX (pyb_pin_PORTB_RX) // Port D -#define MICROPY_HW_UART5_TX (pin_C12) -#define MICROPY_HW_UART5_RX (pin_D2) +#define MICROPY_HW_UART5_TX (pyb_pin_PORTD_TX) +#define MICROPY_HW_UART5_RX (pyb_pin_PORTD_RX) // Port A -#define MICROPY_HW_UART7_TX (pin_E8) -#define MICROPY_HW_UART7_RX (pin_E7) +#define MICROPY_HW_UART7_TX (pyb_pin_PORTA_TX) +#define MICROPY_HW_UART7_RX (pyb_pin_PORTA_RX) // Port C -#define MICROPY_HW_UART8_TX (pin_E1) -#define MICROPY_HW_UART8_RX (pin_E0) +#define MICROPY_HW_UART8_TX (pyb_pin_PORTC_TX) +#define MICROPY_HW_UART8_RX (pyb_pin_PORTC_RX) // Port F -#define MICROPY_HW_UART9_TX (pin_D15) -#define MICROPY_HW_UART9_RX (pin_D14) +#define MICROPY_HW_UART9_TX (pyb_pin_PORTF_TX) +#define MICROPY_HW_UART9_RX (pyb_pin_PORTF_RX) // Port E -#define MICROPY_HW_UART10_TX (pin_E3) -#define MICROPY_HW_UART10_RX (pin_E2) +#define MICROPY_HW_UART10_TX (pyb_pin_PORTE_TX) +#define MICROPY_HW_UART10_RX (pyb_pin_PORTE_RX) // SPI buses -#define MICROPY_HW_SPI1_NSS (pin_A4) // shared with DAC -#define MICROPY_HW_SPI1_SCK (pin_A5) // shared with DAC -#define MICROPY_HW_SPI1_MISO (pin_A6) -#define MICROPY_HW_SPI1_MOSI (pin_A7) -#define MICROPY_HW_SPI2_NSS (pin_B12) -#define MICROPY_HW_SPI2_SCK (pin_B13) -#define MICROPY_HW_SPI2_MISO (pin_C2) -#define MICROPY_HW_SPI2_MOSI (pin_C3) +#define MICROPY_HW_SPI1_SCK (pyb_pin_TLC_SCLK) +#define MICROPY_HW_SPI1_MISO (pyb_pin_TLC_SOUT) +#define MICROPY_HW_SPI1_MOSI (pyb_pin_TLC_SIN) +#define MICROPY_HW_SPI2_NSS (pyb_pin_FLASH_NSS) +#define MICROPY_HW_SPI2_SCK (pyb_pin_FLASH_SCK) +#define MICROPY_HW_SPI2_MISO (pyb_pin_FLASH_MISO) +#define MICROPY_HW_SPI2_MOSI (pyb_pin_FLASH_MOSI) // USB config -#define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) +#define MICROPY_HW_USB_VBUS_DETECT_PIN (pyb_pin_USB_VBUS) #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_MSC (1) diff --git a/ports/stm32/boards/LEGO_HUB_NO6/pins.csv b/ports/stm32/boards/LEGO_HUB_NO6/pins.csv index 9e56e2c79d..1d0b8f35d8 100644 --- a/ports/stm32/boards/LEGO_HUB_NO6/pins.csv +++ b/ports/stm32/boards/LEGO_HUB_NO6/pins.csv @@ -26,14 +26,14 @@ PORTD_M1,PB8 PORTD_M2,PB9 LSM6_SCL,PB10 ,PB11 -,PB12 -,PB13 +FLASH_NSS,PB12 +FLASH_SCK,PB13 ,PB14 TLC_GS_CLK,PB15 BAT_IMON_ADC,PC0 BAT_VMON_ADC,PC1 -,PC2 -,PC3 +FLASH_MISO,PC2 +FLASH_MOSI,PC3 CHGOK_CENBTN_3V3OK_ADC,PC4 PORTF_EN,PC5 PORTE_M1,PC6 From 9a51273d96405527e3950441cfebc6c7314a6bcf Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 29 Jul 2022 15:25:10 -0500 Subject: [PATCH 0232/1041] stm32/boards/LEGO_HUB_NO6/appupdate: Detect filesystem size at runtime. This changes appupdate.py to get the filesystem size at runtime. This will allow the code to be shared with LEGO_HUB_NO7 which has a similar flash chip with a different size. Signed-off-by: David Lechner --- ports/stm32/boards/LEGO_HUB_NO6/appupdate.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/LEGO_HUB_NO6/appupdate.py b/ports/stm32/boards/LEGO_HUB_NO6/appupdate.py index 0927f16111..57b24d3f2e 100644 --- a/ports/stm32/boards/LEGO_HUB_NO6/appupdate.py +++ b/ports/stm32/boards/LEGO_HUB_NO6/appupdate.py @@ -2,13 +2,20 @@ # MIT license; Copyright (c) 2022 Damien P. George from micropython import const -import struct, machine, fwupdate, spiflash +import struct, machine, fwupdate, spiflash, pyb + +_IOCTL_BLOCK_COUNT = const(4) +_IOCTL_BLOCK_SIZE = const(5) _SPIFLASH_UPDATE_KEY_ADDR = const(1020 * 1024) _SPIFLASH_UPDATE_KEY_VALUE = const(0x12345678) _FILESYSTEM_ADDR = const(0x8000_0000 + 1024 * 1024) -_FILESYSTEM_LEN = const(31 * 1024 * 1024) + +# Roundabout way to get actual filesystem size from config. +# This takes into account the 1M "reserved" section of the flash memory. +flash = pyb.Flash(start=0) +_FILESYSTEM_LEN = flash.ioctl(_IOCTL_BLOCK_COUNT, None) * flash.ioctl(_IOCTL_BLOCK_SIZE, None) def update_app(filename): @@ -30,6 +37,8 @@ def update_app(filename): baudrate=50_000_000, ) cs = machine.Pin(machine.Pin.board.FLASH_NSS, machine.Pin.OUT, value=1) + + # We can't use pyb.Flash() because we need to write to the "reserved" 1M area. flash = spiflash.SPIFlash(spi, cs) # Write the update key and elements to the SPI flash. From f69af1661923c05149b2a998d5d074d85c51026d Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 29 Jul 2022 15:45:13 -0500 Subject: [PATCH 0233/1041] stm32/boards/LEGO_HUB_NO6/spiflash: Pick command type at runtime. This changes spiflash.py to read the flash chip ID at runtime to select the read/write/erase commands. This will allow the code to be shared with LEGO_HUB_NO7 which doesn't use the 32-bit commands. Also remove an unused constant while we are touching this. Signed-off-by: David Lechner --- ports/stm32/boards/LEGO_HUB_NO6/spiflash.py | 24 +++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/ports/stm32/boards/LEGO_HUB_NO6/spiflash.py b/ports/stm32/boards/LEGO_HUB_NO6/spiflash.py index e052f7738b..e483ace950 100644 --- a/ports/stm32/boards/LEGO_HUB_NO6/spiflash.py +++ b/ports/stm32/boards/LEGO_HUB_NO6/spiflash.py @@ -4,18 +4,34 @@ from micropython import const _PAGE_SIZE = const(256) # maximum bytes writable in one SPI transfer +_CMD_WRITE = const(0x02) +_CMD_READ = const(0x03) _CMD_RDSR = const(0x05) _CMD_WREN = const(0x06) _CMD_WRITE_32 = const(0x12) _CMD_READ_32 = const(0x13) +_CMD_SEC_ERASE = const(0x20) _CMD_SEC_ERASE_32 = const(0x21) -_CMD_C4READ_32 = const(0xEC) +_CMD_JEDEC_ID = const(0x9F) class SPIFlash: def __init__(self, spi, cs): self.spi = spi self.cs = cs + self.id = self._get_id() + # flash chip on Hub No. 6 uses 32-bit addressing + _32_bit = self.id == b"\xef\x40\x19" + self._READ = _CMD_READ_32 if _32_bit else _CMD_READ + self._WRITE = _CMD_WRITE_32 if _32_bit else _CMD_WRITE + self._ERASE = _CMD_SEC_ERASE_32 if _32_bit else _CMD_SEC_ERASE + + def _get_id(self): + self.cs(0) + self.spi.write(bytearray([_CMD_JEDEC_ID])) + buf = self.spi.read(3) + self.cs(1) + return buf def _wait_wel1(self): # wait WEL=1 @@ -52,11 +68,11 @@ class SPIFlash: self._wait_wip0() def erase_block(self, addr): - self._flash_modify(_CMD_SEC_ERASE_32, addr, None) + self._flash_modify(self._ERASE, addr, None) def readinto(self, addr, buf): self.cs(0) - self.spi.write(bytearray([_CMD_READ_32, addr >> 16, addr >> 8, addr])) + self.spi.write(bytearray([self._READ, addr >> 16, addr >> 8, addr])) self.spi.readinto(buf) self.cs(1) @@ -67,7 +83,7 @@ class SPIFlash: buf_offset = 0 while remain: l = min(_PAGE_SIZE - offset, remain) - self._flash_modify(_CMD_WRITE_32, addr, buf[buf_offset : buf_offset + l]) + self._flash_modify(self._WRITE, addr, buf[buf_offset : buf_offset + l]) remain -= l addr += l buf_offset += l From 0f0f2351bb3c45801250352e72e026e1671fd5d8 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Tue, 14 Jun 2022 22:32:44 -0500 Subject: [PATCH 0234/1041] stm32/boards/LEGO_HUB_NO6/cc2564: Make timer configurable. This adds configurable macros to define the timer and channel used to provide the Bluetooth 32768 MHz clock. This will allow code to be shared with LEGO_HUB_NO7. Signed-off-by: David Lechner --- ports/stm32/boards/LEGO_HUB_NO6/cc2564.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/ports/stm32/boards/LEGO_HUB_NO6/cc2564.c b/ports/stm32/boards/LEGO_HUB_NO6/cc2564.c index c54daf3002..50ba81c57a 100644 --- a/ports/stm32/boards/LEGO_HUB_NO6/cc2564.c +++ b/ports/stm32/boards/LEGO_HUB_NO6/cc2564.c @@ -38,6 +38,12 @@ #define CC2564_PIN_BT_SLOWCLK (pyb_pin_BT_SLOWCLK) #define CC2564_PIN_BT_ENABLE (pyb_pin_BT_ENABLE) +// slight difference between LEGO_HUB_NO6 and LEGO_HUB_NO7 +#ifndef CC2564_TIMER_BT_SLOWCLOCK_TIM +#define CC2564_TIMER_BT_SLOWCLOCK_TIM 8 +#define CC2564_TIMER_BT_SLOWCLOCK_TIM_CH 4 +#endif + STATIC void cc2564_wait_cts_low(mp_hal_pin_obj_t cts, uint32_t timeout_ms) { for (int i = 0; i < timeout_ms; ++i) { if (mp_hal_pin_read(cts) == 0) { @@ -53,18 +59,18 @@ int mp_bluetooth_hci_controller_init(void) { mp_hal_pin_low(CC2564_PIN_BT_ENABLE); // Output a 32768Hz signal on BTSLOWCLK. - // tim8 = pyb.Timer(8, freq=32768) - // tim8_ch4 = tim8.channel(4, pyb.Timer.PWM, pin=btclk) - // tim8_ch4.pulse_width_percent(50) - mp_obj_t args[6] = { MP_OBJ_NEW_SMALL_INT(8), MP_OBJ_NEW_QSTR(MP_QSTR_freq), MP_OBJ_NEW_SMALL_INT(32768), MP_OBJ_NULL }; - mp_obj_t tim8 = pyb_timer_type.make_new(&pyb_timer_type, 1, 1, args); - mp_load_method(tim8, MP_QSTR_channel, args); - args[2] = MP_OBJ_NEW_SMALL_INT(4); + // tim = pyb.Timer(TIM, freq=32768) + // tim_ch = tim.channel(TIM_CH, pyb.Timer.PWM, pin=btclk) + // tim_ch.pulse_width_percent(50) + mp_obj_t args[6] = { MP_OBJ_NEW_SMALL_INT(CC2564_TIMER_BT_SLOWCLOCK_TIM), MP_OBJ_NEW_QSTR(MP_QSTR_freq), MP_OBJ_NEW_SMALL_INT(32768), MP_OBJ_NULL }; + mp_obj_t tim = pyb_timer_type.make_new(&pyb_timer_type, 1, 1, args); + mp_load_method(tim, MP_QSTR_channel, args); + args[2] = MP_OBJ_NEW_SMALL_INT(CC2564_TIMER_BT_SLOWCLOCK_TIM_CH); args[3] = MP_OBJ_NEW_SMALL_INT(0); // CHANNEL_MODE_PWM_NORMAL args[4] = MP_OBJ_NEW_QSTR(MP_QSTR_pin); args[5] = (mp_obj_t)CC2564_PIN_BT_SLOWCLK; - mp_obj_t tim8_ch4 = mp_call_method_n_kw(2, 1, args); - mp_load_method(tim8_ch4, MP_QSTR_pulse_width_percent, args); + mp_obj_t tim_ch = mp_call_method_n_kw(2, 1, args); + mp_load_method(tim_ch, MP_QSTR_pulse_width_percent, args); args[2] = MP_OBJ_NEW_SMALL_INT(50); mp_call_method_n_kw(1, 0, args); From 10f85fee183404a3cba2795e6cd22c12be742fb3 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Tue, 14 Jun 2022 22:32:44 -0500 Subject: [PATCH 0235/1041] stm32/boards/LEGO_HUB_NO7: Add LEGO Hub No. 7 board definition. This adds support for the LEGO Hub No. 7, aka LEGO Technic Small hub, aka LEGO SPIKE Essential hub. This board is largely similar to Hub No. 6: - Same MCU (STM32F413 - different packaging with fewer pins). - Same Bluetooth chip (TI CC2564). - Same IMU chip. - Similar external flash chip - 4MiB instead of 32MiB. - 2 I/O ports instead of 6. - No display - only status and battery LEDs. - Different LED driver chip. - Only 1 button which is also the power button. - No speaker. Signed-off-by: David Lechner --- ports/stm32/boards/LEGO_HUB_NO7/README.md | 135 +++++++++++ ports/stm32/boards/LEGO_HUB_NO7/bdev.c | 3 + .../LEGO_HUB_NO7/bluetooth_init_cc2564C_1.5.c | 3 + ports/stm32/boards/LEGO_HUB_NO7/board.json | 13 ++ ports/stm32/boards/LEGO_HUB_NO7/board_init.c | 212 ++++++++++++++++++ ports/stm32/boards/LEGO_HUB_NO7/cc2564.c | 6 + ports/stm32/boards/LEGO_HUB_NO7/hub_display.c | 190 ++++++++++++++++ ports/stm32/boards/LEGO_HUB_NO7/hub_display.h | 4 + ports/stm32/boards/LEGO_HUB_NO7/manifest.py | 5 + .../stm32/boards/LEGO_HUB_NO7/mpconfigboard.h | 152 +++++++++++++ .../boards/LEGO_HUB_NO7/mpconfigboard.mk | 50 +++++ ports/stm32/boards/LEGO_HUB_NO7/pins.csv | 114 ++++++++++ .../boards/LEGO_HUB_NO7/stm32f4xx_hal_conf.h | 23 ++ 13 files changed, 910 insertions(+) create mode 100644 ports/stm32/boards/LEGO_HUB_NO7/README.md create mode 100644 ports/stm32/boards/LEGO_HUB_NO7/bdev.c create mode 100644 ports/stm32/boards/LEGO_HUB_NO7/bluetooth_init_cc2564C_1.5.c create mode 100644 ports/stm32/boards/LEGO_HUB_NO7/board.json create mode 100644 ports/stm32/boards/LEGO_HUB_NO7/board_init.c create mode 100644 ports/stm32/boards/LEGO_HUB_NO7/cc2564.c create mode 100644 ports/stm32/boards/LEGO_HUB_NO7/hub_display.c create mode 100644 ports/stm32/boards/LEGO_HUB_NO7/hub_display.h create mode 100644 ports/stm32/boards/LEGO_HUB_NO7/manifest.py create mode 100644 ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.h create mode 100644 ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.mk create mode 100644 ports/stm32/boards/LEGO_HUB_NO7/pins.csv create mode 100644 ports/stm32/boards/LEGO_HUB_NO7/stm32f4xx_hal_conf.h diff --git a/ports/stm32/boards/LEGO_HUB_NO7/README.md b/ports/stm32/boards/LEGO_HUB_NO7/README.md new file mode 100644 index 0000000000..8159cf3f47 --- /dev/null +++ b/ports/stm32/boards/LEGO_HUB_NO7/README.md @@ -0,0 +1,135 @@ +LEGO Hub No.7 +============= + +This board definition is for the LEGO Hub No. 7, a LEGO control unit with 1 button, +2 RGB LEDs, 2 Powered Up ports, 6-DOF sensor, Bluetooth, USB, 4MiB external SPI +flash storage, and a rechargeable battery. + +Features that are currently supported: +- standard MicroPython +- machine and bluetooth modules +- filesystem +- USB VCP, MSC and HID + +The Hub has a bootloader preinstalled at 0x08000000 (which is 32kiB in size) which +cannot be erased. This bootloader is entered by holding down the button for 5 seconds, +at which point the USB DFU device appears. If the battery is installed then the +RGB LED will flash purple. If the battery is not installed, the LED will flash orange +briefly and then the hub will turn off (so having the battery installed is required). +When this bootloader is active, the flash from 0x08008000 and up can be erased +and programmed via USB DFU. + +The built-in bootloader has some drawbacks: it cannot be entered programmatically, +and it does not keep the Hub powered up when running from battery (which requires +keeping BAT_PWR_EN high). As such, this board is configured to work with mboot as +a secondary bootloader: mboot is placed at 0x08008000 and the main application +firmware at 0x08010000. When mboot is installed it can be entered programatically +via machine.bootloader(). + +Backing up original Hub firmware +-------------------------------- + +Before installing MicroPython it is advised to backup the original LEGO firmware that +the Hub comes installed with. To do this, enter the built-in bootloader by holding +down the power button for 5 seconds while powering up the Hub via USB (you may +need to take out the battery and disconnect USB to power off the Hub first). Then +run the following command from the root of this repository: + + $ cd ports/stm32 + $ make BOARD=LEGO_HUB_NO7 backup-hub-firmware + +This will create a file called `lego_hub_firmware.dfu`. Put this file in a safe +location. To restore it, enter the built-in bootloader again and run: + + $ make BOARD=LEGO_HUB_NO7 restore-hub-firmware + +This will restore the original firmware but not the filesystem. To recreate the +original filesystem the Hub must be updated using the appropriate LEGO PC +application. + +Installing MicroPython +---------------------- + +You first need to build and install mboot, which only needs to be done once. From +the root of this repository run: + + $ cd ports/stm32/mboot + $ make BOARD=LEGO_HUB_NO7 + +Now enter the built-in bootloader by holding down the power button for 5 +seconds while powering up the Hub via USB (you may need to take out the battery +and disconnect USB to power off the Hub first). Then run: + + $ make BOARD=LEGO_HUB_NO7 deploy + +mboot should now be installed. To enter mboot, remove USB and the battery. +Connect the USB cable (the other end of the USB cable must be connected to +something that provides power). The status light should start cycling through +different colors. Replace the battery (the button will not work without the +battery present). Press the button to activate the desired boot mode: + +- Status light is red - run application (normal boot). +- Status light is green - run application in factory file system mode. +- Status light is blue - run application in safe mode. +- Status light is white - start DFU on the USB port. + + +Now build MicroPython (start at the root of this repository): + + $ cd mpy-cross + $ make + $ cd ../ports/stm32 + $ make submodules + $ make BOARD=LEGO_HUB_NO7 + +And deploy to the Hub (making sure mboot DFU is active, the center button is +blinking red): + + $ make BOARD=LEGO_HUB_NO7 deploy + +If successful, the Hub should now appear as a USB serial and mass storage device. + +Using MicroPython on the Hub +---------------------------- + +Access the MicroPython REPL using mpremote (pip install mpremote), or with any +serial terminal program. + +To scan for BLE devices: + + >>> import bluetooth + >>> ble = bluetooth.BLE() + >>> ble.irq(lambda *x: print(*x)) + >>> ble.active(1) + >>> ble.gap_scan(2000, 625, 625) + +Use help("modules") to see available built-in modules. + +Updating MicroPython from the Hub's filesystem +---------------------------------------------- + +You can update the MicroPython application firmware using the instructions above +for installing the firmware for the first time. The Hub also supports updating +the application firmware from within MicroPython itself, using the on-board +filesystem. + +To use this feature, build the firmware (see above for details) then gzip it and +copy the resulting file to the Hub (eg using mpremote): + + $ make BOARD=LEGO_HUB_NO7 + $ gzip build-LEGO_HUB_NO7/firmware.dfu + $ mpremote cp build-LEGO_HUB_NO7/firmware.dfu.gz : + +Then get a REPL on the Hub and execute: + + >>> import appupdate + >>> appupdate.update_app("firmware.dfu.gz") + +You can alternatively run this REPL command using mpremote: + + $ mpremote exec --no-follow "import appupdate; appupdate.update_app('firmware.dfu.gz')" + +At that point the Hub should restart and the LED on the central button will flash +different colours. Once the update is complete the LED will stop flashing and the +Hub will appear again as a USB device. The application firmware is now updated +and you can remove the firmware.dfu.gz file if desired. diff --git a/ports/stm32/boards/LEGO_HUB_NO7/bdev.c b/ports/stm32/boards/LEGO_HUB_NO7/bdev.c new file mode 100644 index 0000000000..f104c0f3f4 --- /dev/null +++ b/ports/stm32/boards/LEGO_HUB_NO7/bdev.c @@ -0,0 +1,3 @@ +// LEGO_HUB_NO7 is identical to LEGO_HUB_NO6 in this regard. + +#include "../LEGO_HUB_NO6/bdev.c" diff --git a/ports/stm32/boards/LEGO_HUB_NO7/bluetooth_init_cc2564C_1.5.c b/ports/stm32/boards/LEGO_HUB_NO7/bluetooth_init_cc2564C_1.5.c new file mode 100644 index 0000000000..6ea298f688 --- /dev/null +++ b/ports/stm32/boards/LEGO_HUB_NO7/bluetooth_init_cc2564C_1.5.c @@ -0,0 +1,3 @@ +// LEGO_HUB_NO7 is identical to LEGO_HUB_NO6 in this regard. + +#include "../LEGO_HUB_NO6/bluetooth_init_cc2564C_1.5.c" diff --git a/ports/stm32/boards/LEGO_HUB_NO7/board.json b/ports/stm32/boards/LEGO_HUB_NO7/board.json new file mode 100644 index 0000000000..1ef02c17a0 --- /dev/null +++ b/ports/stm32/boards/LEGO_HUB_NO7/board.json @@ -0,0 +1,13 @@ +{ + "deploy": [ + "../deploy.md" + ], + "docs": "", + "features": [], + "images": [], + "mcu": "stm32f4", + "product": "Hub No.7", + "thumbnail": "", + "url": "", + "vendor": "LEGO" +} diff --git a/ports/stm32/boards/LEGO_HUB_NO7/board_init.c b/ports/stm32/boards/LEGO_HUB_NO7/board_init.c new file mode 100644 index 0000000000..7b155b1c3c --- /dev/null +++ b/ports/stm32/boards/LEGO_HUB_NO7/board_init.c @@ -0,0 +1,212 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021-2022 Damien P. George + * Copyright (c) 2022 David Lechner + * + * 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/mphal.h" +#include "irq.h" + +void board_init(void) { + if (query_irq() == IRQ_STATE_DISABLED) { + enable_irq(IRQ_STATE_ENABLED); + } + + // Enable 3V3 for all ports + mp_hal_pin_output(pyb_pin_PORT_3V3_EN); + mp_hal_pin_high(pyb_pin_PORT_3V3_EN); + + // Port A + // Enable RX/TX buffer + mp_hal_pin_output(pyb_pin_PORTA_EN); + mp_hal_pin_low(pyb_pin_PORTA_EN); + + // Port B + // Enable RX/TX buffer + mp_hal_pin_output(pyb_pin_PORTB_EN); + mp_hal_pin_low(pyb_pin_PORTB_EN); +} + +#if BUILDING_MBOOT + +#include "drivers/memory/spiflash.h" +#include "mboot/mboot.h" +#include "boardctrl.h" +#include "adc.h" +#include "hub_display.h" + +#define RESET_MODE_NUM_STATES (4) +#define RESET_MODE_TIMEOUT_CYCLES (8) + +// Location and value for the SPI flash update key. If this key exists at the defined +// location then mboot will attempt to do a filesystem-load update of the main firmware. +// This makes the update robust to power failures: if the update does not complete then +// it will be restarted the next time it powers up. Only when it fully completes will +// this key be erased, and then the application can run. +#define SPIFLASH_UPDATE_KEY_ADDR (1020 * 1024) +#define SPIFLASH_UPDATE_KEY_VALUE (0x12345678) + +static void board_led_pattern(int reset_mode, uint16_t brightness) { + switch (reset_mode) { + case BOARDCTRL_RESET_MODE_NORMAL: + // set status light to red + hub_display_set(3, brightness); + hub_display_set(4, 0); + hub_display_set(5, 0); + break; + case BOARDCTRL_RESET_MODE_SAFE_MODE: + // set status light to green + hub_display_set(3, 0); + hub_display_set(4, brightness); + hub_display_set(5, 0); + break; + case BOARDCTRL_RESET_MODE_FACTORY_FILESYSTEM: + // set status light to blue + hub_display_set(3, 0); + hub_display_set(4, 0); + hub_display_set(5, brightness); + break; + case BOARDCTRL_RESET_MODE_BOOTLOADER: + // set status light to white + hub_display_set(3, brightness); + hub_display_set(4, brightness); + hub_display_set(5, brightness); + break; + } + + hub_display_update(); +} + +static void board_battery_init(void) { + mp_hal_pin_config(pyb_pin_BAT_VMON_ADC, MP_HAL_PIN_MODE_ADC, MP_HAL_PIN_PULL_NONE, 0); + adc_config(ADC1, 12); +} + +// returns true if the battery is pressed, otherwise false +static int board_battery_state(void) { + uint16_t value = adc_config_and_read_u16(ADC1, 6, ADC_SAMPLETIME_15CYCLES); + // If battery voltage is above USB voltage, then we consider the battery + // to be present. + return value > 41100; // 41100 is approx 5.5V +} + +static void board_button_init(void) { + mp_hal_pin_input(pyb_pin_BUTTON); +} + +// returns true if the button is pressed, otherwise false +static int board_button_state(void) { + // button is active low + return !mp_hal_pin_read(pyb_pin_BUTTON); +} + +void board_mboot_cleanup(int reset_mode) { + board_led_pattern(0, 0); + hub_display_off(); +} + +void board_mboot_led_init(void) { + hub_display_on(); +} + +void board_mboot_led_state(int led, int state) { + if (state) { + hub_display_set(3 + led, 0x7fff); + } else { + hub_display_set(3 + led, 0); + } + + hub_display_update(); +} + +int board_mboot_get_reset_mode(uint32_t *initial_r0) { + board_battery_init(); + board_button_init(); + int reset_mode = BOARDCTRL_RESET_MODE_NORMAL; + + if (board_battery_state()) { + // Battery is present, check flash for update key and start an update if the key exists. + // Otherwise, boot normally. + + // Initialise the external SPI flash. + MBOOT_SPIFLASH_SPIFLASH->config = MBOOT_SPIFLASH_CONFIG; + mp_spiflash_init(MBOOT_SPIFLASH_SPIFLASH); + + // Read in the key. + uint32_t buf; + mp_spiflash_read(MBOOT_SPIFLASH_SPIFLASH, SPIFLASH_UPDATE_KEY_ADDR, 4, (uint8_t *)&buf); + + if (buf == SPIFLASH_UPDATE_KEY_VALUE) { + // The key has the correct value, so read in the FS-load elements and enter the bootloader. + mp_spiflash_read(MBOOT_SPIFLASH_SPIFLASH, SPIFLASH_UPDATE_KEY_ADDR + 4, ELEM_DATA_SIZE, ELEM_DATA_START); + *initial_r0 = MBOOT_INITIAL_R0_KEY_FSLOAD; + reset_mode = BOARDCTRL_RESET_MODE_BOOTLOADER; + } + } else { + // Battery is not present. Cycle through reset modes until button is pressed. + systick_init(); + hub_display_on(); + reset_mode = 0; + for (int i = 0; i < (RESET_MODE_NUM_STATES * RESET_MODE_TIMEOUT_CYCLES + 1) * 64; i++) { + if (i % 64 == 0) { + if (++reset_mode > RESET_MODE_NUM_STATES) { + reset_mode = BOARDCTRL_RESET_MODE_NORMAL; + } + board_led_pattern(reset_mode, 0x7fff); + } + + if (board_button_state()) { + break; + } + + mp_hal_delay_ms(19); + } + + // Flash the selected reset mode. + for (int i = 0; i < 6; i++) { + board_led_pattern(reset_mode, 0x0fff); + mp_hal_delay_ms(50); + board_led_pattern(reset_mode, 0x7fff); + mp_hal_delay_ms(50); + } + + mp_hal_delay_ms(300); + } + + board_led_pattern(0, 0); + return reset_mode; +} + +void board_mboot_state_change(int state, uint32_t arg) { + if (state == MBOOT_STATE_FSLOAD_END) { + // The FS-load update completed (either with success or failure), so erase the + // update key and write the result of the FS-load operation into flash. + mp_spiflash_erase_block(MBOOT_SPIFLASH_SPIFLASH, SPIFLASH_UPDATE_KEY_ADDR); + mp_spiflash_write(MBOOT_SPIFLASH_SPIFLASH, SPIFLASH_UPDATE_KEY_ADDR + 4, 4, (const uint8_t *)&arg); + } + + mboot_state_change_default(state, arg); +} + +#endif diff --git a/ports/stm32/boards/LEGO_HUB_NO7/cc2564.c b/ports/stm32/boards/LEGO_HUB_NO7/cc2564.c new file mode 100644 index 0000000000..e5bfe1b4d4 --- /dev/null +++ b/ports/stm32/boards/LEGO_HUB_NO7/cc2564.c @@ -0,0 +1,6 @@ +// LEGO_HUB_NO7 is nearly identical to LEGO_HUB_NO6 in this regard. + +#define CC2564_TIMER_BT_SLOWCLOCK_TIM 2 +#define CC2564_TIMER_BT_SLOWCLOCK_TIM_CH 2 + +#include "../LEGO_HUB_NO6/cc2564.c" diff --git a/ports/stm32/boards/LEGO_HUB_NO7/hub_display.c b/ports/stm32/boards/LEGO_HUB_NO7/hub_display.c new file mode 100644 index 0000000000..e19485b064 --- /dev/null +++ b/ports/stm32/boards/LEGO_HUB_NO7/hub_display.c @@ -0,0 +1,190 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Damien P. George + * Copyright (c) 2022 David Lechner + * + * 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/mphal.h" +#include "hub_display.h" + +#include STM32_HAL_H + +#define I2C_ADDR 0x28 + +// Registers +#define DEVICE_CONFIG0 0x00 +#define DEVICE_CONFIG1 0x01 +#define LED_CONFIG0 0x02 +#define BANK_BRIGHTNESS 0x03 +#define BANK_A_COLOR 0x04 +#define BANK_B_COLOR 0x05 +#define BANK_C_COLOR 0x06 +#define LED0_BRIGHTNESS 0x07 +#define LED1_BRIGHTNESS 0x08 +#define LED2_BRIGHTNESS 0x09 +#define LED3_BRIGHTNESS 0x0A +#define OUT0_COLOR 0x0B +#define OUT1_COLOR 0x0C +#define OUT2_COLOR 0x0D +#define OUT3_COLOR 0x0E +#define OUT4_COLOR 0x0F +#define OUT5_COLOR 0x10 +#define OUT6_COLOR 0x11 +#define OUT7_COLOR 0x12 +#define OUT8_COLOR 0x13 +#define OUT9_COLOR 0x14 +#define OUT10_COLOR 0x15 +#define OUT11_COLOR 0x16 +#define RESET 0x17 + +// Flags +#define DEVICE_CONFIG0_CHIP_EN (1 << 6) +#define DEVICE_CONFIG1_LOG_SCALE_EN (1 << 5) +#define DEVICE_CONFIG1_POWER_SAVE_EN (1 << 4) +#define DEVICE_CONFIG1_AUTO_INCR_EN (1 << 3) +#define DEVICE_CONFIG1_PWM_DITHERING_EN (1 << 2) +#define DEVICE_CONFIG1_MAX_CURRENT_OPTION (1 << 1) +#define DEVICE_CONFIG1_LED_GLOBAL_OFF (1 << 0) +#define LED_CONFIG0_LED3_BANK_EN (1 << 3) +#define LED_CONFIG0_LED2_BANK_EN (1 << 2) +#define LED_CONFIG0_LED1_BANK_EN (1 << 1) +#define LED_CONFIG0_LED0_BANK_EN (1 << 0) + +#define LP50XX_NUM_CH 6 + +// channel mapping: +// CH 0 = battery LED - red +// CH 1 = battery LED - green +// CH 2 = battery LED - blue +// CH 3 = status LED - red +// CH 4 = status LED - green +// CH 5 = status LED - blue + +#define FMPI2C_CONVERT_TIMINGS(PRESC, SCLDEL, SDADEL, SCLH, SCLL) \ + (((PRESC) << FMPI2C_TIMINGR_PRESC_Pos) | \ + ((SCLDEL) << FMPI2C_TIMINGR_SCLDEL_Pos) | \ + ((SDADEL) << FMPI2C_TIMINGR_SDADEL_Pos) | \ + ((SCLH) << FMPI2C_TIMINGR_SCLH_Pos) | \ + ((SCLL) << FMPI2C_TIMINGR_SCLL_Pos)) + +static FMPI2C_HandleTypeDef hub_display_i2c; +static bool hub_display_init; + +static struct { + uint8_t reg; + uint8_t values[LP50XX_NUM_CH]; +} __attribute__((packed)) hub_display_data = { + .reg = OUT0_COLOR, +}; + +void HAL_FMPI2C_MspInit(FMPI2C_HandleTypeDef *hfmpi2c) { + __HAL_RCC_FMPI2C1_CLK_ENABLE(); + mp_hal_pin_config(pyb_pin_LED_SCL, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_NONE, 4); + mp_hal_pin_config(pyb_pin_LED_SDA, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_NONE, 4); +} + +void HAL_FMPI2C_MspDeInit(FMPI2C_HandleTypeDef *hfmpi2c) { + __HAL_RCC_FMPI2C1_CLK_DISABLE(); + __HAL_RCC_FMPI2C1_FORCE_RESET(); + __HAL_RCC_FMPI2C1_RELEASE_RESET(); + mp_hal_pin_config(pyb_pin_LED_SCL, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); + mp_hal_pin_config(pyb_pin_LED_SDA, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); +} + +static void hub_display_i2c_init(void) { + hub_display_i2c.Instance = FMPI2C1; + hub_display_i2c.Init.Timing = FMPI2C_CONVERT_TIMINGS(0, 4, 0, 19, 28); + hub_display_i2c.Init.OwnAddress1 = 0; + hub_display_i2c.Init.AddressingMode = FMPI2C_ADDRESSINGMODE_7BIT; + hub_display_i2c.Init.DualAddressMode = FMPI2C_DUALADDRESS_DISABLE; + hub_display_i2c.Init.OwnAddress2 = 0; + hub_display_i2c.Init.OwnAddress2Masks = FMPI2C_OA2_NOMASK; + hub_display_i2c.Init.GeneralCallMode = FMPI2C_GENERALCALL_DISABLE; + hub_display_i2c.Init.NoStretchMode = FMPI2C_NOSTRETCH_DISABLE; + HAL_FMPI2C_Init(&hub_display_i2c); +} + +void hub_display_set(uint8_t led, uint16_t value) { + if (led >= LP50XX_NUM_CH) { + return; + } + + hub_display_data.values[led] = value >> 8; +} + +void hub_display_update(void) { + if (!hub_display_init) { + return; + } + + HAL_FMPI2C_Master_Transmit(&hub_display_i2c, I2C_ADDR, (uint8_t *)&hub_display_data, + sizeof(hub_display_data), HAL_MAX_DELAY); +} + +void hub_display_on(void) { + if (hub_display_init) { + return; + } + + hub_display_i2c_init(); + mp_hal_pin_output(pyb_pin_LED_EN); + mp_hal_pin_high(pyb_pin_LED_EN); + + static const struct { + uint8_t reg; + uint8_t values[11]; + } __attribute__((packed)) init_data = { + .reg = DEVICE_CONFIG0, + .values = { + [DEVICE_CONFIG0] = DEVICE_CONFIG0_CHIP_EN, + [DEVICE_CONFIG1] = DEVICE_CONFIG1_POWER_SAVE_EN | DEVICE_CONFIG1_PWM_DITHERING_EN | DEVICE_CONFIG1_AUTO_INCR_EN, + [LED_CONFIG0] = 0, + [BANK_BRIGHTNESS] = 0, + [BANK_A_COLOR] = 0, + [BANK_B_COLOR] = 0, + [BANK_C_COLOR] = 0, + [LED0_BRIGHTNESS] = 51, // battery LED + [LED1_BRIGHTNESS] = 38, // status LED + [LED2_BRIGHTNESS] = 0, + [LED3_BRIGHTNESS] = 0, + } + }; + + HAL_FMPI2C_Master_Transmit(&hub_display_i2c, I2C_ADDR, (uint8_t *)&init_data, + sizeof(init_data), HAL_MAX_DELAY); + + hub_display_init = true; +} + +void hub_display_off(void) { + if (!hub_display_init) { + return; + } + + HAL_FMPI2C_DeInit(&hub_display_i2c); + + mp_hal_pin_config(pyb_pin_LED_EN, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); + + hub_display_init = false; +} diff --git a/ports/stm32/boards/LEGO_HUB_NO7/hub_display.h b/ports/stm32/boards/LEGO_HUB_NO7/hub_display.h new file mode 100644 index 0000000000..7623e128a8 --- /dev/null +++ b/ports/stm32/boards/LEGO_HUB_NO7/hub_display.h @@ -0,0 +1,4 @@ +void hub_display_on(void); +void hub_display_off(void); +void hub_display_update(void); +void hub_display_set(uint8_t led, uint16_t value); diff --git a/ports/stm32/boards/LEGO_HUB_NO7/manifest.py b/ports/stm32/boards/LEGO_HUB_NO7/manifest.py new file mode 100644 index 0000000000..d746381637 --- /dev/null +++ b/ports/stm32/boards/LEGO_HUB_NO7/manifest.py @@ -0,0 +1,5 @@ +include("$(PORT_DIR)/boards/manifest.py") + +# Modules for application firmware update. +freeze("$(PORT_DIR)/mboot", "fwupdate.py", opt=3) +freeze("$(PORT_DIR)/boards/LEGO_HUB_NO6", ("spiflash.py", "appupdate.py"), opt=3) diff --git a/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.h b/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.h new file mode 100644 index 0000000000..50fb6c0607 --- /dev/null +++ b/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.h @@ -0,0 +1,152 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2021 Damien P. George + */ + +#include + +#define MICROPY_HW_BOARD_NAME "LEGO Technic Hub No.7" +#define MICROPY_HW_MCU_NAME "STM32F413" + +#define MICROPY_HW_HAS_SWITCH (0) +#define MICROPY_HW_HAS_FLASH (1) +#define MICROPY_PY_PYB_LEGACY (0) +#define MICROPY_HW_ENTER_BOOTLOADER_VIA_RESET (0) +#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_RNG (1) +#define MICROPY_HW_ENABLE_DAC (1) +#define MICROPY_HW_ENABLE_USB (1) +#define MICROPY_HW_FLASH_FS_LABEL "HUB_NO7" + +// HSE is 16MHz, CPU freq set to 100MHz, buses at maximum freq +#define MICROPY_HW_CLK_PLLM (16) +#define MICROPY_HW_CLK_PLLN (200) +#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) +#define MICROPY_HW_CLK_PLLQ (4) +#define MICROPY_HW_CLK_AHB_DIV (RCC_SYSCLK_DIV1) +#define MICROPY_HW_CLK_APB1_DIV (RCC_HCLK_DIV2) +#define MICROPY_HW_CLK_APB2_DIV (RCC_HCLK_DIV1) + +// For 2.7 to 3.6 V, 75 to 100 MHz: 3 wait states. +#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_3 + +// UART buses +// Bluetooth HCI +#define MICROPY_HW_UART2_CTS (pyb_pin_BT_CTS) +#define MICROPY_HW_UART2_RTS (pyb_pin_BT_RTS) +#define MICROPY_HW_UART2_TX (pyb_pin_BT_TX) +#define MICROPY_HW_UART2_RX (pyb_pin_BT_RX) +// Port B +#define MICROPY_HW_UART3_TX (pyb_pin_PORTB_TX) +#define MICROPY_HW_UART3_RX (pyb_pin_PORTB_RX) +// Port A +#define MICROPY_HW_UART5_TX (pyb_pin_PORTA_TX) +#define MICROPY_HW_UART5_RX (pyb_pin_PORTA_RX) + +// SPI buses +#define MICROPY_HW_SPI2_NSS (pyb_pin_FLASH_NSS) +#define MICROPY_HW_SPI2_SCK (pyb_pin_FLASH_SCK) +#define MICROPY_HW_SPI2_MISO (pyb_pin_FLASH_MISO) +#define MICROPY_HW_SPI2_MOSI (pyb_pin_FLASH_MOSI) + +// USB config +#define MICROPY_HW_USB_VBUS_DETECT_PIN (pyb_pin_USB_VBUS) +#define MICROPY_HW_USB_FS (1) +#define MICROPY_HW_USB_MSC (1) + +// Bluetooth config +#define MICROPY_HW_BLE_UART_ID (PYB_UART_2) +#define MICROPY_HW_BLE_UART_BAUDRATE (115200) +#define MICROPY_HW_BLE_UART_BAUDRATE_SECONDARY (921600) +#define MICROPY_HW_BLE_BTSTACK_CHIPSET_INSTANCE btstack_chipset_cc256x_instance() + +// SPI flash, for R/W storage +// The first 1MiB is skipped because it's used by the built-in bootloader +// Note: MICROPY_HW_SPIFLASH_OFFSET_BYTES must be a multiple of MP_SPIFLASH_ERASE_BLOCK_SIZE +#define MICROPY_HW_SPIFLASH_OFFSET_BYTES (1024 * 1024) +#define MICROPY_HW_SPIFLASH_BLOCKMAP(bl) ((bl) + MICROPY_HW_SPIFLASH_OFFSET_BYTES / FLASH_BLOCK_SIZE) +#define MICROPY_HW_SPIFLASH_BLOCKMAP_EXT(bl) ((bl) + MICROPY_HW_SPIFLASH_OFFSET_BYTES / MP_SPIFLASH_ERASE_BLOCK_SIZE) +#define MICROPY_HW_SPIFLASH_ENABLE_CACHE (1) +#define MICROPY_HW_SPIFLASH_SIZE_BITS (32 * 1024 * 1024 - MICROPY_HW_SPIFLASH_OFFSET_BYTES * 8) +#define MICROPY_HW_SPIFLASH_CS (MICROPY_HW_SPI2_NSS) +#define MICROPY_HW_SPIFLASH_SCK (MICROPY_HW_SPI2_SCK) +#define MICROPY_HW_SPIFLASH_MISO (MICROPY_HW_SPI2_MISO) +#define MICROPY_HW_SPIFLASH_MOSI (MICROPY_HW_SPI2_MOSI) + +// SPI flash, block device config +#define MICROPY_HW_BDEV_IOCTL(op, arg) ( \ + (op) == BDEV_IOCTL_NUM_BLOCKS ? (MICROPY_HW_SPIFLASH_SIZE_BITS / 8 / FLASH_BLOCK_SIZE) : \ + (op) == BDEV_IOCTL_INIT ? spi_bdev_ioctl(&spi_bdev, (op), (uint32_t)&spiflash_config) : \ + spi_bdev_ioctl(&spi_bdev, (op), (arg)) \ + ) + +// Configuration for stardard block protocol (block size FLASH_BLOCK_SIZE). +#define MICROPY_HW_BDEV_READBLOCKS(dest, bl, n) \ + spi_bdev_readblocks(&spi_bdev, (dest), MICROPY_HW_SPIFLASH_BLOCKMAP(bl), (n)) +#define MICROPY_HW_BDEV_WRITEBLOCKS(src, bl, n) \ + spi_bdev_writeblocks(&spi_bdev, (src), MICROPY_HW_SPIFLASH_BLOCKMAP(bl), (n)) + +// Configuration for extended block protocol (block size MP_SPIFLASH_ERASE_BLOCK_SIZE). +#define MICROPY_HW_BDEV_BLOCKSIZE_EXT (MP_SPIFLASH_ERASE_BLOCK_SIZE) +#define MICROPY_HW_BDEV_READBLOCKS_EXT(dest, bl, off, len) \ + (spi_bdev_readblocks_raw(&spi_bdev, (dest), MICROPY_HW_SPIFLASH_BLOCKMAP_EXT(bl), (off), (len))) +#define MICROPY_HW_BDEV_WRITEBLOCKS_EXT(src, bl, off, len) \ + (spi_bdev_writeblocks_raw(&spi_bdev, (src), MICROPY_HW_SPIFLASH_BLOCKMAP_EXT(bl), (off), (len))) +#define MICROPY_HW_BDEV_ERASEBLOCKS_EXT(bl, len) \ + (spi_bdev_eraseblocks_raw(&spi_bdev, MICROPY_HW_SPIFLASH_BLOCKMAP_EXT(bl), (len))) + +// Board control config +#define MICROPY_BOARD_STARTUP board_init + +/******************************************************************************/ +// Bootloader configuration + +// Configure CPU frequency to 96MHz, to make updates from SPI flash faster +#define MBOOT_CLK_PLLM (MICROPY_HW_CLK_VALUE / 1000000) +#define MBOOT_CLK_PLLN (192) +#define MBOOT_CLK_PLLP (RCC_PLLP_DIV2) +#define MBOOT_CLK_PLLQ (4) +#define MBOOT_CLK_AHB_DIV (RCC_SYSCLK_DIV1) +#define MBOOT_CLK_APB1_DIV (RCC_HCLK_DIV4) +#define MBOOT_CLK_APB2_DIV (RCC_HCLK_DIV2) +#define MBOOT_FLASH_LATENCY FLASH_LATENCY_3 + +#define MBOOT_FSLOAD (1) +#define MBOOT_VFS_FAT (1) +#define MBOOT_LEAVE_BOOTLOADER_VIA_RESET (0) + +#define MBOOT_SPIFLASH_ADDR (0x80000000) +#define MBOOT_SPIFLASH_BYTE_SIZE (4 * 1024 * 1024) +#define MBOOT_SPIFLASH_LAYOUT "/0x80000000/1024*4Kg" +#define MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE (1) +#define MBOOT_SPIFLASH_SPIFLASH (&board_mboot_spiflash) +#define MBOOT_SPIFLASH_CONFIG (&board_mboot_spiflash_config) + +#define MBOOT_LED1 0 +#define MBOOT_LED2 1 +#define MBOOT_LED3 2 +#define MBOOT_BOARD_LED_INIT board_mboot_led_init +#define MBOOT_BOARD_LED_STATE board_mboot_led_state + +#define MBOOT_BOARD_EARLY_INIT(initial_r0) board_init() +#define MBOOT_BOARD_CLEANUP board_mboot_cleanup +#define MBOOT_BOARD_GET_RESET_MODE board_mboot_get_reset_mode +#define MBOOT_BOARD_STATE_CHANGE board_mboot_state_change + +/******************************************************************************/ +// Function declarations + +extern const struct _mp_spiflash_config_t spiflash_config; +extern struct _spi_bdev_t spi_bdev; +extern const struct _mp_spiflash_config_t board_mboot_spiflash_config; +extern struct _mp_spiflash_t board_mboot_spiflash; + +void board_init(void); +void board_mboot_cleanup(int reset_mode); +void board_mboot_led_init(void); +void board_mboot_led_state(int led, int state); +int board_mboot_get_reset_mode(uint32_t *initial_r0); +void board_mboot_state_change(int state, uint32_t arg); +void *btstack_chipset_cc256x_instance(void); diff --git a/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.mk b/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.mk new file mode 100644 index 0000000000..c06f9a26ad --- /dev/null +++ b/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.mk @@ -0,0 +1,50 @@ +MCU_SERIES = f4 +CMSIS_MCU = STM32F413xx +AF_FILE = boards/stm32f413_af.csv +LD_FILES = boards/LEGO_HUB_NO6/stm32f413xg.ld boards/common_bl.ld +TEXT0_ADDR = 0x08010000 + +BOOTLOADER_DFU_USB_VID ?= 0x0694 +BOOTLOADER_DFU_USB_PID ?= 0x000C + +# MicroPython settings +MICROPY_PY_BLUETOOTH ?= 1 +MICROPY_BLUETOOTH_NIMBLE ?= 0 +MICROPY_BLUETOOTH_BTSTACK ?= 1 +MICROPY_VFS_LFS2 ?= 1 + +# Board specific frozen modules +FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py + +SRC_HAL += $(STM32LIB_HAL_BASE)/Src/stm32f4xx_hal_fmpi2c.c + +ifneq ($(BUILDING_MBOOT),1) +LIB_SRC_C += lib/btstack/chipset/cc256x/btstack_chipset_cc256x.c +endif + +# Bootloader settings +MBOOT_TEXT0_ADDR = 0x08008000 +MBOOT_LD_FILES = ../boards/LEGO_HUB_NO6/mboot_memory.ld stm32_sections.ld + +# Backup/restore original Hub firmware + +HUB_FIRMWARE = lego_hub_firmware.dfu +HUB_FIRMWARE_ADDR = $(MBOOT_TEXT0_ADDR) +HUB_FIRMWARE_SIZE = 0xf8000 + +backup-hub-firmware: + $(Q)$(DFU_UTIL) -a 0 \ + -d $(BOOTLOADER_DFU_USB_VID):$(BOOTLOADER_DFU_USB_PID) \ + -U $(HUB_FIRMWARE).bin \ + -s $(HUB_FIRMWARE_ADDR):$(HUB_FIRMWARE_SIZE) + $(Q)$(PYTHON) $(DFU) \ + -b $(HUB_FIRMWARE_ADDR):$(HUB_FIRMWARE).bin \ + -D $(BOOTLOADER_DFU_USB_VID):$(BOOTLOADER_DFU_USB_PID) \ + $(HUB_FIRMWARE) + $(Q)$(RM) $(HUB_FIRMWARE).bin + $(ECHO) "Backup created in $(HUB_FIRMWARE)" + +restore-hub-firmware: + $(Q)$(DFU_UTIL) -a 0 \ + -d $(BOOTLOADER_DFU_USB_VID):$(BOOTLOADER_DFU_USB_PID) \ + -D $(HUB_FIRMWARE) diff --git a/ports/stm32/boards/LEGO_HUB_NO7/pins.csv b/ports/stm32/boards/LEGO_HUB_NO7/pins.csv new file mode 100644 index 0000000000..dd19518b78 --- /dev/null +++ b/ports/stm32/boards/LEGO_HUB_NO7/pins.csv @@ -0,0 +1,114 @@ +BT_CTS,PA0 +BT_RTS,PA1 +BT_TX,PA2 +BT_RX,PA3 +,PA4 +,PA5 +BAT_VMON_ADC,PA6 +BAT_IMON_ADC,PA7 +LSM6_SCL,PA8 +USB_VBUS,PA9 +CHGMODE,PA10 +USB_DM,PA11 +USB_DP,PA12 +,PA13 +,PA14 +,PA15 +BAT_NTC,PB0 +BAT_PWR_EN,PB1 +BUTTON,PB2 +BT_SLOWCLK,PB3 +PORTB_M1,PB4 +PORTB_M2,PB5 +PORTA_M1,PB6 +PORTA_M2,PB7 +PORTB_EN,PB8 +PORTA_EN,PB9 +FLASH_SCK,PB10 +,PB11 +FLASH_NSS,PB12 +LED_EN,PB13 +LED_SDA,PB14 +LED_SCL,PB15 +,PC0 +,PC1 +FLASH_MISO,PC2 +FLASH_MOSI,PC3 +CHG_IMON_ADC,PC4 +,PC5 +CHGOK,PC6 +PORT_3V3_EN,PC7 +BT_ENABLE,PC8 +LSM6_SDA,PC9 +PORTB_TX,PC10 +PORTB_RX,PC11 +PORTA_TX,PC12 +LSM6_INT1,PC13 +,PC14 +,PC15 +,PD0 +,PD1 +PORTA_RX,PD2 +,PD3 +,PD4 +,PD5 +,PD6 +,PD7 +,PD8 +,PD9 +,PD10 +,PD11 +,PD12 +,PD13 +,PD14 +,PD15 +,PE0 +,PE1 +,PE2 +,PE3 +,PE4 +,PE5 +,PE6 +,PE7 +,PE8 +,PE9 +,PE10 +,PE11 +,PE12 +,PE13 +,PE14 +,PE15 +,PF0 +,PF1 +,PF2 +,PF3 +,PF4 +,PF5 +,PF6 +,PF7 +,PF8 +,PF9 +,PF10 +,PF11 +,PF12 +,PF13 +,PF14 +,PF15 +,PG0 +,PG1 +,PG2 +,PG3 +,PG4 +,PG5 +,PG6 +,PG7 +,PG8 +,PG9 +,PG10 +,PG11 +,PG12 +,PG13 +,PG14 +,PG15 +,PH0 +,PH1 diff --git a/ports/stm32/boards/LEGO_HUB_NO7/stm32f4xx_hal_conf.h b/ports/stm32/boards/LEGO_HUB_NO7/stm32f4xx_hal_conf.h new file mode 100644 index 0000000000..bd70912748 --- /dev/null +++ b/ports/stm32/boards/LEGO_HUB_NO7/stm32f4xx_hal_conf.h @@ -0,0 +1,23 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H + +#include "boards/stm32f4xx_hal_conf_base.h" + +#include "stm32f4xx_hal_fmpi2c.h" + +#define HAL_FMPI2C_MODULE_ENABLED + +// Oscillator values in Hz +#define HSE_VALUE (16000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H From b560b9fe715e293caef80533d61d8c3b179b0339 Mon Sep 17 00:00:00 2001 From: Ian Davies Date: Sun, 3 Jul 2022 18:35:17 +0100 Subject: [PATCH 0236/1041] rp2/mbedtls: Enable certificate validity time validation. --- ports/rp2/mbedtls/mbedtls_config.h | 6 ++++++ ports/rp2/mbedtls/mbedtls_port.c | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/ports/rp2/mbedtls/mbedtls_config.h b/ports/rp2/mbedtls/mbedtls_config.h index 4bf606f5ea..743d0a6a84 100644 --- a/ports/rp2/mbedtls/mbedtls_config.h +++ b/ports/rp2/mbedtls/mbedtls_config.h @@ -93,6 +93,8 @@ #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE #define MBEDTLS_X509_CRT_PARSE_C #define MBEDTLS_X509_USE_C +#define MBEDTLS_HAVE_TIME +#define MBEDTLS_HAVE_TIME_DATE // Memory allocation hooks #include @@ -103,6 +105,10 @@ void m_tracked_free(void *ptr); #define MBEDTLS_PLATFORM_STD_FREE m_tracked_free #define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf +// Time hook +time_t rp2_rtctime_seconds(time_t *timer); +#define MBEDTLS_PLATFORM_TIME_MACRO rp2_rtctime_seconds + #include "mbedtls/check_config.h" #endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_H */ diff --git a/ports/rp2/mbedtls/mbedtls_port.c b/ports/rp2/mbedtls/mbedtls_port.c index aa0f9a36e0..9067eca90e 100644 --- a/ports/rp2/mbedtls/mbedtls_port.c +++ b/ports/rp2/mbedtls/mbedtls_port.c @@ -29,6 +29,9 @@ #include "mbedtls_config.h" +#include "hardware/rtc.h" +#include "shared/timeutils/timeutils.h" + extern uint8_t rosc_random_u8(size_t cycles); int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen) { @@ -39,4 +42,10 @@ int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t return 0; } +time_t rp2_rtctime_seconds(time_t *timer) { + datetime_t t; + rtc_get_datetime(&t); + return timeutils_seconds_since_epoch(t.year, t.month, t.day, t.hour, t.min, t.sec); +} + #endif From fbe9417b90474dd1a08749b3a79311a8007a98fb Mon Sep 17 00:00:00 2001 From: Ian Davies Date: Wed, 6 Jul 2022 16:22:57 +0100 Subject: [PATCH 0237/1041] extmod/ntptime: Factor out ntptime module from esp8266 port. The ntptime module was previously only included in the ESP8266 port. This commit factors that module out into the extmod directory, makes it support different epochs, and includes it in the rp2 port. --- {ports/esp8266/modules => extmod}/ntptime.py | 17 +++++++++++++---- ports/esp32/boards/manifest.py | 2 +- ports/esp8266/boards/GENERIC_512K/manifest.py | 1 - ports/esp8266/boards/manifest.py | 1 + ports/rp2/boards/PICO_W/manifest.py | 1 + 5 files changed, 16 insertions(+), 6 deletions(-) rename {ports/esp8266/modules => extmod}/ntptime.py (69%) diff --git a/ports/esp8266/modules/ntptime.py b/extmod/ntptime.py similarity index 69% rename from ports/esp8266/modules/ntptime.py rename to extmod/ntptime.py index dd07e46f1d..05d7e9717d 100644 --- a/ports/esp8266/modules/ntptime.py +++ b/extmod/ntptime.py @@ -1,3 +1,5 @@ +import utime + try: import usocket as socket except: @@ -7,9 +9,6 @@ try: except: import struct -# (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60 -NTP_DELTA = 3155673600 - # The NTP host can be configured at runtime by doing: ntptime.host = 'myhost.org' host = "pool.ntp.org" @@ -26,6 +25,17 @@ def time(): finally: s.close() val = struct.unpack("!I", msg[40:44])[0] + + EPOCH_YEAR = utime.gmtime(0)[0] + if EPOCH_YEAR == 2000: + # (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60 + NTP_DELTA = 3155673600 + elif EPOCH_YEAR == 1970: + # (date(1970, 1, 1) - date(1900, 1, 1)).days * 24*60*60 + NTP_DELTA = 2208988800 + else: + raise Exception("Unsupported epoch: {}".format(EPOCH_YEAR)) + return val - NTP_DELTA @@ -33,7 +43,6 @@ def time(): def settime(): t = time() import machine - import utime tm = utime.gmtime(t) machine.RTC().datetime((tm[0], tm[1], tm[2], tm[6] + 1, tm[3], tm[4], tm[5], 0)) diff --git a/ports/esp32/boards/manifest.py b/ports/esp32/boards/manifest.py index 1dc1481a42..f0ed38b515 100644 --- a/ports/esp32/boards/manifest.py +++ b/ports/esp32/boards/manifest.py @@ -1,6 +1,6 @@ freeze("$(PORT_DIR)/modules") freeze("$(MPY_DIR)/tools", ("upip.py", "upip_utarfile.py")) -freeze("$(MPY_DIR)/ports/esp8266/modules", "ntptime.py") +freeze("$(MPY_DIR)/extmod", "ntptime.py") freeze("$(MPY_DIR)/drivers/dht", "dht.py") freeze("$(MPY_DIR)/drivers/onewire") include("$(MPY_DIR)/extmod/uasyncio/manifest.py") diff --git a/ports/esp8266/boards/GENERIC_512K/manifest.py b/ports/esp8266/boards/GENERIC_512K/manifest.py index ee148c8089..e43d94843f 100644 --- a/ports/esp8266/boards/GENERIC_512K/manifest.py +++ b/ports/esp8266/boards/GENERIC_512K/manifest.py @@ -1,5 +1,4 @@ freeze("$(BOARD_DIR)", "_boot.py", opt=3) -freeze("$(PORT_DIR)/modules", ("apa102.py", "ntptime.py", "port_diag.py")) freeze("$(MPY_DIR)/drivers/dht", "dht.py") freeze("$(MPY_DIR)/drivers/onewire") include("$(MPY_DIR)/extmod/webrepl/manifest.py") diff --git a/ports/esp8266/boards/manifest.py b/ports/esp8266/boards/manifest.py index 598572d62a..c5809717e6 100644 --- a/ports/esp8266/boards/manifest.py +++ b/ports/esp8266/boards/manifest.py @@ -1,4 +1,5 @@ freeze("$(PORT_DIR)/modules") +freeze("$(MPY_DIR)/extmod", "ntptime.py") freeze("$(MPY_DIR)/tools", ("upip.py", "upip_utarfile.py")) freeze("$(MPY_DIR)/drivers/dht", "dht.py") freeze("$(MPY_DIR)/drivers/onewire") diff --git a/ports/rp2/boards/PICO_W/manifest.py b/ports/rp2/boards/PICO_W/manifest.py index 1953d5cbd0..eb748da485 100644 --- a/ports/rp2/boards/PICO_W/manifest.py +++ b/ports/rp2/boards/PICO_W/manifest.py @@ -2,6 +2,7 @@ include("../manifest.py") freeze("$(MPY_DIR)/tools", "upip.py") freeze("$(MPY_DIR)/tools", "upip_utarfile.py") +freeze("$(MPY_DIR)/extmod", "ntptime.py") if os.path.isdir(convert_path("$(MPY_LIB_DIR)")): freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py") From 1bf2fd0592df999f913dd96be981cdabc0b557ca Mon Sep 17 00:00:00 2001 From: Ian Davies Date: Thu, 21 Jul 2022 21:00:24 +0100 Subject: [PATCH 0238/1041] extmod/modussl_mbedtls: Set a more sensible default debug log level. --- extmod/modussl_mbedtls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c index 8365c7a4a4..b14ed9ad0e 100644 --- a/extmod/modussl_mbedtls.c +++ b/extmod/modussl_mbedtls.c @@ -74,7 +74,7 @@ STATIC const mp_obj_type_t ussl_socket_type; STATIC void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) { (void)ctx; (void)level; - printf("DBG:%s:%04d: %s\n", file, line, str); + mp_printf(&mp_plat_print, "DBG:%s:%04d: %s\n", file, line, str); } #endif @@ -175,7 +175,7 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) { mbedtls_ctr_drbg_init(&o->ctr_drbg); #ifdef MBEDTLS_DEBUG_C // Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose - mbedtls_debug_set_threshold(0); + mbedtls_debug_set_threshold(3); #endif mbedtls_entropy_init(&o->entropy); From b6c2196fbd27834079d9d306d21c0a0897f03c91 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Sun, 17 Jul 2022 12:59:02 +0200 Subject: [PATCH 0239/1041] drivers/cyw43: Allow configuring the netif/mDNS hostname. Allow boards to configure/override the default hostname used for netif and mDNS. --- drivers/cyw43/cyw43.h | 9 +++++++++ drivers/cyw43/cyw43_ctrl.c | 2 ++ drivers/cyw43/cyw43_lwip.c | 7 ++++--- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/cyw43/cyw43.h b/drivers/cyw43/cyw43.h index 7d3e30f5d4..5ca4898318 100644 --- a/drivers/cyw43/cyw43.h +++ b/drivers/cyw43/cyw43.h @@ -47,6 +47,14 @@ #define CYW43_LINK_NONET (-2) #define CYW43_LINK_BADAUTH (-3) +#ifndef MICROPY_BOARD_HOSTNAME +#define MICROPY_BOARD_HOSTNAME "PYBD" +#endif + +#ifndef MICROPY_BOARD_HOSTNAME_LENGTH +#define MICROPY_BOARD_HOSTNAME_LENGTH 16 +#endif + typedef struct _cyw43_t { cyw43_ll_t cyw43_ll; @@ -76,6 +84,7 @@ typedef struct _cyw43_t { struct netif netif[2]; struct dhcp dhcp_client; dhcp_server_t dhcp_server; + char hostname[MICROPY_BOARD_HOSTNAME_LENGTH]; } cyw43_t; extern cyw43_t cyw43_state; diff --git a/drivers/cyw43/cyw43_ctrl.c b/drivers/cyw43/cyw43_ctrl.c index 203bc812ac..73e6e58957 100644 --- a/drivers/cyw43/cyw43_ctrl.c +++ b/drivers/cyw43/cyw43_ctrl.c @@ -101,6 +101,8 @@ void cyw43_init(cyw43_t *self) { self->ap_channel = 3; self->ap_ssid_len = 0; self->ap_key_len = 0; + strncpy(self->hostname, MICROPY_BOARD_HOSTNAME, MICROPY_BOARD_HOSTNAME_LENGTH); + self->hostname[MICROPY_BOARD_HOSTNAME_LENGTH - 1] = 0; cyw43_poll = NULL; } diff --git a/drivers/cyw43/cyw43_lwip.c b/drivers/cyw43/cyw43_lwip.c index 16ae602375..f12a378c5d 100644 --- a/drivers/cyw43/cyw43_lwip.c +++ b/drivers/cyw43/cyw43_lwip.c @@ -117,7 +117,7 @@ void cyw43_tcpip_init(cyw43_t *self, int itf) { #else netif_add(n, &ipconfig[0], &ipconfig[1], &ipconfig[2], self, cyw43_netif_init, netif_input); #endif - netif_set_hostname(n, "PYBD"); + netif_set_hostname(n, self->hostname); netif_set_default(n); netif_set_up(n); @@ -132,8 +132,9 @@ void cyw43_tcpip_init(cyw43_t *self, int itf) { #if LWIP_MDNS_RESPONDER // TODO better to call after IP address is set char mdns_hostname[9]; - memcpy(&mdns_hostname[0], "PYBD", 4); - mp_hal_get_mac_ascii(MP_HAL_MAC_WLAN0, 8, 4, &mdns_hostname[4]); + int len = MIN(strlen(self->hostname), 4); + memcpy(&mdns_hostname[0], self->hostname, len); + mp_hal_get_mac_ascii(MP_HAL_MAC_WLAN0, 4 + len, 8 - len, &mdns_hostname[len]); mdns_hostname[8] = '\0'; mdns_resp_add_netif(n, mdns_hostname, 60); #endif From 9dfabcd6d3d080aced888e8474e921f11dc979bb Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Sun, 17 Jul 2022 13:05:56 +0200 Subject: [PATCH 0240/1041] extmod/network_cyw43: Add hostname config option. --- extmod/network_cyw43.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/extmod/network_cyw43.c b/extmod/network_cyw43.c index c131fbb109..9df799119f 100644 --- a/extmod/network_cyw43.c +++ b/extmod/network_cyw43.c @@ -381,6 +381,11 @@ STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map cyw43_ioctl(self->cyw, CYW43_IOCTL_GET_VAR, 13, buf, self->itf); return MP_OBJ_NEW_SMALL_INT(nw_get_le32(buf) / 4); } + #if !MICROPY_PY_NETWORK_CYW43_USE_LIB_DRIVER + case MP_QSTR_hostname: { + return mp_obj_new_str(self->cyw->hostname, strlen(self->cyw->hostname)); + } + #endif default: mp_raise_ValueError(MP_ERROR_TEXT("unknown config param")); } @@ -453,6 +458,14 @@ STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map cyw43_ioctl(self->cyw, CYW43_IOCTL_SET_VAR, 9 + 4, buf, self->itf); break; } + #if !MICROPY_PY_NETWORK_CYW43_USE_LIB_DRIVER + case MP_QSTR_hostname: { + const char *hostname = mp_obj_str_get_str(e->value); + strncpy(self->cyw->hostname, hostname, MICROPY_BOARD_HOSTNAME_LENGTH); + self->cyw->hostname[MICROPY_BOARD_HOSTNAME_LENGTH - 1] = 0; + break; + } + #endif default: mp_raise_ValueError(MP_ERROR_TEXT("unknown config param")); } From 6baeded32236feb9ba57ce78477fd1ee80fb4697 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 5 Aug 2022 18:52:13 -0500 Subject: [PATCH 0241/1041] py/runtime: Fix crash in star arg unpacking. The reallocation trigger for unpacking star args with unknown length did not take into account the number of fixed args remaining. So it was possible that the unpacked iterators could take up exactly the memory allocated then nothing would be left for fixed args after the star args. This causes a segfault crash. This is fixed by taking into account the remaining number of fixed args in the check to decide whether to realloc yet or not. Signed-off-by: David Lechner --- py/runtime.c | 2 +- tests/basics/fun_callstardblstar.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/py/runtime.c b/py/runtime.c index 2c3b3ddde4..ea3553db72 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -814,7 +814,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ mp_obj_t iterable = mp_getiter(arg, &iter_buf); mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { - if (args2_len >= args2_alloc) { + if (args2_len + (n_args - i) >= args2_alloc) { args2 = mp_nonlocal_realloc(args2, args2_alloc * sizeof(mp_obj_t), args2_alloc * 2 * sizeof(mp_obj_t)); args2_alloc *= 2; diff --git a/tests/basics/fun_callstardblstar.py b/tests/basics/fun_callstardblstar.py index f395df3333..c08e46f668 100644 --- a/tests/basics/fun_callstardblstar.py +++ b/tests/basics/fun_callstardblstar.py @@ -37,3 +37,7 @@ f2(*iter(range(4)), **{'a': 1}) # case where *args is not a tuple/list and takes up most of the memory allocated for **kwargs f2(*iter(range(100)), **{str(i): i for i in range(100)}) + +# regression test - iterable with unknown len() was exactly using preallocated +# memory causing args 4 and 5 to overflow the allocated arg array +print(1, *iter((1, 2, 3)), *iter((1, 2, 3)), 4, 5, sep=",") From 6804b6f54fbed1f0fdb86668ebb46274e4876fa6 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Tue, 5 Apr 2022 08:25:54 +1000 Subject: [PATCH 0242/1041] stm32/boards/NUCLEO_WB55: Add error handling to firmware update scripts. In-the-field use of these FUS/WS firmware update scripts has exposed some weak points, causing corrupted FUS/WS firmware to be flashed to the unit. The problems are mostly caused with the ST GUI application, but sometimes from un-recognised failures during bin file transfer to the WB55 prior to running the rfcore_firmware.py script. Other failures were caused by incorrect load addresses being used, again both from user error copying the address from the HTML release notes to the GUI tool, but also from similarly not updating the address correctly in rfcore_firmware.py To guard against these errors and make it easier to prepare different versions, this commit adds a few features to the rfcore firmware update tools: - When creating the bin file, automatically parse the release note in the folder to get the correct address. - Add a footer to the bin file containing the name, version, CRC, address etc. - Before flashing rfcore, check if the same version is already installed. - Verify the CRC and obfuscation key before flashing bin. - Log the name and version of file being flashed. --- .../boards/NUCLEO_WB55/rfcore_firmware.py | 249 ++++++++++++++---- .../boards/NUCLEO_WB55/rfcore_makefirmware.py | 116 +++++++- 2 files changed, 308 insertions(+), 57 deletions(-) diff --git a/ports/stm32/boards/NUCLEO_WB55/rfcore_firmware.py b/ports/stm32/boards/NUCLEO_WB55/rfcore_firmware.py index 4085da90fd..7cc81b4c68 100644 --- a/ports/stm32/boards/NUCLEO_WB55/rfcore_firmware.py +++ b/ports/stm32/boards/NUCLEO_WB55/rfcore_firmware.py @@ -34,36 +34,54 @@ # # To perform a firmware update: # -# 1. Generate "obfuscated" binary images using rfcore_makefirmware.py -# ./boards/NUCLEO_WB55/rfcore_makefirmware.py ~/src/github.com/STMicroelectronics/STM32CubeWB/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x/ /tmp +# 1. Generate "obfuscated" binary images using rfcore_makefirmware.py, eg. +# $ python3 ./boards/NUCLEO_WB55/rfcore_makefirmware.py ~/src/github.com/STMicroelectronics/STM32CubeWB/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x/ /tmp # This will generate /tmp/{fus_102,fus_110,ws_ble_hci}.bin +# It may warn that stm32wb5x_FUS_fw_1_0_2.bin cannot be found, newer packs don't include this +# which can be ignored unless your currently flashed FUS is older than 1.0.2 # # 2. Copy required files to the device filesystem. -# In general, it's always safe to copy all three files and the updater will -# figure out what needs to be done. This is the recommended option. -# However, if you already have the latest FUS (1.1.0) installed, then just the -# WS firmware is required. -# If a FUS binary is present, then the existing WS will be removed so it's a good -# idea to always include the WS binary if updating FUS. -# Note that a WS binary will not be installed unless FUS 1.1.0 is installed. +# $ mpremote cp /tmp/fus_102.bin : +# $ mpremote cp /tmp/fus_110.bin : +# $ mpremote cp /tmp/ws_ble_hci.bin : +# $ mpremote cp ./boards/NUCLEO_WB55/rfcore_firmware.py : +# In general, it's always safe to copy all three files and the updater will +# figure out what needs to be done. This is the recommended option. +# However, if you already have the latest FUS (1.1.0) installed, then just the +# WS firmware is required. +# If a FUS binary is present, then the existing WS will be removed so it's a good +# idea to always include the WS binary if updating FUS. +# Note that a WS binary will not be installed unless FUS 1.1.0 is installed. # # 3. Ensure boot.py calls `rfcore_firmware.resume()`. -# The WB55 will reset several times during the firmware update process, so this -# script manages the update state using RTC backup registers. -# `rfcore_firmware.resume()` will continue the update operation on startup to -# resume any in-progress update operation, and either trigger another reset, or -# return 0 to indicate that the operation completed successfully, or a reason -# code (see REASON_* below) to indicate failure. +# $ mpremote exec "import rfcore_firmware; rfcore_firmware.install_boot()" +# The WB55 will reset several times during the firmware update process, so this +# script manages the update state using RTC backup registers. +# `rfcore_firmware.resume()` will continue the update operation on startup to +# resume any in-progress update operation, and either trigger another reset, or +# return 0 to indicate that the operation completed successfully, or a reason +# code (see REASON_* below) to indicate failure. # # 4. Call rfcore_firmware.check_for_updates() to start the update process. -# The device will then immediately reboot and when the firmware update completes, -# the status will be returned from rfcore_firmware.resume(). See the REASON_ codes below. -# You can use the built-in stm.rfcore_fw_version() to query the installed version -# from your application code. +# $ mpremote exec "import rfcore_firmware; rfcore_firmware.check_for_updates()" +# The device will then immediately reboot and when the firmware update completes, +# the status will be returned from rfcore_firmware.resume(). See the REASON_ codes below. +# You can use the built-in stm.rfcore_fw_version() to query the installed version +# from your application code. import struct, os -import machine, stm -from micropython import const + +try: + import machine, stm + from ubinascii import crc32 + from micropython import const +except ImportError: + # cpython + from binascii import crc32 + + machine = stm = None + const = lambda x: x + _OGF_VENDOR = const(0x3F) @@ -174,13 +192,6 @@ _PATH_FUS_102 = "fus_102.bin" _PATH_FUS_110 = "fus_110.bin" _PATH_WS_BLE_HCI = "ws_ble_hci.bin" -# This address is correct for versions up to v1.8 (assuming existing firmware deleted). -# Note any address from the end of the filesystem to the SFSA would be fine, but if -# the FUS is fixed in the future to use the specified address then these are the "correct" -# ones. -_ADDR_FUS = 0x080EC000 -_ADDR_WS_BLE_HCI = 0x080DC000 - # When installing the FUS/WS it can take a long time to return to the first # GET_STATE HCI command. # e.g. Installing stm32wb5x_BLE_Stack_full_fw.bin takes 3600ms to respond. @@ -242,10 +253,79 @@ class _Flash: machine.mem32[stm.FLASH + stm.FLASH_CR] = 0 -def _copy_file_to_flash(filename, addr): +def validate_crc(f): + """Should match copy of function in rfcore_makefirmware.py to confirm operation""" + f.seek(0) + file_crc = 0 + chunk = 16 * 1024 + buff = bytearray(chunk) + while True: + read = f.readinto(buff) + if read < chunk: + file_crc = crc32(buff[0:read], file_crc) + break + file_crc = crc32(buff, file_crc) + + file_crc = 0xFFFFFFFF & -file_crc - 1 + f.seek(0) + return file_crc == 0 + + +def check_file_details(filename): + with open(filename, "rb") as f: + if not validate_crc(f): + raise ValueError("file validation failed: incorrect crc") + + # Check the footer on the file + f.seek(-64, 2) + footer = f.read() + details = struct.unpack("<37sIIIIbbbII", footer) + ( + src_filename, + addr_1m, + addr_640k, + addr_512k, + addr_256k, + vers_major, + vers_minor, + vers_patch, + KEY, + crc, + ) = details + src_filename = src_filename.strip(b"\x00").decode() + if KEY != _OBFUSCATION_KEY: + raise ValueError("file validation failed: incorrect key") + + return ( + src_filename, + addr_1m, + addr_640k, + addr_512k, + addr_256k, + (vers_major, vers_minor, vers_patch), + ) + + +def _copy_file_to_flash(filename): flash = _Flash() flash.unlock() + # Reset any previously stored address + _write_target_addr(0) try: + ( + src_filename, + addr_1m, + addr_640k, + addr_512k, + addr_256k, + vers, + ) = check_file_details(filename) + + # TODO add support for querying the correct flash size on chip + addr = load_addr = addr_1m + + log(f"Writing {src_filename} v{vers[0]}.{vers[1]}.{vers[2]} to addr: 0x{addr:x}") + # Erase the entire staging area in flash. erase_addr = STAGING_AREA_START sfr_sfsa = machine.mem32[stm.FLASH + stm.FLASH_SFR] & 0xFF @@ -266,6 +346,9 @@ def _copy_file_to_flash(filename, addr): flash.write(addr, buf, sz, _OBFUSCATION_KEY) addr += 4096 + # Cache the intended target load address + _write_target_addr(load_addr) + finally: flash.lock() @@ -308,17 +391,25 @@ def _fus_fwdelete(): return _run_sys_hci_cmd(_OGF_VENDOR, _OCF_FUS_FW_DELETE) -def _fus_run_fwupgrade(addr): +def _fus_run_fwupgrade(): # Note: Address is ignored by the FUS (see comments above). + addr = _read_target_addr() + if not addr: + log(f"Update failed: Invalid load address: 0x{addr:x}") + return False + + log(f"Loading to: 0x{addr:x}") return _run_sys_hci_cmd(_OGF_VENDOR, _OCF_FUS_FW_UPGRADE, struct.pack("= _FUS_VERSION_102 and fus_version < _FUS_VERSION_110: log("FUS 1.0.2 detected") - if _stat_and_start_copy( - _PATH_FUS_110, _ADDR_FUS, _STATE_COPYING_FUS, _STATE_COPIED_FUS - ): + if _stat_and_start_copy(_PATH_FUS_110, _STATE_COPYING_FUS, _STATE_COPIED_FUS): continue else: log("FUS is up-to-date") if fus_version >= _FUS_VERSION_110: if _stat_and_start_copy( - _PATH_WS_BLE_HCI, _ADDR_WS_BLE_HCI, _STATE_COPYING_WS, _STATE_COPIED_WS + _PATH_WS_BLE_HCI, + _STATE_COPYING_WS, + _STATE_COPIED_WS, ): continue else: @@ -465,7 +562,7 @@ def resume(): if fus_is_idle(): log("FUS copy complete, installing") _write_state(_STATE_INSTALLING_FUS) - _fus_run_fwupgrade(_ADDR_FUS) + _fus_run_fwupgrade() else: log("FUS copy bad state") _write_failure_state(REASON_FLASH_FUS_BAD_STATE) @@ -519,7 +616,7 @@ def resume(): if fus_is_idle(): log("WS copy complete, installing") _write_state(_STATE_INSTALLING_WS) - _fus_run_fwupgrade(_ADDR_WS_BLE_HCI) + _fus_run_fwupgrade() else: log("WS copy bad state") _write_failure_state(REASON_FLASH_WS_BAD_STATE) @@ -556,9 +653,59 @@ def resume(): _write_failure_state(REASON_WS_VENDOR + result) +def install_boot(): + boot_py = "/flash/boot.py" + header = "" + mode = "w" + try: + with open(boot_py, "r") as boot: + header = "\n" + mode = "a" + for line in boot: + if "rfcore_firmware.resume()" in line: + print("Already installed.") + return + + print("boot.py exists, adding upgrade handler.") + except OSError: + print("boot.py doesn't exists, adding with upgrade handler.") + + with open(boot_py, mode) as boot: + boot.write(header) + boot.write("# Handle rfcore updates.\n") + boot.write("import rfcore_firmware\n") + boot.write("rfcore_firmware.resume()\n") + + # Start a firmware update. # This will immediately trigger a reset and start the update process on boot. -def check_for_updates(): - log("Starting firmware update") - _write_state(_STATE_WAITING_FOR_FUS) - machine.reset() +def check_for_updates(force=False): + ( + src_filename, + addr_1m, + addr_640k, + addr_512k, + addr_256k, + vers_fus, + ) = check_file_details(_PATH_FUS_110) + ( + src_filename, + addr_1m, + addr_640k, + addr_512k, + addr_256k, + vers_ws, + ) = check_file_details(_PATH_WS_BLE_HCI) + current_version_fus = stm.rfcore_fw_version(_FW_VERSION_FUS) + fus_uptodate = current_version_fus[0:3] == vers_fus + + current_version_ws = stm.rfcore_fw_version(_FW_VERSION_WS) + ws_uptodate = current_version_ws[0:3] == vers_ws + if fus_uptodate and ws_uptodate and not force: + log(f"Already up to date: fus: {current_version_fus}, ws: {current_version_ws}") + else: + log(f"Starting firmware update") + log(f" - fus: {current_version_fus} -> {vers_fus}") + log(f" - ws: {current_version_ws} -> {vers_ws}") + _write_state(_STATE_WAITING_FOR_FUS) + machine.reset() diff --git a/ports/stm32/boards/NUCLEO_WB55/rfcore_makefirmware.py b/ports/stm32/boards/NUCLEO_WB55/rfcore_makefirmware.py index 23f3d20f0c..6b2fb60892 100755 --- a/ports/stm32/boards/NUCLEO_WB55/rfcore_makefirmware.py +++ b/ports/stm32/boards/NUCLEO_WB55/rfcore_makefirmware.py @@ -30,28 +30,70 @@ # rfcore_firmware.py as well as instructions on how to use. import os +import re import struct import sys +from binascii import crc32 +from rfcore_firmware import validate_crc, _OBFUSCATION_KEY -# Must match rfcore_firmware.py. -_OBFUSCATION_KEY = 0x0573B55AA _FIRMWARE_FILES = { "stm32wb5x_FUS_fw_1_0_2.bin": "fus_102.bin", "stm32wb5x_FUS_fw.bin": "fus_110.bin", "stm32wb5x_BLE_HCILayer_fw.bin": "ws_ble_hci.bin", } +_RELEASE_NOTES = "Release_Notes.html" + + +def get_details(release_notes, filename): + if not release_notes: + return None + file_details = re.findall( + rb"%s,(((0x[\d\S]+?),)+[vV][\d\.]+)[<,]" % filename.encode(), + release_notes, + flags=re.DOTALL, + ) + # The release note has all past version details also, but current is at top + latest_details = file_details[0][0].split(b",") + addr_1m, addr_640k, addr_512k, addr_256k, version = latest_details + addr_1m = int(addr_1m, 0) + addr_640k = int(addr_640k, 0) + addr_512k = int(addr_512k, 0) + addr_256k = int(addr_256k, 0) + version = [int(v) for v in version.lower().lstrip(b"v").split(b".")] + return addr_1m, addr_640k, addr_512k, addr_256k, version def main(src_path, dest_path): - for src_file, dest_file in _FIRMWARE_FILES.items(): - src_file = os.path.join(src_path, src_file) + + # Load the release note to parse for important details + with open(os.path.join(src_path, _RELEASE_NOTES), "rb") as f: + release_notes = f.read() + # remove some formatting + release_notes = re.sub(rb"", b"", release_notes) + # flatten tables + release_notes = re.sub( + rb"\W*\n*\W*", + b",", + release_notes.replace(b"", b"").replace(b"", b""), + ) + if ( + b"Wireless Coprocessor Binary,STM32WB5xxG(1M),STM32WB5xxY(640k),STM32WB5xxE(512K),STM32WB5xxC(256K),Version," + not in release_notes + ): + raise SystemExit( + "Cannot determine binary load address, please confirm Coprocessor folder / Release Notes format." + ) + + for src_filename, dest_file in _FIRMWARE_FILES.items(): + src_file = os.path.join(src_path, src_filename) dest_file = os.path.join(dest_path, dest_file) if not os.path.exists(src_file): print("Unable to find: {}".format(src_file)) continue sz = 0 with open(src_file, "rb") as src: + crc = 0 with open(dest_file, "wb") as dest: while True: b = src.read(4) @@ -59,9 +101,71 @@ def main(src_path, dest_path): break (v,) = struct.unpack(" Date: Sat, 23 Jul 2022 13:38:32 +0800 Subject: [PATCH 0243/1041] mpy-cross/Makefile: Respect existing CFLAGS and LDFLAGS. --- mpy-cross/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mpy-cross/Makefile b/mpy-cross/Makefile index 2189dff905..4b6e03df8e 100644 --- a/mpy-cross/Makefile +++ b/mpy-cross/Makefile @@ -19,7 +19,7 @@ INC += -I$(TOP) # compiler settings CWARN = -Wall -Werror CWARN += -Wextra -Wno-unused-parameter -Wpointer-arith -CFLAGS = $(INC) $(CWARN) -std=gnu99 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) +CFLAGS += $(INC) $(CWARN) -std=gnu99 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) CFLAGS += -fdata-sections -ffunction-sections -fno-asynchronous-unwind-tables # Debugging/Optimization @@ -42,7 +42,7 @@ else # Use gcc syntax for map file LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref -Wl,--gc-sections endif -LDFLAGS = $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA) +LDFLAGS += $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA) # source files SRC_C = \ From 736b427220ae0689694fc784bd4426605d556c4c Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 27 Jul 2022 10:45:38 +0200 Subject: [PATCH 0244/1041] extmod/network_wiznet5k: Register NIC when the lwIP stack is used. That was missing, and network.route() returned an empty list. --- extmod/network_wiznet5k.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extmod/network_wiznet5k.c b/extmod/network_wiznet5k.c index f328276a5b..fecb6ae8c2 100644 --- a/extmod/network_wiznet5k.c +++ b/extmod/network_wiznet5k.c @@ -224,6 +224,9 @@ STATIC void wiznet5k_init(void) { netif_set_link_up(&wiznet5k_obj.netif); netif_set_up(&wiznet5k_obj.netif); + + // register with network module + mod_network_register_nic(&wiznet5k_obj); } void wiznet5k_deinit(void) { From be2beab71a1a1047299601af70e99053fac508e5 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 27 Jul 2022 10:51:03 +0200 Subject: [PATCH 0245/1041] extmod/network_wiznet5k: Drop obsolete argument count check. Drop an obsolete and wrong argument check, which prevented specifying a pin for the interrupt signal. The proper checks are now done further down in the code. --- extmod/network_wiznet5k.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/extmod/network_wiznet5k.c b/extmod/network_wiznet5k.c index fecb6ae8c2..02bf90244d 100644 --- a/extmod/network_wiznet5k.c +++ b/extmod/network_wiznet5k.c @@ -689,10 +689,8 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size #endif #ifdef MICROPY_HW_WIZNET_SPI_ID - // check arguments - mp_arg_check_num(n_args, n_kw, 0, 3, false); // Allow auto-configuration of SPI if defined for board and no args passed - if (n_args == 0) { + if (n_args == 0 && n_kw == 0) { // Initialize SPI. mp_obj_t spi_obj = MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_SPI_SCK); mp_obj_t miso_obj = MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_SPI_MISO); From 73699a846c031ecde70cf6bd629ef9a8232291e3 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 27 Jul 2022 21:01:29 +0200 Subject: [PATCH 0246/1041] extmod/network_wiznet5k: Deinit the NIC before (re-)initialisation. If nic.active(True) is called several times in a row, the device may lock up. Even if that is bad coding practice, calling wiznet5k_deinit() in wiznet5k_init() prevents the lock. --- extmod/network_wiznet5k.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/extmod/network_wiznet5k.c b/extmod/network_wiznet5k.c index 02bf90244d..5a26c08952 100644 --- a/extmod/network_wiznet5k.c +++ b/extmod/network_wiznet5k.c @@ -198,6 +198,16 @@ STATIC void wiznet5k_config_interrupt(bool enabled) { ); } +void wiznet5k_deinit(void) { + for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { + if (netif == &wiznet5k_obj.netif) { + netif_remove(netif); + netif->flags = 0; + break; + } + } +} + STATIC void wiznet5k_init(void) { // Configure wiznet for raw ethernet frame usage. @@ -219,6 +229,9 @@ STATIC void wiznet5k_init(void) { wiznet5k_config_interrupt(true); } + // Deinit before a new init to clear the state from a previous activation + wiznet5k_deinit(); + // Hook the Wiznet into lwIP wiznet5k_lwip_init(&wiznet5k_obj); @@ -229,16 +242,6 @@ STATIC void wiznet5k_init(void) { mod_network_register_nic(&wiznet5k_obj); } -void wiznet5k_deinit(void) { - for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { - if (netif == &wiznet5k_obj.netif) { - netif_remove(netif); - netif->flags = 0; - break; - } - } -} - STATIC void wiznet5k_send_ethernet(wiznet5k_obj_t *self, size_t len, const uint8_t *buf) { uint8_t ip[4] = {1, 1, 1, 1}; // dummy int ret = WIZCHIP_EXPORT(sendto)(0, (byte *)buf, len, ip, 11); // dummy port From 999b66d53108a014194e7a30f20d4a269fdda6b4 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 29 Jul 2022 08:22:42 +0200 Subject: [PATCH 0247/1041] extmod/network_wiznet5k: Schedule clearing of interrupt flags. Avoiding conflicts between the IRQ and an active transfers. Before this change the device could lock up in heavy traffic situations. Fix found and code supplied by @omogenot. --- extmod/network_wiznet5k.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/extmod/network_wiznet5k.c b/extmod/network_wiznet5k.c index 5a26c08952..bdf94993d1 100644 --- a/extmod/network_wiznet5k.c +++ b/extmod/network_wiznet5k.c @@ -177,11 +177,10 @@ STATIC void wiznet5k_lwip_init(wiznet5k_obj_t *self); STATIC mp_obj_t mpy_wiznet_read_int(mp_obj_t none_in) { (void)none_in; - wizchip_clrinterrupt(IK_SOCK_0); - setSn_IR(0, Sn_IR_RECV); - - // Handle incoming data - wiznet5k_try_poll(); + // Handle incoming data, unless the SPI bus is busy + if (mp_hal_pin_read(wiznet5k_obj.cs)) { + wiznet5k_try_poll(); + } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mpy_wiznet_read_int_obj, mpy_wiznet_read_int); @@ -343,6 +342,10 @@ void wiznet5k_poll(void) { } } } + wizchip_clrinterrupt(IK_SOCK_0); + #if _WIZCHIP_ == W5100S + setSn_IR(0, Sn_IR_RECV); // W5100S driver bug: must write to the Sn_IR register to reset the IRQ signal + #endif } #endif // MICROPY_PY_LWIP From f000ac9e824cfa2f2f3e50d902e80b576367b4c1 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 30 Jul 2022 12:30:09 +0200 Subject: [PATCH 0248/1041] extmod/network_wiznet5k: Rearrange the function wiznet5k_poll(). To have just one exit and a more compact flag test. This is just a style change without impact to the functionality. --- extmod/network_wiznet5k.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/extmod/network_wiznet5k.c b/extmod/network_wiznet5k.c index bdf94993d1..c862f16c0e 100644 --- a/extmod/network_wiznet5k.c +++ b/extmod/network_wiznet5k.c @@ -325,20 +325,18 @@ STATIC void wiznet5k_lwip_init(wiznet5k_obj_t *self) { void wiznet5k_poll(void) { wiznet5k_obj_t *self = &wiznet5k_obj; - if (!(self->netif.flags & NETIF_FLAG_UP) || - !(self->netif.flags & NETIF_FLAG_LINK_UP)) { - return; - } - uint16_t len; - while ((len = wiznet5k_recv_ethernet(self)) > 0) { - if (self->trace_flags & TRACE_ETH_RX) { - netutils_ethernet_trace(MP_PYTHON_PRINTER, len, self->eth_frame, NETUTILS_TRACE_NEWLINE); - } - struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); - if (p != NULL) { - pbuf_take(p, self->eth_frame, len); - if (self->netif.input(p, &self->netif) != ERR_OK) { - pbuf_free(p); + if ((self->netif.flags & (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) == (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) { + uint16_t len; + while ((len = wiznet5k_recv_ethernet(self)) > 0) { + if (self->trace_flags & TRACE_ETH_RX) { + netutils_ethernet_trace(MP_PYTHON_PRINTER, len, self->eth_frame, NETUTILS_TRACE_NEWLINE); + } + struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + if (p != NULL) { + pbuf_take(p, self->eth_frame, len); + if (self->netif.input(p, &self->netif) != ERR_OK) { + pbuf_free(p); + } } } } From af6d2845fad4fde2d36f220efce876a4b1facdaa Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 10 Aug 2022 00:53:13 +1000 Subject: [PATCH 0249/1041] extmod/network_wiznet5k: Extract SPI transfer function dynamically. Instead of using the fixed machine_spi_type entity to get the SPI transfer function, this transfer function is now extracted dynamically from the type of the SPI object. This allows the SPI object used to communicate with the WIZNET5K hardware to be SoftSPI or hardware SPI, or anything that has the SPI protocol (at the C level). Signed-off-by: Damien George --- extmod/network_wiznet5k.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/extmod/network_wiznet5k.c b/extmod/network_wiznet5k.c index c862f16c0e..89c933c2d4 100644 --- a/extmod/network_wiznet5k.c +++ b/extmod/network_wiznet5k.c @@ -91,12 +91,11 @@ #endif #endif -extern struct _machine_spi_obj_t *spi_from_mp_obj(mp_obj_t o); - typedef struct _wiznet5k_obj_t { mp_obj_base_t base; mp_uint_t cris_state; - struct _machine_spi_obj_t *spi; + mp_obj_base_t *spi; + void (*spi_transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest); mp_hal_pin_obj_t cs; mp_hal_pin_obj_t rst; #if WIZNET5K_WITH_LWIP_STACK @@ -148,21 +147,21 @@ void mpy_wiznet_yield(void) { } STATIC void wiz_spi_read(uint8_t *buf, uint16_t len) { - ((mp_machine_spi_p_t *)machine_spi_type.protocol)->transfer((mp_obj_base_t *)wiznet5k_obj.spi, len, buf, buf); + wiznet5k_obj.spi_transfer(wiznet5k_obj.spi, len, buf, buf); } STATIC void wiz_spi_write(const uint8_t *buf, uint16_t len) { - ((mp_machine_spi_p_t *)machine_spi_type.protocol)->transfer((mp_obj_base_t *)wiznet5k_obj.spi, len, buf, NULL); + wiznet5k_obj.spi_transfer(wiznet5k_obj.spi, len, buf, NULL); } STATIC uint8_t wiz_spi_readbyte() { uint8_t buf = 0; - ((mp_machine_spi_p_t *)machine_spi_type.protocol)->transfer((mp_obj_base_t *)wiznet5k_obj.spi, 1, &buf, &buf); + wiznet5k_obj.spi_transfer(wiznet5k_obj.spi, 1, &buf, &buf); return buf; } STATIC void wiz_spi_writebyte(const uint8_t buf) { - ((mp_machine_spi_p_t *)machine_spi_type.protocol)->transfer((mp_obj_base_t *)wiznet5k_obj.spi, 1, &buf, NULL); + wiznet5k_obj.spi_transfer(wiznet5k_obj.spi, 1, &buf, NULL); } STATIC void wiznet5k_get_mac_address(wiznet5k_obj_t *self, uint8_t mac[6]) { @@ -680,7 +679,7 @@ STATIC void wiznet5k_dhcp_init(wiznet5k_obj_t *self) { // WIZNET5K(spi, pin_cs, pin_rst[, pin_intn]) // Create and return a WIZNET5K object. STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - struct _machine_spi_obj_t *spi; + mp_obj_base_t *spi; mp_hal_pin_obj_t cs; mp_hal_pin_obj_t rst; @@ -706,7 +705,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size MP_ROM_QSTR(MP_QSTR_miso), mp_pin_make_new(NULL, 1, 0, &miso_obj), MP_ROM_QSTR(MP_QSTR_mosi), mp_pin_make_new(NULL, 1, 0, &mosi_obj), }; - spi = machine_spi_type.make_new((mp_obj_t)&machine_spi_type, 2, 3, args); + spi = MP_OBJ_TO_PTR(machine_spi_type.make_new((mp_obj_t)&machine_spi_type, 2, 3, args)); cs = mp_hal_get_pin_obj(mp_pin_make_new(NULL, 1, 0, (mp_obj_t[]) {MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_PIN_CS)})); rst = mp_hal_get_pin_obj(mp_pin_make_new(NULL, 1, 0, (mp_obj_t[]) {MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_PIN_RST)})); @@ -724,7 +723,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size #else mp_arg_check_num(n_args, n_kw, 3, 3, false); #endif - spi = spi_from_mp_obj(args[0]); + spi = mp_hal_get_spi_obj(args[0]); cs = mp_hal_get_pin_obj(args[1]); rst = mp_hal_get_pin_obj(args[2]); #if WIZNET5K_WITH_LWIP_STACK @@ -742,6 +741,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size wiznet5k_obj.base.type = (mp_obj_type_t *)&mod_network_nic_type_wiznet5k; wiznet5k_obj.cris_state = 0; wiznet5k_obj.spi = spi; + wiznet5k_obj.spi_transfer = ((mp_machine_spi_p_t *)spi->type->protocol)->transfer; wiznet5k_obj.cs = cs; wiznet5k_obj.rst = rst; #if WIZNET5K_WITH_LWIP_STACK From f72d3cec2338e88b9aa6e28d345f0007042d692b Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 10 Aug 2022 00:52:03 +1000 Subject: [PATCH 0250/1041] rp2/machine_spi: Add mp_hal_get_spi_obj helper function. And remove the now-obsolete spi_from_mp_obj() function. Signed-off-by: Damien George --- ports/rp2/machine_spi.c | 23 ++++++++++++++--------- ports/rp2/mphalport.h | 2 ++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/ports/rp2/machine_spi.c b/ports/rp2/machine_spi.c index 742a3cfddf..42998664a7 100644 --- a/ports/rp2/machine_spi.c +++ b/ports/rp2/machine_spi.c @@ -269,15 +269,6 @@ STATIC void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8 } } -machine_spi_obj_t *spi_from_mp_obj(mp_obj_t o) { - if (mp_obj_is_type(o, &machine_spi_type)) { - machine_spi_obj_t *self = MP_OBJ_TO_PTR(o); - return self; - } else { - mp_raise_TypeError(MP_ERROR_TEXT("expecting an SPI object")); - } -} - STATIC const mp_machine_spi_p_t machine_spi_p = { .init = machine_spi_init, .transfer = machine_spi_transfer, @@ -291,3 +282,17 @@ const mp_obj_type_t machine_spi_type = { .protocol = &machine_spi_p, .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict, }; + +mp_obj_base_t *mp_hal_get_spi_obj(mp_obj_t o) { + if (mp_obj_is_type(o, &machine_spi_type)) { + return MP_OBJ_TO_PTR(o); + } + #if MICROPY_PY_MACHINE_SOFTSPI + else if (mp_obj_is_type(o, &mp_machine_soft_spi_type)) { + return MP_OBJ_TO_PTR(o); + } + #endif + else { + mp_raise_TypeError(MP_ERROR_TEXT("expecting an SPI object")); + } +} diff --git a/ports/rp2/mphalport.h b/ports/rp2/mphalport.h index 88683d9360..31bedf3381 100644 --- a/ports/rp2/mphalport.h +++ b/ports/rp2/mphalport.h @@ -148,6 +148,8 @@ enum mp_hal_pin_interrupt_trigger { void mp_hal_pin_interrupt(mp_hal_pin_obj_t pin, mp_obj_t handler, mp_uint_t trigger, bool hard); +mp_obj_base_t *mp_hal_get_spi_obj(mp_obj_t spi_in); + enum { MP_HAL_MAC_WLAN0 = 0, MP_HAL_MAC_BDADDR, From 7d91a9bf5b30c11ea2dcf90e8b3d031e40b6e985 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 10 Aug 2022 14:09:02 +1000 Subject: [PATCH 0251/1041] py/mpprint: Fix formatting typo with mp_print_ext_t struct name. Signed-off-by: Damien George --- py/mpprint.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/mpprint.h b/py/mpprint.h index 0dff9a770a..8383ea8579 100644 --- a/py/mpprint.h +++ b/py/mpprint.h @@ -56,7 +56,7 @@ typedef struct _mp_print_ext_t { mp_print_t base; const char *item_separator; const char *key_separator; -}mp_print_ext_t; +} mp_print_ext_t; #define MP_PRINT_GET_EXT(print) ((mp_print_ext_t *)print) From b5986784e4341d7d34b97b2481567d842453732d Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 10 Aug 2022 14:09:22 +1000 Subject: [PATCH 0252/1041] py/objstr: Reformat str access macros to make them readable. Signed-off-by: Damien George --- py/objstr.h | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/py/objstr.h b/py/objstr.h index 8c450baed6..8f87c3018a 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -41,24 +41,38 @@ typedef struct _mp_obj_str_t { // use this macro to extract the string hash // warning: the hash can be 0, meaning invalid, and must then be explicitly computed from the data #define GET_STR_HASH(str_obj_in, str_hash) \ - mp_uint_t str_hash; if (mp_obj_is_qstr(str_obj_in)) \ - { str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t *)MP_OBJ_TO_PTR(str_obj_in))->hash; } + mp_uint_t str_hash; \ + if (mp_obj_is_qstr(str_obj_in)) { \ + str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); \ + } else { \ + str_hash = ((mp_obj_str_t *)MP_OBJ_TO_PTR(str_obj_in))->hash; \ + } // use this macro to extract the string length #define GET_STR_LEN(str_obj_in, str_len) \ - size_t str_len; if (mp_obj_is_qstr(str_obj_in)) \ - { str_len = qstr_len(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_len = ((mp_obj_str_t *)MP_OBJ_TO_PTR(str_obj_in))->len; } + size_t str_len; \ + if (mp_obj_is_qstr(str_obj_in)) { \ + str_len = qstr_len(MP_OBJ_QSTR_VALUE(str_obj_in)); \ + } else { \ + str_len = ((mp_obj_str_t *)MP_OBJ_TO_PTR(str_obj_in))->len; \ + } // use this macro to extract the string data and length #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D const byte *mp_obj_str_get_data_no_check(mp_obj_t self_in, size_t *len); #define GET_STR_DATA_LEN(str_obj_in, str_data, str_len) \ - size_t str_len; const byte *str_data = mp_obj_str_get_data_no_check(str_obj_in, &str_len); + size_t str_len; \ + const byte *str_data = mp_obj_str_get_data_no_check(str_obj_in, &str_len); #else #define GET_STR_DATA_LEN(str_obj_in, str_data, str_len) \ - const byte *str_data; size_t str_len; if (mp_obj_is_qstr(str_obj_in)) \ - { str_data = qstr_data(MP_OBJ_QSTR_VALUE(str_obj_in), &str_len); } \ - else { str_len = ((mp_obj_str_t *)MP_OBJ_TO_PTR(str_obj_in))->len; str_data = ((mp_obj_str_t *)MP_OBJ_TO_PTR(str_obj_in))->data; } + const byte *str_data; \ + size_t str_len; \ + if (mp_obj_is_qstr(str_obj_in)) { \ + str_data = qstr_data(MP_OBJ_QSTR_VALUE(str_obj_in), &str_len); \ + } else { \ + str_len = ((mp_obj_str_t *)MP_OBJ_TO_PTR(str_obj_in))->len; \ + str_data = ((mp_obj_str_t *)MP_OBJ_TO_PTR(str_obj_in))->data; \ + } #endif mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args); From 5cfbf18d5fb70a907984781b3ac01aa5c27148be Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 10 Aug 2022 14:09:44 +1000 Subject: [PATCH 0253/1041] javascript/Makefile: Remove obsolete disable of array-bounds warning. This was fixed in bb70874111dbb246624a68c013e8f1c3245ca0d8 Signed-off-by: Damien George --- ports/javascript/Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/ports/javascript/Makefile b/ports/javascript/Makefile index 046d303336..93c7b5609b 100644 --- a/ports/javascript/Makefile +++ b/ports/javascript/Makefile @@ -53,7 +53,4 @@ test: $(BUILD)/micropython.js $(TOP)/tests/run-tests.py $(eval DIRNAME=ports/$(notdir $(CURDIR))) cd $(TOP)/tests && MICROPY_MICROPYTHON=../ports/javascript/node_run.sh ./run-tests.py -j1 -# Disable errors for array-bounds warnings on "sp[-MP_OBJ_ITER_BUF_NSLOTS + 2]" access. -$(BUILD)/py/vm.o: CFLAGS += -Wno-error=array-bounds - include $(TOP)/py/mkrules.mk From b2e82402688b53829f37475583231b067b9faea7 Mon Sep 17 00:00:00 2001 From: Daniel Jour Date: Tue, 2 Aug 2022 21:39:02 +0200 Subject: [PATCH 0254/1041] py/mkrules.mk: Keep all build artefacts inside $(BUILD) directory. The rules for lib (static library with name $(LIBMICROPYTHON)) and the default rule to build a binary (name $(PROG)) produced outputs in the current working directory. Change this to build these files in the build directory. Note: An empty BUILD variable can cause issues (references to the root directory); this is not addressed by this commit due to multiple other places having the same issue. --- py/mkrules.mk | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/py/mkrules.mk b/py/mkrules.mk index 41ec4b0641..af11678679 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -196,9 +196,9 @@ ifneq (,$(findstring mingw,$(COMPILER_TARGET))) PROG := $(PROG).exe endif -all: $(PROG) +all: $(BUILD)/$(PROG) -$(PROG): $(OBJ) +$(BUILD)/$(PROG): $(OBJ) $(ECHO) "LINK $@" # Do not pass COPT here - it's *C* compiler optimizations. For example, # we may want to compile using Thumb, but link with non-Thumb libc. @@ -210,8 +210,8 @@ endif clean: clean-prog clean-prog: - $(RM) -f $(PROG) - $(RM) -f $(PROG).map + $(RM) -f $(BUILD)/$(PROG) + $(RM) -f $(BUILD)/$(PROG).map .PHONY: clean-prog endif @@ -231,8 +231,8 @@ LIBMICROPYTHON = libmicropython.a # with 3rd-party projects which don't have proper dependency # tracking. Then LIBMICROPYTHON_EXTRA_CMD can e.g. touch some # other file to cause needed effect, e.g. relinking with new lib. -lib $(LIBMICROPYTHON): $(OBJ) - $(Q)$(AR) rcs $(LIBMICROPYTHON) $^ +lib $(BUILD)/$(LIBMICROPYTHON): $(OBJ) + $(Q)$(AR) rcs $(BUILD)/$(LIBMICROPYTHON) $^ $(LIBMICROPYTHON_EXTRA_CMD) clean: From 47c84286e8c8d9873e99f12711a683ecd6b9ca62 Mon Sep 17 00:00:00 2001 From: Daniel Jour Date: Tue, 2 Aug 2022 23:48:41 +0200 Subject: [PATCH 0255/1041] all: Fix paths to mpy-cross and micropython binaries. Binaries built using the Make build system now no longer appear in the working directory of the build, but rather in the build directory. Thus some paths had to be adjusted. --- .github/workflows/ports_unix.yml | 2 +- examples/embedding/Makefile | 2 +- ports/unix/Makefile | 22 +++++++++++----------- py/dynruntime.mk | 2 +- py/mkenv.mk | 2 +- py/mkrules.cmake | 2 +- py/mkrules.mk | 2 +- tests/run-natmodtests.py | 2 +- tests/run-tests.py | 6 ++++-- tools/ci.sh | 20 ++++++++++---------- tools/makemanifest.py | 2 +- 11 files changed, 33 insertions(+), 31 deletions(-) diff --git a/.github/workflows/ports_unix.yml b/.github/workflows/ports_unix.yml index 63cc1c0faa..ab2406647a 100644 --- a/.github/workflows/ports_unix.yml +++ b/.github/workflows/ports_unix.yml @@ -35,7 +35,7 @@ jobs: env: SOURCE_DATE_EPOCH: 1234567890 - name: Check reproducible build date - run: echo | ports/unix/micropython-minimal -i | grep 'on 2009-02-13;' + run: echo | ports/unix/build-minimal/micropython-minimal -i | grep 'on 2009-02-13;' standard: runs-on: ubuntu-latest diff --git a/examples/embedding/Makefile b/examples/embedding/Makefile index 99f239a7c5..7de1219b26 100644 --- a/examples/embedding/Makefile +++ b/examples/embedding/Makefile @@ -1,6 +1,6 @@ MPTOP = ../.. CFLAGS = -std=c99 -I. -I$(MPTOP) -DNO_QSTR -LDFLAGS = -L. +LDFLAGS = -L./build hello-embed: hello-embed.o -lmicropython diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 3b339c3d3f..709cc79853 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -304,18 +304,18 @@ include $(TOP)/py/mkrules.mk .PHONY: test test_full -test: $(PROG) $(TOP)/tests/run-tests.py +test: $(BUILD)/$(PROG) $(TOP)/tests/run-tests.py $(eval DIRNAME=ports/$(notdir $(CURDIR))) - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py -test_full: $(PROG) $(TOP)/tests/run-tests.py +test_full: $(BUILD)/$(PROG) $(TOP)/tests/run-tests.py $(eval DIRNAME=ports/$(notdir $(CURDIR))) - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py -d thread - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py --emit native - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py --via-mpy $(RUN_TESTS_MPY_CROSS_FLAGS) -d basics float micropython - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py --via-mpy $(RUN_TESTS_MPY_CROSS_FLAGS) --emit native -d basics float micropython - cat $(TOP)/tests/basics/0prelim.py | ./$(PROG) | grep -q 'abc' + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py -d thread + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py --emit native + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py --via-mpy $(RUN_TESTS_MPY_CROSS_FLAGS) -d basics float micropython + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py --via-mpy $(RUN_TESTS_MPY_CROSS_FLAGS) --emit native -d basics float micropython + cat $(TOP)/tests/basics/0prelim.py | ./$(BUILD)/$(PROG) | grep -q 'abc' test_gcov: test_full gcov -o $(BUILD)/py $(TOP)/py/*.c @@ -346,9 +346,9 @@ $(BUILD)/lib/libffi/include/ffi.h: $(TOP)/lib/libffi/configure PREFIX = /usr/local BINDIR = $(DESTDIR)$(PREFIX)/bin -install: $(PROG) +install: $(BUILD)/$(PROG) install -d $(BINDIR) - install $(PROG) $(BINDIR)/$(PROG) + install $(BUILD)/$(PROG) $(BINDIR)/$(PROG) uninstall: -rm $(BINDIR)/$(PROG) diff --git a/py/dynruntime.mk b/py/dynruntime.mk index 09cbb2dd37..10feefc4a7 100644 --- a/py/dynruntime.mk +++ b/py/dynruntime.mk @@ -7,7 +7,7 @@ ECHO = @echo RM = /bin/rm MKDIR = /bin/mkdir PYTHON = python3 -MPY_CROSS = $(MPY_DIR)/mpy-cross/mpy-cross +MPY_CROSS = $(MPY_DIR)/mpy-cross/build/mpy-cross MPY_TOOL = $(PYTHON) $(MPY_DIR)/tools/mpy-tool.py MPY_LD = $(PYTHON) $(MPY_DIR)/tools/mpy_ld.py diff --git a/py/mkenv.mk b/py/mkenv.mk index cc04a8c0b3..ea2e34f3b6 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -61,7 +61,7 @@ MPY_LIB_SUBMODULE_DIR = $(TOP)/lib/micropython-lib MPY_LIB_DIR = $(MPY_LIB_SUBMODULE_DIR) ifeq ($(MICROPY_MPYCROSS),) -MICROPY_MPYCROSS = $(TOP)/mpy-cross/mpy-cross +MICROPY_MPYCROSS = $(TOP)/mpy-cross/build/mpy-cross MICROPY_MPYCROSS_DEPENDENCY = $(MICROPY_MPYCROSS) endif diff --git a/py/mkrules.cmake b/py/mkrules.cmake index 2f168ede6f..e7c4101ddb 100644 --- a/py/mkrules.cmake +++ b/py/mkrules.cmake @@ -193,7 +193,7 @@ if(MICROPY_FROZEN_MANIFEST) # to automatically build mpy-cross if needed. set(MICROPY_MPYCROSS $ENV{MICROPY_MPYCROSS}) if(NOT MICROPY_MPYCROSS) - set(MICROPY_MPYCROSS_DEPENDENCY ${MICROPY_DIR}/mpy-cross/mpy-cross) + set(MICROPY_MPYCROSS_DEPENDENCY ${MICROPY_DIR}/mpy-cross/build/mpy-cross) if(NOT MICROPY_MAKE_EXECUTABLE) set(MICROPY_MAKE_EXECUTABLE make) endif() diff --git a/py/mkrules.mk b/py/mkrules.mk index af11678679..73c33227c0 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -162,7 +162,7 @@ $(HEADER_BUILD): ifneq ($(MICROPY_MPYCROSS_DEPENDENCY),) # to automatically build mpy-cross, if needed $(MICROPY_MPYCROSS_DEPENDENCY): - $(MAKE) -C $(dir $@) + $(MAKE) -C $(dir $@).. endif ifneq ($(FROZEN_DIR),) diff --git a/tests/run-natmodtests.py b/tests/run-natmodtests.py index 8eb27169c4..9130e00d6e 100755 --- a/tests/run-natmodtests.py +++ b/tests/run-natmodtests.py @@ -14,7 +14,7 @@ import pyboard # Paths for host executables CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") -MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/micropython-coverage") +MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/build-coverage/micropython-coverage") NATMOD_EXAMPLE_DIR = "../examples/natmod/" diff --git a/tests/run-tests.py b/tests/run-tests.py index 2745ee1393..8e9bd84313 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -33,14 +33,16 @@ if os.name == "nt": MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", base_path("../ports/windows/micropython.exe")) else: CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") - MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", base_path("../ports/unix/micropython")) + MICROPYTHON = os.getenv( + "MICROPY_MICROPYTHON", base_path("../ports/unix/build-standard/micropython") + ) # Use CPython options to not save .pyc files, to only access the core standard library # (not site packages which may clash with u-module names), and improve start up time. CPYTHON3_CMD = [CPYTHON3, "-BS"] # mpy-cross is only needed if --via-mpy command-line arg is passed -MPYCROSS = os.getenv("MICROPY_MPYCROSS", base_path("../mpy-cross/mpy-cross")) +MPYCROSS = os.getenv("MICROPY_MPYCROSS", base_path("../mpy-cross/build/mpy-cross")) # For diff'ing test output DIFF = os.getenv("MICROPY_DIFF", "diff -u") diff --git a/tools/ci.sh b/tools/ci.sh index 7e2479e43d..20119342cf 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -409,9 +409,9 @@ function ci_unix_run_tests_full_helper { variant=$1 shift if [ $variant = standard ]; then - micropython=micropython + micropython=build-$variant/micropython else - micropython=micropython-$variant + micropython=build-$variant/micropython-$variant fi make -C ports/unix VARIANT=$variant "$@" test_full (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/$micropython ./run-multitests.py multi_net/*.py) @@ -444,7 +444,7 @@ function ci_unix_minimal_build { } function ci_unix_minimal_run_tests { - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython-minimal ./run-tests.py -e exception_chain -e self_type_check -e subclass_native_init -d basics) + (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/build-minimal/micropython-minimal ./run-tests.py -e exception_chain -e self_type_check -e subclass_native_init -d basics) } function ci_unix_standard_build { @@ -491,21 +491,21 @@ function ci_unix_coverage_run_mpy_merge_tests { test=$(basename $inpy .py) echo $test outmpy=$outdir/$test.mpy - $mptop/mpy-cross/mpy-cross -o $outmpy $inpy - (cd $outdir && $mptop/ports/unix/micropython-coverage -m $test >> out-individual) + $mptop/mpy-cross/build/mpy-cross -o $outmpy $inpy + (cd $outdir && $mptop/ports/unix/build-coverage/micropython-coverage -m $test >> out-individual) allmpy+=($outmpy) done # Merge all the tests into one .mpy file, and then execute it. python3 $mptop/tools/mpy-tool.py --merge -o $outdir/merged.mpy ${allmpy[@]} - (cd $outdir && $mptop/ports/unix/micropython-coverage -m merged > out-merged) + (cd $outdir && $mptop/ports/unix/build-coverage/micropython-coverage -m merged > out-merged) # Make sure the outputs match. diff $outdir/out-individual $outdir/out-merged && /bin/rm -rf $outdir } function ci_unix_coverage_run_native_mpy_tests { - MICROPYPATH=examples/natmod/features2 ./ports/unix/micropython-coverage -m features2 + MICROPYPATH=examples/natmod/features2 ./ports/unix/build-coverage/micropython-coverage -m features2 (cd tests && ./run-natmodtests.py "$@" extmod/{btree*,framebuf*,uheapq*,urandom*,ure*,uzlib*}.py) } @@ -614,7 +614,7 @@ function ci_unix_macos_run_tests { # Issues with macOS tests: # - import_pkg7 has a problem with relative imports # - urandom_basic has a problem with getrandbits(0) - (cd tests && ./run-tests.py --exclude 'import_pkg7.py' --exclude 'urandom_basic.py') + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-standard/micropython ./run-tests.py --exclude 'import_pkg7.py' --exclude 'urandom_basic.py') } function ci_unix_qemu_mips_setup { @@ -634,7 +634,7 @@ function ci_unix_qemu_mips_run_tests { # - (i)listdir does not work, it always returns the empty list (it's an issue with the underlying C call) # - ffi tests do not work file ./ports/unix/micropython-coverage - (cd tests && MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests.py --exclude 'vfs_posix.py' --exclude 'ffi_(callback|float|float2).py') + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython-coverage ./run-tests.py --exclude 'vfs_posix.py' --exclude 'ffi_(callback|float|float2).py') } function ci_unix_qemu_arm_setup { @@ -654,7 +654,7 @@ function ci_unix_qemu_arm_run_tests { # - (i)listdir does not work, it always returns the empty list (it's an issue with the underlying C call) export QEMU_LD_PREFIX=/usr/arm-linux-gnueabi file ./ports/unix/micropython-coverage - (cd tests && MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests.py --exclude 'vfs_posix.py') + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython-coverage ./run-tests.py --exclude 'vfs_posix.py') } ######################################################################################## diff --git a/tools/makemanifest.py b/tools/makemanifest.py index 8cdc3eb774..e69698d3f2 100644 --- a/tools/makemanifest.py +++ b/tools/makemanifest.py @@ -329,7 +329,7 @@ def main(): sys.exit(1) # Get paths to tools - MPY_CROSS = VARS["MPY_DIR"] + "/mpy-cross/mpy-cross" + MPY_CROSS = VARS["MPY_DIR"] + "/mpy-cross/build/mpy-cross" if sys.platform == "win32": MPY_CROSS += ".exe" MPY_CROSS = os.getenv("MICROPY_MPYCROSS", MPY_CROSS) From 409995ac6828dc6bb70fcbe0bf9f26fd087ed22b Mon Sep 17 00:00:00 2001 From: Daniel Jour Date: Wed, 3 Aug 2022 01:32:51 +0200 Subject: [PATCH 0256/1041] tools/ci.sh: Force mpy-cross build for samd and teensy. --- tools/ci.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/ci.sh b/tools/ci.sh index 20119342cf..cf6fc41705 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -293,6 +293,7 @@ function ci_samd_setup { } function ci_samd_build { + make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/samd submodules make ${MAKEOPTS} -C ports/samd } @@ -356,6 +357,7 @@ function ci_teensy_setup { } function ci_teensy_build { + make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/teensy submodules make ${MAKEOPTS} -C ports/teensy } From c7aa6a2c73854af9c0e9561e9213ef20abccf246 Mon Sep 17 00:00:00 2001 From: Daniel Jour Date: Wed, 3 Aug 2022 16:29:55 +0200 Subject: [PATCH 0257/1041] tests/run-tests.py: Provide better default MPYCROSS value for Windows. --- tests/run-tests.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/run-tests.py b/tests/run-tests.py index 8e9bd84313..ca7941f626 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -31,18 +31,20 @@ def base_path(*p): if os.name == "nt": CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python") MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", base_path("../ports/windows/micropython.exe")) + # mpy-cross is only needed if --via-mpy command-line arg is passed + MPYCROSS = os.getenv("MICROPY_MPYCROSS", base_path("../mpy-cross/mpy-cross.exe")) else: CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") MICROPYTHON = os.getenv( "MICROPY_MICROPYTHON", base_path("../ports/unix/build-standard/micropython") ) + # mpy-cross is only needed if --via-mpy command-line arg is passed + MPYCROSS = os.getenv("MICROPY_MPYCROSS", base_path("../mpy-cross/build/mpy-cross")) # Use CPython options to not save .pyc files, to only access the core standard library # (not site packages which may clash with u-module names), and improve start up time. CPYTHON3_CMD = [CPYTHON3, "-BS"] -# mpy-cross is only needed if --via-mpy command-line arg is passed -MPYCROSS = os.getenv("MICROPY_MPYCROSS", base_path("../mpy-cross/build/mpy-cross")) # For diff'ing test output DIFF = os.getenv("MICROPY_DIFF", "diff -u") From d53c3b6ade01650f88972ccf7e3002d2b5a84ff6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 11 Aug 2022 12:40:23 +1000 Subject: [PATCH 0258/1041] unix/variants: Remove variant suffix from executable filename. The executable now lives in the build directory, and since the build directory already contains the variant name there is no need to also add it to the executable. Signed-off-by: Damien George --- .github/workflows/ports_unix.yml | 2 +- .../unix/variants/coverage/mpconfigvariant.mk | 2 -- ports/unix/variants/dev/mpconfigvariant.mk | 2 -- ports/unix/variants/fast/mpconfigvariant.mk | 2 -- .../unix/variants/freedos/mpconfigvariant.mk | 2 -- .../unix/variants/minimal/mpconfigvariant.mk | 1 - ports/unix/variants/nanbox/mpconfigvariant.mk | 1 - .../unix/variants/standard/mpconfigvariant.mk | 2 -- ports/windows/variants/dev/mpconfigvariant.mk | 2 -- tests/run-natmodtests.py | 2 +- tools/ci.sh | 26 ++++++++----------- tools/metrics.py | 4 +-- 12 files changed, 15 insertions(+), 33 deletions(-) diff --git a/.github/workflows/ports_unix.yml b/.github/workflows/ports_unix.yml index ab2406647a..45cc87e723 100644 --- a/.github/workflows/ports_unix.yml +++ b/.github/workflows/ports_unix.yml @@ -35,7 +35,7 @@ jobs: env: SOURCE_DATE_EPOCH: 1234567890 - name: Check reproducible build date - run: echo | ports/unix/build-minimal/micropython-minimal -i | grep 'on 2009-02-13;' + run: echo | ports/unix/build-minimal/micropython -i | grep 'on 2009-02-13;' standard: runs-on: ubuntu-latest diff --git a/ports/unix/variants/coverage/mpconfigvariant.mk b/ports/unix/variants/coverage/mpconfigvariant.mk index fac8c0d275..bbbb0432b5 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.mk +++ b/ports/unix/variants/coverage/mpconfigvariant.mk @@ -1,5 +1,3 @@ -PROG ?= micropython-coverage - # Disable optimisations and enable assert() on coverage builds. DEBUG ?= 1 diff --git a/ports/unix/variants/dev/mpconfigvariant.mk b/ports/unix/variants/dev/mpconfigvariant.mk index 78588d379b..058eda2f8d 100644 --- a/ports/unix/variants/dev/mpconfigvariant.mk +++ b/ports/unix/variants/dev/mpconfigvariant.mk @@ -1,5 +1,3 @@ -PROG ?= micropython-dev - FROZEN_MANIFEST ?= $(VARIANT_DIR)/manifest.py MICROPY_ROM_TEXT_COMPRESSION = 1 diff --git a/ports/unix/variants/fast/mpconfigvariant.mk b/ports/unix/variants/fast/mpconfigvariant.mk index 595e575645..b8fe69e487 100644 --- a/ports/unix/variants/fast/mpconfigvariant.mk +++ b/ports/unix/variants/fast/mpconfigvariant.mk @@ -2,6 +2,4 @@ COPT += -fno-crossjumping -O2 -PROG = micropython-fast - FROZEN_MANIFEST = diff --git a/ports/unix/variants/freedos/mpconfigvariant.mk b/ports/unix/variants/freedos/mpconfigvariant.mk index a30db3e0c1..86ab6864f4 100644 --- a/ports/unix/variants/freedos/mpconfigvariant.mk +++ b/ports/unix/variants/freedos/mpconfigvariant.mk @@ -10,8 +10,6 @@ CFLAGS += \ -DMICROPY_EMIT_X86=0 \ -DMICROPY_NO_ALLOCA=1 \ -PROG = micropython-freedos - MICROPY_PY_SOCKET = 0 MICROPY_PY_FFI = 0 MICROPY_PY_JNI = 0 diff --git a/ports/unix/variants/minimal/mpconfigvariant.mk b/ports/unix/variants/minimal/mpconfigvariant.mk index ec3b21c0b9..9d4ddab956 100644 --- a/ports/unix/variants/minimal/mpconfigvariant.mk +++ b/ports/unix/variants/minimal/mpconfigvariant.mk @@ -1,5 +1,4 @@ # build a minimal interpreter -PROG = micropython-minimal FROZEN_MANIFEST = diff --git a/ports/unix/variants/nanbox/mpconfigvariant.mk b/ports/unix/variants/nanbox/mpconfigvariant.mk index 9752b922c1..e588e657ef 100644 --- a/ports/unix/variants/nanbox/mpconfigvariant.mk +++ b/ports/unix/variants/nanbox/mpconfigvariant.mk @@ -1,4 +1,3 @@ # build interpreter with nan-boxing as object model (object repr D) -PROG = micropython-nanbox MICROPY_FORCE_32BIT = 1 diff --git a/ports/unix/variants/standard/mpconfigvariant.mk b/ports/unix/variants/standard/mpconfigvariant.mk index cf3efab8ae..def7987d8d 100644 --- a/ports/unix/variants/standard/mpconfigvariant.mk +++ b/ports/unix/variants/standard/mpconfigvariant.mk @@ -1,3 +1 @@ # This is the default variant when you `make` the Unix port. - -PROG ?= micropython diff --git a/ports/windows/variants/dev/mpconfigvariant.mk b/ports/windows/variants/dev/mpconfigvariant.mk index b2a0b5bb33..6d83f5b4db 100644 --- a/ports/windows/variants/dev/mpconfigvariant.mk +++ b/ports/windows/variants/dev/mpconfigvariant.mk @@ -1,5 +1,3 @@ -PROG ?= micropython-dev - FROZEN_MANIFEST ?= $(VARIANT_DIR)/manifest.py MICROPY_ROM_TEXT_COMPRESSION = 1 diff --git a/tests/run-natmodtests.py b/tests/run-natmodtests.py index 9130e00d6e..16bb469222 100755 --- a/tests/run-natmodtests.py +++ b/tests/run-natmodtests.py @@ -14,7 +14,7 @@ import pyboard # Paths for host executables CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") -MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/build-coverage/micropython-coverage") +MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/build-coverage/micropython") NATMOD_EXAMPLE_DIR = "../examples/natmod/" diff --git a/tools/ci.sh b/tools/ci.sh index cf6fc41705..e3203f8bfb 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -410,14 +410,10 @@ function ci_unix_run_tests_helper { function ci_unix_run_tests_full_helper { variant=$1 shift - if [ $variant = standard ]; then - micropython=build-$variant/micropython - else - micropython=build-$variant/micropython-$variant - fi + micropython=../ports/unix/build-$variant/micropython make -C ports/unix VARIANT=$variant "$@" test_full - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/$micropython ./run-multitests.py multi_net/*.py) - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/$micropython ./run-perfbench.py 1000 1000) + (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=$micropython ./run-multitests.py multi_net/*.py) + (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=$micropython ./run-perfbench.py 1000 1000) } function ci_native_mpy_modules_build { @@ -446,7 +442,7 @@ function ci_unix_minimal_build { } function ci_unix_minimal_run_tests { - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/build-minimal/micropython-minimal ./run-tests.py -e exception_chain -e self_type_check -e subclass_native_init -d basics) + (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/build-minimal/micropython ./run-tests.py -e exception_chain -e self_type_check -e subclass_native_init -d basics) } function ci_unix_standard_build { @@ -494,20 +490,20 @@ function ci_unix_coverage_run_mpy_merge_tests { echo $test outmpy=$outdir/$test.mpy $mptop/mpy-cross/build/mpy-cross -o $outmpy $inpy - (cd $outdir && $mptop/ports/unix/build-coverage/micropython-coverage -m $test >> out-individual) + (cd $outdir && $mptop/ports/unix/build-coverage/micropython -m $test >> out-individual) allmpy+=($outmpy) done # Merge all the tests into one .mpy file, and then execute it. python3 $mptop/tools/mpy-tool.py --merge -o $outdir/merged.mpy ${allmpy[@]} - (cd $outdir && $mptop/ports/unix/build-coverage/micropython-coverage -m merged > out-merged) + (cd $outdir && $mptop/ports/unix/build-coverage/micropython -m merged > out-merged) # Make sure the outputs match. diff $outdir/out-individual $outdir/out-merged && /bin/rm -rf $outdir } function ci_unix_coverage_run_native_mpy_tests { - MICROPYPATH=examples/natmod/features2 ./ports/unix/build-coverage/micropython-coverage -m features2 + MICROPYPATH=examples/natmod/features2 ./ports/unix/build-coverage/micropython -m features2 (cd tests && ./run-natmodtests.py "$@" extmod/{btree*,framebuf*,uheapq*,urandom*,ure*,uzlib*}.py) } @@ -635,8 +631,8 @@ function ci_unix_qemu_mips_run_tests { # Issues with MIPS tests: # - (i)listdir does not work, it always returns the empty list (it's an issue with the underlying C call) # - ffi tests do not work - file ./ports/unix/micropython-coverage - (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython-coverage ./run-tests.py --exclude 'vfs_posix.py' --exclude 'ffi_(callback|float|float2).py') + file ./ports/unix/build-coverage/micropython + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py --exclude 'vfs_posix.py' --exclude 'ffi_(callback|float|float2).py') } function ci_unix_qemu_arm_setup { @@ -655,8 +651,8 @@ function ci_unix_qemu_arm_run_tests { # Issues with ARM tests: # - (i)listdir does not work, it always returns the empty list (it's an issue with the underlying C call) export QEMU_LD_PREFIX=/usr/arm-linux-gnueabi - file ./ports/unix/micropython-coverage - (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython-coverage ./run-tests.py --exclude 'vfs_posix.py') + file ./ports/unix/build-coverage/micropython + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py --exclude 'vfs_posix.py') } ######################################################################################## diff --git a/tools/metrics.py b/tools/metrics.py index c79b998e18..da4d188568 100755 --- a/tools/metrics.py +++ b/tools/metrics.py @@ -60,8 +60,8 @@ class PortData: port_data = { "b": PortData("bare-arm", "bare-arm", "build/firmware.elf"), "m": PortData("minimal x86", "minimal", "build/firmware.elf"), - "u": PortData("unix x64", "unix", "micropython"), - "n": PortData("unix nanbox", "unix", "micropython-nanbox", "VARIANT=nanbox"), + "u": PortData("unix x64", "unix", "build-standard/micropython"), + "n": PortData("unix nanbox", "unix", "build-nanbox/micropython", "VARIANT=nanbox"), "s": PortData("stm32", "stm32", "build-PYBV10/firmware.elf", "BOARD=PYBV10"), "c": PortData("cc3200", "cc3200", "build/WIPY/release/application.axf", "BTARGET=application"), "8": PortData("esp8266", "esp8266", "build-GENERIC/firmware.elf"), From 2e8816de915244ee5612178711237f4f88d754ed Mon Sep 17 00:00:00 2001 From: Mat Booth Date: Sun, 31 Jul 2022 11:41:54 +0100 Subject: [PATCH 0259/1041] py/dynruntime.mk: Allow building assembly source in natmods. Allow inclusion of assembly source files in dynamic native modules. --- py/dynruntime.mk | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/py/dynruntime.mk b/py/dynruntime.mk index 10feefc4a7..62db43ad14 100644 --- a/py/dynruntime.mk +++ b/py/dynruntime.mk @@ -35,7 +35,7 @@ CFLAGS += -U _FORTIFY_SOURCE # prevent use of __*_chk libc functions MPY_CROSS_FLAGS += -march=$(ARCH) -SRC_O += $(addprefix $(BUILD)/, $(patsubst %.c,%.o,$(filter %.c,$(SRC)))) +SRC_O += $(addprefix $(BUILD)/, $(patsubst %.c,%.o,$(filter %.c,$(SRC))) $(patsubst %.S,%.o,$(filter %.S,$(SRC)))) SRC_MPY += $(addprefix $(BUILD)/, $(patsubst %.py,%.mpy,$(filter %.py,$(SRC)))) ################################################################################ @@ -134,6 +134,11 @@ $(BUILD)/%.o: %.c $(CONFIG_H) Makefile $(ECHO) "CC $<" $(Q)$(CROSS)gcc $(CFLAGS) -o $@ -c $< +# Build .o from .S source files +$(BUILD)/%.o: %.S $(CONFIG_H) Makefile + $(ECHO) "AS $<" + $(Q)$(CROSS)gcc $(CFLAGS) -o $@ -c $< + # Build .mpy from .py source files $(BUILD)/%.mpy: %.py $(ECHO) "MPY $<" From f3285fef07b4baa64cb05ef6dc034496cb0effdc Mon Sep 17 00:00:00 2001 From: Efi Weiss Date: Sun, 31 Jul 2022 22:16:49 +0300 Subject: [PATCH 0260/1041] py/nlrpowerpc: Fix generation of ppc64 code on ppc32 build. Due to inline assembly, wrong instructions were generated. Use corresponding 32 bit instructions and fix the offsets used. Signed-off-by: Efi Weiss --- py/nlrpowerpc.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/py/nlrpowerpc.c b/py/nlrpowerpc.c index 940d8562e1..448459216b 100644 --- a/py/nlrpowerpc.c +++ b/py/nlrpowerpc.c @@ -32,6 +32,8 @@ // Saving all ABI non-vol registers here +#ifdef __LP64__ + unsigned int nlr_push(nlr_buf_t *nlr) { __asm__ volatile ( @@ -118,4 +120,95 @@ NORETURN void nlr_jump(void *val) { MP_UNREACHABLE; } +#else +// Saving all ABI non-vol registers here + +unsigned int nlr_push(nlr_buf_t *nlr) { + + __asm__ volatile ( + "li 4, 0x4eed ; " // Store canary + "stw 4, 0x00(%0) ;" + "stw 0, 0x04(%0) ;" + "stw 1, 0x08(%0) ;" + "stw 2, 0x0c(%0) ;" + "stw 14, 0x10(%0) ;" + "stw 15, 0x14(%0) ;" + "stw 16, 0x18(%0) ;" + "stw 17, 0x1c(%0) ;" + "stw 18, 0x20(%0) ;" + "stw 19, 0x24(%0) ;" + "stw 20, 0x28(%0) ;" + "stw 21, 0x2c(%0) ;" + "stw 22, 0x30(%0) ;" + "stw 23, 0x34(%0) ;" + "stw 24, 0x38(%0) ;" + "stw 25, 0x3c(%0) ;" + "stw 26, 0x40(%0) ;" + "stw 27, 0x44(%0) ;" + "stw 28, 0x48(%0) ;" + "stw 29, 0x4c(%0) ;" + "stw 30, 0x50(%0) ;" + "stw 31, 0x54(%0) ;" + + "mfcr 4 ; " + "stw 4, 0x58(%0) ;" + "mflr 4 ;" + "stw 4, 0x5c(%0) ;" + "li 4, nlr_push_tail@l ;" + "oris 4, 4, nlr_push_tail@h ;" + "mtctr 4 ;" + "mr 3, %1 ; " + "bctr ;" + : + : "r" (&nlr->regs), "r" (nlr) + : + ); + + return 0; +} + +NORETURN void nlr_jump(void *val) { + MP_NLR_JUMP_HEAD(val, top) + + __asm__ volatile ( + "l 3, 0x0(%0) ;" + "cmpdi 3, 0x4eed ; " // Check canary + "bne . ; " + "l 0, 0x04(%0) ;" + "l 1, 0x08(%0) ;" + "l 2, 0x0c(%0) ;" + "l 14, 0x10(%0) ;" + "l 15, 0x14(%0) ;" + "l 16, 0x18(%0) ;" + "l 17, 0x1c(%0) ;" + "l 18, 0x20(%0) ;" + "l 19, 0x24(%0) ;" + "l 20, 0x28(%0) ;" + "l 21, 0x2c(%0) ;" + "l 22, 0x30(%0) ;" + "l 23, 0x34(%0) ;" + "l 24, 0x38(%0) ;" + "l 25, 0x3c(%0) ;" + "l 26, 0x40(%0) ;" + "l 27, 0x44(%0) ;" + "l 28, 0x48(%0) ;" + "l 29, 0x4c(%0) ;" + "l 30, 0x50(%0) ;" + "l 31, 0x54(%0) ;" + "l 3, 0x58(%0) ;" + "mtcr 3 ;" + "l 3, 0x5c(%0) ;" + "mtlr 3 ; " + "li 3, 1;" + "blr ;" + : + : "r" (&top->regs) + : + ); + + MP_UNREACHABLE; +} + +#endif // __LP64__ + #endif // MICROPY_NLR_POWERPC From 9c6fd974f769ef1e907c1a41f4a5d9b1c1774df7 Mon Sep 17 00:00:00 2001 From: Daniel Jour Date: Sun, 31 Jul 2022 18:01:13 +0200 Subject: [PATCH 0261/1041] minimal/Makefile: Avoid terminal reset, use BUILD variable. stty can provide the current terminal settings, so that they can be stored in a shell variable and restored after running the firmware. This avoids the complete "blanking" of the terminal, and thus also removes the need for the sleep call. The run target now references the firmware file using the BUILD variable instead of using the hard coded "build/" path. --- ports/minimal/Makefile | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ports/minimal/Makefile b/ports/minimal/Makefile index 169132a1a2..5ba6514c9e 100644 --- a/ports/minimal/Makefile +++ b/ports/minimal/Makefile @@ -103,12 +103,11 @@ deploy: $(BUILD)/firmware.dfu # Run emulation build on a POSIX system with suitable terminal settings run: - stty raw opost -echo - build/firmware.elf - @echo Resetting terminal... -# This sleep is useful to spot segfaults - sleep 1 - reset + @saved_=`stty -g`; \ + stty raw opost -echo; \ + $(BUILD)/firmware.elf; \ + echo "Exit status: $$?"; \ + stty $$saved_ test: $(BUILD)/firmware.elf $(Q)/bin/echo -e "print('hello world!', list(x+1 for x in range(10)), end='eol\\\\n')\\r\\n\\x04" | $(BUILD)/firmware.elf | tail -n2 | grep "^hello world! \\[1, 2, 3, 4, 5, 6, 7, 8, 9, 10\\]eol" From b6651a7a89a666ca76cdc03e065e339dbf3b9298 Mon Sep 17 00:00:00 2001 From: David Yang Date: Mon, 4 Jan 2021 23:22:08 +0800 Subject: [PATCH 0262/1041] unix/modjni: Add missing const qualifier. --- ports/unix/modjni.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/unix/modjni.c b/ports/unix/modjni.c index c86f30653c..6fa00731fb 100644 --- a/ports/unix/modjni.c +++ b/ports/unix/modjni.c @@ -376,7 +376,7 @@ STATIC const char *strprev(const char *s, char c) { STATIC bool py2jvalue(const char **jtypesig, mp_obj_t arg, jvalue *out) { const char *arg_type = *jtypesig; - mp_obj_type_t *type = mp_obj_get_type(arg); + const mp_obj_type_t *type = mp_obj_get_type(arg); if (type == &mp_type_str) { if (IMATCH(arg_type, "java.lang.String") || IMATCH(arg_type, "java.lang.Object")) { From 6e51dbd95aa051533e2618e2df8f51cb0f06cfed Mon Sep 17 00:00:00 2001 From: omogenot Date: Tue, 26 Jul 2022 16:36:10 +0200 Subject: [PATCH 0263/1041] rp2/boards/W5500_EVB_PICO: Add new board definition for W5500_EVB_PICO. Signed-off-by: github@mymeterinfo.info --- ports/rp2/boards/W5500_EVB_PICO/board.json | 20 +++++++++++++++++++ .../boards/W5500_EVB_PICO/mpconfigboard.cmake | 4 ++++ .../rp2/boards/W5500_EVB_PICO/mpconfigboard.h | 19 ++++++++++++++++++ ports/rp2/boards/W5500_EVB_PICO/readme.md | 18 +++++++++++++++++ 4 files changed, 61 insertions(+) create mode 100644 ports/rp2/boards/W5500_EVB_PICO/board.json create mode 100644 ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.cmake create mode 100644 ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.h create mode 100644 ports/rp2/boards/W5500_EVB_PICO/readme.md diff --git a/ports/rp2/boards/W5500_EVB_PICO/board.json b/ports/rp2/boards/W5500_EVB_PICO/board.json new file mode 100644 index 0000000000..90b3186cd6 --- /dev/null +++ b/ports/rp2/boards/W5500_EVB_PICO/board.json @@ -0,0 +1,20 @@ +{ + "deploy": [ + "../deploy.md" + ], + "docs": "", + "features": [ + "Breadboard Friendly", + "Castellated Pads", + "Ethernet", + "Micro USB" + ], + "images": [ + "W5500-EVB-Pico.jpg" + ], + "mcu": "rp2040", + "product": "Wiznet W5500-EVB-Pico", + "thumbnail": "", + "url": "https://www.wiznet.io/product-item/w5500-evb-pico/", + "vendor": "Wiznet" +} diff --git a/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.cmake b/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.cmake new file mode 100644 index 0000000000..875b89f2be --- /dev/null +++ b/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.cmake @@ -0,0 +1,4 @@ +# cmake file for Wiznet W5500-EVB-Pico. +set(PICO_BOARD pico) +set(MICROPY_PY_NETWORK_WIZNET5K W5500) +set(MICROPY_PY_LWIP 1) diff --git a/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.h b/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.h new file mode 100644 index 0000000000..1ad7a0e905 --- /dev/null +++ b/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.h @@ -0,0 +1,19 @@ +// Board config for Wiznet W5500-EVB-Pico. + +// Board and hardware specific configuration +#define MICROPY_HW_BOARD_NAME "W5500-EVB-Pico" +#define MICROPY_HW_FLASH_STORAGE_BYTES (1408 * 1024) + +// Enable networking. +#define MICROPY_PY_NETWORK (1) + +// Wiznet HW config. +#define MICROPY_HW_WIZNET_SPI_ID (0) +#define MICROPY_HW_WIZNET_SPI_BAUDRATE (20 * 1000 * 1000) +#define MICROPY_HW_WIZNET_SPI_SCK (18) +#define MICROPY_HW_WIZNET_SPI_MOSI (19) +#define MICROPY_HW_WIZNET_SPI_MISO (16) +#define MICROPY_HW_WIZNET_PIN_CS (17) +#define MICROPY_HW_WIZNET_PIN_RST (20) +// Connecting the INTN pin enables RECV interrupt handling of incoming data. +#define MICROPY_HW_WIZNET_PIN_INTN (21) diff --git a/ports/rp2/boards/W5500_EVB_PICO/readme.md b/ports/rp2/boards/W5500_EVB_PICO/readme.md new file mode 100644 index 0000000000..be28286695 --- /dev/null +++ b/ports/rp2/boards/W5500_EVB_PICO/readme.md @@ -0,0 +1,18 @@ +# Wiznet W5500-EVB-Pico + +## Network Example + +To use network / socket based code, connect ethernet port to network with DHCP running: + +``` +>>> import network +>>> nic = network.WIZNET5K() +>>> nic.active(True) +>>> nic.ifconfig() +('0.0.0.0', '0.0.0.0', '0.0.0.0', '0.0.0.0') +>>> nic.ifconfig("dhcp") +('192.168.0.10', '255.255.255.0', '192.168.0.1', '192.168.0.1') +>>> nic.isconnected() +True +``` +At this point standard network communications libraries should work. From 71f6eb5ac953637e815ec9c5cbc785b4027a8759 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Fri, 5 Aug 2022 09:43:22 +0100 Subject: [PATCH 0264/1041] rp2: Mark gc_heap NOLOAD for faster boot. Create a new linker section .unitialized_bss for bss that does not need zero-initialising. Move gc_heap to this section, which saves ~30ms from rising edge of RESET to setting a pin HIGH in MicroPython. Zero fill happens in Pico SDK crt0.S before ROSC is configured. It's very, very slow. Signed-off-by: Phil Howard --- ports/rp2/main.c | 2 +- ports/rp2/memmap_mp.ld | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ports/rp2/main.c b/ports/rp2/main.c index d976464de1..1062236a39 100644 --- a/ports/rp2/main.c +++ b/ports/rp2/main.c @@ -66,7 +66,7 @@ #endif extern uint8_t __StackTop, __StackBottom; -static char gc_heap[MICROPY_GC_HEAP_SIZE]; +__attribute__((section(".uninitialized_bss"))) static char gc_heap[MICROPY_GC_HEAP_SIZE]; // Embed version info in the binary in machine readable form bi_decl(bi_program_version_string(MICROPY_GIT_TAG)); diff --git a/ports/rp2/memmap_mp.ld b/ports/rp2/memmap_mp.ld index 0dc96743ea..82f9cb01c3 100644 --- a/ports/rp2/memmap_mp.ld +++ b/ports/rp2/memmap_mp.ld @@ -180,6 +180,12 @@ SECTIONS *(.uninitialized_data*) } > RAM + /* bss without zero init on startup */ + .uninitialized_bss (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_bss*) + } > RAM + /* Start and end symbols must be word-aligned */ .scratch_x : { __scratch_x_start__ = .; From 0546a12238b53f3243cc6ae5dfbb7bcac1d0be9a Mon Sep 17 00:00:00 2001 From: Jacob Siverskog Date: Tue, 9 Aug 2022 14:21:05 +0200 Subject: [PATCH 0265/1041] rp2: Correctly determine path to arm-none-eabi-size. Figure out path to arm-none-eabi-size the same way it's done for the other binaries, instead of assuming it to be in the user's $PATH. Signed-off-by: Jacob Siverskog --- ports/rp2/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index f5bd61c44e..37ac78b733 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -412,9 +412,11 @@ endif() pico_add_extra_outputs(${MICROPY_TARGET}) +pico_find_compiler(PICO_COMPILER_SIZE ${PICO_GCC_TRIPLE}-size) + add_custom_command(TARGET ${MICROPY_TARGET} POST_BUILD - COMMAND arm-none-eabi-size --format=berkeley ${PROJECT_BINARY_DIR}/${MICROPY_TARGET}.elf + COMMAND ${PICO_COMPILER_SIZE} --format=berkeley ${PROJECT_BINARY_DIR}/${MICROPY_TARGET}.elf VERBATIM ) From 888e831bf78518c367d40a6b77b29c6aab13a7f0 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 8 Jul 2022 13:47:54 -0500 Subject: [PATCH 0266/1041] docs: Update links for Arm GCC toolchain. The separate A and RM toolchains have been discontinued and replaced by a single toolchain. This updates the links to the RM toolchain to the new toolchain. Signed-off-by: David Lechner --- README.md | 2 +- docs/develop/gettingstarted.rst | 2 +- ports/qemu-arm/README.md | 2 +- ports/renesas-ra/README.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 920f10a503..6941102f0a 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,7 @@ The STM32 version The "stm32" port requires an ARM compiler, arm-none-eabi-gcc, and associated bin-utils. For those using Arch Linux, you need arm-none-eabi-binutils, arm-none-eabi-gcc and arm-none-eabi-newlib packages. Otherwise, try here: -https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm +https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads To build: diff --git a/docs/develop/gettingstarted.rst b/docs/develop/gettingstarted.rst index 36062ddc00..000b7d6139 100644 --- a/docs/develop/gettingstarted.rst +++ b/docs/develop/gettingstarted.rst @@ -103,7 +103,7 @@ For the stm32 port, the ARM cross-compiler is required: $ sudo apt-get install arm-none-eabi-gcc arm-none-eabi-binutils arm-none-eabi-newlib See the `ARM GCC -toolchain `_ +toolchain `_ for the latest details. Python is also required. Python 2 is supported for now, but we recommend using Python 3. diff --git a/ports/qemu-arm/README.md b/ports/qemu-arm/README.md index 2c815c54b0..f821c4d1e2 100644 --- a/ports/qemu-arm/README.md +++ b/ports/qemu-arm/README.md @@ -16,7 +16,7 @@ The purposes of this port are to enable: process in terms of plugging things together, pressing buttons, etc. This port will only work with the [GNU ARM Embedded Toolchain]( -https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm) +https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads and not with CodeSourcery toolchain. You will need to modify `LDFLAGS` if you want to use CodeSourcery's version of `arm-none-eabi`. The difference is that CodeSourcery needs `-T generic-m-hosted.ld` while diff --git a/ports/renesas-ra/README.md b/ports/renesas-ra/README.md index 482870e1c0..c75a9e13d1 100644 --- a/ports/renesas-ra/README.md +++ b/ports/renesas-ra/README.md @@ -36,7 +36,7 @@ All other commands below should be executed from the ports/renesas-ra/ directory * Arm compiler An `Arm compiler` is required for the build, along with the associated binary utilities. The default compiler is `arm-none-eabi-gcc`, which is available for -Arch Linux and Windows hosts via https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads. +Linux, Mac and Windows hosts via https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads. The compiler can be changed using the `CROSS_COMPILE` variable when invoking `make`. From 9bcb2c0a209f7970e63757a5f99dd23e010dbc48 Mon Sep 17 00:00:00 2001 From: Nathan Hendler Date: Sun, 31 Jul 2022 11:40:44 -0700 Subject: [PATCH 0267/1041] docs/library/rp2: Fix pull_thresh docs to use pull instead of push. --- docs/library/rp2.StateMachine.rst | 4 ++-- docs/library/rp2.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/library/rp2.StateMachine.rst b/docs/library/rp2.StateMachine.rst index 8d73ccf772..7e38ba8b1a 100644 --- a/docs/library/rp2.StateMachine.rst +++ b/docs/library/rp2.StateMachine.rst @@ -55,8 +55,8 @@ Methods `PIO.SHIFT_LEFT` or `PIO.SHIFT_RIGHT`. - *push_thresh* is the threshold in bits before auto-push or conditional re-pushing is triggered. - - *pull_thresh* is the threshold in bits before auto-push or conditional - re-pushing is triggered. + - *pull_thresh* is the threshold in bits before auto-pull or conditional + re-pulling is triggered. .. method:: StateMachine.active([value]) diff --git a/docs/library/rp2.rst b/docs/library/rp2.rst index 06affaae8c..ec7666d7ce 100644 --- a/docs/library/rp2.rst +++ b/docs/library/rp2.rst @@ -47,8 +47,8 @@ For running PIO programs, see :class:`rp2.StateMachine`. `PIO.SHIFT_LEFT` or `PIO.SHIFT_RIGHT`. - *push_thresh* is the threshold in bits before auto-push or conditional re-pushing is triggered. - - *pull_thresh* is the threshold in bits before auto-push or conditional - re-pushing is triggered. + - *pull_thresh* is the threshold in bits before auto-pull or conditional + re-pulling is triggered. The remaining parameters are: From bfc63a5c844cd9efa25a44b418be201984fa231c Mon Sep 17 00:00:00 2001 From: Kyuchumimo <74131798+Kyuchumimo@users.noreply.github.com> Date: Tue, 9 Aug 2022 18:30:21 -0600 Subject: [PATCH 0268/1041] drivers/sdcard: Add delay in init_card_v1 to make timeout work. This now follows how init_card_v2 works. --- drivers/sdcard/sdcard.py | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/sdcard/sdcard.py b/drivers/sdcard/sdcard.py index f4520acbb5..df28bd9534 100644 --- a/drivers/sdcard/sdcard.py +++ b/drivers/sdcard/sdcard.py @@ -118,6 +118,7 @@ class SDCard: def init_card_v1(self): for i in range(_CMD_TIMEOUT): + time.sleep_ms(50) self.cmd(55, 0, 0) if self.cmd(41, 0, 0) == 0: # SDSC card, uses byte addressing in read/write/erase commands From 94a19f10628f9c3a9978daae9f6f4c7ac352e9a2 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 11 Aug 2022 16:53:42 +1000 Subject: [PATCH 0269/1041] windows/Makefile: Update test dependency on $(PROG). PR #9012 (b2e82402688b53829f37475583231b067b9faea7) changed the output to $(BUILD)/$(PROG) but the tests are still looking for $(PROG). Also remove the now-unnecessary override of $(PROG) in the standard variant. Signed-off-by: Jim Mussared --- ports/windows/Makefile | 7 +++---- ports/windows/variants/standard/mpconfigvariant.mk | 2 -- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/ports/windows/Makefile b/ports/windows/Makefile index 45d61b0b50..1e793800f8 100644 --- a/ports/windows/Makefile +++ b/ports/windows/Makefile @@ -16,7 +16,6 @@ include $(VARIANT_DIR)/mpconfigvariant.mk FROZEN_MANIFEST ?= variants/manifest.py # Define main target -# This should be configured by the mpconfigvariant.mk PROG ?= micropython # qstr definitions (must come before including py.mk) @@ -98,10 +97,10 @@ include $(TOP)/py/mkrules.mk RUN_TESTS_SKIP += -e math_fun -e float2int_double -e float_parse -e math_domain_special -test: $(PROG) $(TOP)/tests/run-tests.py +test: $(BUILD)/$(PROG) $(TOP)/tests/run-tests.py $(eval DIRNAME=ports/$(notdir $(CURDIR))) - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) $(PYTHON) ./run-tests.py $(RUN_TESTS_SKIP) + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) $(PYTHON) ./run-tests.py $(RUN_TESTS_SKIP) test_full: test $(eval DIRNAME=ports/$(notdir $(CURDIR))) - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) $(PYTHON) ./run-tests.py --via-mpy $(RUN_TESTS_MPY_CROSS_FLAGS) $(RUN_TESTS_SKIP) -d basics float micropython + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) $(PYTHON) ./run-tests.py --via-mpy $(RUN_TESTS_MPY_CROSS_FLAGS) $(RUN_TESTS_SKIP) -d basics float micropython diff --git a/ports/windows/variants/standard/mpconfigvariant.mk b/ports/windows/variants/standard/mpconfigvariant.mk index 9e1f5ae059..a0d6712c55 100644 --- a/ports/windows/variants/standard/mpconfigvariant.mk +++ b/ports/windows/variants/standard/mpconfigvariant.mk @@ -1,3 +1 @@ # This is the default variant when you `make` the Windows port. - -PROG ?= micropython From 82b3500724206f2baa342a3559bbe716e9819426 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 11 Aug 2022 16:34:02 +1000 Subject: [PATCH 0270/1041] py/qstr: Change qstr hash type from mp_uint_t to size_t. The hash is either 8 or 16 bits (depending on MICROPY_QSTR_BYTES_IN_HASH) so will fit in a size_t. This saves 268 bytes on the unix nanbox build. Non-nanbox configurations are unchanged because mp_uint_t is the same size as size_t. Signed-off-by: Damien George --- py/objstr.h | 4 ++-- py/qstr.c | 8 ++++---- py/qstr.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/py/objstr.h b/py/objstr.h index 8f87c3018a..92b065d869 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -30,7 +30,7 @@ typedef struct _mp_obj_str_t { mp_obj_base_t base; - mp_uint_t hash; + size_t hash; // len == number of bytes used in data, alloc = len + 1 because (at the moment) we also append a null byte size_t len; const byte *data; @@ -41,7 +41,7 @@ typedef struct _mp_obj_str_t { // use this macro to extract the string hash // warning: the hash can be 0, meaning invalid, and must then be explicitly computed from the data #define GET_STR_HASH(str_obj_in, str_hash) \ - mp_uint_t str_hash; \ + size_t str_hash; \ if (mp_obj_is_qstr(str_obj_in)) { \ str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); \ } else { \ diff --git a/py/qstr.c b/py/qstr.c index f9ca106837..ea700566f4 100644 --- a/py/qstr.c +++ b/py/qstr.c @@ -60,9 +60,9 @@ #define MICROPY_ALLOC_QSTR_ENTRIES_INIT (10) // this must match the equivalent function in makeqstrdata.py -mp_uint_t qstr_compute_hash(const byte *data, size_t len) { +size_t qstr_compute_hash(const byte *data, size_t len) { // djb2 algorithm; see http://www.cse.yorku.ca/~oz/hash.html - mp_uint_t hash = 5381; + size_t hash = 5381; for (const byte *top = data + len; data < top; data++) { hash = ((hash << 5) + hash) ^ (*data); // hash * 33 ^ data } @@ -181,7 +181,7 @@ STATIC qstr qstr_add(mp_uint_t hash, mp_uint_t len, const char *q_ptr) { qstr qstr_find_strn(const char *str, size_t str_len) { // work out hash of str - mp_uint_t str_hash = qstr_compute_hash((const byte *)str, str_len); + size_t str_hash = qstr_compute_hash((const byte *)str, str_len); // search pools for the data for (const qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL; pool = pool->prev) { @@ -254,7 +254,7 @@ qstr qstr_from_strn(const char *str, size_t len) { MP_STATE_VM(qstr_last_used) += n_bytes; // store the interned strings' data - mp_uint_t hash = qstr_compute_hash((const byte *)str, len); + size_t hash = qstr_compute_hash((const byte *)str, len); memcpy(q_ptr, str, len); q_ptr[len] = '\0'; q = qstr_add(hash, len, q_ptr); diff --git a/py/qstr.h b/py/qstr.h index a463b67a18..0ef861f33e 100644 --- a/py/qstr.h +++ b/py/qstr.h @@ -78,7 +78,7 @@ typedef struct _qstr_pool_t { void qstr_init(void); -mp_uint_t qstr_compute_hash(const byte *data, size_t len); +size_t qstr_compute_hash(const byte *data, size_t len); qstr qstr_find_strn(const char *str, size_t str_len); // returns MP_QSTRnull if not found qstr qstr_from_str(const char *str); From f7f56d42851aaff2027e23a8ca45c1f1973f1aca Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 10 Aug 2022 14:13:17 +1000 Subject: [PATCH 0271/1041] py/objstr: Consolidate methods for str/bytes/bytearray/array. This commit adds the bytes methods to bytearray, matching CPython. The existing implementations of these methods for str/bytes are reused for bytearray with minor updates to match CPython return types. For details on the CPython behaviour see https://docs.python.org/3/library/stdtypes.html#bytes-and-bytearray-operations The work to merge locals tables for str/bytes/bytearray/array was done by @jimmo. Because of this merging of locals the change in code size for this commit is mostly negative: bare-arm: +0 +0.000% minimal x86: +29 +0.018% unix x64: -792 -0.128% standard[incl -448(data)] unix nanbox: -436 -0.078% nanbox[incl -448(data)] stm32: -40 -0.010% PYBV10 cc3200: -32 -0.017% esp8266: -28 -0.004% GENERIC esp32: -72 -0.005% GENERIC[incl -200(data)] mimxrt: -40 -0.011% TEENSY40 renesas-ra: -40 -0.006% RA6M2_EK nrf: -16 -0.009% pca10040 rp2: -64 -0.013% PICO samd: +148 +0.105% ADAFRUIT_ITSYBITSY_M4_EXPRESS --- py/obj.h | 10 +- py/objarray.c | 22 +-- py/objarray.h | 5 + py/objstr.c | 157 ++++++++++++++++------ py/objstr.h | 19 +++ py/objstrunicode.c | 50 +------ tests/basics/bytearray_byte_operations.py | 35 +++++ tests/basics/bytearray_center.py | 8 ++ tests/basics/bytearray_count.py | 7 + tests/basics/bytearray_partition.py | 8 ++ tests/basics/bytes_center.py | 13 ++ 11 files changed, 225 insertions(+), 109 deletions(-) create mode 100644 tests/basics/bytearray_byte_operations.py create mode 100644 tests/basics/bytearray_center.py create mode 100644 tests/basics/bytearray_count.py create mode 100644 tests/basics/bytearray_partition.py create mode 100644 tests/basics/bytes_center.py diff --git a/py/obj.h b/py/obj.h index 7ba4c0a5f2..598d6508da 100644 --- a/py/obj.h +++ b/py/obj.h @@ -394,19 +394,21 @@ typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t; .table = (mp_map_elem_t *)(mp_rom_map_elem_t *)table_name, \ } -#define MP_DEFINE_CONST_DICT(dict_name, table_name) \ +#define MP_DEFINE_CONST_DICT_WITH_SIZE(dict_name, table_name, n) \ const mp_obj_dict_t dict_name = { \ .base = {&mp_type_dict}, \ .map = { \ .all_keys_are_qstrs = 1, \ .is_fixed = 1, \ .is_ordered = 1, \ - .used = MP_ARRAY_SIZE(table_name), \ - .alloc = MP_ARRAY_SIZE(table_name), \ + .used = n, \ + .alloc = n, \ .table = (mp_map_elem_t *)(mp_rom_map_elem_t *)table_name, \ }, \ } +#define MP_DEFINE_CONST_DICT(dict_name, table_name) MP_DEFINE_CONST_DICT_WITH_SIZE(dict_name, table_name, MP_ARRAY_SIZE(table_name)) + // These macros are used to declare and define constant staticmethond and classmethod objects // You can put "static" in front of the definitions to make them local @@ -789,7 +791,7 @@ mp_obj_t mp_obj_new_str(const char *data, size_t len); mp_obj_t mp_obj_new_str_via_qstr(const char *data, size_t len); mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr); mp_obj_t mp_obj_new_bytes(const byte *data, size_t len); -mp_obj_t mp_obj_new_bytearray(size_t n, void *items); +mp_obj_t mp_obj_new_bytearray(size_t n, const void *items); mp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items); #if MICROPY_PY_BUILTINS_FLOAT mp_obj_t mp_obj_new_int_from_float(mp_float_t val); diff --git a/py/objarray.c b/py/objarray.c index bff3126a2b..11bd7bb15c 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -381,7 +381,7 @@ STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) { self->free--; return mp_const_none; // return None, as per CPython } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(array_append_obj, array_append); +MP_DEFINE_CONST_FUN_OBJ_2(mp_obj_array_append_obj, array_append); STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) { // self is not a memoryview, so we don't need to use (& TYPECODE_MASK) @@ -413,7 +413,7 @@ STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) { return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(array_extend_obj, array_extend); +MP_DEFINE_CONST_FUN_OBJ_2(mp_obj_array_extend_obj, array_extend); #endif STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { @@ -564,18 +564,6 @@ STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_ui return 0; } -#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY -STATIC const mp_rom_map_elem_t array_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&array_append_obj) }, - { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&array_extend_obj) }, - #if MICROPY_CPYTHON_COMPAT - { MP_ROM_QSTR(MP_QSTR_decode), MP_ROM_PTR(&bytes_decode_obj) }, - #endif -}; - -STATIC MP_DEFINE_CONST_DICT(array_locals_dict, array_locals_dict_table); -#endif - #if MICROPY_PY_ARRAY const mp_obj_type_t mp_type_array = { { &mp_type_type }, @@ -587,7 +575,7 @@ const mp_obj_type_t mp_type_array = { .binary_op = array_binary_op, .subscr = array_subscr, .buffer_p = { .get_buffer = array_get_buffer }, - .locals_dict = (mp_obj_dict_t *)&array_locals_dict, + .locals_dict = (mp_obj_dict_t *)&mp_obj_array_locals_dict, }; #endif @@ -603,7 +591,7 @@ const mp_obj_type_t mp_type_bytearray = { .binary_op = array_binary_op, .subscr = array_subscr, .buffer_p = { .get_buffer = array_get_buffer }, - .locals_dict = (mp_obj_dict_t *)&array_locals_dict, + .locals_dict = (mp_obj_dict_t *)&mp_obj_bytearray_locals_dict, }; #endif @@ -631,7 +619,7 @@ size_t mp_obj_array_len(mp_obj_t self_in) { */ #if MICROPY_PY_BUILTINS_BYTEARRAY -mp_obj_t mp_obj_new_bytearray(size_t n, void *items) { +mp_obj_t mp_obj_new_bytearray(size_t n, const void *items) { mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, n); memcpy(o->items, items, n); return MP_OBJ_FROM_PTR(o); diff --git a/py/objarray.h b/py/objarray.h index 94c31c9693..48a26c3fb3 100644 --- a/py/objarray.h +++ b/py/objarray.h @@ -59,4 +59,9 @@ static inline void mp_obj_memoryview_init(mp_obj_array_t *self, size_t typecode, } #endif +#if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY +MP_DECLARE_CONST_FUN_OBJ_2(mp_obj_array_append_obj); +MP_DECLARE_CONST_FUN_OBJ_2(mp_obj_array_extend_obj); +#endif + #endif // MICROPY_INCLUDED_PY_OBJARRAY_H diff --git a/py/objstr.c b/py/objstr.c index f15a2d9744..162229c62b 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -41,6 +41,26 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_ STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in); +STATIC void str_check_arg_type(const mp_obj_type_t *self_type, const mp_obj_t arg) { + // String operations generally need the args type to match the object they're called on, + // e.g. str.find(str), byte.startswith(byte) + // with the exception that bytes may be used for bytearray and vice versa. + const mp_obj_type_t *arg_type = mp_obj_get_type(arg); + + #if MICROPY_PY_BUILTINS_BYTEARRAY + if (arg_type == &mp_type_bytearray) { + arg_type = &mp_type_bytes; + } + if (self_type == &mp_type_bytearray) { + self_type = &mp_type_bytes; + } + #endif + + if (arg_type != self_type) { + bad_implicit_conversion(arg); + } +} + /******************************************************************************/ /* str */ @@ -452,6 +472,7 @@ STATIC mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { mp_check_self(mp_obj_is_str_or_bytes(self_in)); const mp_obj_type_t *self_type = mp_obj_get_type(self_in); + const mp_obj_type_t *ret_type = self_type; // get separation string GET_STR_DATA_LEN(self_in, sep_str, sep_len); @@ -469,8 +490,19 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { // count required length size_t required_len = 0; + #if MICROPY_PY_BUILTINS_BYTEARRAY + if (self_type == &mp_type_bytearray) { + self_type = &mp_type_bytes; + } + #endif for (size_t i = 0; i < seq_len; i++) { - if (mp_obj_get_type(seq_items[i]) != self_type) { + const mp_obj_type_t *seq_type = mp_obj_get_type(seq_items[i]); + #if MICROPY_PY_BUILTINS_BYTEARRAY + if (seq_type == &mp_type_bytearray) { + seq_type = &mp_type_bytes; + } + #endif + if (seq_type != self_type) { mp_raise_TypeError( MP_ERROR_TEXT("join expects a list of str/bytes objects consistent with self object")); } @@ -496,7 +528,7 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { } // return joined string - return mp_obj_new_str_from_vstr(self_type, &vstr); + return mp_obj_new_str_from_vstr(ret_type, &vstr); } MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join); @@ -545,9 +577,7 @@ mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args) { } else { // sep given - if (mp_obj_get_type(sep) != self_type) { - bad_implicit_conversion(sep); - } + str_check_arg_type(self_type, sep); size_t sep_len; const char *sep_str = mp_obj_str_get_data(sep, &sep_len); @@ -699,9 +729,7 @@ STATIC mp_obj_t str_finder(size_t n_args, const mp_obj_t *args, int direction, b mp_check_self(mp_obj_is_str_or_bytes(args[0])); // check argument type - if (mp_obj_get_type(args[1]) != self_type) { - bad_implicit_conversion(args[1]); - } + str_check_arg_type(self_type, args[1]); GET_STR_DATA_LEN(args[0], haystack, haystack_len); GET_STR_DATA_LEN(args[1], needle, needle_len); @@ -805,9 +833,7 @@ STATIC mp_obj_t str_uni_strip(int type, size_t n_args, const mp_obj_t *args) { chars_to_del = whitespace; chars_to_del_len = sizeof(whitespace) - 1; } else { - if (mp_obj_get_type(args[1]) != self_type) { - bad_implicit_conversion(args[1]); - } + str_check_arg_type(self_type, args[1]); GET_STR_DATA_LEN(args[1], s, l); chars_to_del = s; chars_to_del_len = l; @@ -1633,13 +1659,8 @@ STATIC mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) { const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); - if (mp_obj_get_type(args[1]) != self_type) { - bad_implicit_conversion(args[1]); - } - - if (mp_obj_get_type(args[2]) != self_type) { - bad_implicit_conversion(args[2]); - } + str_check_arg_type(self_type, args[1]); + str_check_arg_type(self_type, args[2]); // extract string data @@ -1726,9 +1747,7 @@ STATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) { mp_check_self(mp_obj_is_str_or_bytes(args[0])); // check argument type - if (mp_obj_get_type(args[1]) != self_type) { - bad_implicit_conversion(args[1]); - } + str_check_arg_type(self_type, args[1]); GET_STR_DATA_LEN(args[0], haystack, haystack_len); GET_STR_DATA_LEN(args[1], needle, needle_len); @@ -1767,9 +1786,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj, 2, 4, str_count); STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, int direction) { mp_check_self(mp_obj_is_str_or_bytes(self_in)); const mp_obj_type_t *self_type = mp_obj_get_type(self_in); - if (self_type != mp_obj_get_type(arg)) { - bad_implicit_conversion(arg); - } + str_check_arg_type(self_type, arg); GET_STR_DATA_LEN(self_in, str, str_len); GET_STR_DATA_LEN(arg, sep, sep_len); @@ -1795,6 +1812,12 @@ STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, int direction) { result[2] = self_in; } + #if MICROPY_PY_BUILTINS_BYTEARRAY + if (mp_obj_get_type(arg) != self_type) { + arg = mp_obj_new_str_of_type(self_type, sep, sep_len); + } + #endif + const byte *position_ptr = find_subbytes(str, str_len, sep, sep_len, direction); if (position_ptr != NULL) { size_t position = position_ptr - str; @@ -1940,17 +1963,15 @@ mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_u } } -STATIC const mp_rom_map_elem_t str8_locals_dict_table[] = { +// This locals table is used for the following types: str, bytes, bytearray, array.array. +// Each type takes a different section (start to end offset) of this table. +STATIC const mp_rom_map_elem_t array_bytearray_str_bytes_locals_table[] = { + #if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY + { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&mp_obj_array_append_obj) }, + { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&mp_obj_array_extend_obj) }, + #endif #if MICROPY_CPYTHON_COMPAT { MP_ROM_QSTR(MP_QSTR_decode), MP_ROM_PTR(&bytes_decode_obj) }, - #if !MICROPY_PY_BUILTINS_STR_UNICODE - // If we have separate unicode type, then here we have methods only - // for bytes type, and it should not have encode() methods. Otherwise, - // we have non-compliant-but-practical bytestring type, which shares - // method table with bytes, so they both have encode() and decode() - // methods (which should do type checking at runtime). - { MP_ROM_QSTR(MP_QSTR_encode), MP_ROM_PTR(&str_encode_obj) }, - #endif #endif { MP_ROM_QSTR(MP_QSTR_find), MP_ROM_PTR(&str_find_obj) }, { MP_ROM_QSTR(MP_QSTR_rfind), MP_ROM_PTR(&str_rfind_obj) }, @@ -1986,9 +2007,46 @@ STATIC const mp_rom_map_elem_t str8_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_isdigit), MP_ROM_PTR(&str_isdigit_obj) }, { MP_ROM_QSTR(MP_QSTR_isupper), MP_ROM_PTR(&str_isupper_obj) }, { MP_ROM_QSTR(MP_QSTR_islower), MP_ROM_PTR(&str_islower_obj) }, + #if MICROPY_CPYTHON_COMPAT + { MP_ROM_QSTR(MP_QSTR_encode), MP_ROM_PTR(&str_encode_obj) }, + #endif }; -STATIC MP_DEFINE_CONST_DICT(str8_locals_dict, str8_locals_dict_table); +#if MICROPY_CPYTHON_COMPAT +#define TABLE_ENTRIES_COMPAT 1 +#else +#define TABLE_ENTRIES_COMPAT 0 +#endif + +#if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY +#define TABLE_ENTRIES_ARRAY 2 +#else +#define TABLE_ENTRIES_ARRAY 0 +#endif + +MP_DEFINE_CONST_DICT_WITH_SIZE(mp_obj_str_locals_dict, + array_bytearray_str_bytes_locals_table + TABLE_ENTRIES_ARRAY + TABLE_ENTRIES_COMPAT, + MP_ARRAY_SIZE(array_bytearray_str_bytes_locals_table) - (TABLE_ENTRIES_ARRAY + TABLE_ENTRIES_COMPAT)); + +#if TABLE_ENTRIES_COMPAT == 0 +#define mp_obj_bytes_locals_dict mp_obj_str_locals_dict +#else +MP_DEFINE_CONST_DICT_WITH_SIZE(mp_obj_bytes_locals_dict, + array_bytearray_str_bytes_locals_table + TABLE_ENTRIES_ARRAY, + MP_ARRAY_SIZE(array_bytearray_str_bytes_locals_table) - (TABLE_ENTRIES_ARRAY + TABLE_ENTRIES_COMPAT)); +#endif + +#if MICROPY_PY_BUILTINS_BYTEARRAY +MP_DEFINE_CONST_DICT_WITH_SIZE(mp_obj_bytearray_locals_dict, + array_bytearray_str_bytes_locals_table, + MP_ARRAY_SIZE(array_bytearray_str_bytes_locals_table) - TABLE_ENTRIES_COMPAT); +#endif + +#if MICROPY_PY_ARRAY +MP_DEFINE_CONST_DICT_WITH_SIZE(mp_obj_array_locals_dict, + array_bytearray_str_bytes_locals_table, + TABLE_ENTRIES_ARRAY); +#endif #if !MICROPY_PY_BUILTINS_STR_UNICODE STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); @@ -2002,9 +2060,9 @@ const mp_obj_type_t mp_type_str = { .subscr = bytes_subscr, .getiter = mp_obj_new_str_iterator, .buffer_p = { .get_buffer = mp_obj_str_get_buffer }, - .locals_dict = (mp_obj_dict_t *)&str8_locals_dict, + .locals_dict = (mp_obj_dict_t *)&mp_obj_str_locals_dict, }; -#endif +#endif // !MICROPY_PY_BUILTINS_STR_UNICODE // Reuses most of methods from str const mp_obj_type_t mp_type_bytes = { @@ -2016,7 +2074,7 @@ const mp_obj_type_t mp_type_bytes = { .subscr = bytes_subscr, .getiter = mp_obj_new_bytes_iterator, .buffer_p = { .get_buffer = mp_obj_str_get_buffer }, - .locals_dict = (mp_obj_dict_t *)&str8_locals_dict, + .locals_dict = (mp_obj_dict_t *)&mp_obj_bytes_locals_dict, }; // The zero-length bytes object, with data that includes a null-terminating byte @@ -2044,6 +2102,10 @@ mp_obj_t mp_obj_new_str_copy(const mp_obj_type_t *type, const byte *data, size_t mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte *data, size_t len) { if (type == &mp_type_str) { return mp_obj_new_str((const char *)data, len); + #if MICROPY_PY_BUILTINS_BYTEARRAY + } else if (type == &mp_type_bytearray) { + return mp_obj_new_bytearray(len, data); + #endif } else { return mp_obj_new_bytes(data, len); } @@ -2068,18 +2130,24 @@ mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) { } } - // make a new str/bytes object - mp_obj_str_t *o = mp_obj_malloc(mp_obj_str_t, type); - o->len = vstr->len; - o->hash = qstr_compute_hash((byte *)vstr->buf, vstr->len); + byte *data; if (vstr->len + 1 == vstr->alloc) { - o->data = (byte *)vstr->buf; + data = (byte *)vstr->buf; } else { - o->data = (byte *)m_renew(char, vstr->buf, vstr->alloc, vstr->len + 1); + data = (byte *)m_renew(char, vstr->buf, vstr->alloc, vstr->len + 1); } - ((byte *)o->data)[o->len] = '\0'; // add null byte + data[vstr->len] = '\0'; // add null byte vstr->buf = NULL; vstr->alloc = 0; + #if MICROPY_PY_BUILTINS_BYTEARRAY + if (type == &mp_type_bytearray) { + return mp_obj_new_bytearray_by_ref(vstr->len, data); + } + #endif + mp_obj_str_t *o = mp_obj_malloc(mp_obj_str_t, type); + o->len = vstr->len; + o->hash = qstr_compute_hash(data, vstr->len); + o->data = data; return MP_OBJ_FROM_PTR(o); } @@ -2179,6 +2247,7 @@ const byte *mp_obj_str_get_data_no_check(mp_obj_t self_in, size_t *len) { if (mp_obj_is_qstr(self_in)) { return qstr_data(MP_OBJ_QSTR_VALUE(self_in), len); } else { + MP_STATIC_ASSERT_STR_ARRAY_COMPATIBLE; *len = ((mp_obj_str_t *)MP_OBJ_TO_PTR(self_in))->len; return ((mp_obj_str_t *)MP_OBJ_TO_PTR(self_in))->data; } diff --git a/py/objstr.h b/py/objstr.h index 92b065d869..7d86ec30ba 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -27,6 +27,7 @@ #define MICROPY_INCLUDED_PY_OBJSTR_H #include "py/obj.h" +#include "py/objarray.h" typedef struct _mp_obj_str_t { mp_obj_base_t base; @@ -36,6 +37,13 @@ typedef struct _mp_obj_str_t { const byte *data; } mp_obj_str_t; +// This static assert is used to ensure that mp_obj_str_t and mp_obj_array_t are compatible, +// meaning that their len and data/items entries are at the same offsets in the struct. +// This allows the same code to be used for str/bytes and bytearray. +#define MP_STATIC_ASSERT_STR_ARRAY_COMPATIBLE \ + MP_STATIC_ASSERT(offsetof(mp_obj_str_t, len) == offsetof(mp_obj_array_t, len) \ + && offsetof(mp_obj_str_t, data) == offsetof(mp_obj_array_t, items)) + #define MP_DEFINE_STR_OBJ(obj_name, str) mp_obj_str_t obj_name = {{&mp_type_str}, 0, sizeof(str) - 1, (const byte *)str} // use this macro to extract the string hash @@ -70,6 +78,7 @@ const byte *mp_obj_str_get_data_no_check(mp_obj_t self_in, size_t *len); if (mp_obj_is_qstr(str_obj_in)) { \ str_data = qstr_data(MP_OBJ_QSTR_VALUE(str_obj_in), &str_len); \ } else { \ + MP_STATIC_ASSERT_STR_ARRAY_COMPATIBLE; \ str_len = ((mp_obj_str_t *)MP_OBJ_TO_PTR(str_obj_in))->len; \ str_data = ((mp_obj_str_t *)MP_OBJ_TO_PTR(str_obj_in))->data; \ } @@ -118,4 +127,14 @@ MP_DECLARE_CONST_FUN_OBJ_1(str_isupper_obj); MP_DECLARE_CONST_FUN_OBJ_1(str_islower_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj); +extern const mp_obj_dict_t mp_obj_str_locals_dict; + +#if MICROPY_PY_BUILTINS_BYTEARRAY +extern const mp_obj_dict_t mp_obj_bytearray_locals_dict; +#endif + +#if MICROPY_PY_ARRAY +extern const mp_obj_dict_t mp_obj_array_locals_dict; +#endif + #endif // MICROPY_INCLUDED_PY_OBJSTR_H diff --git a/py/objstrunicode.c b/py/objstrunicode.c index ed79ad68a9..d36dd8b137 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -116,7 +116,11 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s mp_obj_t index, bool is_slice) { // All str functions also handle bytes objects, and they call str_index_to_ptr(), // so it must handle bytes. - if (type == &mp_type_bytes) { + if (type == &mp_type_bytes + #if MICROPY_PY_BUILTINS_BYTEARRAY + || type == &mp_type_bytearray + #endif + ) { // Taken from objstr.c:str_index_to_ptr() size_t index_val = mp_get_index(type, self_len, index, is_slice); return self_data + index_val; @@ -225,48 +229,6 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } } -STATIC const mp_rom_map_elem_t struni_locals_dict_table[] = { - #if MICROPY_CPYTHON_COMPAT - { MP_ROM_QSTR(MP_QSTR_encode), MP_ROM_PTR(&str_encode_obj) }, - #endif - { MP_ROM_QSTR(MP_QSTR_find), MP_ROM_PTR(&str_find_obj) }, - { MP_ROM_QSTR(MP_QSTR_rfind), MP_ROM_PTR(&str_rfind_obj) }, - { MP_ROM_QSTR(MP_QSTR_index), MP_ROM_PTR(&str_index_obj) }, - { MP_ROM_QSTR(MP_QSTR_rindex), MP_ROM_PTR(&str_rindex_obj) }, - { MP_ROM_QSTR(MP_QSTR_join), MP_ROM_PTR(&str_join_obj) }, - { MP_ROM_QSTR(MP_QSTR_split), MP_ROM_PTR(&str_split_obj) }, - #if MICROPY_PY_BUILTINS_STR_SPLITLINES - { MP_ROM_QSTR(MP_QSTR_splitlines), MP_ROM_PTR(&str_splitlines_obj) }, - #endif - { MP_ROM_QSTR(MP_QSTR_rsplit), MP_ROM_PTR(&str_rsplit_obj) }, - { MP_ROM_QSTR(MP_QSTR_startswith), MP_ROM_PTR(&str_startswith_obj) }, - { MP_ROM_QSTR(MP_QSTR_endswith), MP_ROM_PTR(&str_endswith_obj) }, - { MP_ROM_QSTR(MP_QSTR_strip), MP_ROM_PTR(&str_strip_obj) }, - { MP_ROM_QSTR(MP_QSTR_lstrip), MP_ROM_PTR(&str_lstrip_obj) }, - { MP_ROM_QSTR(MP_QSTR_rstrip), MP_ROM_PTR(&str_rstrip_obj) }, - { MP_ROM_QSTR(MP_QSTR_format), MP_ROM_PTR(&str_format_obj) }, - { MP_ROM_QSTR(MP_QSTR_replace), MP_ROM_PTR(&str_replace_obj) }, - #if MICROPY_PY_BUILTINS_STR_COUNT - { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&str_count_obj) }, - #endif - #if MICROPY_PY_BUILTINS_STR_PARTITION - { MP_ROM_QSTR(MP_QSTR_partition), MP_ROM_PTR(&str_partition_obj) }, - { MP_ROM_QSTR(MP_QSTR_rpartition), MP_ROM_PTR(&str_rpartition_obj) }, - #endif - #if MICROPY_PY_BUILTINS_STR_CENTER - { MP_ROM_QSTR(MP_QSTR_center), MP_ROM_PTR(&str_center_obj) }, - #endif - { MP_ROM_QSTR(MP_QSTR_lower), MP_ROM_PTR(&str_lower_obj) }, - { MP_ROM_QSTR(MP_QSTR_upper), MP_ROM_PTR(&str_upper_obj) }, - { MP_ROM_QSTR(MP_QSTR_isspace), MP_ROM_PTR(&str_isspace_obj) }, - { MP_ROM_QSTR(MP_QSTR_isalpha), MP_ROM_PTR(&str_isalpha_obj) }, - { MP_ROM_QSTR(MP_QSTR_isdigit), MP_ROM_PTR(&str_isdigit_obj) }, - { MP_ROM_QSTR(MP_QSTR_isupper), MP_ROM_PTR(&str_isupper_obj) }, - { MP_ROM_QSTR(MP_QSTR_islower), MP_ROM_PTR(&str_islower_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(struni_locals_dict, struni_locals_dict_table); - const mp_obj_type_t mp_type_str = { { &mp_type_type }, .name = MP_QSTR_str, @@ -277,7 +239,7 @@ const mp_obj_type_t mp_type_str = { .subscr = str_subscr, .getiter = mp_obj_new_str_iterator, .buffer_p = { .get_buffer = mp_obj_str_get_buffer }, - .locals_dict = (mp_obj_dict_t *)&struni_locals_dict, + .locals_dict = (mp_obj_dict_t *)&mp_obj_str_locals_dict, }; /******************************************************************************/ diff --git a/tests/basics/bytearray_byte_operations.py b/tests/basics/bytearray_byte_operations.py new file mode 100644 index 0000000000..7ce53cac53 --- /dev/null +++ b/tests/basics/bytearray_byte_operations.py @@ -0,0 +1,35 @@ +# test bytearray with its re-use of byte functions + +print(bytearray(b"hello world").find(b"ll")) +print(bytearray(b"hello\x00world").rfind(b"l")) + +print(bytearray(b"abc efg ").strip(b"g a")) +print(bytearray(b" spacious ").lstrip()) +print(bytearray(b"www.example.com").lstrip(b"cmowz.")) +print(bytearray(b" spacious ").rstrip()) +print(bytearray(b"mississippi").rstrip(b"ipz")) + +print(bytearray(b"abc").split(b"a")) +print(bytearray(b"abcabc").rsplit(b"bc")) + +print(bytearray(b"asdfasdf").replace(b"a", b"b")) + +print("00\x0000".index("0", 0)) +print("00\x0000".index("0", 3)) +print("00\x0000".rindex("0", 0)) +print("00\x0000".rindex("0", 3)) + +print(bytearray(b"foobar").endswith(b"bar")) +print(bytearray(b"1foo").startswith(b"foo", 1)) + +print(bytearray(b" T E \x00 S T").lower()) +print(bytearray(b" te \x00 st").upper()) + +print(bytearray(b" \t\n\r\v\f").isspace()) +print(bytearray(b"this ").isalpha()) +print(bytearray(b"0123456789").isdigit()) +print(bytearray(b"AB").isupper()) +print(bytearray(b"cheese-cake").islower()) + +print(bytearray(b",").join((bytearray(b"abc"), bytearray(b"def")))) +print(type(bytearray(b",").join((b"a", b"b", b"c")))) diff --git a/tests/basics/bytearray_center.py b/tests/basics/bytearray_center.py new file mode 100644 index 0000000000..c262a8c209 --- /dev/null +++ b/tests/basics/bytearray_center.py @@ -0,0 +1,8 @@ +try: + bytearray.center +except AttributeError: + print("SKIP") + raise SystemExit + +print(bytearray(b"foo").center(6)) +print(type(bytearray(b"foo").center(6))) diff --git a/tests/basics/bytearray_count.py b/tests/basics/bytearray_count.py new file mode 100644 index 0000000000..a151c1e818 --- /dev/null +++ b/tests/basics/bytearray_count.py @@ -0,0 +1,7 @@ +try: + bytearray.count +except AttributeError: + print("SKIP") + raise SystemExit + +print(bytearray(b"aaaa").count(b"a")) diff --git a/tests/basics/bytearray_partition.py b/tests/basics/bytearray_partition.py new file mode 100644 index 0000000000..b48ec4ed9b --- /dev/null +++ b/tests/basics/bytearray_partition.py @@ -0,0 +1,8 @@ +try: + bytearray.partition +except AttributeError: + print("SKIP") + raise SystemExit + +print(bytearray(b"asdsf").partition(b"s")) +print(bytearray(b"asdsf").rpartition(b"s")) diff --git a/tests/basics/bytes_center.py b/tests/basics/bytes_center.py new file mode 100644 index 0000000000..5d8b41d92f --- /dev/null +++ b/tests/basics/bytes_center.py @@ -0,0 +1,13 @@ +try: + bytes.center +except: + print("SKIP") + raise SystemExit + +print(b"foo".center(0)) +print(b"foo".center(1)) +print(b"foo".center(3)) +print(b"foo".center(4)) +print(b"foo".center(5)) +print(b"foo".center(6)) +print(b"foo".center(20)) From 787bd9991903dc736b5eb79826dd34e4c17f72ec Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 11 Aug 2022 21:43:09 +1000 Subject: [PATCH 0272/1041] nrf/modules/ubluepy: Use mp_obj_str_get_data to extract str data. Instead of GET_STR_DATA_LEN, which is intended to be a private macro. Signed-off-by: Damien George --- ports/nrf/modules/ubluepy/ubluepy_peripheral.c | 8 ++++---- ports/nrf/modules/ubluepy/ubluepy_uuid.c | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ports/nrf/modules/ubluepy/ubluepy_peripheral.c b/ports/nrf/modules/ubluepy/ubluepy_peripheral.c index 05a72b1de6..acfe316c0c 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_peripheral.c +++ b/ports/nrf/modules/ubluepy/ubluepy_peripheral.c @@ -193,9 +193,8 @@ STATIC mp_obj_t peripheral_advertise(mp_uint_t n_args, const mp_obj_t *pos_args, memset(&adv_data, 0, sizeof(ubluepy_advertise_data_t)); if (device_name_obj != mp_const_none && mp_obj_is_str(device_name_obj)) { - GET_STR_DATA_LEN(device_name_obj, str_data, str_len); - - adv_data.p_device_name = (uint8_t *)str_data; + size_t str_len; + adv_data.p_device_name = (uint8_t *)mp_obj_str_get_data(device_name_obj, &str_len); adv_data.device_name_len = str_len; } @@ -357,7 +356,8 @@ STATIC mp_obj_t peripheral_connect(mp_uint_t n_args, const mp_obj_t *pos_args, m ble_drv_gap_event_handler_set(MP_OBJ_FROM_PTR(self), gap_event_handler); if (mp_obj_is_str(dev_addr)) { - GET_STR_DATA_LEN(dev_addr, str_data, str_len); + size_t str_len; + const byte *str_data = (const byte *)mp_obj_str_get_data(dev_addr, &str_len); if (str_len == 17) { // Example "11:22:33:aa:bb:cc" uint8_t * p_addr = m_new(uint8_t, 6); diff --git a/ports/nrf/modules/ubluepy/ubluepy_uuid.c b/ports/nrf/modules/ubluepy/ubluepy_uuid.c index 594d0d9130..aee7b9a1a8 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_uuid.c +++ b/ports/nrf/modules/ubluepy/ubluepy_uuid.c @@ -70,7 +70,8 @@ STATIC mp_obj_t ubluepy_uuid_make_new(const mp_obj_type_t *type, size_t n_args, s->value[1] = (((uint16_t)mp_obj_get_int(uuid_obj)) >> 8) & 0xFF; s->value[0] = ((uint8_t)mp_obj_get_int(uuid_obj)) & 0xFF; } else if (mp_obj_is_str(uuid_obj)) { - GET_STR_DATA_LEN(uuid_obj, str_data, str_len); + size_t str_len; + const byte *str_data = (const byte *)mp_obj_str_get_data(uuid_obj, &str_len); if (str_len == 6) { // Assume hex digit prefixed with 0x s->type = UBLUEPY_UUID_16_BIT; s->value[0] = unichar_xdigit_value(str_data[5]); From 6c67fbc280625c59fff7cdf93f16d5e2ad0bad8a Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 11 Aug 2022 21:44:53 +1000 Subject: [PATCH 0273/1041] zephyr/machine_uart: Use mp_obj_str_get_str to get device name. This checks that the argument is actually a string. Signed-off-by: Damien George --- ports/zephyr/machine_uart.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ports/zephyr/machine_uart.c b/ports/zephyr/machine_uart.c index 47ca0945a5..3520795c5a 100644 --- a/ports/zephyr/machine_uart.c +++ b/ports/zephyr/machine_uart.c @@ -75,10 +75,9 @@ 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) { mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); - GET_STR_DATA_LEN(args[0], name, name_len); machine_uart_obj_t *self = mp_obj_malloc(machine_uart_obj_t, &machine_uart_type); - self->dev = device_get_binding(name); + self->dev = device_get_binding(mp_obj_str_get_str(args[0])); if (!self->dev) { mp_raise_ValueError(MP_ERROR_TEXT("Bad device name")); } From 28aaab95909aab092cc8c16188fec157142f18a9 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 13 Jul 2021 18:01:12 +1000 Subject: [PATCH 0274/1041] py/objstr: Add hex/fromhex to bytes/memoryview/bytearray. These were added in Python 3.5. Enabled via MICROPY_PY_BUILTINS_BYTES_HEX, and enabled by default for all ports that currently have ubinascii. Rework ubinascii to use the implementation of these methods. Signed-off-by: Jim Mussared --- extmod/modubinascii.c | 81 +++++---------------------- ports/cc3200/mpconfigport.h | 1 + ports/javascript/mpconfigport.h | 1 + ports/mimxrt/mpconfigport.h | 1 + ports/qemu-arm/mpconfigport.h | 1 + ports/samd/mpconfigport.h | 1 + ports/unix/mpconfigport.h | 1 + ports/windows/mpconfigport.h | 1 + ports/zephyr/mpconfigport.h | 1 + py/mpconfig.h | 5 ++ py/objarray.c | 9 +++ py/objstr.c | 98 ++++++++++++++++++++++++++++++++- py/objstr.h | 7 +++ 13 files changed, 138 insertions(+), 70 deletions(-) diff --git a/extmod/modubinascii.c b/extmod/modubinascii.c index c0e2c587fd..49c8d1fb97 100644 --- a/extmod/modubinascii.c +++ b/extmod/modubinascii.c @@ -30,78 +30,21 @@ #include "py/runtime.h" #include "py/binary.h" +#include "py/objstr.h" #if MICROPY_PY_UBINASCII -STATIC mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) { - // First argument is the data to convert. - // Second argument is an optional separator to be used between values. - const char *sep = NULL; - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); - - // Code below assumes non-zero buffer length when computing size with - // separator, so handle the zero-length case here. - if (bufinfo.len == 0) { - return mp_const_empty_bytes; - } - - vstr_t vstr; - size_t out_len = bufinfo.len * 2; - if (n_args > 1) { - // 1-char separator between hex numbers - out_len += bufinfo.len - 1; - sep = mp_obj_str_get_str(args[1]); - } - vstr_init_len(&vstr, out_len); - byte *in = bufinfo.buf, *out = (byte *)vstr.buf; - for (mp_uint_t i = bufinfo.len; i--;) { - byte d = (*in >> 4); - if (d > 9) { - d += 'a' - '9' - 1; - } - *out++ = d + '0'; - d = (*in++ & 0xf); - if (d > 9) { - d += 'a' - '9' - 1; - } - *out++ = d + '0'; - if (sep != NULL && i != 0) { - *out++ = *sep; - } - } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +#if MICROPY_PY_BUILTINS_BYTES_HEX +STATIC mp_obj_t bytes_hex_as_bytes(size_t n_args, const mp_obj_t *args) { + return mp_obj_bytes_hex(n_args, args, &mp_type_bytes); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_hexlify_obj, 1, 2, mod_binascii_hexlify); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_hex_as_bytes_obj, 1, 2, bytes_hex_as_bytes); -STATIC mp_obj_t mod_binascii_unhexlify(mp_obj_t data) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); - - if ((bufinfo.len & 1) != 0) { - mp_raise_ValueError(MP_ERROR_TEXT("odd-length string")); - } - vstr_t vstr; - vstr_init_len(&vstr, bufinfo.len / 2); - byte *in = bufinfo.buf, *out = (byte *)vstr.buf; - byte hex_byte = 0; - for (mp_uint_t i = bufinfo.len; i--;) { - byte hex_ch = *in++; - if (unichar_isxdigit(hex_ch)) { - hex_byte += unichar_xdigit_value(hex_ch); - } else { - mp_raise_ValueError(MP_ERROR_TEXT("non-hex digit found")); - } - if (i & 1) { - hex_byte <<= 4; - } else { - *out++ = hex_byte; - hex_byte = 0; - } - } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +STATIC mp_obj_t bytes_fromhex_bytes(mp_obj_t data) { + return mp_obj_bytes_fromhex(MP_OBJ_FROM_PTR(&mp_type_bytes), data); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_unhexlify_obj, mod_binascii_unhexlify); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bytes_fromhex_obj, bytes_fromhex_bytes); +#endif // If ch is a character in the base64 alphabet, and is not a pad character, then // the corresponding integer between 0 and 63, inclusively, is returned. @@ -242,8 +185,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj, 1, 2, mod_bin STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubinascii) }, - { MP_ROM_QSTR(MP_QSTR_hexlify), MP_ROM_PTR(&mod_binascii_hexlify_obj) }, - { MP_ROM_QSTR(MP_QSTR_unhexlify), MP_ROM_PTR(&mod_binascii_unhexlify_obj) }, + #if MICROPY_PY_BUILTINS_BYTES_HEX + { MP_ROM_QSTR(MP_QSTR_hexlify), MP_ROM_PTR(&bytes_hex_as_bytes_obj) }, + { MP_ROM_QSTR(MP_QSTR_unhexlify), MP_ROM_PTR(&bytes_fromhex_obj) }, + #endif { MP_ROM_QSTR(MP_QSTR_a2b_base64), MP_ROM_PTR(&mod_binascii_a2b_base64_obj) }, { MP_ROM_QSTR(MP_QSTR_b2a_base64), MP_ROM_PTR(&mod_binascii_b2a_base64_obj) }, #if MICROPY_PY_UBINASCII_CRC32 diff --git a/ports/cc3200/mpconfigport.h b/ports/cc3200/mpconfigport.h index e81a2fc29b..f41c1fe99d 100644 --- a/ports/cc3200/mpconfigport.h +++ b/ports/cc3200/mpconfigport.h @@ -78,6 +78,7 @@ #define MICROPY_VFS_FAT (1) #define MICROPY_PY_ASYNC_AWAIT (0) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) +#define MICROPY_PY_BUILTINS_BYTES_HEX (1) #define MICROPY_PY_BUILTINS_INPUT (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_TEXT cc3200_help_text diff --git a/ports/javascript/mpconfigport.h b/ports/javascript/mpconfigport.h index 01a61e391d..6c86d816bd 100644 --- a/ports/javascript/mpconfigport.h +++ b/ports/javascript/mpconfigport.h @@ -89,6 +89,7 @@ #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_PY_FUNCTION_ATTRS (1) +#define MICROPY_PY_BUILTINS_BYTES_HEX (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_STR_CENTER (1) #define MICROPY_PY_BUILTINS_STR_PARTITION (1) diff --git a/ports/mimxrt/mpconfigport.h b/ports/mimxrt/mpconfigport.h index 00714ca8d0..54d649795d 100644 --- a/ports/mimxrt/mpconfigport.h +++ b/ports/mimxrt/mpconfigport.h @@ -74,6 +74,7 @@ uint32_t trng_random_u32(void); #define MICROPY_PY_DESCRIPTORS (1) #define MICROPY_PY_DELATTR_SETATTR (1) #define MICROPY_PY_FSTRINGS (1) +#define MICROPY_PY_BUILTINS_BYTES_HEX (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_STR_CENTER (1) #define MICROPY_PY_BUILTINS_STR_PARTITION (1) diff --git a/ports/qemu-arm/mpconfigport.h b/ports/qemu-arm/mpconfigport.h index 8809d17154..972dce61b4 100644 --- a/ports/qemu-arm/mpconfigport.h +++ b/ports/qemu-arm/mpconfigport.h @@ -28,6 +28,7 @@ #define MICROPY_PY_ALL_SPECIAL_METHODS (1) #define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) +#define MICROPY_PY_BUILTINS_BYTES_HEX (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_POW3 (1) diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 24b9cbfe19..c02d9316de 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -56,6 +56,7 @@ #define MICROPY_MODULE_WEAK_LINKS (1) // Control over Python builtins #define MICROPY_PY_ASYNC_AWAIT (0) +#define MICROPY_PY_BUILTINS_BYTES_HEX (1) #define MICROPY_PY_BUILTINS_STR_COUNT (0) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_SET (0) diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index ed4c71097f..5545a74f57 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -61,6 +61,7 @@ #define MICROPY_PY_DESCRIPTORS (1) #define MICROPY_PY_DELATTR_SETATTR (1) #define MICROPY_PY_FSTRINGS (1) +#define MICROPY_PY_BUILTINS_BYTES_HEX (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_STR_CENTER (1) #define MICROPY_PY_BUILTINS_STR_PARTITION (1) diff --git a/ports/windows/mpconfigport.h b/ports/windows/mpconfigport.h index 5f8ad983ad..4ed9f316e7 100644 --- a/ports/windows/mpconfigport.h +++ b/ports/windows/mpconfigport.h @@ -84,6 +84,7 @@ #define MICROPY_PY_DESCRIPTORS (1) #define MICROPY_PY_DELATTR_SETATTR (1) #define MICROPY_PY_FSTRINGS (1) +#define MICROPY_PY_BUILTINS_BYTES_HEX (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_STR_CENTER (1) #define MICROPY_PY_BUILTINS_STR_PARTITION (1) diff --git a/ports/zephyr/mpconfigport.h b/ports/zephyr/mpconfigport.h index 586b0ec916..4c8096b441 100644 --- a/ports/zephyr/mpconfigport.h +++ b/ports/zephyr/mpconfigport.h @@ -45,6 +45,7 @@ #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_PY_ASYNC_AWAIT (0) #define MICROPY_PY_ATTRTUPLE (0) +#define MICROPY_PY_BUILTINS_BYTES_HEX (1) #define MICROPY_PY_BUILTINS_ENUMERATE (0) #define MICROPY_PY_BUILTINS_FILTER (0) #define MICROPY_PY_BUILTINS_MIN_MAX (0) diff --git a/py/mpconfig.h b/py/mpconfig.h index 25f37ff8b3..1ed34bb6fd 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -987,6 +987,11 @@ typedef double mp_float_t; #define MICROPY_PY_STR_BYTES_CMP_WARN (0) #endif +// Add bytes.hex and bytes.fromhex +#ifndef MICROPY_PY_BUILTINS_BYTES_HEX +#define MICROPY_PY_BUILTINS_BYTES_HEX (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) +#endif + // Whether str object is proper unicode #ifndef MICROPY_PY_BUILTINS_STR_UNICODE #define MICROPY_PY_BUILTINS_STR_UNICODE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) diff --git a/py/objarray.c b/py/objarray.c index 11bd7bb15c..ecaffeb6a2 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -245,6 +245,12 @@ STATIC void memoryview_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in); dest[0] = MP_OBJ_NEW_SMALL_INT(mp_binary_get_size('@', self->typecode & TYPECODE_MASK, NULL)); } + #if MICROPY_PY_BUILTINS_BYTES_HEX + else { + // Need to forward to locals dict. + dest[1] = MP_OBJ_SENTINEL; + } + #endif } #endif @@ -607,6 +613,9 @@ const mp_obj_type_t mp_type_memoryview = { #if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE .attr = memoryview_attr, #endif + #if MICROPY_PY_BUILTINS_BYTES_HEX + .locals_dict = (mp_obj_dict_t *)&mp_obj_memoryview_locals_dict, + #endif .subscr = array_subscr, .buffer_p = { .get_buffer = array_get_buffer }, }; diff --git a/py/objstr.c b/py/objstr.c index 162229c62b..45dbb9b3eb 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -1950,6 +1950,84 @@ STATIC mp_obj_t str_encode(size_t n_args, const mp_obj_t *args) { MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj, 1, 3, str_encode); #endif +#if MICROPY_PY_BUILTINS_BYTES_HEX +mp_obj_t mp_obj_bytes_hex(size_t n_args, const mp_obj_t *args, const mp_obj_type_t *type) { + // First argument is the data to convert. + // Second argument is an optional separator to be used between values. + const char *sep = NULL; + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); + + // Code below assumes non-zero buffer length when computing size with + // separator, so handle the zero-length case here. + if (bufinfo.len == 0) { + return mp_const_empty_bytes; + } + + vstr_t vstr; + size_t out_len = bufinfo.len * 2; + if (n_args > 1) { + // 1-char separator between hex numbers + out_len += bufinfo.len - 1; + sep = mp_obj_str_get_str(args[1]); + } + vstr_init_len(&vstr, out_len); + byte *in = bufinfo.buf, *out = (byte *)vstr.buf; + for (mp_uint_t i = bufinfo.len; i--;) { + byte d = (*in >> 4); + if (d > 9) { + d += 'a' - '9' - 1; + } + *out++ = d + '0'; + d = (*in++ & 0xf); + if (d > 9) { + d += 'a' - '9' - 1; + } + *out++ = d + '0'; + if (sep != NULL && i != 0) { + *out++ = *sep; + } + } + return mp_obj_new_str_from_vstr(type, &vstr); +} + +mp_obj_t mp_obj_bytes_fromhex(mp_obj_t type_in, mp_obj_t data) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); + + if ((bufinfo.len & 1) != 0) { + mp_raise_ValueError(MP_ERROR_TEXT("odd-length string")); + } + vstr_t vstr; + vstr_init_len(&vstr, bufinfo.len / 2); + byte *in = bufinfo.buf, *out = (byte *)vstr.buf; + byte hex_byte = 0; + for (mp_uint_t i = bufinfo.len; i--;) { + byte hex_ch = *in++; + if (unichar_isxdigit(hex_ch)) { + hex_byte += unichar_xdigit_value(hex_ch); + } else { + mp_raise_ValueError(MP_ERROR_TEXT("non-hex digit found")); + } + if (i & 1) { + hex_byte <<= 4; + } else { + *out++ = hex_byte; + hex_byte = 0; + } + } + return mp_obj_new_str_from_vstr(MP_OBJ_TO_PTR(type_in), &vstr); +} + +STATIC mp_obj_t bytes_hex_as_str(size_t n_args, const mp_obj_t *args) { + return mp_obj_bytes_hex(n_args, args, &mp_type_str); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_hex_as_str_obj, 1, 2, bytes_hex_as_str); + +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bytes_fromhex_obj, mp_obj_bytes_fromhex); +STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(bytes_fromhex_classmethod_obj, MP_ROM_PTR(&bytes_fromhex_obj)); +#endif // MICROPY_PY_BUILTINS_BYTES_HEX + mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { if (flags == MP_BUFFER_READ) { GET_STR_DATA_LEN(self_in, str_data, str_len); @@ -1970,6 +2048,10 @@ STATIC const mp_rom_map_elem_t array_bytearray_str_bytes_locals_table[] = { { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&mp_obj_array_append_obj) }, { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&mp_obj_array_extend_obj) }, #endif + #if MICROPY_PY_BUILTINS_BYTES_HEX + { MP_ROM_QSTR(MP_QSTR_hex), MP_ROM_PTR(&bytes_hex_as_str_obj) }, + { MP_ROM_QSTR(MP_QSTR_fromhex), MP_ROM_PTR(&bytes_fromhex_classmethod_obj) }, + #endif #if MICROPY_CPYTHON_COMPAT { MP_ROM_QSTR(MP_QSTR_decode), MP_ROM_PTR(&bytes_decode_obj) }, #endif @@ -2018,6 +2100,12 @@ STATIC const mp_rom_map_elem_t array_bytearray_str_bytes_locals_table[] = { #define TABLE_ENTRIES_COMPAT 0 #endif +#if MICROPY_PY_BUILTINS_BYTES_HEX +#define TABLE_ENTRIES_HEX 2 +#else +#define TABLE_ENTRIES_HEX 0 +#endif + #if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY #define TABLE_ENTRIES_ARRAY 2 #else @@ -2025,8 +2113,8 @@ STATIC const mp_rom_map_elem_t array_bytearray_str_bytes_locals_table[] = { #endif MP_DEFINE_CONST_DICT_WITH_SIZE(mp_obj_str_locals_dict, - array_bytearray_str_bytes_locals_table + TABLE_ENTRIES_ARRAY + TABLE_ENTRIES_COMPAT, - MP_ARRAY_SIZE(array_bytearray_str_bytes_locals_table) - (TABLE_ENTRIES_ARRAY + TABLE_ENTRIES_COMPAT)); + array_bytearray_str_bytes_locals_table + TABLE_ENTRIES_ARRAY + TABLE_ENTRIES_HEX + TABLE_ENTRIES_COMPAT, + MP_ARRAY_SIZE(array_bytearray_str_bytes_locals_table) - (TABLE_ENTRIES_ARRAY + TABLE_ENTRIES_HEX + TABLE_ENTRIES_COMPAT)); #if TABLE_ENTRIES_COMPAT == 0 #define mp_obj_bytes_locals_dict mp_obj_str_locals_dict @@ -2048,6 +2136,12 @@ MP_DEFINE_CONST_DICT_WITH_SIZE(mp_obj_array_locals_dict, TABLE_ENTRIES_ARRAY); #endif +#if MICROPY_PY_BUILTINS_MEMORYVIEW && MICROPY_PY_BUILTINS_BYTES_HEX +MP_DEFINE_CONST_DICT_WITH_SIZE(mp_obj_memoryview_locals_dict, + array_bytearray_str_bytes_locals_table + TABLE_ENTRIES_ARRAY, + 1); // Just the "hex" entry. +#endif + #if !MICROPY_PY_BUILTINS_STR_UNICODE STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); diff --git a/py/objstr.h b/py/objstr.h index 7d86ec30ba..b1217d5872 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -127,8 +127,15 @@ MP_DECLARE_CONST_FUN_OBJ_1(str_isupper_obj); MP_DECLARE_CONST_FUN_OBJ_1(str_islower_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj); +mp_obj_t mp_obj_bytes_hex(size_t n_args, const mp_obj_t *args, const mp_obj_type_t *type); +mp_obj_t mp_obj_bytes_fromhex(mp_obj_t type_in, mp_obj_t data); + extern const mp_obj_dict_t mp_obj_str_locals_dict; +#if MICROPY_PY_BUILTINS_MEMORYVIEW && MICROPY_PY_BUILTINS_BYTES_HEX +extern const mp_obj_dict_t mp_obj_memoryview_locals_dict; +#endif + #if MICROPY_PY_BUILTINS_BYTEARRAY extern const mp_obj_dict_t mp_obj_bytearray_locals_dict; #endif From f694058f2bce7d6e5ef82c8efd2bcb6cdebfe7a8 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 13 Jul 2021 22:49:49 +1000 Subject: [PATCH 0275/1041] tests/extmod/ubinascii: Add tests for bytes.hex etc. Also make the sep test not micropython-specific. Signed-off-by: Jim Mussared --- tests/basics/builtin_str_hex.py | 24 +++++++++++++++++++++++ tests/extmod/ubinascii_hexlify.py | 17 ++++++++++++---- tests/extmod/ubinascii_micropython.py | 15 -------------- tests/extmod/ubinascii_micropython.py.exp | 2 -- tests/extmod/ubinascii_unhexlify.py | 11 +++++++---- 5 files changed, 44 insertions(+), 25 deletions(-) create mode 100644 tests/basics/builtin_str_hex.py delete mode 100644 tests/extmod/ubinascii_micropython.py delete mode 100644 tests/extmod/ubinascii_micropython.py.exp diff --git a/tests/basics/builtin_str_hex.py b/tests/basics/builtin_str_hex.py new file mode 100644 index 0000000000..7390c8eaee --- /dev/null +++ b/tests/basics/builtin_str_hex.py @@ -0,0 +1,24 @@ +if not hasattr(bytes, "fromhex"): + print("SKIP") + raise SystemExit + +for x in ( + b"\x00\x01\x02\x03\x04\x05\x06\x07", + b"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + b"\x7f\x80\xff", + b"1234ABCDabcd", +): + print(x.hex()) + print(bytearray(x).hex()) + print(memoryview(x).hex()) + print(x.hex(":")) + print(bytearray(x).hex(":")) + print(memoryview(x).hex(":")) + +for x in ( + "0001020304050607", + "08090a0b0c0d0e0f", + "7f80ff", + "313233344142434461626364", +): + print(bytes.fromhex(x)) diff --git a/tests/extmod/ubinascii_hexlify.py b/tests/extmod/ubinascii_hexlify.py index 2329f53edd..3c266fb6cc 100644 --- a/tests/extmod/ubinascii_hexlify.py +++ b/tests/extmod/ubinascii_hexlify.py @@ -7,7 +7,16 @@ except ImportError: print("SKIP") raise SystemExit -print(binascii.hexlify(b"\x00\x01\x02\x03\x04\x05\x06\x07")) -print(binascii.hexlify(b"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f")) -print(binascii.hexlify(b"\x7f\x80\xff")) -print(binascii.hexlify(b"1234ABCDabcd")) +for x in ( + b"\x00\x01\x02\x03\x04\x05\x06\x07", + b"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + b"\x7f\x80\xff", + b"1234ABCDabcd", +): + print(binascii.hexlify(x)) + +# Two-argument version (now supported in CPython) +print(binascii.hexlify(b"123", ":")) + +# zero length buffer +print(binascii.hexlify(b"", b":")) diff --git a/tests/extmod/ubinascii_micropython.py b/tests/extmod/ubinascii_micropython.py deleted file mode 100644 index 94e8daa557..0000000000 --- a/tests/extmod/ubinascii_micropython.py +++ /dev/null @@ -1,15 +0,0 @@ -try: - try: - import ubinascii as binascii - except ImportError: - import binascii -except ImportError: - print("SKIP") - raise SystemExit - -# two arguments supported in uPy but not CPython -a = binascii.hexlify(b"123", ":") -print(a) - -# zero length buffer -print(binascii.hexlify(b"", b":")) diff --git a/tests/extmod/ubinascii_micropython.py.exp b/tests/extmod/ubinascii_micropython.py.exp deleted file mode 100644 index a195d2602c..0000000000 --- a/tests/extmod/ubinascii_micropython.py.exp +++ /dev/null @@ -1,2 +0,0 @@ -b'31:32:33' -b'' diff --git a/tests/extmod/ubinascii_unhexlify.py b/tests/extmod/ubinascii_unhexlify.py index 413eaf1b6f..2c3598ab98 100644 --- a/tests/extmod/ubinascii_unhexlify.py +++ b/tests/extmod/ubinascii_unhexlify.py @@ -7,10 +7,13 @@ except ImportError: print("SKIP") raise SystemExit -print(binascii.unhexlify(b"0001020304050607")) -print(binascii.unhexlify(b"08090a0b0c0d0e0f")) -print(binascii.unhexlify(b"7f80ff")) -print(binascii.unhexlify(b"313233344142434461626364")) +for x in ( + b"0001020304050607", + b"08090a0b0c0d0e0f", + b"7f80ff", + b"313233344142434461626364", +): + print(binascii.unhexlify(x)) try: a = binascii.unhexlify(b"0") # odd buffer length From ec24cd1d25a322192be93dc54a02ca4564fc9e7b Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 12 Aug 2022 10:12:21 +1000 Subject: [PATCH 0276/1041] mpy-cross,unix: Remove .gitignore file. Now that all build artefacts are placed in a build/ directory the gitignore is no longer needed. Signed-off-by: Damien George --- mpy-cross/.gitignore | 1 - ports/unix/.gitignore | 3 --- 2 files changed, 4 deletions(-) delete mode 100644 mpy-cross/.gitignore delete mode 100644 ports/unix/.gitignore diff --git a/mpy-cross/.gitignore b/mpy-cross/.gitignore deleted file mode 100644 index 82a0a7efaa..0000000000 --- a/mpy-cross/.gitignore +++ /dev/null @@ -1 +0,0 @@ -mpy-cross diff --git a/ports/unix/.gitignore b/ports/unix/.gitignore deleted file mode 100644 index 3ca8f6cb27..0000000000 --- a/ports/unix/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -micropython -micropython-* -*.gcov From 945f377b436d3ba6d0ac9962762038133e864604 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 12 Aug 2022 10:15:27 +1000 Subject: [PATCH 0277/1041] py/objstr: Remove str function object declarations from header file. Since f7f56d42851aaff2027e23a8ca45c1f1973f1aca consolidated all uses of these to a single locals dict, they no longer need to be made public. Signed-off-by: Damien George --- py/objstr.h | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/py/objstr.h b/py/objstr.h index b1217d5872..78441fedaf 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -98,35 +98,6 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s mp_obj_t index, bool is_slice); const byte *find_subbytes(const byte *haystack, size_t hlen, const byte *needle, size_t nlen, int direction); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj); -MP_DECLARE_CONST_FUN_OBJ_2(str_join_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj); -MP_DECLARE_CONST_FUN_OBJ_KW(str_splitlines_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_lstrip_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rstrip_obj); -MP_DECLARE_CONST_FUN_OBJ_KW(str_format_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj); -MP_DECLARE_CONST_FUN_OBJ_2(str_partition_obj); -MP_DECLARE_CONST_FUN_OBJ_2(str_rpartition_obj); -MP_DECLARE_CONST_FUN_OBJ_2(str_center_obj); -MP_DECLARE_CONST_FUN_OBJ_1(str_lower_obj); -MP_DECLARE_CONST_FUN_OBJ_1(str_upper_obj); -MP_DECLARE_CONST_FUN_OBJ_1(str_isspace_obj); -MP_DECLARE_CONST_FUN_OBJ_1(str_isalpha_obj); -MP_DECLARE_CONST_FUN_OBJ_1(str_isdigit_obj); -MP_DECLARE_CONST_FUN_OBJ_1(str_isupper_obj); -MP_DECLARE_CONST_FUN_OBJ_1(str_islower_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj); - mp_obj_t mp_obj_bytes_hex(size_t n_args, const mp_obj_t *args, const mp_obj_type_t *type); mp_obj_t mp_obj_bytes_fromhex(mp_obj_t type_in, mp_obj_t data); From cf90e24335652462bb7eb4bd105e061683bc316a Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 12 Aug 2022 10:32:20 +1000 Subject: [PATCH 0278/1041] py/mkrules: Use abspath to find directory for mpy-cross dependency. Otherwise if the `mpy-cross/build/` directory doesn't exist then `mpy-cross/build/..` won't work. Signed-off-by: Damien George --- py/mkrules.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/mkrules.mk b/py/mkrules.mk index 73c33227c0..14f1b953cd 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -162,7 +162,7 @@ $(HEADER_BUILD): ifneq ($(MICROPY_MPYCROSS_DEPENDENCY),) # to automatically build mpy-cross, if needed $(MICROPY_MPYCROSS_DEPENDENCY): - $(MAKE) -C $(dir $@).. + $(MAKE) -C $(abspath $(dir $@)..) endif ifneq ($(FROZEN_DIR),) From 5543b2a9cc7381931431c69d93a77ba5d5d58e2e Mon Sep 17 00:00:00 2001 From: Ned Konz Date: Wed, 1 Sep 2021 10:48:15 -0700 Subject: [PATCH 0279/1041] extmod/uasyncio: Add clear method to ThreadSafeFlag. This is useful in situations where the ThreadSafeFlag is reused and needs to be cleared of any previous, unwanted event. For example, clear the flag at the start of an operation, trigger the operation (eg an I2C write), then (a)wait for an external event to set the flag (eg a pin IRQ). Further events may trigger the flag again but these are unwanted and should be cleared before the next cycle starts. --- docs/library/uasyncio.rst | 7 ++++++- extmod/uasyncio/event.py | 5 ++++- tests/extmod/uasyncio_threadsafeflag.py | 20 ++++++++++++++++++++ tests/extmod/uasyncio_threadsafeflag.py.exp | 11 +++++++++++ 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/docs/library/uasyncio.rst b/docs/library/uasyncio.rst index 0abbf8dd8d..859d505d79 100644 --- a/docs/library/uasyncio.rst +++ b/docs/library/uasyncio.rst @@ -153,9 +153,14 @@ class ThreadSafeFlag .. method:: ThreadSafeFlag.set() - Set the flag. If there is a task waiting on the event, it will be scheduled + Set the flag. If there is a task waiting on the flag, it will be scheduled to run. +.. method:: ThreadSafeFlag.clear() + + Clear the flag. This may be used to ensure that a possibly previously-set + flag is clear before waiting for it. + .. method:: ThreadSafeFlag.wait() Wait for the flag to be set. If the flag is already set then it returns diff --git a/extmod/uasyncio/event.py b/extmod/uasyncio/event.py index c48904b983..654ccefa98 100644 --- a/extmod/uasyncio/event.py +++ b/extmod/uasyncio/event.py @@ -36,7 +36,7 @@ class Event: # MicroPython-extension: This can be set from outside the asyncio event loop, # such as other threads, IRQs or scheduler context. Implementation is a stream # that asyncio will poll until a flag is set. -# Note: Unlike Event, this is self-clearing. +# Note: Unlike Event, this is self-clearing after a wait(). try: import uio @@ -52,6 +52,9 @@ try: def set(self): self._flag = 1 + def clear(self): + self._flag = 0 + async def wait(self): if not self._flag: yield core._io_queue.queue_read(self) diff --git a/tests/extmod/uasyncio_threadsafeflag.py b/tests/extmod/uasyncio_threadsafeflag.py index 4e002a3d2a..a8a08d2e92 100644 --- a/tests/extmod/uasyncio_threadsafeflag.py +++ b/tests/extmod/uasyncio_threadsafeflag.py @@ -75,5 +75,25 @@ async def main(): print("wait task") await t + # Flag set, cleared, and set again. + print("----") + print("set event") + flag.set() + print("yield") + await asyncio.sleep(0) + print("clear event") + flag.clear() + print("yield") + await asyncio.sleep(0) + t = asyncio.create_task(task(4, flag)) + print("yield") + await asyncio.sleep(0) + print("set event") + flag.set() + print("yield") + await asyncio.sleep(0) + print("wait task") + await t + asyncio.run(main()) diff --git a/tests/extmod/uasyncio_threadsafeflag.py.exp b/tests/extmod/uasyncio_threadsafeflag.py.exp index aef4e479ba..757115ac4b 100644 --- a/tests/extmod/uasyncio_threadsafeflag.py.exp +++ b/tests/extmod/uasyncio_threadsafeflag.py.exp @@ -19,3 +19,14 @@ yield task 3 task 3 done wait task +---- +set event +yield +clear event +yield +yield +task 4 +set event +yield +wait task +task 4 done From 01514e80c9a150f0506bd6c8c43590ca05f8598f Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 12 Aug 2022 17:03:38 +1000 Subject: [PATCH 0280/1041] extmod/uasyncio: Rename internal _flag to state, to save a qstr. Saves about 16 bytes of flash when uasyncio is frozen in. Signed-off-by: Damien George --- extmod/uasyncio/event.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/extmod/uasyncio/event.py b/extmod/uasyncio/event.py index 654ccefa98..3b5e79d8f2 100644 --- a/extmod/uasyncio/event.py +++ b/extmod/uasyncio/event.py @@ -42,23 +42,23 @@ try: class ThreadSafeFlag(uio.IOBase): def __init__(self): - self._flag = 0 + self.state = 0 def ioctl(self, req, flags): if req == 3: # MP_STREAM_POLL - return self._flag * flags + return self.state * flags return None def set(self): - self._flag = 1 + self.state = 1 def clear(self): - self._flag = 0 + self.state = 0 async def wait(self): - if not self._flag: + if not self.state: yield core._io_queue.queue_read(self) - self._flag = 0 + self.state = 0 except ImportError: pass From 69719927f1752b2d6333708c5b60067fe3b7965d Mon Sep 17 00:00:00 2001 From: MrJake222 Date: Thu, 16 Sep 2021 19:49:42 +0200 Subject: [PATCH 0281/1041] extmod/modlwip: Add support for leaving multicast groups. --- extmod/modlwip.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/extmod/modlwip.c b/extmod/modlwip.c index 25669228df..c6ee02132f 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -66,6 +66,7 @@ // All socket options should be globally distinct, // because we ignore option levels for efficiency. #define IP_ADD_MEMBERSHIP 0x400 +#define IP_DROP_MEMBERSHIP 0x401 // For compatibilily with older lwIP versions. #ifndef ip_set_option @@ -1376,7 +1377,8 @@ STATIC mp_obj_t lwip_socket_setsockopt(size_t n_args, const mp_obj_t *args) { } // level: IPPROTO_IP - case IP_ADD_MEMBERSHIP: { + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); if (bufinfo.len != sizeof(ip_addr_t) * 2) { @@ -1384,7 +1386,12 @@ STATIC mp_obj_t lwip_socket_setsockopt(size_t n_args, const mp_obj_t *args) { } // POSIX setsockopt has order: group addr, if addr, lwIP has it vice-versa - err_t err = igmp_joingroup((ip_addr_t *)bufinfo.buf + 1, bufinfo.buf); + err_t err; + if (opt == IP_ADD_MEMBERSHIP) { + err = igmp_joingroup((ip_addr_t *)bufinfo.buf + 1, bufinfo.buf); + } else { + err = igmp_leavegroup((ip_addr_t *)bufinfo.buf + 1, bufinfo.buf); + } if (err != ERR_OK) { mp_raise_OSError(error_lookup_table[-err]); } @@ -1769,6 +1776,7 @@ STATIC const mp_rom_map_elem_t mp_module_lwip_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(0) }, { MP_ROM_QSTR(MP_QSTR_IP_ADD_MEMBERSHIP), MP_ROM_INT(IP_ADD_MEMBERSHIP) }, + { MP_ROM_QSTR(MP_QSTR_IP_DROP_MEMBERSHIP), MP_ROM_INT(IP_DROP_MEMBERSHIP) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_lwip_globals, mp_module_lwip_globals_table); From 6cd2e4191803e95580bdfc57c06ea818454a25d1 Mon Sep 17 00:00:00 2001 From: Dan Ellis Date: Thu, 28 Jul 2022 23:21:00 -0400 Subject: [PATCH 0282/1041] py/parsenum: Ensure that trailing zeros lead to identical results. Prior to this commit, parsenum would calculate "1e-20" as 1.0*pow(10, -20), and "1.000e-20" as 1000.0*pow(10, -23); in certain cases, this could make seemingly-identical values compare as not equal. This commit watches for trailing zeros as a special case, and ignores them when appropriate, so "1.000e-20" is also calculated as 1.0*pow(10, -20). Fixes issue #5831. --- py/parsenum.c | 84 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 28 deletions(-) diff --git a/py/parsenum.c b/py/parsenum.c index 5e8e5dfe8c..19cc719201 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -178,6 +178,44 @@ typedef enum { PARSE_DEC_IN_EXP, } parse_dec_in_t; +#if MICROPY_PY_BUILTINS_FLOAT +// DEC_VAL_MAX only needs to be rough and is used to retain precision while not overflowing +// SMALL_NORMAL_VAL is the smallest power of 10 that is still a normal float +// EXACT_POWER_OF_10 is the largest value of x so that 10^x can be stored exactly in a float +// Note: EXACT_POWER_OF_10 is at least floor(log_5(2^mantissa_length)). Indeed, 10^n = 2^n * 5^n +// so we only have to store the 5^n part in the mantissa (the 2^n part will go into the float's +// exponent). +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT +#define DEC_VAL_MAX 1e20F +#define SMALL_NORMAL_VAL (1e-37F) +#define SMALL_NORMAL_EXP (-37) +#define EXACT_POWER_OF_10 (9) +#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE +#define DEC_VAL_MAX 1e200 +#define SMALL_NORMAL_VAL (1e-307) +#define SMALL_NORMAL_EXP (-307) +#define EXACT_POWER_OF_10 (22) +#endif + +// Break out inner digit accumulation routine to ease trailing zero deferral. +static void accept_digit(mp_float_t *p_dec_val, int dig, int *p_exp_extra, int in) { + // Core routine to ingest an additional digit. + if (*p_dec_val < DEC_VAL_MAX) { + // dec_val won't overflow so keep accumulating + *p_dec_val = 10 * *p_dec_val + dig; + if (in == PARSE_DEC_IN_FRAC) { + --(*p_exp_extra); + } + } else { + // dec_val might overflow and we anyway can't represent more digits + // of precision, so ignore the digit and just adjust the exponent + if (in == PARSE_DEC_IN_INTG) { + ++(*p_exp_extra); + } + } +} +#endif // MICROPY_BUILTINS_FLOAT + #if MICROPY_PY_BUILTINS_COMPLEX mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex) #else @@ -186,24 +224,6 @@ mp_obj_t mp_parse_num_float(const char *str, size_t len, bool allow_imag, mp_lex { #if MICROPY_PY_BUILTINS_FLOAT -// DEC_VAL_MAX only needs to be rough and is used to retain precision while not overflowing -// SMALL_NORMAL_VAL is the smallest power of 10 that is still a normal float -// EXACT_POWER_OF_10 is the largest value of x so that 10^x can be stored exactly in a float -// Note: EXACT_POWER_OF_10 is at least floor(log_5(2^mantissa_length)). Indeed, 10^n = 2^n * 5^n -// so we only have to store the 5^n part in the mantissa (the 2^n part will go into the float's -// exponent). - #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT -#define DEC_VAL_MAX 1e20F -#define SMALL_NORMAL_VAL (1e-37F) -#define SMALL_NORMAL_EXP (-37) -#define EXACT_POWER_OF_10 (9) - #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE -#define DEC_VAL_MAX 1e200 -#define SMALL_NORMAL_VAL (1e-307) -#define SMALL_NORMAL_EXP (-307) -#define EXACT_POWER_OF_10 (22) - #endif - const char *top = str + len; mp_float_t dec_val = 0; bool dec_neg = false; @@ -255,6 +275,7 @@ parse_start: bool exp_neg = false; int exp_val = 0; int exp_extra = 0; + int trailing_zeros_intg = 0, trailing_zeros_frac = 0; while (str < top) { unsigned int dig = *str++; if ('0' <= dig && dig <= '9') { @@ -267,18 +288,25 @@ parse_start: exp_val = 10 * exp_val + dig; } } else { - if (dec_val < DEC_VAL_MAX) { - // dec_val won't overflow so keep accumulating - dec_val = 10 * dec_val + dig; - if (in == PARSE_DEC_IN_FRAC) { - --exp_extra; + if (dig == 0 || dec_val >= DEC_VAL_MAX) { + // Defer treatment of zeros in fractional part. If nothing comes afterwards, ignore them. + // Also, once we reach DEC_VAL_MAX, treat every additional digit as a trailing zero. + if (in == PARSE_DEC_IN_INTG) { + ++trailing_zeros_intg; + } else { + ++trailing_zeros_frac; } } else { - // dec_val might overflow and we anyway can't represent more digits - // of precision, so ignore the digit and just adjust the exponent - if (in == PARSE_DEC_IN_INTG) { - ++exp_extra; + // Time to un-defer any trailing zeros. Intg zeros first. + while (trailing_zeros_intg) { + accept_digit(&dec_val, 0, &exp_extra, PARSE_DEC_IN_INTG); + --trailing_zeros_intg; } + while (trailing_zeros_frac) { + accept_digit(&dec_val, 0, &exp_extra, PARSE_DEC_IN_FRAC); + --trailing_zeros_frac; + } + accept_digit(&dec_val, dig, &exp_extra, in); } } } else if (in == PARSE_DEC_IN_INTG && dig == '.') { @@ -311,7 +339,7 @@ parse_start: } // apply the exponent, making sure it's not a subnormal value - exp_val += exp_extra; + exp_val += exp_extra + trailing_zeros_intg; if (exp_val < SMALL_NORMAL_EXP) { exp_val -= SMALL_NORMAL_EXP; dec_val *= SMALL_NORMAL_VAL; From 6f4d424f461bede1afb69637763f4fce5f27cd90 Mon Sep 17 00:00:00 2001 From: Dan Ellis Date: Thu, 28 Jul 2022 10:49:18 -0400 Subject: [PATCH 0283/1041] py/formatfloat: Use pow(10, e) instead of pos/neg_pow lookup tables. Rework the conversion of floats to decimal strings so it aligns precisely with the conversion of strings to floats in parsenum.c. This is to avoid rendering 1eX as 9.99999eX-1 etc. This is achieved by removing the power- of-10 tables and using pow() to compute the exponent directly, and that's done efficiently by first estimating the power-of-10 exponent from the power-of-2 exponent in the floating-point representation. Code size is reduced by roughly 100 to 200 bytes by this commit. Signed-off-by: Dan Ellis --- py/formatfloat.c | 132 ++++++-------------- py/misc.h | 2 + tests/float/float_format.py | 8 ++ tests/float/float_format_ints_doubleprec.py | 3 + tests/float/string_format_modulo.py | 5 +- 5 files changed, 53 insertions(+), 97 deletions(-) diff --git a/py/formatfloat.c b/py/formatfloat.c index 357b73ace3..fc1b2fe7fc 100644 --- a/py/formatfloat.c +++ b/py/formatfloat.c @@ -62,26 +62,20 @@ #define FPMIN_BUF_SIZE 6 // +9e+99 #define FLT_SIGN_MASK 0x80000000 -#define FLT_EXP_MASK 0x7F800000 -#define FLT_MAN_MASK 0x007FFFFF -union floatbits { - float f; - uint32_t u; -}; static inline int fp_signbit(float x) { - union floatbits fb = {x}; - return fb.u & FLT_SIGN_MASK; + mp_float_union_t fb = {x}; + return fb.i & FLT_SIGN_MASK; } #define fp_isnan(x) isnan(x) #define fp_isinf(x) isinf(x) static inline int fp_iszero(float x) { - union floatbits fb = {x}; - return fb.u == 0; + mp_float_union_t fb = {x}; + return fb.i == 0; } static inline int fp_isless1(float x) { - union floatbits fb = {x}; - return fb.u < 0x3f800000; + mp_float_union_t fb = {x}; + return fb.i < 0x3f800000; } #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE @@ -99,28 +93,11 @@ static inline int fp_isless1(float x) { #endif // MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT/DOUBLE -static inline int fp_ge_eps(FPTYPE x, FPTYPE y) { - mp_float_union_t fb_y = {y}; - // Back off 2 eps. - // This is valid for almost all values, but in practice - // it's only used when y = 1eX for X>=0. - fb_y.i -= 2; - return x >= fb_y.f; +static inline int fp_expval(FPTYPE x) { + mp_float_union_t fb = {x}; + return (int)((fb.i >> MP_FLOAT_FRAC_BITS) & (~(0xFFFFFFFF << MP_FLOAT_EXP_BITS))) - MP_FLOAT_EXP_OFFSET; } -static const FPTYPE g_pos_pow[] = { - #if FPDECEXP > 32 - MICROPY_FLOAT_CONST(1e256), MICROPY_FLOAT_CONST(1e128), MICROPY_FLOAT_CONST(1e64), - #endif - MICROPY_FLOAT_CONST(1e32), MICROPY_FLOAT_CONST(1e16), MICROPY_FLOAT_CONST(1e8), MICROPY_FLOAT_CONST(1e4), MICROPY_FLOAT_CONST(1e2), MICROPY_FLOAT_CONST(1e1) -}; -static const FPTYPE g_neg_pow[] = { - #if FPDECEXP > 32 - MICROPY_FLOAT_CONST(1e-256), MICROPY_FLOAT_CONST(1e-128), MICROPY_FLOAT_CONST(1e-64), - #endif - MICROPY_FLOAT_CONST(1e-32), MICROPY_FLOAT_CONST(1e-16), MICROPY_FLOAT_CONST(1e-8), MICROPY_FLOAT_CONST(1e-4), MICROPY_FLOAT_CONST(1e-2), MICROPY_FLOAT_CONST(1e-1) -}; - int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, char sign) { char *s = buf; @@ -177,14 +154,15 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch if (fmt == 'g' && prec == 0) { prec = 1; } - int e, e1; + int e; int dec = 0; char e_sign = '\0'; int num_digits = 0; - const FPTYPE *pos_pow = g_pos_pow; - const FPTYPE *neg_pow = g_neg_pow; int signed_e = 0; + // Approximate power of 10 exponent from binary exponent. + // abs(e_guess) is lower bound on abs(power of 10 exponent). + int e_guess = (int)(fp_expval(f) * FPCONST(0.3010299956639812)); // 1/log2(10). if (fp_iszero(f)) { e = 0; if (fmt == 'f') { @@ -203,25 +181,18 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch } } } else if (fp_isless1(f)) { - FPTYPE f_mod = f; + FPTYPE f_entry = f; // Save f in case we go to 'f' format. // Build negative exponent - for (e = 0, e1 = FPDECEXP; e1; e1 >>= 1, pos_pow++, neg_pow++) { - if (*neg_pow > f_mod) { - e += e1; - f_mod *= *pos_pow; - } - } - - char e_sign_char = '-'; - if (fp_isless1(f_mod) && f_mod >= FPROUND_TO_ONE) { - f_mod = FPCONST(1.0); - if (e == 0) { - e_sign_char = '+'; - } - } else if (fp_isless1(f_mod)) { - e++; - f_mod *= FPCONST(10.0); + e = -e_guess; + FPTYPE u_base = MICROPY_FLOAT_C_FUN(pow)(10, -e); + while (u_base > f) { + ++e; + u_base = MICROPY_FLOAT_C_FUN(pow)(10, -e); } + // Normalize out the inferred unit. Use divide because + // pow(10, e) * pow(10, -e) is slightly < 1 for some e in float32 + // (e.g. print("%.12f" % ((1e13) * (1e-13)))) + f /= u_base; // If the user specified 'g' format, and e is <= 4, then we'll switch // to the fixed format ('f') @@ -241,11 +212,12 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch num_digits = prec; signed_e = 0; + f = f_entry; ++num_digits; } else { // For e & g formats, we'll be printing the exponent, so set the // sign. - e_sign = e_sign_char; + e_sign = '-'; dec = 0; if (prec > (buf_remaining - FPMIN_BUF_SIZE)) { @@ -262,19 +234,11 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch // scaling it. Instead, we find the product of powers of 10 // that is not greater than it, and use that to start the // mantissa. - FPTYPE u_base = FPCONST(1.0); - for (e = 0, e1 = FPDECEXP; e1; e1 >>= 1, pos_pow++) { - FPTYPE next_u = u_base * *pos_pow; - // fp_ge_eps performs "f >= (next_u - 2eps)" so that if, for - // numerical reasons, f is very close to a power of ten but - // not strictly equal, we still treat it as that power of 10. - // The comparison was failing for maybe 10% of 1eX values, but - // although rounding fixed many of them, there were still some - // rendering as 9.99999998e(X-1). - if (fp_ge_eps(f, next_u)) { - u_base = next_u; - e += e1; - } + e = e_guess; + FPTYPE next_u = MICROPY_FLOAT_C_FUN(pow)(10, e + 1); + while (f >= next_u) { + ++e; + next_u = MICROPY_FLOAT_C_FUN(pow)(10, e + 1); } // If the user specified fixed format (fmt == 'f') and e makes the @@ -341,46 +305,22 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch num_digits = prec; } - if (signed_e < 0) { - // The algorithm below treats numbers smaller than 1 by scaling them - // repeatedly by 10 to bring the new digit to the top. Our input number - // was smaller than 1, so scale it up to be 1 <= f < 10. - FPTYPE u_base = FPCONST(1.0); - const FPTYPE *pow_u = g_pos_pow; - for (int m = FPDECEXP; m; m >>= 1, pow_u++) { - if (m & e) { - u_base *= *pow_u; - } - } - f *= u_base; - } - int d = 0; - int num_digits_left = num_digits; - for (int digit_index = signed_e; num_digits_left >= 0; --digit_index) { + for (int digit_index = signed_e; num_digits >= 0; --digit_index) { FPTYPE u_base = FPCONST(1.0); if (digit_index > 0) { // Generate 10^digit_index for positive digit_index. - const FPTYPE *pow_u = g_pos_pow; - int target_index = digit_index; - for (int m = FPDECEXP; m; m >>= 1, pow_u++) { - if (m & target_index) { - u_base *= *pow_u; - } - } + u_base = MICROPY_FLOAT_C_FUN(pow)(10, digit_index); } for (d = 0; d < 9; ++d) { - // This is essentially "if (f < u_base)", but with 2eps margin - // so that if f is just a tiny bit smaller, we treat it as - // equal (and accept the additional digit value). - if (!fp_ge_eps(f, u_base)) { + if (f < u_base) { break; } f -= u_base; } // We calculate one more digit than we display, to use in rounding // below. So only emit the digit if it's one that we display. - if (num_digits_left > 0) { + if (num_digits > 0) { // Emit this number (the leading digit). *s++ = '0' + d; if (dec == 0 && prec > 0) { @@ -388,9 +328,9 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch } } --dec; - --num_digits_left; + --num_digits; if (digit_index <= 0) { - // Once we get below 1.0, we scale up f instead of calculting + // Once we get below 1.0, we scale up f instead of calculating // negative powers of 10 in u_base. This provides better // renditions of exact decimals like 1/16 etc. f *= FPCONST(10.0); diff --git a/py/misc.h b/py/misc.h index e642598c56..134325f894 100644 --- a/py/misc.h +++ b/py/misc.h @@ -243,10 +243,12 @@ extern mp_uint_t mp_verbose_flag; #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE #define MP_FLOAT_EXP_BITS (11) +#define MP_FLOAT_EXP_OFFSET (1023) #define MP_FLOAT_FRAC_BITS (52) typedef uint64_t mp_float_uint_t; #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT #define MP_FLOAT_EXP_BITS (8) +#define MP_FLOAT_EXP_OFFSET (127) #define MP_FLOAT_FRAC_BITS (23) typedef uint32_t mp_float_uint_t; #endif diff --git a/tests/float/float_format.py b/tests/float/float_format.py index 4c8a217567..98ed0eb096 100644 --- a/tests/float/float_format.py +++ b/tests/float/float_format.py @@ -17,3 +17,11 @@ print("%.2e" % float("9" * 40 + "e-21")) # check a case that would render negative digit values, eg ")" characters # the string is converted back to a float to check for no illegal characters float("%.23e" % 1e-80) + +# Check a problem with malformed "e" format numbers on the edge of 1.0e-X. +for r in range(38): + s = "%.12e" % float("1e-" + str(r)) + # It may format as 1e-r, or 9.999...e-(r+1), both are OK. + # But formatting as 0.999...e-r is NOT ok. + if s[0] == "0": + print("FAIL:", s) diff --git a/tests/float/float_format_ints_doubleprec.py b/tests/float/float_format_ints_doubleprec.py index 57899d6d65..67101d3e45 100644 --- a/tests/float/float_format_ints_doubleprec.py +++ b/tests/float/float_format_ints_doubleprec.py @@ -13,3 +13,6 @@ v1 = 0x54B249AD2594C37D # 1e100 v2 = 0x6974E718D7D7625A # 1e200 print("{:.12e}".format(array.array("d", v1.to_bytes(8, sys.byteorder))[0])) print("{:.12e}".format(array.array("d", v2.to_bytes(8, sys.byteorder))[0])) + +for i in range(300): + print(float("1e" + str(i))) diff --git a/tests/float/string_format_modulo.py b/tests/float/string_format_modulo.py index 0944615381..3c206b7393 100644 --- a/tests/float/string_format_modulo.py +++ b/tests/float/string_format_modulo.py @@ -41,7 +41,10 @@ print(("%.40f" % 1e-300)[:2]) print(("%.40g" % 1e-1)[:2]) print(("%.40g" % 1e-2)[:2]) print(("%.40g" % 1e-3)[:2]) -print(("%.40g" % 1e-4)[:2]) +# Under Appveyor Release builds, 1e-4 was being formatted as 9.99999...e-5 +# instead of 0.0001. (Interestingly, it formatted correctly for the Debug +# build). Avoid the edge case. +print(("%.40g" % 1.1e-4)[:2]) print("%.0g" % 1) # 0 precision 'g' From a16a330da54afd392252d7ea04139fd4702f48f8 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 15 Aug 2022 16:07:00 +1000 Subject: [PATCH 0284/1041] nrf,stm32: Don't enable debug info by default if LTO is on. It seems sometimes gcc with LTO will generate otherwise valid assembly listings that cause 'as' to error out when generating DWARF debug info; see https://sourceware.org/bugzilla/show_bug.cgi?id=29494 Therefore, don't enable -g by default if LTO is on. Enabling LTO=1 DEBUG=1 is still possible but may result in random errors at link time due to 'as' (the error in this case is "Error: unaligned opcodes detected in executable segment", and the only other easy workaround is CFLAGS+=-fno-jump-tables which may increase code size significantly). Follows on from fdfe4eca745dce5f20fb65a3c197006b9053999a --- ports/nrf/Makefile | 6 ++++-- ports/stm32/Makefile | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 23be4430f3..bc295cac80 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -138,12 +138,14 @@ LDFLAGS += -Wl,'--defsym=_fs_size=$(FS_SIZE)' endif #Debugging/Optimization -CFLAGS += -g # always include debug info in the ELF ifeq ($(DEBUG), 1) #ASMFLAGS += -g -gtabs+ -CFLAGS += -O0 +CFLAGS += -g -O0 LDFLAGS += -O0 else +ifneq ($(LTO), 1) +CFLAGS += -g # always include debug info in the ELF, unless LTO is on +endif CFLAGS += -Os -DNDEBUG LDFLAGS += -Os endif diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 657524798c..14a93a5aa7 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -114,13 +114,15 @@ $(BUILD)/stm32_it.o $(BUILD)/pendsv.o: CFLAGS += -fno-lto endif # Debugging/Optimization -CFLAGS += -g # always include debug info in the ELF ifeq ($(DEBUG), 1) -CFLAGS += -DPENDSV_DEBUG +CFLAGS += -g -DPENDSV_DEBUG COPT ?= -Og # Disable text compression in debug builds MICROPY_ROM_TEXT_COMPRESSION = 0 else +ifneq ($(LTO), 1) +CFLAGS += -g # always include debug info in the ELF, unless LTO is on +endif COPT ?= -Os -DNDEBUG endif From 454d969781564567864bb431f416df1fc1852765 Mon Sep 17 00:00:00 2001 From: David Peake Date: Mon, 15 Aug 2022 20:17:41 +1000 Subject: [PATCH 0285/1041] docs/esp32: Fix string quoting consistency in SDCard mount example. It appears that strings in the documentation are typically single quoted. --- docs/esp32/quickref.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 3cbb673c04..1529c0ef49 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -589,7 +589,7 @@ See :ref:`machine.SDCard `. :: # Slot 2 uses pins sck=18, cs=5, miso=19, mosi=23 sd = machine.SDCard(slot=2) - os.mount(sd, "/sd") # mount + os.mount(sd, '/sd') # mount os.listdir('/sd') # list directory contents From 98bd7e33b32fb00ad2900e71cbe5cc4938598a7a Mon Sep 17 00:00:00 2001 From: Efi Weiss Date: Sun, 14 Aug 2022 22:12:24 +0300 Subject: [PATCH 0286/1041] unix/modusocket: Support proto and flags arguments to getaddrinfo. Signed-off-by: Efi Weiss --- ports/unix/modusocket.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c index 03d069cb89..69ae2a78eb 100644 --- a/ports/unix/modusocket.c +++ b/ports/unix/modusocket.c @@ -564,7 +564,6 @@ STATIC mp_obj_t mod_socket_inet_ntop(mp_obj_t family_in, mp_obj_t binaddr_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_socket_inet_ntop_obj, mod_socket_inet_ntop); STATIC mp_obj_t mod_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { - // TODO: Implement 5th and 6th args const char *host = mp_obj_str_get_str(args[0]); const char *serv = NULL; @@ -600,6 +599,12 @@ STATIC mp_obj_t mod_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { hints.ai_family = MP_OBJ_SMALL_INT_VALUE(args[2]); if (n_args > 3) { hints.ai_socktype = MP_OBJ_SMALL_INT_VALUE(args[3]); + if (n_args > 4) { + hints.ai_protocol = MP_OBJ_SMALL_INT_VALUE(args[4]); + if (n_args > 5) { + hints.ai_flags = MP_OBJ_SMALL_INT_VALUE(args[5]); + } + } } } @@ -633,7 +638,7 @@ STATIC mp_obj_t mod_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { freeaddrinfo(addr_list); return list; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_socket_getaddrinfo_obj, 2, 4, mod_socket_getaddrinfo); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_socket_getaddrinfo_obj, 2, 6, mod_socket_getaddrinfo); STATIC mp_obj_t mod_socket_sockaddr(mp_obj_t sockaddr_in) { mp_buffer_info_t bufinfo; From cbc9f944c4db6e3aee0bce0584b1eab674f0e5b9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 18 Aug 2022 11:46:53 +1000 Subject: [PATCH 0287/1041] tests,tools: Update path to unix micropython executable. These were missed by 47c84286e8c8d9873e99f12711a683ecd6b9ca62 Signed-off-by: Damien George --- tests/run-internalbench.py | 2 +- tests/run-multitests.py | 2 +- tests/run-perfbench.py | 2 +- tools/codestats.sh | 2 +- tools/gen-cpydiff.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/run-internalbench.py b/tests/run-internalbench.py index 606fc3b772..0d21978501 100755 --- a/tests/run-internalbench.py +++ b/tests/run-internalbench.py @@ -16,7 +16,7 @@ if os.name == "nt": MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/windows/micropython.exe") else: CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") - MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/micropython") + MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/build-standard/micropython") def run_tests(pyb, test_dict): diff --git a/tests/run-multitests.py b/tests/run-multitests.py index d8a4a48fa7..bd6cc70f7a 100755 --- a/tests/run-multitests.py +++ b/tests/run-multitests.py @@ -18,7 +18,7 @@ if os.name == "nt": MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/windows/micropython.exe") else: CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") - MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/micropython") + MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/build-standard/micropython") # For diff'ing test output DIFF = os.getenv("MICROPY_DIFF", "diff -u") diff --git a/tests/run-perfbench.py b/tests/run-perfbench.py index d70b996937..6f340968b2 100755 --- a/tests/run-perfbench.py +++ b/tests/run-perfbench.py @@ -21,7 +21,7 @@ if os.name == "nt": MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/windows/micropython.exe") else: CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") - MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/micropython") + MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/build-standard/micropython") PYTHON_TRUTH = CPYTHON3 diff --git a/tools/codestats.sh b/tools/codestats.sh index 09284a30de..7443073991 100755 --- a/tools/codestats.sh +++ b/tools/codestats.sh @@ -23,7 +23,7 @@ AWK=awk MAKE="make -j2" # these are the binaries that are built; some have 2 or 3 depending on version -bin_unix=ports/unix/micropython +bin_unix=ports/unix/build-standard/micropython bin_stm32=ports/stm32/build-PYBV10/firmware.elf bin_barearm_1=ports/bare-arm/build/flash.elf bin_barearm_2=ports/bare-arm/build/firmware.elf diff --git a/tools/gen-cpydiff.py b/tools/gen-cpydiff.py index d4c8a5736d..46b3079cac 100644 --- a/tools/gen-cpydiff.py +++ b/tools/gen-cpydiff.py @@ -42,7 +42,7 @@ if os.name == "nt": MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/windows/micropython.exe") else: CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") - MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/micropython") + MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/build-standard/micropython") TESTPATH = "../tests/cpydiff/" DOCPATH = "../docs/genrst/" From 237a393bec51ae564b2b9ded404ef58949a3bc63 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 18 Aug 2022 11:48:45 +1000 Subject: [PATCH 0288/1041] extmod/vfs_posix_file: Remove unused MICROPY_VFS_POSIX_FILE. This was made obsolete by 2b409ef8a46015f8f3bd20bc44e644637dbe9bd3 Signed-off-by: Damien George --- extmod/vfs_posix_file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index 795ad7bbd9..a758db14c3 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -30,7 +30,7 @@ #include "py/stream.h" #include "extmod/vfs_posix.h" -#if MICROPY_VFS_POSIX || MICROPY_VFS_POSIX_FILE +#if MICROPY_VFS_POSIX #include #include @@ -285,4 +285,4 @@ const mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_vfs_posix_textio}, S const mp_obj_vfs_posix_file_t mp_sys_stdout_obj = {{&mp_type_vfs_posix_textio}, STDOUT_FILENO}; const mp_obj_vfs_posix_file_t mp_sys_stderr_obj = {{&mp_type_vfs_posix_textio}, STDERR_FILENO}; -#endif // MICROPY_VFS_POSIX || MICROPY_VFS_POSIX_FILE +#endif // MICROPY_VFS_POSIX From 8f4c108025d4590a1b7f9d062ad64f95c45e0bc2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 18 Aug 2022 11:54:17 +1000 Subject: [PATCH 0289/1041] all: Remove MICROPY_PY_IO_FILEIO config option. Since commit e65d1e69e88268145ff0e7e73240f028885915be there is no longer an io.FileIO class, so this option is no longer needed. This option also controlled whether or not files supported being opened in binary mode (eg 'rb'), and could, if disabled, lead to confusion as to why opening a file in binary mode silently did the wrong thing (it would just open in text mode if MICROPY_PY_IO_FILEIO was disabled). The various VFS implementations (POSIX, FAT, LFS) were the only places where enabling this option made a difference, and in almost all cases where one of these filesystems were enabled, MICROPY_PY_IO_FILEIO was also enabled. So it makes sense to just unconditionally enable this feature (ability to open a file in binary mode) in all cases, and so just remove this config option altogether. That makes configuration simpler and means binary file support always exists (and opening a file in binary mode is arguably more fundamental than opening in text mode, so if anything should be configurable then it should be the ability to open in text mode). Signed-off-by: Damien George --- examples/embedding/mpconfigport_minimal.h | 1 - extmod/vfs_fat_file.c | 4 ---- extmod/vfs_lfsx_file.c | 4 ---- extmod/vfs_posix_file.c | 5 ----- ports/cc3200/mpconfigport.h | 1 - ports/esp8266/mpconfigport.h | 1 - ports/mimxrt/mpconfigport.h | 1 - ports/nrf/mpconfigport.h | 1 - ports/renesas-ra/mpconfigport.h | 1 - ports/samd/mpconfigport.h | 1 - ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h | 1 - ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h | 1 - ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h | 1 - ports/unix/mpconfigport.h | 1 - ports/unix/variants/minimal/mpconfigvariant.h | 1 - ports/windows/mpconfigport.h | 1 - py/mpconfig.h | 5 ----- 17 files changed, 31 deletions(-) diff --git a/examples/embedding/mpconfigport_minimal.h b/examples/embedding/mpconfigport_minimal.h index 91b194bc7b..02089c1a62 100644 --- a/examples/embedding/mpconfigport_minimal.h +++ b/examples/embedding/mpconfigport_minimal.h @@ -69,7 +69,6 @@ #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (0) -#define MICROPY_PY_IO_FILEIO (0) #define MICROPY_PY_STRUCT (0) #define MICROPY_PY_SYS (1) #define MICROPY_PY_SYS_EXIT (0) diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index ebf36fc397..874f10c500 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -170,7 +170,6 @@ STATIC const mp_rom_map_elem_t vfs_fat_rawfile_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(vfs_fat_rawfile_locals_dict, vfs_fat_rawfile_locals_dict_table); -#if MICROPY_PY_IO_FILEIO STATIC const mp_stream_p_t vfs_fat_fileio_stream_p = { .read = file_obj_read, .write = file_obj_write, @@ -186,7 +185,6 @@ const mp_obj_type_t mp_type_vfs_fat_fileio = { .protocol = &vfs_fat_fileio_stream_p, .locals_dict = (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict, }; -#endif STATIC const mp_stream_p_t vfs_fat_textio_stream_p = { .read = file_obj_read, @@ -230,11 +228,9 @@ STATIC mp_obj_t fat_vfs_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_i case '+': mode |= FA_READ | FA_WRITE; break; - #if MICROPY_PY_IO_FILEIO case 'b': type = &mp_type_vfs_fat_fileio; break; - #endif case 't': type = &mp_type_vfs_fat_textio; break; diff --git a/extmod/vfs_lfsx_file.c b/extmod/vfs_lfsx_file.c index bc1a37b90b..124361feb9 100644 --- a/extmod/vfs_lfsx_file.c +++ b/extmod/vfs_lfsx_file.c @@ -68,11 +68,9 @@ mp_obj_t MP_VFS_LFSx(file_open)(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mod case '+': flags |= LFSx_MACRO(_O_RDWR); break; - #if MICROPY_PY_IO_FILEIO case 'b': type = &MP_TYPE_VFS_LFSx_(_fileio); break; - #endif case 't': type = &MP_TYPE_VFS_LFSx_(_textio); break; @@ -216,7 +214,6 @@ STATIC const mp_rom_map_elem_t MP_VFS_LFSx(file_locals_dict_table)[] = { }; STATIC MP_DEFINE_CONST_DICT(MP_VFS_LFSx(file_locals_dict), MP_VFS_LFSx(file_locals_dict_table)); -#if MICROPY_PY_IO_FILEIO STATIC const mp_stream_p_t MP_VFS_LFSx(fileio_stream_p) = { .read = MP_VFS_LFSx(file_read), .write = MP_VFS_LFSx(file_write), @@ -232,7 +229,6 @@ const mp_obj_type_t MP_TYPE_VFS_LFSx_(_fileio) = { .protocol = &MP_VFS_LFSx(fileio_stream_p), .locals_dict = (mp_obj_dict_t *)&MP_VFS_LFSx(file_locals_dict), }; -#endif STATIC const mp_stream_p_t MP_VFS_LFSx(textio_stream_p) = { .read = MP_VFS_LFSx(file_read), diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index a758db14c3..c550842cd4 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -83,15 +83,12 @@ mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_ case '+': mode_rw = O_RDWR; break; - #if MICROPY_PY_IO_FILEIO - // If we don't have io.FileIO, then files are in text mode implicitly case 'b': type = &mp_type_vfs_posix_fileio; break; case 't': type = &mp_type_vfs_posix_textio; break; - #endif } } @@ -246,7 +243,6 @@ STATIC const mp_rom_map_elem_t vfs_posix_rawfile_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(vfs_posix_rawfile_locals_dict, vfs_posix_rawfile_locals_dict_table); -#if MICROPY_PY_IO_FILEIO STATIC const mp_stream_p_t vfs_posix_fileio_stream_p = { .read = vfs_posix_file_read, .write = vfs_posix_file_write, @@ -262,7 +258,6 @@ const mp_obj_type_t mp_type_vfs_posix_fileio = { .protocol = &vfs_posix_fileio_stream_p, .locals_dict = (mp_obj_dict_t *)&vfs_posix_rawfile_locals_dict, }; -#endif STATIC const mp_stream_p_t vfs_posix_textio_stream_p = { .read = vfs_posix_file_read, diff --git a/ports/cc3200/mpconfigport.h b/ports/cc3200/mpconfigport.h index f41c1fe99d..93fc291c1a 100644 --- a/ports/cc3200/mpconfigport.h +++ b/ports/cc3200/mpconfigport.h @@ -105,7 +105,6 @@ #define MICROPY_PY_SYS_STDFILES (1) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (1) -#define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_UERRNO (1) #define MICROPY_PY_UERRNO_ERRORCODE (0) #define MICROPY_PY_THREAD (1) diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 9ff6a34ffd..ded56663b3 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -35,7 +35,6 @@ #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (0) #define MICROPY_PY_MATH_FACTORIAL (0) #define MICROPY_PY_MATH_ISCLOSE (0) -#define MICROPY_PY_IO_FILEIO (MICROPY_VFS) #define MICROPY_PY_SYS_PS1_PS2 (0) #define MICROPY_PY_UBINASCII_CRC32 (0) #define MICROPY_PY_URANDOM_EXTRA_FUNCS (0) diff --git a/ports/mimxrt/mpconfigport.h b/ports/mimxrt/mpconfigport.h index 54d649795d..8642d53ecc 100644 --- a/ports/mimxrt/mpconfigport.h +++ b/ports/mimxrt/mpconfigport.h @@ -101,7 +101,6 @@ uint32_t trng_random_u32(void); #define MICROPY_PY_MATH_ISCLOSE (1) #define MICROPY_PY_CMATH (1) #define MICROPY_PY_IO_IOBASE (1) -#define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_PY_SYS_PLATFORM "mimxrt" #define MICROPY_PY_SYS_STDFILES (1) diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index a25ca1ec27..ac238057dd 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -155,7 +155,6 @@ #define MICROPY_MODULE_BUILTIN_INIT (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_SYS_MAXSIZE (1) -#define MICROPY_PY_IO_FILEIO (MICROPY_VFS_FAT || MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2) #define MICROPY_PY_URANDOM (1) #define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) #define MICROPY_PY_UTIME_MP_HAL (1) diff --git a/ports/renesas-ra/mpconfigport.h b/ports/renesas-ra/mpconfigport.h index 65b194274a..b77a3c4923 100644 --- a/ports/renesas-ra/mpconfigport.h +++ b/ports/renesas-ra/mpconfigport.h @@ -83,7 +83,6 @@ #ifndef MICROPY_PY_BUILTINS_HELP_TEXT #define MICROPY_PY_BUILTINS_HELP_TEXT ra_help_text #endif -#define MICROPY_PY_IO_FILEIO (MICROPY_VFS_FAT || MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2) #ifndef MICROPY_PY_SYS_PLATFORM // let boards override it if they want #define MICROPY_PY_SYS_PLATFORM "renesas-ra" #endif diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index c02d9316de..0b16b5e817 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -77,7 +77,6 @@ #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_STDFILES (1) #define MICROPY_PY_SYS_MAXSIZE (1) -#define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_IO (1) #define MICROPY_PY_IO_IOBASE (1) diff --git a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h index d4996e6c74..dfcca72afb 100644 --- a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h +++ b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h @@ -11,7 +11,6 @@ #define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_PY_GENERATOR_PEND_THROW (0) #define MICROPY_PY_MATH (0) -#define MICROPY_PY_IO_FILEIO (0) #define MICROPY_PY_FRAMEBUF (0) #define MICROPY_PY_USOCKET (0) #define MICROPY_PY_NETWORK (0) diff --git a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h index a68b939939..d44bfb0bb6 100644 --- a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h @@ -5,7 +5,6 @@ #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_OPT_COMPUTED_GOTO (0) #define MICROPY_PY_BUILTINS_COMPLEX (0) -#define MICROPY_PY_IO_FILEIO (0) #define MICROPY_PY_USOCKET (0) #define MICROPY_PY_NETWORK (0) #define MICROPY_PY_STM (0) diff --git a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h index 9af925d451..c8c809eb48 100644 --- a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h @@ -11,7 +11,6 @@ #define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_PY_GENERATOR_PEND_THROW (0) #define MICROPY_PY_MATH (0) -#define MICROPY_PY_IO_FILEIO (0) #define MICROPY_PY_FRAMEBUF (0) #define MICROPY_PY_USOCKET (0) #define MICROPY_PY_NETWORK (0) diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 5545a74f57..03b8ceb1f6 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -87,7 +87,6 @@ #define MICROPY_PY_MATH_ISCLOSE (MICROPY_PY_MATH_SPECIAL_FUNCTIONS) #define MICROPY_PY_CMATH (1) #define MICROPY_PY_IO_IOBASE (1) -#define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_PY_SYS_STDFILES (1) #define MICROPY_PY_UERRNO (1) diff --git a/ports/unix/variants/minimal/mpconfigvariant.h b/ports/unix/variants/minimal/mpconfigvariant.h index d6e5fc4726..2e2c1de0cc 100644 --- a/ports/unix/variants/minimal/mpconfigvariant.h +++ b/ports/unix/variants/minimal/mpconfigvariant.h @@ -86,7 +86,6 @@ #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (0) -#define MICROPY_PY_IO_FILEIO (0) #define MICROPY_PY_STRUCT (0) #define MICROPY_PY_SYS (1) #define MICROPY_PY_SYS_EXIT (0) diff --git a/ports/windows/mpconfigport.h b/ports/windows/mpconfigport.h index 4ed9f316e7..8967242aee 100644 --- a/ports/windows/mpconfigport.h +++ b/ports/windows/mpconfigport.h @@ -125,7 +125,6 @@ #define MICROPY_PY_MATH_ISCLOSE (MICROPY_PY_MATH_SPECIAL_FUNCTIONS) #define MICROPY_PY_CMATH (1) #define MICROPY_PY_IO_IOBASE (1) -#define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_GC_COLLECT_RETVAL (1) #ifndef MICROPY_STACKLESS #define MICROPY_STACKLESS (0) diff --git a/py/mpconfig.h b/py/mpconfig.h index 1ed34bb6fd..d478c654d0 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -1321,11 +1321,6 @@ typedef double mp_float_t; #define MICROPY_PY_IO_IOBASE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) #endif -// Whether to provide "io.FileIO" class -#ifndef MICROPY_PY_IO_FILEIO -#define MICROPY_PY_IO_FILEIO (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) -#endif - // Whether to provide "io.BytesIO" class #ifndef MICROPY_PY_IO_BYTESIO #define MICROPY_PY_IO_BYTESIO (1) From a311e9e3d419cf447c8a4cf2beed4a341e8387e3 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 18 Aug 2022 12:32:10 +1000 Subject: [PATCH 0290/1041] tools/mpremote: Allow + terminator for fs commands. Signed-off-by: Jim Mussared --- docs/reference/mpremote.rst | 5 +++++ tools/mpremote/mpremote/main.py | 36 ++++++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/docs/reference/mpremote.rst b/docs/reference/mpremote.rst index 2bbed56b89..80290657f4 100644 --- a/docs/reference/mpremote.rst +++ b/docs/reference/mpremote.rst @@ -30,6 +30,9 @@ For REPL access, running ``mpremote`` without any arguments is usually all that is needed. ``mpremote`` also supports a set of commands given at the command line which will perform various actions on remote MicroPython devices. +For commands that support multiple arguments (e.g. a list of files), the +argument list can be terminated with ``+``. + The full list of supported commands are: - connect to a specified device via a device-name shortcut: @@ -248,3 +251,5 @@ Examples mpremote cp main.py : mpremote cp -r dir/ : + + mpremote cp a.py b.py : + repl diff --git a/tools/mpremote/mpremote/main.py b/tools/mpremote/mpremote/main.py index e0266fd719..73cd5e153b 100644 --- a/tools/mpremote/mpremote/main.py +++ b/tools/mpremote/mpremote/main.py @@ -300,6 +300,19 @@ def show_progress_bar(size, total_size): ) +# Get all args up to the terminator ("+"). +# The passed args will be updated with these ones removed. +def get_fs_args(args): + n = 0 + for src in args: + if src == "+": + break + n += 1 + fs_args = args[:n] + args[:] = args[n + 1 :] + return fs_args + + def do_filesystem(pyb, args): def _list_recursive(files, path): if os.path.isdir(path): @@ -308,16 +321,18 @@ def do_filesystem(pyb, args): else: files.append(os.path.split(path)) - # Don't be verbose when using cat, so output can be redirected to something. - verbose = args[0] != "cat" + fs_args = get_fs_args(args) - if args[0] == "cp" and args[1] == "-r": - args.pop(0) - args.pop(0) - assert args[-1] == ":" - args.pop() + # Don't be verbose when using cat, so output can be redirected to something. + verbose = fs_args[0] != "cat" + + if fs_args[0] == "cp" and fs_args[1] == "-r": + fs_args.pop(0) + fs_args.pop(0) + assert fs_args[-1] == ":" + fs_args.pop() src_files = [] - for path in args: + for path in fs_args: _list_recursive(src_files, path) known_dirs = {""} pyb.exec_("import uos") @@ -335,8 +350,9 @@ def do_filesystem(pyb, args): verbose=verbose, ) else: - pyboard.filesystem_command(pyb, args, progress_callback=show_progress_bar, verbose=verbose) - args.clear() + pyboard.filesystem_command( + pyb, fs_args, progress_callback=show_progress_bar, verbose=verbose + ) def do_repl_main_loop(pyb, console_in, console_out_write, *, code_to_inject, file_to_inject): From 263737ecfea6ec1049ef3aff37913866ebd463e5 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 18 Aug 2022 12:34:15 +1000 Subject: [PATCH 0291/1041] tools/pyboard.py: Add "touch" filesystem command. Signed-off-by: Jim Mussared --- docs/reference/mpremote.rst | 5 +++-- docs/reference/pyboard.py.rst | 5 +++-- tools/pyboard.py | 8 ++++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/reference/mpremote.rst b/docs/reference/mpremote.rst index 80290657f4..3927c9badf 100644 --- a/docs/reference/mpremote.rst +++ b/docs/reference/mpremote.rst @@ -131,6 +131,7 @@ The full list of supported commands are: - ``rm `` to remove files on the device - ``mkdir `` to create directories on the device - ``rmdir `` to remove directories on the device + - ``touch `` to create the files (if they don't already exist) - mount the local directory on the remote device: @@ -192,8 +193,8 @@ Shortcuts can be defined using the macro system. Built-in shortcuts are:: - ``c0``, ``c1``, ``c2``, ``c3``: connect to COM? -- ``cat``, ``ls``, ``cp``, ``rm``, ``mkdir``, ``rmdir``, ``df``: filesystem - commands +- ``cat``, ``ls``, ``cp``, ``rm``, ``mkdir``, ``rmdir``, ``touch``, ``df``: + filesystem commands - ``reset``: reset the device diff --git a/docs/reference/pyboard.py.rst b/docs/reference/pyboard.py.rst index 4fedbb7aab..a06ffdcd8f 100644 --- a/docs/reference/pyboard.py.rst +++ b/docs/reference/pyboard.py.rst @@ -92,12 +92,13 @@ Filesystem access Using the ``-f`` flag, the following filesystem operations are supported: -* ``cp src [src...] dest`` Copy files to/from the device. * ``cat path`` Print the contents of a file on the device. +* ``cp src [src...] dest`` Copy files to/from the device. * ``ls [path]`` List contents of a directory (defaults to current working directory). -* ``rm path`` Remove a file. * ``mkdir path`` Create a directory. +* ``rm path`` Remove a file. * ``rmdir path`` Remove a directory. +* ``touch path`` Create a file if it doesn't already exist. The ``cp`` command uses a ``ssh``-like convention for referring to local and remote files. Any path starting with a ``:`` will be interpreted as on the diff --git a/tools/pyboard.py b/tools/pyboard.py index 7d0ab6bcd7..7525049875 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -543,6 +543,9 @@ class Pyboard: def fs_rm(self, src): self.exec_("import uos\nuos.remove('%s')" % src) + def fs_touch(self, src): + self.exec_("f=open('%s','a')\nf.close()" % src) + # in Python2 exec is a keyword so one must use "exec_" # but for Python3 we want to provide the nicer version "exec" @@ -595,11 +598,12 @@ def filesystem_command(pyb, args, progress_callback=None, verbose=False): op(src, dest2, progress_callback=progress_callback) else: op = { - "ls": pyb.fs_ls, "cat": pyb.fs_cat, + "ls": pyb.fs_ls, "mkdir": pyb.fs_mkdir, - "rmdir": pyb.fs_rmdir, "rm": pyb.fs_rm, + "rmdir": pyb.fs_rmdir, + "touch": pyb.fs_touch, }[cmd] if cmd == "ls" and not args: args = [""] From 59e3348c101efee4071dd2224d01ccce6075b692 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 18 Aug 2022 12:36:42 +1000 Subject: [PATCH 0292/1041] tools/mpremote: Add "edit" command. This allows a remote file to be edited locally by copying it over, running the local editor, then copying it back. Signed-off-by: Jim Mussared --- docs/reference/mpremote.rst | 11 +++++++++++ tools/mpremote/mpremote/main.py | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/docs/reference/mpremote.rst b/docs/reference/mpremote.rst index 3927c9badf..eb0233bdda 100644 --- a/docs/reference/mpremote.rst +++ b/docs/reference/mpremote.rst @@ -133,6 +133,17 @@ The full list of supported commands are: - ``rmdir `` to remove directories on the device - ``touch `` to create the files (if they don't already exist) +- edit a file on the device: + + .. code-block:: bash + + $ mpremote edit + + The ``edit`` command will copy each file from the device to a local temporary + directory and then launch your editor for each file (defined by the environment + variable ``$EDITOR``). If the editor exits successfully, the updated file will + be copied back to the device. + - mount the local directory on the remote device: .. code-block:: bash diff --git a/tools/mpremote/mpremote/main.py b/tools/mpremote/mpremote/main.py index 73cd5e153b..e614156dbf 100644 --- a/tools/mpremote/mpremote/main.py +++ b/tools/mpremote/mpremote/main.py @@ -19,6 +19,7 @@ MicroPython device over a serial connection. Commands supported are: import os, sys from collections.abc import Mapping +import tempfile from textwrap import dedent import serial.tools.list_ports @@ -28,6 +29,7 @@ from .console import Console, ConsolePosix _PROG = "mpremote" +# (need_raw_repl, is_action, num_args_min, help_text) _COMMANDS = { "connect": ( False, @@ -39,6 +41,7 @@ _COMMANDS = { or any valid device name/path""", ), "disconnect": (False, False, 0, "disconnect current device"), + "edit": (True, True, 1, "edit files on the device"), "resume": (False, False, 0, "resume a previous mpremote session (will not auto soft-reset)"), "soft-reset": (False, True, 0, "perform a soft-reset of the device"), "mount": ( @@ -82,6 +85,7 @@ _BUILTIN_COMMAND_EXPANSIONS = { "ls": "fs ls", "cp": "fs cp", "rm": "fs rm", + "touch": "fs touch", "mkdir": "fs mkdir", "rmdir": "fs rmdir", "df": [ @@ -355,6 +359,23 @@ def do_filesystem(pyb, args): ) +def do_edit(pyb, args): + if not os.getenv("EDITOR"): + raise pyboard.PyboardError("edit: $EDITOR not set") + for src in get_fs_args(args): + src = src.lstrip(":") + dest_fd, dest = tempfile.mkstemp(suffix=os.path.basename(src)) + try: + print("edit :%s" % (src,)) + os.close(dest_fd) + pyb.fs_touch(src) + pyb.fs_get(src, dest, progress_callback=show_progress_bar) + if os.system("$EDITOR '%s'" % (dest,)) == 0: + pyb.fs_put(dest, src, progress_callback=show_progress_bar) + finally: + os.unlink(dest) + + def do_repl_main_loop(pyb, console_in, console_out_write, *, code_to_inject, file_to_inject): while True: console_in.waitchar(pyb.serial) @@ -587,6 +608,8 @@ def main(): return ret elif cmd == "fs": do_filesystem(pyb, args) + elif cmd == "edit": + do_edit(pyb, args) elif cmd == "repl": do_repl(pyb, args) From 470a44bd3ade45fd10d63aabfb14c3696b60e251 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 12 Aug 2022 16:47:02 +1000 Subject: [PATCH 0293/1041] extmod/modframebuf: Optimise argument handling. Several methods extract mp_int_t from adjacent arguments. This reduces code size for the repeated calls to mp_obj_get_int. Signed-off-by: Jim Mussared --- extmod/modframebuf.c | 165 ++++++++++++++++++++----------------------- 1 file changed, 77 insertions(+), 88 deletions(-) diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index 5b6575d5a6..fe32e44a26 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -263,21 +263,21 @@ STATIC void fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, u formats[fb->format].fill_rect(fb, x, y, xend - x, yend - y, col); } -STATIC mp_obj_t framebuf_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 framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args_in) { mp_arg_check_num(n_args, n_kw, 4, 5, false); mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, type); - o->buf_obj = args[0]; + o->buf_obj = args_in[0]; mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE); + mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE); o->buf = bufinfo.buf; - o->width = mp_obj_get_int(args[1]); - o->height = mp_obj_get_int(args[2]); - o->format = mp_obj_get_int(args[3]); + o->width = mp_obj_get_int(args_in[1]); + o->height = mp_obj_get_int(args_in[2]); + o->format = mp_obj_get_int(args_in[3]); if (n_args >= 5) { - o->stride = mp_obj_get_int(args[4]); + o->stride = mp_obj_get_int(args_in[4]); } else { o->stride = o->width; } @@ -305,6 +305,12 @@ STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size return MP_OBJ_FROM_PTR(o); } +STATIC void framebuf_args(const mp_obj_t *args_in, mp_int_t *args_out, int n) { + for (int i = 0; i < n; ++i) { + args_out[i] = mp_obj_get_int(args_in[i + 1]); + } +} + STATIC mp_int_t framebuf_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { (void)flags; mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in); @@ -322,98 +328,71 @@ STATIC mp_obj_t framebuf_fill(mp_obj_t self_in, mp_obj_t col_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_2(framebuf_fill_obj, framebuf_fill); -STATIC mp_obj_t framebuf_fill_rect(size_t n_args, const mp_obj_t *args) { - (void)n_args; - - mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_int_t width = mp_obj_get_int(args[3]); - mp_int_t height = mp_obj_get_int(args[4]); - mp_int_t col = mp_obj_get_int(args[5]); - - fill_rect(self, x, y, width, height, col); - +STATIC mp_obj_t framebuf_fill_rect(size_t n_args, const mp_obj_t *args_in) { + mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); + mp_int_t args[5]; // x, y, w, h, col + framebuf_args(args_in, args, 5); + fill_rect(self, args[0], args[1], args[2], args[3], args[4]); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_fill_rect_obj, 6, 6, framebuf_fill_rect); -STATIC mp_obj_t framebuf_pixel(size_t n_args, const mp_obj_t *args) { - mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); +STATIC mp_obj_t framebuf_pixel(size_t n_args, const mp_obj_t *args_in) { + mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); + mp_int_t x = mp_obj_get_int(args_in[1]); + mp_int_t y = mp_obj_get_int(args_in[2]); if (0 <= x && x < self->width && 0 <= y && y < self->height) { if (n_args == 3) { // get return MP_OBJ_NEW_SMALL_INT(getpixel(self, x, y)); } else { // set - setpixel(self, x, y, mp_obj_get_int(args[3])); + setpixel(self, x, y, mp_obj_get_int(args_in[3])); } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_pixel_obj, 3, 4, framebuf_pixel); -STATIC mp_obj_t framebuf_hline(size_t n_args, const mp_obj_t *args) { +STATIC mp_obj_t framebuf_hline(size_t n_args, const mp_obj_t *args_in) { (void)n_args; - mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_int_t w = mp_obj_get_int(args[3]); - mp_int_t col = mp_obj_get_int(args[4]); + mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); + mp_int_t args[4]; // x, y, w, col + framebuf_args(args_in, args, 4); - fill_rect(self, x, y, w, 1, col); + fill_rect(self, args[0], args[1], args[2], 1, args[3]); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_hline_obj, 5, 5, framebuf_hline); -STATIC mp_obj_t framebuf_vline(size_t n_args, const mp_obj_t *args) { +STATIC mp_obj_t framebuf_vline(size_t n_args, const mp_obj_t *args_in) { (void)n_args; - mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_int_t h = mp_obj_get_int(args[3]); - mp_int_t col = mp_obj_get_int(args[4]); + mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); + mp_int_t args[4]; // x, y, h, col + framebuf_args(args_in, args, 4); - fill_rect(self, x, y, 1, h, col); + fill_rect(self, args[0], args[1], 1, args[2], args[3]); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_vline_obj, 5, 5, framebuf_vline); -STATIC mp_obj_t framebuf_rect(size_t n_args, const mp_obj_t *args) { - (void)n_args; - - mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_int_t w = mp_obj_get_int(args[3]); - mp_int_t h = mp_obj_get_int(args[4]); - mp_int_t col = mp_obj_get_int(args[5]); - - fill_rect(self, x, y, w, 1, col); - fill_rect(self, x, y + h - 1, w, 1, col); - fill_rect(self, x, y, 1, h, col); - fill_rect(self, x + w - 1, y, 1, h, col); - +STATIC mp_obj_t framebuf_rect(size_t n_args, const mp_obj_t *args_in) { + mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); + mp_int_t args[5]; // x, y, w, h, col + framebuf_args(args_in, args, 5); + fill_rect(self, args[0], args[1], args[2], 1, args[4]); + fill_rect(self, args[0], args[1] + args[3] - 1, args[2], 1, args[4]); + fill_rect(self, args[0], args[1], 1, args[3], args[4]); + fill_rect(self, args[0] + args[2] - 1, args[1], 1, args[3], args[4]); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_rect_obj, 6, 6, framebuf_rect); -STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args) { - (void)n_args; - - mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x1 = mp_obj_get_int(args[1]); - mp_int_t y1 = mp_obj_get_int(args[2]); - mp_int_t x2 = mp_obj_get_int(args[3]); - mp_int_t y2 = mp_obj_get_int(args[4]); - mp_int_t col = mp_obj_get_int(args[5]); - +STATIC void line(const mp_obj_framebuf_t *fb, mp_int_t x1, mp_int_t y1, mp_int_t x2, mp_int_t y2, mp_int_t col) { mp_int_t dx = x2 - x1; mp_int_t sx; if (dx > 0) { @@ -452,12 +431,12 @@ STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args) { mp_int_t e = 2 * dy - dx; for (mp_int_t i = 0; i < dx; ++i) { if (steep) { - if (0 <= y1 && y1 < self->width && 0 <= x1 && x1 < self->height) { - setpixel(self, y1, x1, col); + if (0 <= y1 && y1 < fb->width && 0 <= x1 && x1 < fb->height) { + setpixel(fb, y1, x1, col); } } else { - if (0 <= x1 && x1 < self->width && 0 <= y1 && y1 < self->height) { - setpixel(self, x1, y1, col); + if (0 <= x1 && x1 < fb->width && 0 <= y1 && y1 < fb->height) { + setpixel(fb, x1, y1, col); } } while (e >= 0) { @@ -468,31 +447,41 @@ STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args) { e += 2 * dy; } - if (0 <= x2 && x2 < self->width && 0 <= y2 && y2 < self->height) { - setpixel(self, x2, y2, col); + if (0 <= x2 && x2 < fb->width && 0 <= y2 && y2 < fb->height) { + setpixel(fb, x2, y2, col); } +} + +STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args_in) { + (void)n_args; + + mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); + mp_int_t args[5]; // x1, y1, x2, y2, col + framebuf_args(args_in, args, 5); + + line(self, args[0], args[1], args[2], args[3], args[4]); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_line_obj, 6, 6, framebuf_line); -STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args) { - mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); - mp_obj_t source_in = mp_obj_cast_to_native_base(args[1], MP_OBJ_FROM_PTR(&mp_type_framebuf)); +STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args_in) { + mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); + mp_obj_t source_in = mp_obj_cast_to_native_base(args_in[1], MP_OBJ_FROM_PTR(&mp_type_framebuf)); if (source_in == MP_OBJ_NULL) { mp_raise_TypeError(NULL); } mp_obj_framebuf_t *source = MP_OBJ_TO_PTR(source_in); - mp_int_t x = mp_obj_get_int(args[2]); - mp_int_t y = mp_obj_get_int(args[3]); + mp_int_t x = mp_obj_get_int(args_in[2]); + mp_int_t y = mp_obj_get_int(args_in[3]); mp_int_t key = -1; if (n_args > 4) { - key = mp_obj_get_int(args[4]); + key = mp_obj_get_int(args_in[4]); } mp_obj_framebuf_t *palette = NULL; - if (n_args > 5 && args[5] != mp_const_none) { - palette = MP_OBJ_TO_PTR(mp_obj_cast_to_native_base(args[5], MP_OBJ_FROM_PTR(&mp_type_framebuf))); + if (n_args > 5 && args_in[5] != mp_const_none) { + palette = MP_OBJ_TO_PTR(mp_obj_cast_to_native_base(args_in[5], MP_OBJ_FROM_PTR(&mp_type_framebuf))); } if ( @@ -563,15 +552,15 @@ STATIC mp_obj_t framebuf_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t ys } STATIC MP_DEFINE_CONST_FUN_OBJ_3(framebuf_scroll_obj, framebuf_scroll); -STATIC mp_obj_t framebuf_text(size_t n_args, const mp_obj_t *args) { +STATIC mp_obj_t framebuf_text(size_t n_args, const mp_obj_t *args_in) { // extract arguments - mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); - const char *str = mp_obj_str_get_str(args[1]); - mp_int_t x0 = mp_obj_get_int(args[2]); - mp_int_t y0 = mp_obj_get_int(args[3]); + mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); + const char *str = mp_obj_str_get_str(args_in[1]); + mp_int_t x0 = mp_obj_get_int(args_in[2]); + mp_int_t y0 = mp_obj_get_int(args_in[3]); mp_int_t col = 1; if (n_args >= 5) { - col = mp_obj_get_int(args[4]); + col = mp_obj_get_int(args_in[4]); } // loop over chars @@ -626,18 +615,18 @@ STATIC const mp_obj_type_t mp_type_framebuf = { #endif // this factory function is provided for backwards compatibility with old FrameBuffer1 class -STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args) { +STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args_in) { mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, &mp_type_framebuf); mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE); + mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE); o->buf = bufinfo.buf; - o->width = mp_obj_get_int(args[1]); - o->height = mp_obj_get_int(args[2]); + o->width = mp_obj_get_int(args_in[1]); + o->height = mp_obj_get_int(args_in[2]); o->format = FRAMEBUF_MVLSB; if (n_args >= 4) { - o->stride = mp_obj_get_int(args[3]); + o->stride = mp_obj_get_int(args_in[3]); } else { o->stride = o->width; } From af1f167820e685390d43dd7e250a0ffa078e138d Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 13 Aug 2022 00:46:00 +1000 Subject: [PATCH 0294/1041] py/dynruntime: Add mp_obj_is_true. Signed-off-by: Jim Mussared --- py/dynruntime.h | 1 + 1 file changed, 1 insertion(+) diff --git a/py/dynruntime.h b/py/dynruntime.h index e3200a2719..fb748eb93f 100644 --- a/py/dynruntime.h +++ b/py/dynruntime.h @@ -127,6 +127,7 @@ static inline void *m_realloc_dyn(void *ptr, size_t new_num_bytes) { #define mp_obj_str_get_data(o, len) (mp_obj_str_get_data_dyn((o), (len))) #define mp_get_buffer_raise(o, bufinfo, fl) (mp_fun_table.get_buffer_raise((o), (bufinfo), (fl))) #define mp_get_stream_raise(s, flags) (mp_fun_table.get_stream_raise((s), (flags))) +#define mp_obj_is_true(o) (mp_fun_table.native_from_obj(o, MP_NATIVE_TYPE_BOOL)) #define mp_obj_len(o) (mp_obj_len_dyn(o)) #define mp_obj_subscr(base, index, val) (mp_fun_table.obj_subscr((base), (index), (val))) From 127b340438cddd55748e066cacbc1ab64131e232 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 12 Aug 2022 16:34:51 +1000 Subject: [PATCH 0295/1041] extmod/modframebuf: Add fill argument to rect(). We plan to add `ellipse` and `poly` methods, but rather than having to implement a `fill_xyz` version of each, we can make them take an optional fill argument. This commit add this to `rect` as a starting point. Signed-off-by: Jim Mussared --- docs/library/framebuf.rst | 10 +++++----- extmod/modframebuf.c | 14 +++++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/library/framebuf.rst b/docs/library/framebuf.rst index 098ada8153..7024616653 100644 --- a/docs/library/framebuf.rst +++ b/docs/library/framebuf.rst @@ -77,12 +77,12 @@ The following methods draw shapes onto the FrameBuffer. methods draw horizontal and vertical lines respectively up to a given length. -.. method:: FrameBuffer.rect(x, y, w, h, c) -.. method:: FrameBuffer.fill_rect(x, y, w, h, c) +.. method:: FrameBuffer.rect(x, y, w, h, c[, f]) - Draw a rectangle at the given location, size and color. The `rect` - method draws only a 1 pixel outline whereas the `fill_rect` method - draws both the outline and interior. + Draw a rectangle at the given location, size and color. + + The optional *f* parameter can be set to ``True`` to fill the rectangle. + Otherwise just a one pixel outline is drawn. Drawing text ------------ diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index fe32e44a26..590bd08545 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -384,13 +384,17 @@ STATIC mp_obj_t framebuf_rect(size_t n_args, const mp_obj_t *args_in) { mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); mp_int_t args[5]; // x, y, w, h, col framebuf_args(args_in, args, 5); - fill_rect(self, args[0], args[1], args[2], 1, args[4]); - fill_rect(self, args[0], args[1] + args[3] - 1, args[2], 1, args[4]); - fill_rect(self, args[0], args[1], 1, args[3], args[4]); - fill_rect(self, args[0] + args[2] - 1, args[1], 1, args[3], args[4]); + if (n_args > 6 && mp_obj_is_true(args_in[6])) { + fill_rect(self, args[0], args[1], args[2], args[3], args[4]); + } else { + fill_rect(self, args[0], args[1], args[2], 1, args[4]); + fill_rect(self, args[0], args[1] + args[3] - 1, args[2], 1, args[4]); + fill_rect(self, args[0], args[1], 1, args[3], args[4]); + fill_rect(self, args[0] + args[2] - 1, args[1], 1, args[3], args[4]); + } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_rect_obj, 6, 6, framebuf_rect); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_rect_obj, 6, 7, framebuf_rect); STATIC void line(const mp_obj_framebuf_t *fb, mp_int_t x1, mp_int_t y1, mp_int_t x2, mp_int_t y2, mp_int_t col) { mp_int_t dx = x2 - x1; From 42ec9703a07d1d0b55091f5557ff5f81c5134fb8 Mon Sep 17 00:00:00 2001 From: Peter Hinch Date: Wed, 10 Aug 2022 14:51:19 +0100 Subject: [PATCH 0296/1041] extmod/modframebuf: Add ellipse drawing method. --- docs/library/framebuf.rst | 18 +- examples/natmod/framebuf/framebuf.c | 9 +- extmod/modframebuf.c | 95 ++++ tests/extmod/framebuf_ellipse.py | 65 +++ tests/extmod/framebuf_ellipse.py.exp | 704 +++++++++++++++++++++++++++ 5 files changed, 885 insertions(+), 6 deletions(-) create mode 100644 tests/extmod/framebuf_ellipse.py create mode 100644 tests/extmod/framebuf_ellipse.py.exp diff --git a/docs/library/framebuf.rst b/docs/library/framebuf.rst index 7024616653..1e23abd0f1 100644 --- a/docs/library/framebuf.rst +++ b/docs/library/framebuf.rst @@ -11,8 +11,8 @@ class FrameBuffer ----------------- The FrameBuffer class provides a pixel buffer which can be drawn upon with -pixels, lines, rectangles, text and even other FrameBuffer's. It is useful -when generating output for displays. +pixels, lines, rectangles, ellipses, text and even other FrameBuffers. It is +useful when generating output for displays. For example:: @@ -84,6 +84,20 @@ The following methods draw shapes onto the FrameBuffer. The optional *f* parameter can be set to ``True`` to fill the rectangle. Otherwise just a one pixel outline is drawn. +.. method:: FrameBuffer.ellipse(x, y, xr, yr, c[, f, m]) + + Draw an ellipse at the given location. Radii *xr* and *yr* define the + geometry; equal values cause a circle to be drawn. The *c* parameter + defines the color. + + The optional *f* parameter can be set to ``True`` to fill the ellipse. + Otherwise just a one pixel outline is drawn. + + The optional *m* parameter enables drawing to be restricted to certain + quadrants of the ellipse. The LS four bits determine which quadrants are + to be drawn, with bit 0 specifying Q1, b1 Q2, b2 Q3 and b3 Q4. Quadrants + are numbered counterclockwise with Q1 being top right. + Drawing text ------------ diff --git a/examples/natmod/framebuf/framebuf.c b/examples/natmod/framebuf/framebuf.c index 8d488cffd6..53fb90c625 100644 --- a/examples/natmod/framebuf/framebuf.c +++ b/examples/natmod/framebuf/framebuf.c @@ -12,7 +12,7 @@ mp_obj_type_t mp_type_framebuf; #include "extmod/modframebuf.c" -mp_map_elem_t framebuf_locals_dict_table[10]; +mp_map_elem_t framebuf_locals_dict_table[11]; STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table); mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { @@ -29,9 +29,10 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a framebuf_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_vline), MP_OBJ_FROM_PTR(&framebuf_vline_obj) }; framebuf_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_rect), MP_OBJ_FROM_PTR(&framebuf_rect_obj) }; framebuf_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_line), MP_OBJ_FROM_PTR(&framebuf_line_obj) }; - framebuf_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_blit), MP_OBJ_FROM_PTR(&framebuf_blit_obj) }; - framebuf_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), MP_OBJ_FROM_PTR(&framebuf_scroll_obj) }; - framebuf_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_text), MP_OBJ_FROM_PTR(&framebuf_text_obj) }; + framebuf_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ellipse), MP_OBJ_FROM_PTR(&framebuf_ellipse_obj) }; + framebuf_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_blit), MP_OBJ_FROM_PTR(&framebuf_blit_obj) }; + framebuf_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), MP_OBJ_FROM_PTR(&framebuf_scroll_obj) }; + framebuf_locals_dict_table[10] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_text), MP_OBJ_FROM_PTR(&framebuf_text_obj) }; mp_type_framebuf.locals_dict = (void*)&framebuf_locals_dict; mp_store_global(MP_QSTR_FrameBuffer, MP_OBJ_FROM_PTR(&mp_type_framebuf)); diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index 590bd08545..0fa91942c1 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -469,6 +469,100 @@ STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_line_obj, 6, 6, framebuf_line); +STATIC void ellipse_pixel(const mp_obj_framebuf_t *fb, mp_int_t x, mp_int_t y, mp_int_t col, mp_int_t mask) { + if (mask && 0 <= x && x < fb->width && 0 <= y && y < fb->height) { + setpixel(fb, x, y, col); + } +} + +// Q2 Q1 +// Q3 Q4 +#define ELLIPSE_MASK_FILL (0x10) +#define ELLIPSE_MASK_ALL (0x0f) +#define ELLIPSE_MASK_Q1 (0x01) +#define ELLIPSE_MASK_Q2 (0x02) +#define ELLIPSE_MASK_Q3 (0x04) +#define ELLIPSE_MASK_Q4 (0x08) + +STATIC void draw_ellipse_points(const mp_obj_framebuf_t *fb, mp_int_t cx, mp_int_t cy, mp_int_t x, mp_int_t y, mp_int_t col, mp_int_t mask) { + if (mask & ELLIPSE_MASK_FILL) { + if (mask & ELLIPSE_MASK_Q1) { + fill_rect(fb, cx, cy - y, x + 1, 1, col); + } + if (mask & ELLIPSE_MASK_Q2) { + fill_rect(fb, cx - x, cy - y, x + 1, 1, col); + } + if (mask & ELLIPSE_MASK_Q3) { + fill_rect(fb, cx - x, cy + y, x + 1, 1, col); + } + if (mask & ELLIPSE_MASK_Q4) { + fill_rect(fb, cx, cy + y, x + 1, 1, col); + } + } else { + ellipse_pixel(fb, cx + x, cy - y, col, mask & ELLIPSE_MASK_Q1); + ellipse_pixel(fb, cx - x, cy - y, col, mask & ELLIPSE_MASK_Q2); + ellipse_pixel(fb, cx - x, cy + y, col, mask & ELLIPSE_MASK_Q3); + ellipse_pixel(fb, cx + x, cy + y, col, mask & ELLIPSE_MASK_Q4); + } +} + +STATIC mp_obj_t framebuf_ellipse(size_t n_args, const mp_obj_t *args_in) { + mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); + mp_int_t args[5]; + framebuf_args(args_in, args, 5); // cx, cy, xradius, yradius, col + mp_int_t mask = (n_args > 6 && mp_obj_is_true(args_in[6])) ? ELLIPSE_MASK_FILL : 0; + if (n_args > 7) { + mask |= mp_obj_get_int(args_in[7]) & ELLIPSE_MASK_ALL; + } else { + mask |= ELLIPSE_MASK_ALL; + } + mp_int_t two_asquare = 2 * args[2] * args[2]; + mp_int_t two_bsquare = 2 * args[3] * args[3]; + mp_int_t x = args[2]; + mp_int_t y = 0; + mp_int_t xchange = args[3] * args[3] * (1 - 2 * args[2]); + mp_int_t ychange = args[2] * args[2]; + mp_int_t ellipse_error = 0; + mp_int_t stoppingx = two_bsquare * args[2]; + mp_int_t stoppingy = 0; + while (stoppingx >= stoppingy) { // 1st set of points, y' > -1 + draw_ellipse_points(self, args[0], args[1], x, y, args[4], mask); + y += 1; + stoppingy += two_asquare; + ellipse_error += ychange; + ychange += two_asquare; + if ((2 * ellipse_error + xchange) > 0) { + x -= 1; + stoppingx -= two_bsquare; + ellipse_error += xchange; + xchange += two_bsquare; + } + } + // 1st point set is done start the 2nd set of points + x = 0; + y = args[3]; + xchange = args[3] * args[3]; + ychange = args[2] * args[2] * (1 - 2 * args[3]); + ellipse_error = 0; + stoppingx = 0; + stoppingy = two_asquare * args[3]; + while (stoppingx <= stoppingy) { // 2nd set of points, y' < -1 + draw_ellipse_points(self, args[0], args[1], x, y, args[4], mask); + x += 1; + stoppingx += two_bsquare; + ellipse_error += xchange; + xchange += two_bsquare; + if ((2 * ellipse_error + ychange) > 0) { + y -= 1; + stoppingy -= two_asquare; + ellipse_error += ychange; + ychange += two_asquare; + } + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_ellipse_obj, 6, 8, framebuf_ellipse); + STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args_in) { mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); mp_obj_t source_in = mp_obj_cast_to_native_base(args_in[1], MP_OBJ_FROM_PTR(&mp_type_framebuf)); @@ -603,6 +697,7 @@ STATIC const mp_rom_map_elem_t framebuf_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_vline), MP_ROM_PTR(&framebuf_vline_obj) }, { MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&framebuf_rect_obj) }, { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&framebuf_line_obj) }, + { MP_ROM_QSTR(MP_QSTR_ellipse), MP_ROM_PTR(&framebuf_ellipse_obj) }, { MP_ROM_QSTR(MP_QSTR_blit), MP_ROM_PTR(&framebuf_blit_obj) }, { MP_ROM_QSTR(MP_QSTR_scroll), MP_ROM_PTR(&framebuf_scroll_obj) }, { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&framebuf_text_obj) }, diff --git a/tests/extmod/framebuf_ellipse.py b/tests/extmod/framebuf_ellipse.py new file mode 100644 index 0000000000..a4c784aff8 --- /dev/null +++ b/tests/extmod/framebuf_ellipse.py @@ -0,0 +1,65 @@ +try: + import framebuf +except ImportError: + print("SKIP") + raise SystemExit + + +def printbuf(): + print("--8<--") + for y in range(h): + for x in range(w): + print("%02x" % buf[(x + y * w)], end="") + print() + print("-->8--") + + +w = 30 +h = 30 +buf = bytearray(w * h) +fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.GS8) + +# Outline +fbuf.fill(0) +fbuf.ellipse(15, 15, 12, 6, 0xFF, False) +printbuf() + +# Fill +fbuf.fill(0) +fbuf.ellipse(15, 15, 6, 12, 0xAA, True) +printbuf() + +# Outline and fill some different quadrant combos. +for m in (0, 0b0001, 0b0010, 0b0100, 0b1000, 0b1010): + fbuf.fill(0) + fbuf.ellipse(15, 15, 6, 12, 0xAA, False, m) + printbuf() + fbuf.fill(0) + fbuf.ellipse(15, 15, 6, 12, 0xAA, True, m) + printbuf() + +# Draw ellipses that will go out of bounds at each of the edges. +for x, y in ( + ( + 4, + 4, + ), + ( + 26, + 4, + ), + ( + 26, + 26, + ), + ( + 4, + 26, + ), +): + fbuf.fill(0) + fbuf.ellipse(x, y, 6, 12, 0xAA, False) + printbuf() + fbuf.fill(0) + fbuf.ellipse(x, y, 6, 12, 0xAA, True) + printbuf() diff --git a/tests/extmod/framebuf_ellipse.py.exp b/tests/extmod/framebuf_ellipse.py.exp new file mode 100644 index 0000000000..ae6ad1ee7e --- /dev/null +++ b/tests/extmod/framebuf_ellipse.py.exp @@ -0,0 +1,704 @@ +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000ffffffffffffffffff00000000000000000000 +0000000000000000ffffff000000000000000000ffffff00000000000000 +000000000000ffff000000000000000000000000000000ffff0000000000 +0000000000ff00000000000000000000000000000000000000ff00000000 +00000000ff000000000000000000000000000000000000000000ff000000 +000000ff0000000000000000000000000000000000000000000000ff0000 +000000ff0000000000000000000000000000000000000000000000ff0000 +000000ff0000000000000000000000000000000000000000000000ff0000 +00000000ff000000000000000000000000000000000000000000ff000000 +0000000000ff00000000000000000000000000000000000000ff00000000 +000000000000ffff000000000000000000000000000000ffff0000000000 +0000000000000000ffffff000000000000000000ffffff00000000000000 +0000000000000000000000ffffffffffffffffff00000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000aaaaaa00000000000000000000000000 +00000000000000000000000000aaaaaaaaaa000000000000000000000000 +000000000000000000000000aaaaaaaaaaaaaa0000000000000000000000 +0000000000000000000000aaaaaaaaaaaaaaaaaa00000000000000000000 +0000000000000000000000aaaaaaaaaaaaaaaaaa00000000000000000000 +00000000000000000000aaaaaaaaaaaaaaaaaaaaaa000000000000000000 +00000000000000000000aaaaaaaaaaaaaaaaaaaaaa000000000000000000 +00000000000000000000aaaaaaaaaaaaaaaaaaaaaa000000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +00000000000000000000aaaaaaaaaaaaaaaaaaaaaa000000000000000000 +00000000000000000000aaaaaaaaaaaaaaaaaaaaaa000000000000000000 +00000000000000000000aaaaaaaaaaaaaaaaaaaaaa000000000000000000 +0000000000000000000000aaaaaaaaaaaaaaaaaa00000000000000000000 +0000000000000000000000aaaaaaaaaaaaaaaaaa00000000000000000000 +000000000000000000000000aaaaaaaaaaaaaa0000000000000000000000 +00000000000000000000000000aaaaaaaaaa000000000000000000000000 +0000000000000000000000000000aaaaaa00000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000aaaa00000000000000000000000000 +0000000000000000000000000000000000aa000000000000000000000000 +000000000000000000000000000000000000aa0000000000000000000000 +00000000000000000000000000000000000000aa00000000000000000000 +00000000000000000000000000000000000000aa00000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000aaaa00000000000000000000000000 +000000000000000000000000000000aaaaaa000000000000000000000000 +000000000000000000000000000000aaaaaaaa0000000000000000000000 +000000000000000000000000000000aaaaaaaaaa00000000000000000000 +000000000000000000000000000000aaaaaaaaaa00000000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000aaaa0000000000000000000000000000 +00000000000000000000000000aa00000000000000000000000000000000 +000000000000000000000000aa0000000000000000000000000000000000 +0000000000000000000000aa000000000000000000000000000000000000 +0000000000000000000000aa000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000aaaa0000000000000000000000000000 +00000000000000000000000000aaaaaa0000000000000000000000000000 +000000000000000000000000aaaaaaaa0000000000000000000000000000 +0000000000000000000000aaaaaaaaaa0000000000000000000000000000 +0000000000000000000000aaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +0000000000000000000000aa000000000000000000000000000000000000 +0000000000000000000000aa000000000000000000000000000000000000 +000000000000000000000000aa0000000000000000000000000000000000 +00000000000000000000000000aa00000000000000000000000000000000 +0000000000000000000000000000aaaa0000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +0000000000000000000000aaaaaaaaaa0000000000000000000000000000 +0000000000000000000000aaaaaaaaaa0000000000000000000000000000 +000000000000000000000000aaaaaaaa0000000000000000000000000000 +00000000000000000000000000aaaaaa0000000000000000000000000000 +0000000000000000000000000000aaaa0000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +00000000000000000000000000000000000000aa00000000000000000000 +00000000000000000000000000000000000000aa00000000000000000000 +000000000000000000000000000000000000aa0000000000000000000000 +0000000000000000000000000000000000aa000000000000000000000000 +000000000000000000000000000000aaaa00000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaa00000000000000000000 +000000000000000000000000000000aaaaaaaaaa00000000000000000000 +000000000000000000000000000000aaaaaaaa0000000000000000000000 +000000000000000000000000000000aaaaaa000000000000000000000000 +000000000000000000000000000000aaaa00000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000aaaa0000000000000000000000000000 +00000000000000000000000000aa00000000000000000000000000000000 +000000000000000000000000aa0000000000000000000000000000000000 +0000000000000000000000aa000000000000000000000000000000000000 +0000000000000000000000aa000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +00000000000000000000000000000000000000aa00000000000000000000 +00000000000000000000000000000000000000aa00000000000000000000 +000000000000000000000000000000000000aa0000000000000000000000 +0000000000000000000000000000000000aa000000000000000000000000 +000000000000000000000000000000aaaa00000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000aaaa0000000000000000000000000000 +00000000000000000000000000aaaaaa0000000000000000000000000000 +000000000000000000000000aaaaaaaa0000000000000000000000000000 +0000000000000000000000aaaaaaaaaa0000000000000000000000000000 +0000000000000000000000aaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +00000000000000000000aaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaa0000000000000000000000000000 +000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaaaa0000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaaaa000000000000000000 +000000000000000000000000000000aaaaaaaaaa00000000000000000000 +000000000000000000000000000000aaaaaaaaaa00000000000000000000 +000000000000000000000000000000aaaaaaaa0000000000000000000000 +000000000000000000000000000000aaaaaa000000000000000000000000 +000000000000000000000000000000aaaa00000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +aa00000000000000aa000000000000000000000000000000000000000000 +aa00000000000000aa000000000000000000000000000000000000000000 +00aa0000000000aa00000000000000000000000000000000000000000000 +0000aa000000aa0000000000000000000000000000000000000000000000 +000000aaaaaa000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaa0000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaa0000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaa0000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaa000000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaa000000000000000000000000000000000000000000 +00aaaaaaaaaaaaaa00000000000000000000000000000000000000000000 +0000aaaaaaaaaa0000000000000000000000000000000000000000000000 +000000aaaaaa000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +00000000000000000000000000000000000000000000aa00000000000000 +00000000000000000000000000000000000000000000aa00000000000000 +0000000000000000000000000000000000000000000000aa0000000000aa +000000000000000000000000000000000000000000000000aa000000aa00 +00000000000000000000000000000000000000000000000000aaaaaa0000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +000000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaa +000000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaa +000000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaa +00000000000000000000000000000000000000000000aaaaaaaaaaaaaaaa +00000000000000000000000000000000000000000000aaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000000000aaaaaaaaaaaaaa +000000000000000000000000000000000000000000000000aaaaaaaaaa00 +00000000000000000000000000000000000000000000000000aaaaaa0000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000aaaaaa0000 +000000000000000000000000000000000000000000000000aa000000aa00 +0000000000000000000000000000000000000000000000aa0000000000aa +00000000000000000000000000000000000000000000aa00000000000000 +00000000000000000000000000000000000000000000aa00000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +000000000000000000000000000000000000000000aa0000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +0000000000000000000000000000000000000000aa000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000aaaaaa0000 +000000000000000000000000000000000000000000000000aaaaaaaaaa00 +0000000000000000000000000000000000000000000000aaaaaaaaaaaaaa +00000000000000000000000000000000000000000000aaaaaaaaaaaaaaaa +00000000000000000000000000000000000000000000aaaaaaaaaaaaaaaa +000000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaa +000000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaa +000000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +0000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaa +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000aaaaaa000000000000000000000000000000000000000000000000 +0000aa000000aa0000000000000000000000000000000000000000000000 +00aa0000000000aa00000000000000000000000000000000000000000000 +aa00000000000000aa000000000000000000000000000000000000000000 +aa00000000000000aa000000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +000000000000000000aa0000000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +00000000000000000000aa00000000000000000000000000000000000000 +-->8-- +--8<-- +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000 +000000aaaaaa000000000000000000000000000000000000000000000000 +0000aaaaaaaaaa0000000000000000000000000000000000000000000000 +00aaaaaaaaaaaaaa00000000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaa000000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaa000000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaa0000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaa0000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaa0000000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +aaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000 +-->8-- From 04a655c74488128a2c1af9ba8f29fce5e5bbfef9 Mon Sep 17 00:00:00 2001 From: Mat Booth Date: Wed, 13 Jul 2022 21:09:51 +0100 Subject: [PATCH 0297/1041] extmod/modframebuf: Add polygon drawing methods. Add method for drawing polygons. For non-filled polygons, uses the existing line-drawing code to render arbitrary polygons using the given coords list, at the given x,y position, in the given colour. For filled polygons, arbitrary closed polygons are rendered using a fast point-in-polygon algorithm to determine where the edges of the polygon lie on each pixel row. Tests and documentation updates are also included. Signed-off-by: Mat Booth --- docs/library/framebuf.rst | 15 +- extmod/modframebuf.c | 114 ++++++ tests/extmod/framebuf_polygon.py | 222 ++++++++++ tests/extmod/framebuf_polygon.py.exp | 582 +++++++++++++++++++++++++++ 4 files changed, 931 insertions(+), 2 deletions(-) create mode 100644 tests/extmod/framebuf_polygon.py create mode 100644 tests/extmod/framebuf_polygon.py.exp diff --git a/docs/library/framebuf.rst b/docs/library/framebuf.rst index 1e23abd0f1..78ae0c1c34 100644 --- a/docs/library/framebuf.rst +++ b/docs/library/framebuf.rst @@ -11,8 +11,8 @@ class FrameBuffer ----------------- The FrameBuffer class provides a pixel buffer which can be drawn upon with -pixels, lines, rectangles, ellipses, text and even other FrameBuffers. It is -useful when generating output for displays. +pixels, lines, rectangles, ellipses, polygons, text and even other +FrameBuffers. It is useful when generating output for displays. For example:: @@ -98,6 +98,17 @@ The following methods draw shapes onto the FrameBuffer. to be drawn, with bit 0 specifying Q1, b1 Q2, b2 Q3 and b3 Q4. Quadrants are numbered counterclockwise with Q1 being top right. +.. method:: FrameBuffer.poly(x, y, coords, c[, f]) + + Given a list of coordinates, draw an arbitrary (convex or concave) closed + polygon at the given x, y location using the given color. + + The *coords* must be specified as a :mod:`array` of integers, e.g. + ``array('h', [x0, y0, x1, y1, ... xn, yn])``. + + The optional *f* parameter can be set to ``True`` to fill the polygon. + Otherwise just a one pixel outline is drawn. + Drawing text ------------ diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index 0fa91942c1..f17bea70b9 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -28,6 +28,7 @@ #include #include "py/runtime.h" +#include "py/binary.h" #if MICROPY_PY_FRAMEBUF @@ -563,6 +564,116 @@ STATIC mp_obj_t framebuf_ellipse(size_t n_args, const mp_obj_t *args_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_ellipse_obj, 6, 8, framebuf_ellipse); +#if MICROPY_PY_ARRAY && !MICROPY_ENABLE_DYNRUNTIME +// TODO: poly needs mp_binary_get_size & mp_binary_get_val_array which aren't +// available in dynruntime.h yet. + +STATIC mp_int_t poly_int(mp_buffer_info_t *bufinfo, size_t index) { + return mp_obj_get_int(mp_binary_get_val_array(bufinfo->typecode, bufinfo->buf, index)); +} + +STATIC mp_obj_t framebuf_poly(size_t n_args, const mp_obj_t *args_in) { + mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); + + mp_int_t x = mp_obj_get_int(args_in[1]); + mp_int_t y = mp_obj_get_int(args_in[2]); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args_in[3], &bufinfo, MP_BUFFER_READ); + // If an odd number of values was given, this rounds down to multiple of two. + int n_poly = bufinfo.len / (mp_binary_get_size('@', bufinfo.typecode, NULL) * 2); + + if (n_poly == 0) { + return mp_const_none; + } + + mp_int_t col = mp_obj_get_int(args_in[4]); + bool fill = n_args > 5 && mp_obj_is_true(args_in[5]); + + if (fill) { + // This implements an integer version of http://alienryderflex.com/polygon_fill/ + + // The idea is for each scan line, compute the sorted list of x + // coordinates where the scan line intersects the polygon edges, + // then fill between each resulting pair. + + // Restrict just to the scan lines that include the vertical extent of + // this polygon. + mp_int_t y_min = INT_MAX, y_max = INT_MIN; + for (int i = 0; i < n_poly; i++) { + mp_int_t py = poly_int(&bufinfo, i * 2 + 1); + y_min = MIN(y_min, py); + y_max = MAX(y_max, py); + } + + for (mp_int_t row = y_min; row <= y_max; row++) { + // Each node is the x coordinate where an edge crosses this scan line. + mp_int_t nodes[n_poly]; + int n_nodes = 0; + mp_int_t px1 = poly_int(&bufinfo, 0); + mp_int_t py1 = poly_int(&bufinfo, 1); + int i = n_poly * 2 - 1; + do { + mp_int_t py2 = poly_int(&bufinfo, i--); + mp_int_t px2 = poly_int(&bufinfo, i--); + + // Don't include the bottom pixel of a given edge to avoid + // duplicating the node with the start of the next edge. This + // will miss some pixels on the boundary, but we get them at + // the end when we unconditionally draw the outline. + if (py1 != py2 && ((py1 > row && py2 <= row) || (py1 <= row && py2 > row))) { + mp_int_t node = (32 * px1 + 32 * (px2 - px1) * (row - py1) / (py2 - py1) + 16) / 32; + nodes[n_nodes++] = node; + } + + px1 = px2; + py1 = py2; + } while (i >= 0); + + if (!n_nodes) { + continue; + } + + // Sort the nodes left-to-right (bubble-sort for code size). + i = 0; + while (i < n_nodes - 1) { + if (nodes[i] > nodes[i + 1]) { + mp_int_t swap = nodes[i]; + nodes[i] = nodes[i + 1]; + nodes[i + 1] = swap; + if (i) { + i--; + } + } else { + i++; + } + } + + // Fill between each pair of nodes. + for (i = 0; i < n_nodes; i += 2) { + fill_rect(self, x + nodes[i], y + row, (nodes[i + 1] - nodes[i]) + 1, 1, col); + } + } + } + + // Always draw the outline (either because fill=False, or to fix the + // boundary pixels for a fill, see above). + mp_int_t px1 = poly_int(&bufinfo, 0); + mp_int_t py1 = poly_int(&bufinfo, 1); + int i = n_poly * 2 - 1; + do { + mp_int_t py2 = poly_int(&bufinfo, i--); + mp_int_t px2 = poly_int(&bufinfo, i--); + line(self, x + px1, y + py1, x + px2, y + py2, col); + px1 = px2; + py1 = py2; + } while (i >= 0); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_poly_obj, 5, 6, framebuf_poly); +#endif // MICROPY_PY_ARRAY && !MICROPY_ENABLE_DYNRUNTIME + STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args_in) { mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); mp_obj_t source_in = mp_obj_cast_to_native_base(args_in[1], MP_OBJ_FROM_PTR(&mp_type_framebuf)); @@ -698,6 +809,9 @@ STATIC const mp_rom_map_elem_t framebuf_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&framebuf_rect_obj) }, { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&framebuf_line_obj) }, { MP_ROM_QSTR(MP_QSTR_ellipse), MP_ROM_PTR(&framebuf_ellipse_obj) }, + #if MICROPY_PY_ARRAY + { MP_ROM_QSTR(MP_QSTR_poly), MP_ROM_PTR(&framebuf_poly_obj) }, + #endif { MP_ROM_QSTR(MP_QSTR_blit), MP_ROM_PTR(&framebuf_blit_obj) }, { MP_ROM_QSTR(MP_QSTR_scroll), MP_ROM_PTR(&framebuf_scroll_obj) }, { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&framebuf_text_obj) }, diff --git a/tests/extmod/framebuf_polygon.py b/tests/extmod/framebuf_polygon.py new file mode 100644 index 0000000000..03130b3bf0 --- /dev/null +++ b/tests/extmod/framebuf_polygon.py @@ -0,0 +1,222 @@ +import sys + +try: + import framebuf + from array import array +except ImportError: + print("SKIP") + raise SystemExit + + +# TODO: poly needs functions that aren't in dynruntime.h yet. +if not hasattr(framebuf.FrameBuffer, "poly"): + print("SKIP") + raise SystemExit + + +def print_buffer(buffer, width, height): + for row in range(height): + for col in range(width): + val = buffer[(row * width) + col] + sys.stdout.write(" {:02x}".format(val) if val else " ··") + sys.stdout.write("\n") + + +buf = bytearray(70 * 70) + +w = 30 +h = 25 +fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.GS8) +col = 0xFF +col_fill = 0x99 + +# This describes a arbitrary polygon (this happens to be a concave polygon in +# the shape of an upper-case letter 'M'). +poly = array( + "h", + ( + 0, + 20, + 3, + 20, + 3, + 10, + 6, + 17, + 9, + 10, + 9, + 20, + 12, + 20, + 12, + 3, + 9, + 3, + 6, + 10, + 3, + 3, + 0, + 3, + ), +) +# This describes the same polygon, but the points are in reverse order +# (it shouldn't matter if the polygon has clockwise or anti-clockwise +# winding). Also defined as a bytes instead of array. +poly_reversed = bytes( + ( + 0, + 3, + 3, + 3, + 6, + 10, + 9, + 3, + 12, + 3, + 12, + 20, + 9, + 20, + 9, + 10, + 6, + 17, + 3, + 10, + 3, + 20, + 0, + 20, + ) +) + +# Draw the line polygon (at the origin) and the reversed-order polygon (offset). +fbuf.fill(0) +fbuf.poly(0, 0, poly, col) +fbuf.poly(15, -2, poly_reversed, col) +print_buffer(buf, w, h) +print() + +# Same but filled. +fbuf.fill(0) +fbuf.poly(0, 0, poly, col_fill, True) +fbuf.poly(15, -2, poly_reversed, col_fill, True) +print_buffer(buf, w, h) +print() + +# Draw the fill then the outline to ensure that no fill goes outside the outline. +fbuf.fill(0) +fbuf.poly(0, 0, poly, col_fill, True) +fbuf.poly(0, 0, poly, col) +fbuf.poly(15, -2, poly, col_fill, True) +fbuf.poly(15, -2, poly, col) +print_buffer(buf, w, h) +print() + +# Draw the outline then the fill to ensure the fill completely covers the outline. +fbuf.fill(0) +fbuf.poly(0, 0, poly, col) +fbuf.poly(0, 0, poly, col_fill, True) +fbuf.poly(15, -2, poly, col) +fbuf.poly(15, -2, poly, col_fill, True) +print_buffer(buf, w, h) +print() + +# Draw polygons that will go out of bounds at each of the edges. +for x, y in ( + ( + -8, + -8, + ), + ( + 24, + -6, + ), + ( + 20, + 12, + ), + ( + -2, + 10, + ), +): + fbuf.fill(0) + fbuf.poly(x, y, poly, col) + print_buffer(buf, w, h) + print() + fbuf.fill(0) + fbuf.poly(x, y, poly_reversed, col, True) + print_buffer(buf, w, h) + print() + +# Edge cases: These two lists describe self-intersecting polygons +poly_hourglass = array("h", (0, 0, 9, 0, 0, 19, 9, 19)) +poly_star = array("h", (7, 0, 3, 18, 14, 5, 0, 5, 11, 18)) + +# As before, fill then outline. +fbuf.fill(0) +fbuf.poly(0, 2, poly_hourglass, col_fill, True) +fbuf.poly(0, 2, poly_hourglass, col) +fbuf.poly(12, 2, poly_star, col_fill, True) +fbuf.poly(12, 2, poly_star, col) +print_buffer(buf, w, h) +print() + +# Outline then fill. +fbuf.fill(0) +fbuf.poly(0, 2, poly_hourglass, col) +fbuf.poly(0, 2, poly_hourglass, col_fill, True) +fbuf.poly(12, 2, poly_star, col) +fbuf.poly(12, 2, poly_star, col_fill, True) +print_buffer(buf, w, h) +print() + +# Edge cases: These are "degenerate" polygons. +poly_empty = array("h") # Will draw nothing at all. +poly_one = array("h", (20, 20)) # Will draw a single point. +poly_two = array("h", (10, 10, 5, 5)) # Will draw a single line. +poly_wrong_length = array("h", (2, 2, 4)) # Will round down to one point. + +fbuf.fill(0) +fbuf.poly(0, 0, poly_empty, col) +fbuf.poly(0, 0, poly_one, col) +fbuf.poly(0, 0, poly_two, col) +fbuf.poly(0, 0, poly_wrong_length, col) +print_buffer(buf, w, h) +print() + +# A shape with a horizontal overhang. +poly_overhang = array("h", (0, 0, 0, 5, 5, 5, 5, 10, 10, 10, 10, 0)) + +fbuf.fill(0) +fbuf.poly(0, 0, poly_overhang, col) +fbuf.poly(0, 0, poly_overhang, col_fill, True) +print_buffer(buf, w, h) +print() + +fbuf.fill(0) +fbuf.poly(0, 0, poly_overhang, col_fill, True) +fbuf.poly(0, 0, poly_overhang, col) +print_buffer(buf, w, h) +print() + +# Triangles +w = 70 +h = 70 +fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.GS8) +t1 = array("h", [40, 0, 20, 68, 62, 40]) +t2 = array("h", [40, 0, 0, 16, 20, 68]) + +fbuf.fill(0) +fbuf.poly(0, 0, t1, 0xFF, False) +fbuf.poly(0, 0, t2, 0xFF, False) +print_buffer(buf, w, h) + +fbuf.fill(0) +fbuf.poly(0, 0, t1, 0xFF, True) +fbuf.poly(0, 0, t2, 0xFF, True) +print_buffer(buf, w, h) diff --git a/tests/extmod/framebuf_polygon.py.exp b/tests/extmod/framebuf_polygon.py.exp new file mode 100644 index 0000000000..05cd4264ea --- /dev/null +++ b/tests/extmod/framebuf_polygon.py.exp @@ -0,0 +1,582 @@ + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ff ff ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· + ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· + ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ff ·· ff ·· ·· ·· ·· ff ·· ·· + ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ff ·· ff ·· ·· ·· ·· ff ·· ·· + ff ·· ·· ·· ·· ff ·· ff ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· + ff ·· ·· ·· ·· ff ·· ff ·· ·· ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· + ff ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ff ·· ·· ·· ff ff ·· ·· ff ·· ·· + ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ff ·· ·· ·· ff ff ·· ·· ff ·· ·· + ff ·· ·· ff ff ·· ·· ·· ff ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ff ·· ff ·· ff ·· ·· ff ·· ·· + ff ·· ·· ff ff ·· ·· ·· ff ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ff ·· ff ·· ff ·· ·· ff ·· ·· + ff ·· ·· ff ·· ff ·· ff ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· + ff ·· ·· ff ·· ff ·· ff ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· + ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ff ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 99 ·· ·· ·· 99 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 99 ·· ·· ·· 99 99 99 99 99 ·· ·· + 99 99 99 99 99 ·· ·· ·· 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 ·· ·· ·· 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 ·· 99 99 99 ·· 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 ·· 99 99 99 ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· 99 99 99 ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· 99 ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· 99 99 99 ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· 99 ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· 99 ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· 99 ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· ff 99 99 ff ·· ·· + ff ff ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ff 99 99 99 ff ·· ·· ·· ff 99 99 99 ff ·· ·· + ff 99 99 ff ·· ·· ·· ·· ·· ff 99 99 ff ·· ·· ff 99 99 99 ff ·· ·· ·· ff 99 99 99 ff ·· ·· + ff 99 99 99 ff ·· ·· ·· ff 99 99 99 ff ·· ·· ff 99 99 99 99 ff ·· ff 99 99 99 99 ff ·· ·· + ff 99 99 99 ff ·· ·· ·· ff 99 99 99 ff ·· ·· ff 99 99 99 99 ff ·· ff 99 99 99 99 ff ·· ·· + ff 99 99 99 99 ff ·· ff 99 99 99 99 ff ·· ·· ff 99 99 99 99 99 ff 99 99 99 99 99 ff ·· ·· + ff 99 99 99 99 ff ·· ff 99 99 99 99 ff ·· ·· ff 99 99 ff 99 99 ff 99 99 ff 99 99 ff ·· ·· + ff 99 99 99 99 99 ff 99 99 99 99 99 ff ·· ·· ff 99 99 ff 99 99 99 99 99 ff 99 99 ff ·· ·· + ff 99 99 ff 99 99 ff 99 99 ff 99 99 ff ·· ·· ff 99 99 ff ff 99 99 99 ff ff 99 99 ff ·· ·· + ff 99 99 ff 99 99 99 99 99 ff 99 99 ff ·· ·· ff 99 99 ff ff 99 99 99 ff ff 99 99 ff ·· ·· + ff 99 99 ff ff 99 99 99 ff ff 99 99 ff ·· ·· ff 99 99 ff ·· ff 99 ff ·· ff 99 99 ff ·· ·· + ff 99 99 ff ff 99 99 99 ff ff 99 99 ff ·· ·· ff 99 99 ff ·· ff 99 ff ·· ff 99 99 ff ·· ·· + ff 99 99 ff ·· ff 99 ff ·· ff 99 99 ff ·· ·· ff 99 99 ff ·· ·· ff ·· ·· ff 99 99 ff ·· ·· + ff 99 99 ff ·· ff 99 ff ·· ff 99 99 ff ·· ·· ff 99 99 ff ·· ·· ff ·· ·· ff 99 99 ff ·· ·· + ff 99 99 ff ·· ·· ff ·· ·· ff 99 99 ff ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· ff 99 99 ff ·· ·· + ff 99 99 ff ·· ·· ff ·· ·· ff 99 99 ff ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· ff 99 99 ff ·· ·· + ff 99 99 ff ·· ·· ·· ·· ·· ff 99 99 ff ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ff 99 99 ff ·· ·· ·· ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 99 ·· ·· ·· 99 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 99 ·· ·· ·· 99 99 99 99 99 ·· ·· + 99 99 99 99 99 ·· ·· ·· 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 ·· ·· ·· 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 ·· 99 99 99 ·· 99 99 99 99 ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· 99 99 99 99 ·· 99 99 99 ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· 99 99 99 ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· 99 ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· 99 99 99 ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· 99 ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· 99 ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· 99 ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ff ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ff ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ff ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ff ·· ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ff ·· ff ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ff ·· ·· ·· ff ff + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ·· ·· ·· ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ·· ·· ·· ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ·· ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ·· ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ·· ff ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ·· ff ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ff ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ·· ·· ·· ff ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ·· ·· ·· ff ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ff ·· ff ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ·· ·· ·· ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ·· ·· ·· ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ·· ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ·· ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ·· ff ff ff ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff 99 99 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff 99 99 99 99 ff ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· + ·· ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· ·· ff 99 99 99 99 ff ·· ff 99 99 99 99 ff ·· ·· ·· ·· + ·· ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· ·· ·· ff 99 99 ff ·· ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff 99 ff ·· ·· ·· ff 99 ff ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff 99 ff ·· ·· ·· ff 99 ff ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff 99 ff ·· ff 99 ff ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff 99 99 ff 99 99 ff ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ff 99 ff ·· ff 99 ff ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ff 99 ff ·· ff 99 ff ·· ·· ·· ·· ·· ·· ·· + ·· ff 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ff 99 ff ·· ·· ·· ff 99 ff ·· ·· ·· ·· ·· ·· + ·· ff 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· + ff 99 99 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· + ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· ·· 99 99 99 99 99 99 ·· 99 99 99 99 99 99 ·· ·· ·· ·· + ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· 99 99 99 99 ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· + ·· ·· ·· ·· 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 ·· ·· ·· 99 99 99 ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 ·· ·· ·· 99 99 99 ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 ·· ·· ·· 99 99 ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 ·· ·· ·· 99 ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 ·· 99 99 99 ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· + ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 ·· 99 99 99 ·· ·· ·· ·· ·· ·· ·· + ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· 99 99 99 ·· 99 99 99 ·· ·· ·· ·· ·· ·· ·· + ·· 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· 99 99 99 ·· ·· ·· 99 99 99 ·· ·· ·· ·· ·· ·· + ·· 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· 99 99 ·· ·· ·· ·· ·· 99 99 ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· 99 ·· ·· ·· ·· ·· ·· ·· 99 ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + 99 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + 99 99 99 99 99 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· 99 99 99 99 99 99 ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff 99 99 99 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff 99 99 99 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff 99 99 99 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff 99 99 99 99 99 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff 99 99 99 99 ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ff ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ff ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ff ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ff ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· From c616721b1afe176c8d760afc15a93621d411c1dc Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 15 Aug 2022 09:56:26 +1000 Subject: [PATCH 0298/1041] extmod/modframebuf: Improve poly-fill boundary pixels. Rather than drawing the entire boundary to catch missing pixels, just detect the cases where boundary pixels are skipped during node calculation and pre-emptively draw them then. This adds 72 bytes on PYBV11, but makes filled poly() 20% faster. Signed-off-by: Jim Mussared --- extmod/modframebuf.c | 65 ++++++++++++++++------------ tests/extmod/framebuf_polygon.py.exp | 32 +++++++------- 2 files changed, 54 insertions(+), 43 deletions(-) diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index f17bea70b9..bb1f4f6310 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -241,11 +241,17 @@ STATIC mp_framebuf_p_t formats[] = { [FRAMEBUF_MHMSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, }; -static inline void setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) { +STATIC inline void setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) { formats[fb->format].setpixel(fb, x, y, col); } -static inline uint32_t getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) { +STATIC void setpixel_checked(const mp_obj_framebuf_t *fb, mp_int_t x, mp_int_t y, mp_int_t col, mp_int_t mask) { + if (mask && 0 <= x && x < fb->width && 0 <= y && y < fb->height) { + setpixel(fb, x, y, col); + } +} + +STATIC inline uint32_t getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) { return formats[fb->format].getpixel(fb, x, y); } @@ -470,12 +476,6 @@ STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_line_obj, 6, 6, framebuf_line); -STATIC void ellipse_pixel(const mp_obj_framebuf_t *fb, mp_int_t x, mp_int_t y, mp_int_t col, mp_int_t mask) { - if (mask && 0 <= x && x < fb->width && 0 <= y && y < fb->height) { - setpixel(fb, x, y, col); - } -} - // Q2 Q1 // Q3 Q4 #define ELLIPSE_MASK_FILL (0x10) @@ -500,10 +500,10 @@ STATIC void draw_ellipse_points(const mp_obj_framebuf_t *fb, mp_int_t cx, mp_int fill_rect(fb, cx, cy + y, x + 1, 1, col); } } else { - ellipse_pixel(fb, cx + x, cy - y, col, mask & ELLIPSE_MASK_Q1); - ellipse_pixel(fb, cx - x, cy - y, col, mask & ELLIPSE_MASK_Q2); - ellipse_pixel(fb, cx - x, cy + y, col, mask & ELLIPSE_MASK_Q3); - ellipse_pixel(fb, cx + x, cy + y, col, mask & ELLIPSE_MASK_Q4); + setpixel_checked(fb, cx + x, cy - y, col, mask & ELLIPSE_MASK_Q1); + setpixel_checked(fb, cx - x, cy - y, col, mask & ELLIPSE_MASK_Q2); + setpixel_checked(fb, cx - x, cy + y, col, mask & ELLIPSE_MASK_Q3); + setpixel_checked(fb, cx + x, cy + y, col, mask & ELLIPSE_MASK_Q4); } } @@ -619,11 +619,23 @@ STATIC mp_obj_t framebuf_poly(size_t n_args, const mp_obj_t *args_in) { // Don't include the bottom pixel of a given edge to avoid // duplicating the node with the start of the next edge. This - // will miss some pixels on the boundary, but we get them at - // the end when we unconditionally draw the outline. + // will miss some pixels on the boundary, and in particular + // at a local minima or inflection point. if (py1 != py2 && ((py1 > row && py2 <= row) || (py1 <= row && py2 > row))) { mp_int_t node = (32 * px1 + 32 * (px2 - px1) * (row - py1) / (py2 - py1) + 16) / 32; nodes[n_nodes++] = node; + } else if (row == MAX(py1, py2)) { + // At local-minima, try and manually fill in the pixels that get missed above. + if (py1 < py2) { + setpixel_checked(self, x + px2, y + py2, col, 1); + } else if (py2 < py1) { + setpixel_checked(self, x + px1, y + py1, col, 1); + } else { + // Even though this is a hline and would be faster to + // use fill_rect, use line() because it handles x2 < + // x1. + line(self, x + px1, y + py1, x + px2, y + py2, col); + } } px1 = px2; @@ -654,21 +666,20 @@ STATIC mp_obj_t framebuf_poly(size_t n_args, const mp_obj_t *args_in) { fill_rect(self, x + nodes[i], y + row, (nodes[i + 1] - nodes[i]) + 1, 1, col); } } + } else { + // Outline only. + mp_int_t px1 = poly_int(&bufinfo, 0); + mp_int_t py1 = poly_int(&bufinfo, 1); + int i = n_poly * 2 - 1; + do { + mp_int_t py2 = poly_int(&bufinfo, i--); + mp_int_t px2 = poly_int(&bufinfo, i--); + line(self, x + px1, y + py1, x + px2, y + py2, col); + px1 = px2; + py1 = py2; + } while (i >= 0); } - // Always draw the outline (either because fill=False, or to fix the - // boundary pixels for a fill, see above). - mp_int_t px1 = poly_int(&bufinfo, 0); - mp_int_t py1 = poly_int(&bufinfo, 1); - int i = n_poly * 2 - 1; - do { - mp_int_t py2 = poly_int(&bufinfo, i--); - mp_int_t px2 = poly_int(&bufinfo, i--); - line(self, x + px1, y + py1, x + px2, y + py2, col); - px1 = px2; - py1 = py2; - } while (i >= 0); - return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_poly_obj, 5, 6, framebuf_poly); diff --git a/tests/extmod/framebuf_polygon.py.exp b/tests/extmod/framebuf_polygon.py.exp index 05cd4264ea..9b4801c788 100644 --- a/tests/extmod/framebuf_polygon.py.exp +++ b/tests/extmod/framebuf_polygon.py.exp @@ -510,22 +510,22 @@ ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· - ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· - ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· - ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· - ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· - ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· - ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· - ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· - ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· - ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· - ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· - ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· - ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· - ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· - ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· - ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· - ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· + ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· ·· From af54d2ce9f923eba06b19bddb784a1c9da228347 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Fri, 19 Aug 2022 14:58:58 +0100 Subject: [PATCH 0299/1041] javascript: Rename this port to 'webassembly'. --- ...ports_javascript.yml => ports_webassembly.yml} | 10 +++++----- ports/{javascript => webassembly}/Makefile | 2 +- ports/{javascript => webassembly}/README.md | 15 ++++++++++----- ports/{javascript => webassembly}/library.h | 0 ports/{javascript => webassembly}/library.js | 0 ports/{javascript => webassembly}/main.c | 0 ports/{javascript => webassembly}/modutime.c | 0 ports/{javascript => webassembly}/mpconfigport.h | 2 +- ports/{javascript => webassembly}/mphalport.c | 0 ports/{javascript => webassembly}/mphalport.h | 0 ports/{javascript => webassembly}/node_run.sh | 0 ports/{javascript => webassembly}/qstrdefsport.h | 0 ports/{javascript => webassembly}/wrapper.js | 0 tools/ci.sh | 12 ++++++------ 14 files changed, 23 insertions(+), 18 deletions(-) rename .github/workflows/{ports_javascript.yml => ports_webassembly.yml} (57%) rename ports/{javascript => webassembly}/Makefile (93%) rename ports/{javascript => webassembly}/README.md (84%) rename ports/{javascript => webassembly}/library.h (100%) rename ports/{javascript => webassembly}/library.js (100%) rename ports/{javascript => webassembly}/main.c (100%) rename ports/{javascript => webassembly}/modutime.c (100%) rename ports/{javascript => webassembly}/mpconfigport.h (99%) rename ports/{javascript => webassembly}/mphalport.c (100%) rename ports/{javascript => webassembly}/mphalport.h (100%) rename ports/{javascript => webassembly}/node_run.sh (100%) rename ports/{javascript => webassembly}/qstrdefsport.h (100%) rename ports/{javascript => webassembly}/wrapper.js (100%) diff --git a/.github/workflows/ports_javascript.yml b/.github/workflows/ports_webassembly.yml similarity index 57% rename from .github/workflows/ports_javascript.yml rename to .github/workflows/ports_webassembly.yml index 244dc966aa..861039c0fc 100644 --- a/.github/workflows/ports_javascript.yml +++ b/.github/workflows/ports_webassembly.yml @@ -1,4 +1,4 @@ -name: javascript port +name: webassembly port on: push: @@ -9,7 +9,7 @@ on: - 'py/**' - 'extmod/**' - 'lib/**' - - 'ports/javascript/**' + - 'ports/webassembly/**' jobs: build: @@ -17,8 +17,8 @@ jobs: steps: - uses: actions/checkout@v2 - name: Install packages - run: source tools/ci.sh && ci_javascript_setup + run: source tools/ci.sh && ci_webassembly_setup - name: Build - run: source tools/ci.sh && ci_javascript_build + run: source tools/ci.sh && ci_webassembly_build - name: Run tests - run: source tools/ci.sh && ci_javascript_run_tests + run: source tools/ci.sh && ci_webassembly_run_tests diff --git a/ports/javascript/Makefile b/ports/webassembly/Makefile similarity index 93% rename from ports/javascript/Makefile rename to ports/webassembly/Makefile index 93c7b5609b..db3f36ad8e 100644 --- a/ports/javascript/Makefile +++ b/ports/webassembly/Makefile @@ -51,6 +51,6 @@ min: $(BUILD)/micropython.js test: $(BUILD)/micropython.js $(TOP)/tests/run-tests.py $(eval DIRNAME=ports/$(notdir $(CURDIR))) - cd $(TOP)/tests && MICROPY_MICROPYTHON=../ports/javascript/node_run.sh ./run-tests.py -j1 + cd $(TOP)/tests && MICROPY_MICROPYTHON=../ports/webassembly/node_run.sh ./run-tests.py -j1 include $(TOP)/py/mkrules.mk diff --git a/ports/javascript/README.md b/ports/webassembly/README.md similarity index 84% rename from ports/javascript/README.md rename to ports/webassembly/README.md index 39808943b1..3b577233ff 100644 --- a/ports/javascript/README.md +++ b/ports/webassembly/README.md @@ -1,13 +1,18 @@ -MicroPython.js -============== +MicroPython WebAssembly +======================= -MicroPython transmuted into Javascript by Emscripten. +MicroPython for [WebAssembly](https://webassembly.org/). Dependencies ------------ -Building micropython.js bears the same requirements as the standard MicroPython -ports with the addition of Emscripten (and uglify-js for the minified file). +Building webassembly port bears the same requirements as the standard +MicroPython ports with the addition of Emscripten (and uglify-js for the +minified file). + +The output includes `micropython.js` (a JavaScript wrapper for the +MicroPython runtime) and `firmware.wasm` (actual MicroPython compiled to +WASM). Build instructions ------------------ diff --git a/ports/javascript/library.h b/ports/webassembly/library.h similarity index 100% rename from ports/javascript/library.h rename to ports/webassembly/library.h diff --git a/ports/javascript/library.js b/ports/webassembly/library.js similarity index 100% rename from ports/javascript/library.js rename to ports/webassembly/library.js diff --git a/ports/javascript/main.c b/ports/webassembly/main.c similarity index 100% rename from ports/javascript/main.c rename to ports/webassembly/main.c diff --git a/ports/javascript/modutime.c b/ports/webassembly/modutime.c similarity index 100% rename from ports/javascript/modutime.c rename to ports/webassembly/modutime.c diff --git a/ports/javascript/mpconfigport.h b/ports/webassembly/mpconfigport.h similarity index 99% rename from ports/javascript/mpconfigport.h rename to ports/webassembly/mpconfigport.h index 6c86d816bd..4fbd922e15 100644 --- a/ports/javascript/mpconfigport.h +++ b/ports/webassembly/mpconfigport.h @@ -105,7 +105,7 @@ #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) -#define MICROPY_PY_SYS_PLATFORM "javascript" +#define MICROPY_PY_SYS_PLATFORM "webassembly" #define MICROPY_PY_UERRNO (1) #define MICROPY_PY_UCTYPES (1) #define MICROPY_PY_UZLIB (1) diff --git a/ports/javascript/mphalport.c b/ports/webassembly/mphalport.c similarity index 100% rename from ports/javascript/mphalport.c rename to ports/webassembly/mphalport.c diff --git a/ports/javascript/mphalport.h b/ports/webassembly/mphalport.h similarity index 100% rename from ports/javascript/mphalport.h rename to ports/webassembly/mphalport.h diff --git a/ports/javascript/node_run.sh b/ports/webassembly/node_run.sh similarity index 100% rename from ports/javascript/node_run.sh rename to ports/webassembly/node_run.sh diff --git a/ports/javascript/qstrdefsport.h b/ports/webassembly/qstrdefsport.h similarity index 100% rename from ports/javascript/qstrdefsport.h rename to ports/webassembly/qstrdefsport.h diff --git a/ports/javascript/wrapper.js b/ports/webassembly/wrapper.js similarity index 100% rename from ports/javascript/wrapper.js rename to ports/webassembly/wrapper.js diff --git a/tools/ci.sh b/tools/ci.sh index e3203f8bfb..dc2ccf775b 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -172,21 +172,21 @@ function ci_esp8266_build { } ######################################################################################## -# ports/javascript +# ports/webassembly -function ci_javascript_setup { +function ci_webassembly_setup { git clone https://github.com/emscripten-core/emsdk.git (cd emsdk && ./emsdk install latest && ./emsdk activate latest) } -function ci_javascript_build { +function ci_webassembly_build { source emsdk/emsdk_env.sh - make ${MAKEOPTS} -C ports/javascript + make ${MAKEOPTS} -C ports/webassembly } -function ci_javascript_run_tests { +function ci_webassembly_run_tests { # This port is very slow at running, so only run a few of the tests. - (cd tests && MICROPY_MICROPYTHON=../ports/javascript/node_run.sh ./run-tests.py -j1 basics/builtin_*.py) + (cd tests && MICROPY_MICROPYTHON=../ports/webassembly/node_run.sh ./run-tests.py -j1 basics/builtin_*.py) } ######################################################################################## From 7c8ec85fa34279950e44072b22ac26fe41b91886 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 23 Aug 2022 13:02:40 +1000 Subject: [PATCH 0300/1041] shared/runtime/sys_stdio_mphal: Make func static and remove some TODOs. stdio_obj_print is private to this file so can be made static. The __del__ method does nothing so can be removed (it's only called by the GC if it exists, so if it doesn't exist it won't be called). And FileIO doesn't support a constructor in MicroPython at this stage. Signed-off-by: Damien George --- shared/runtime/sys_stdio_mphal.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/shared/runtime/sys_stdio_mphal.c b/shared/runtime/sys_stdio_mphal.c index e72facb981..24f528b0c4 100644 --- a/shared/runtime/sys_stdio_mphal.c +++ b/shared/runtime/sys_stdio_mphal.c @@ -52,7 +52,7 @@ typedef struct _sys_stdio_obj_t { STATIC const sys_stdio_obj_t stdio_buffer_obj; #endif -void stdio_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +STATIC void stdio_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { sys_stdio_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self->fd); } @@ -100,8 +100,6 @@ STATIC mp_obj_t stdio_obj___exit__(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stdio_obj___exit___obj, 4, 4, stdio_obj___exit__); -// TODO gc hook to close the file if not already closed - STATIC const mp_rom_map_elem_t stdio_locals_dict_table[] = { #if MICROPY_PY_SYS_STDIO_BUFFER { MP_ROM_QSTR(MP_QSTR_buffer), MP_ROM_PTR(&stdio_buffer_obj) }, @@ -112,7 +110,6 @@ STATIC const mp_rom_map_elem_t stdio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj)}, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_identity_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&stdio_obj___exit___obj) }, }; @@ -129,7 +126,6 @@ STATIC const mp_stream_p_t stdio_obj_stream_p = { STATIC const mp_obj_type_t stdio_obj_type = { { &mp_type_type }, .name = MP_QSTR_FileIO, - // TODO .make_new? .print = stdio_obj_print, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, From 3d65101a8a55550bdbaa4df4e216edba238fa299 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 23 Aug 2022 13:09:57 +1000 Subject: [PATCH 0301/1041] py: Clean up formatting of union definitions. Signed-off-by: Damien George --- py/binary.c | 22 +++++++++++++--------- py/obj.h | 8 +++++--- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/py/binary.c b/py/binary.c index f59e89ca48..4c8b6ffcdc 100644 --- a/py/binary.c +++ b/py/binary.c @@ -241,13 +241,15 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte * return mp_obj_new_str(s_val, strlen(s_val)); #if MICROPY_PY_BUILTINS_FLOAT } else if (val_type == 'f') { - union { uint32_t i; - float f; + union { + uint32_t i; + float f; } fpu = {val}; return mp_obj_new_float_from_f(fpu.f); } else if (val_type == 'd') { - union { uint64_t i; - double f; + union { + uint64_t i; + double f; } fpu = {val}; return mp_obj_new_float_from_d(fpu.f); #endif @@ -308,17 +310,19 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p break; #if MICROPY_PY_BUILTINS_FLOAT case 'f': { - union { uint32_t i; - float f; + union { + uint32_t i; + float f; } fp_sp; fp_sp.f = mp_obj_get_float_to_f(val_in); val = fp_sp.i; break; } case 'd': { - union { uint64_t i64; - uint32_t i32[2]; - double f; + union { + uint64_t i64; + uint32_t i32[2]; + double f; } fp_dp; fp_dp.f = mp_obj_get_float_to_d(val_in); if (MP_BYTES_PER_OBJ_WORD == 8) { diff --git a/py/obj.h b/py/obj.h index 598d6508da..645fae79f5 100644 --- a/py/obj.h +++ b/py/obj.h @@ -283,9 +283,11 @@ static inline bool mp_obj_is_obj(mp_const_obj_t o) { #define MP_OBJ_FROM_PTR(p) ((mp_obj_t)((uintptr_t)(p))) // rom object storage needs special handling to widen 32-bit pointer to 64-bits -typedef union _mp_rom_obj_t { uint64_t u64; - struct { const void *lo, *hi; - } u32; +typedef union _mp_rom_obj_t { + uint64_t u64; + struct { + const void *lo, *hi; + } u32; } mp_rom_obj_t; #define MP_ROM_INT(i) {MP_OBJ_NEW_SMALL_INT(i)} #define MP_ROM_QSTR(q) {MP_OBJ_NEW_QSTR(q)} From d8ad87843ab38dcc74e7e86354849fff585e1ba8 Mon Sep 17 00:00:00 2001 From: Laurens Valk Date: Fri, 19 Aug 2022 16:40:28 +0200 Subject: [PATCH 0302/1041] py/builtinimport: Allow overriding of mp_builtin___import__. This allows ports to override mp_builtin___import__. This can be useful in MicroPython applications where MICROPY_ENABLE_EXTERNAL_IMPORT has to be disabled due to its impact on build size (2% to 2.5% of the minimal port). By overriding the otherwise very minimal mp_builtin___import__, ports can still allow limited forms of application-specific imports. Signed-off-by: Laurens Valk --- py/builtin.h | 6 ++++++ py/builtinimport.c | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/py/builtin.h b/py/builtin.h index fb11627841..7232142b77 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -64,7 +64,13 @@ MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_open_obj); #endif +// A port can provide its own import handler by defining mp_builtin___import__. +#ifndef mp_builtin___import__ +#define mp_builtin___import__ mp_builtin___import___default +#endif mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args); +mp_obj_t mp_builtin___import___default(size_t n_args, const mp_obj_t *args); + mp_obj_t mp_micropython_mem_info(size_t n_args, const mp_obj_t *args); MP_DECLARE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj); diff --git a/py/builtinimport.c b/py/builtinimport.c index 36cdac0767..a578d4ad27 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -467,7 +467,7 @@ STATIC mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name, return module_obj; } -mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { +mp_obj_t mp_builtin___import___default(size_t n_args, const mp_obj_t *args) { #if DEBUG_PRINT DEBUG_printf("__import__:\n"); for (size_t i = 0; i < n_args; i++) { @@ -566,7 +566,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { #else // MICROPY_ENABLE_EXTERNAL_IMPORT -mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { +mp_obj_t mp_builtin___import___default(size_t n_args, const mp_obj_t *args) { // Check that it's not a relative import if (n_args >= 5 && MP_OBJ_SMALL_INT_VALUE(args[4]) != 0) { mp_raise_NotImplementedError(MP_ERROR_TEXT("relative import")); From b1efc1340af122499e5cf1d7214d51e034d45a20 Mon Sep 17 00:00:00 2001 From: Chris Waggoner Date: Sun, 21 Aug 2022 06:57:12 -0400 Subject: [PATCH 0303/1041] mpy-cross,unix: Include alloca.h for NetBSD. --- mpy-cross/mpconfigport.h | 2 +- ports/unix/mpconfigport.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mpy-cross/mpconfigport.h b/mpy-cross/mpconfigport.h index 9d455c0af1..4304c552bc 100644 --- a/mpy-cross/mpconfigport.h +++ b/mpy-cross/mpconfigport.h @@ -119,7 +119,7 @@ typedef long mp_off_t; #define MP_PLAT_PRINT_STRN(str, len) (void)0 // We need to provide a declaration/definition of alloca() -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__NetBSD__) #include #elif defined(_WIN32) #include diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 03b8ceb1f6..dd73f61e24 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -294,7 +294,7 @@ static inline unsigned long mp_urandom_seed_init(void) { // We need to provide a declaration/definition of alloca() // unless support for it is disabled. #if !defined(MICROPY_NO_ALLOCA) || MICROPY_NO_ALLOCA == 0 -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__NetBSD__) #include #else #include From 717924001d8da40032fd56aa3ba2207059f550d2 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 3 Aug 2022 18:01:11 +0200 Subject: [PATCH 0304/1041] stm32: Switch Wiznet to use lib/wiznet5k and extmod/network_wiznet5k. Instead of the old Wiznet driver in drivers/wiznet5k. --- ports/stm32/Makefile | 17 +- ports/stm32/modnwwiznet5k.c | 513 --------------------------------- ports/stm32/network_wiznet5k.c | 465 ------------------------------ 3 files changed, 10 insertions(+), 985 deletions(-) delete mode 100644 ports/stm32/modnwwiznet5k.c delete mode 100644 ports/stm32/network_wiznet5k.c diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 14a93a5aa7..7c912f4f0b 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -460,19 +460,22 @@ LIBS += $(TOP)/drivers/cyw43/libcyw43.a endif ifneq ($(MICROPY_PY_NETWORK_WIZNET5K),0) -WIZNET5K_DIR=drivers/wiznet5k -INC += -I$(TOP)/$(WIZNET5K_DIR) +WIZNET5K_DIR=lib/wiznet5k +GIT_SUBMODULES += lib/wiznet5k +INC += -I$(TOP)/$(WIZNET5K_DIR) -I$(TOP)/$(WIZNET5K_DIR)/Ethernet CFLAGS_MOD += -DMICROPY_PY_NETWORK_WIZNET5K=$(MICROPY_PY_NETWORK_WIZNET5K) -D_WIZCHIP_=$(MICROPY_PY_NETWORK_WIZNET5K) +CFLAGS_MOD += -DWIZCHIP_PREFIXED_EXPORTS=1 ifeq ($(MICROPY_PY_LWIP),1) # When using MACRAW mode (with lwIP), maximum buffer space must be used for the raw socket CFLAGS_MOD += -DWIZCHIP_USE_MAX_BUFFER endif -SRC_MOD += network_wiznet5k.c modnwwiznet5k.c +SRC_MOD += extmod/network_wiznet5k.c SRC_MOD += $(addprefix $(WIZNET5K_DIR)/,\ - ethernet/w$(MICROPY_PY_NETWORK_WIZNET5K)/w$(MICROPY_PY_NETWORK_WIZNET5K).c \ - ethernet/wizchip_conf.c \ - ethernet/socket.c \ - internet/dns/dns.c \ + Ethernet/W$(MICROPY_PY_NETWORK_WIZNET5K)/w$(MICROPY_PY_NETWORK_WIZNET5K).c \ + Ethernet/wizchip_conf.c \ + Ethernet/socket.c \ + Internet/DNS/dns.c \ + Internet/DHCP/dhcp.c \ ) endif diff --git a/ports/stm32/modnwwiznet5k.c b/ports/stm32/modnwwiznet5k.c deleted file mode 100644 index 2d5044d524..0000000000 --- a/ports/stm32/modnwwiznet5k.c +++ /dev/null @@ -1,513 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2014 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 -#include -#include - -#include "py/objlist.h" -#include "py/runtime.h" -#include "py/stream.h" -#include "py/mperrno.h" -#include "py/mphal.h" -#include "shared/netutils/netutils.h" -#include "extmod/modnetwork.h" -#include "pin.h" -#include "spi.h" - -#if MICROPY_PY_NETWORK_WIZNET5K && !MICROPY_PY_LWIP - -#include "ethernet/wizchip_conf.h" -#include "ethernet/socket.h" -#include "internet/dns/dns.h" - -/// \moduleref network - -typedef struct _wiznet5k_obj_t { - mp_obj_base_t base; - mp_uint_t cris_state; - const spi_t *spi; - const pin_obj_t *cs; - const pin_obj_t *rst; - uint8_t socket_used; -} wiznet5k_obj_t; - -STATIC wiznet5k_obj_t wiznet5k_obj; - -STATIC void wiz_cris_enter(void) { - wiznet5k_obj.cris_state = MICROPY_BEGIN_ATOMIC_SECTION(); -} - -STATIC void wiz_cris_exit(void) { - MICROPY_END_ATOMIC_SECTION(wiznet5k_obj.cris_state); -} - -STATIC void wiz_cs_select(void) { - mp_hal_pin_low(wiznet5k_obj.cs); -} - -STATIC void wiz_cs_deselect(void) { - mp_hal_pin_high(wiznet5k_obj.cs); -} - -STATIC void wiz_spi_read(uint8_t *buf, uint32_t len) { - HAL_StatusTypeDef status = HAL_SPI_Receive(wiznet5k_obj.spi->spi, buf, len, 5000); - (void)status; -} - -STATIC void wiz_spi_write(const uint8_t *buf, uint32_t len) { - HAL_StatusTypeDef status = HAL_SPI_Transmit(wiznet5k_obj.spi->spi, (uint8_t *)buf, len, 5000); - (void)status; -} - -STATIC int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) { - uint8_t dns_ip[MOD_NETWORK_IPADDR_BUF_SIZE] = {8, 8, 8, 8}; - uint8_t *buf = m_new(uint8_t, MAX_DNS_BUF_SIZE); - DNS_init(0, buf); - mp_int_t ret = DNS_run(dns_ip, (uint8_t *)name, out_ip); - m_del(uint8_t, buf, MAX_DNS_BUF_SIZE); - if (ret == 1) { - // success - return 0; - } else { - // failure - return -2; - } -} - -STATIC int wiznet5k_socket_socket(mod_network_socket_obj_t *socket, int *_errno) { - if (socket->domain != MOD_NETWORK_AF_INET) { - *_errno = MP_EAFNOSUPPORT; - return -1; - } - - switch (socket->type) { - case MOD_NETWORK_SOCK_STREAM: - socket->type = Sn_MR_TCP; - break; - case MOD_NETWORK_SOCK_DGRAM: - socket->type = Sn_MR_UDP; - break; - default: - *_errno = MP_EINVAL; - return -1; - } - - if (socket->fileno == -1) { - // get first unused socket number - for (mp_uint_t sn = 0; sn < _WIZCHIP_SOCK_NUM_; sn++) { - if ((wiznet5k_obj.socket_used & (1 << sn)) == 0) { - wiznet5k_obj.socket_used |= (1 << sn); - socket->fileno = sn; - break; - } - } - if (socket->fileno == -1) { - // too many open sockets - *_errno = MP_EMFILE; - return -1; - } - } - - // WIZNET does not have a concept of pure "open socket". You need to know - // if it's a server or client at the time of creation of the socket. - // So, we defer the open until we know what kind of socket we want. - - // use "domain" to indicate that this socket has not yet been opened - socket->domain = 0; - - return 0; -} - -STATIC void wiznet5k_socket_close(mod_network_socket_obj_t *socket) { - uint8_t sn = (uint8_t)socket->fileno; - if (sn < _WIZCHIP_SOCK_NUM_) { - wiznet5k_obj.socket_used &= ~(1 << sn); - WIZCHIP_EXPORT(close)(sn); - } -} - -STATIC int wiznet5k_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) { - // open the socket in server mode (if port != 0) - mp_int_t ret = WIZCHIP_EXPORT(socket)(socket->fileno, socket->type, port, 0); - if (ret < 0) { - wiznet5k_socket_close(socket); - *_errno = -ret; - return -1; - } - - // indicate that this socket has been opened - socket->domain = 1; - - // success - return 0; -} - -STATIC int wiznet5k_socket_listen(mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno) { - mp_int_t ret = WIZCHIP_EXPORT(listen)(socket->fileno); - if (ret < 0) { - wiznet5k_socket_close(socket); - *_errno = -ret; - return -1; - } - return 0; -} - -STATIC int wiznet5k_socket_accept(mod_network_socket_obj_t *socket, mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno) { - for (;;) { - int sr = getSn_SR((uint8_t)socket->fileno); - if (sr == SOCK_ESTABLISHED) { - socket2->domain = socket->domain; - socket2->type = socket->type; - socket2->fileno = socket->fileno; - getSn_DIPR((uint8_t)socket2->fileno, ip); - *port = getSn_PORT(socket2->fileno); - - // WIZnet turns the listening socket into the client socket, so we - // need to re-bind and re-listen on another socket for the server. - // TODO handle errors, especially no-more-sockets error - socket->domain = MOD_NETWORK_AF_INET; - socket->fileno = -1; - int _errno2; - if (wiznet5k_socket_socket(socket, &_errno2) != 0) { - // printf("(bad resocket %d)\n", _errno2); - } else if (wiznet5k_socket_bind(socket, NULL, *port, &_errno2) != 0) { - // printf("(bad rebind %d)\n", _errno2); - } else if (wiznet5k_socket_listen(socket, 0, &_errno2) != 0) { - // printf("(bad relisten %d)\n", _errno2); - } - - return 0; - } - if (sr == SOCK_CLOSED || sr == SOCK_CLOSE_WAIT) { - wiznet5k_socket_close(socket); - *_errno = MP_ENOTCONN; // ?? - return -1; - } - mp_hal_delay_ms(1); - } -} - -STATIC int wiznet5k_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) { - // use "bind" function to open the socket in client mode - if (wiznet5k_socket_bind(socket, ip, 0, _errno) != 0) { - return -1; - } - - // now connect - MP_THREAD_GIL_EXIT(); - mp_int_t ret = WIZCHIP_EXPORT(connect)(socket->fileno, ip, port); - MP_THREAD_GIL_ENTER(); - - if (ret < 0) { - wiznet5k_socket_close(socket); - *_errno = -ret; - return -1; - } - - // success - return 0; -} - -STATIC mp_uint_t wiznet5k_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) { - MP_THREAD_GIL_EXIT(); - mp_int_t ret = WIZCHIP_EXPORT(send)(socket->fileno, (byte *)buf, len); - MP_THREAD_GIL_ENTER(); - - // TODO convert Wiz errno's to POSIX ones - if (ret < 0) { - wiznet5k_socket_close(socket); - *_errno = -ret; - return -1; - } - return ret; -} - -STATIC mp_uint_t wiznet5k_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) { - MP_THREAD_GIL_EXIT(); - mp_int_t ret = WIZCHIP_EXPORT(recv)(socket->fileno, buf, len); - MP_THREAD_GIL_ENTER(); - - // TODO convert Wiz errno's to POSIX ones - if (ret < 0) { - wiznet5k_socket_close(socket); - *_errno = -ret; - return -1; - } - return ret; -} - -STATIC mp_uint_t wiznet5k_socket_sendto(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) { - if (socket->domain == 0) { - // socket not opened; use "bind" function to open the socket in client mode - if (wiznet5k_socket_bind(socket, ip, 0, _errno) != 0) { - return -1; - } - } - - MP_THREAD_GIL_EXIT(); - mp_int_t ret = WIZCHIP_EXPORT(sendto)(socket->fileno, (byte *)buf, len, ip, port); - MP_THREAD_GIL_ENTER(); - - if (ret < 0) { - wiznet5k_socket_close(socket); - *_errno = -ret; - return -1; - } - return ret; -} - -STATIC mp_uint_t wiznet5k_socket_recvfrom(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { - uint16_t port2; - MP_THREAD_GIL_EXIT(); - mp_int_t ret = WIZCHIP_EXPORT(recvfrom)(socket->fileno, buf, len, ip, &port2); - MP_THREAD_GIL_ENTER(); - *port = port2; - if (ret < 0) { - wiznet5k_socket_close(socket); - *_errno = -ret; - return -1; - } - return ret; -} - -STATIC int wiznet5k_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) { - // TODO - *_errno = MP_EINVAL; - return -1; -} - -STATIC int wiznet5k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno) { - // TODO - *_errno = MP_EINVAL; - return -1; - - /* - if (timeout_ms == 0) { - // set non-blocking mode - uint8_t arg = SOCK_IO_NONBLOCK; - WIZCHIP_EXPORT(ctlsocket)(socket->fileno, CS_SET_IOMODE, &arg); - } - */ -} - -STATIC int wiznet5k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno) { - if (request == MP_STREAM_POLL) { - int ret = 0; - if (arg & MP_STREAM_POLL_RD && getSn_RX_RSR(socket->fileno) != 0) { - ret |= MP_STREAM_POLL_RD; - } - if (arg & MP_STREAM_POLL_WR && getSn_TX_FSR(socket->fileno) != 0) { - ret |= MP_STREAM_POLL_WR; - } - return ret; - } else { - *_errno = MP_EINVAL; - return MP_STREAM_ERROR; - } -} - -#if 0 -STATIC void wiznet5k_socket_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { - wiznet5k_socket_obj_t *self = self_in; - print(env, "", self->sn, getSn_MR(self->sn)); -} - -STATIC mp_obj_t wiznet5k_socket_disconnect(mp_obj_t self_in) { - mp_int_t ret = WIZCHIP_EXPORT(disconnect)(self->sn); - return 0; -} -#endif - -/******************************************************************************/ -// MicroPython bindings - -/// \classmethod \constructor(spi, pin_cs, pin_rst) -/// Create and return a WIZNET5K object. -STATIC mp_obj_t wiznet5k_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, 3, 3, false); - - // init the wiznet5k object - wiznet5k_obj.base.type = (mp_obj_type_t *)&mod_network_nic_type_wiznet5k; - wiznet5k_obj.cris_state = 0; - wiznet5k_obj.spi = spi_from_mp_obj(args[0]); - wiznet5k_obj.cs = pin_find(args[1]); - wiznet5k_obj.rst = pin_find(args[2]); - wiznet5k_obj.socket_used = 0; - - /*!< SPI configuration */ - SPI_InitTypeDef *init = &wiznet5k_obj.spi->spi->Init; - init->Mode = SPI_MODE_MASTER; - init->Direction = SPI_DIRECTION_2LINES; - init->DataSize = SPI_DATASIZE_8BIT; - init->CLKPolarity = SPI_POLARITY_LOW; // clock is low when idle - init->CLKPhase = SPI_PHASE_1EDGE; // data latched on first edge, which is rising edge for low-idle - init->NSS = SPI_NSS_SOFT; - init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; // clock freq = f_PCLK / this_prescale_value; Wiz820i can do up to 80MHz - init->FirstBit = SPI_FIRSTBIT_MSB; - init->TIMode = SPI_TIMODE_DISABLED; - init->CRCCalculation = SPI_CRCCALCULATION_DISABLED; - init->CRCPolynomial = 7; // unused - spi_init(wiznet5k_obj.spi, false); - - mp_hal_pin_output(wiznet5k_obj.cs); - mp_hal_pin_output(wiznet5k_obj.rst); - - mp_hal_pin_low(wiznet5k_obj.rst); - mp_hal_delay_ms(1); // datasheet says 2us - mp_hal_pin_high(wiznet5k_obj.rst); - mp_hal_delay_ms(160); // datasheet says 150ms - - reg_wizchip_cris_cbfunc(wiz_cris_enter, wiz_cris_exit); - reg_wizchip_cs_cbfunc(wiz_cs_select, wiz_cs_deselect); - reg_wizchip_spi_cbfunc(wiz_spi_read, wiz_spi_write); - - uint8_t sn_size[16] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; // 2k buffer for each socket - ctlwizchip(CW_INIT_WIZCHIP, sn_size); - - // set some sensible default values; they are configurable using ifconfig method - wiz_NetInfo netinfo = { - .mac = {0x00, 0x08, 0xdc, 0xab, 0xcd, 0xef}, - .ip = {192, 168, 0, 18}, - .sn = {255, 255, 255, 0}, - .gw = {192, 168, 0, 1}, - .dns = {8, 8, 8, 8}, // Google public DNS - .dhcp = NETINFO_STATIC, - }; - ctlnetwork(CN_SET_NETINFO, (void *)&netinfo); - - // seems we need a small delay after init - mp_hal_delay_ms(250); - - // register with network module - mod_network_register_nic(&wiznet5k_obj); - - // return wiznet5k object - return &wiznet5k_obj; -} - -/// \method regs() -/// Dump WIZNET5K registers. -STATIC mp_obj_t wiznet5k_regs(mp_obj_t self_in) { - // wiznet5k_obj_t *self = self_in; - printf("Wiz CREG:"); - for (int i = 0; i < 0x50; ++i) { - if (i % 16 == 0) { - printf("\n %04x:", i); - } - #if MICROPY_PY_NETWORK_WIZNET5K == 5200 - uint32_t reg = i; - #else - uint32_t reg = _W5500_IO_BASE_ | i << 8; - #endif - printf(" %02x", WIZCHIP_READ(reg)); - } - for (int sn = 0; sn < 4; ++sn) { - printf("\nWiz SREG[%d]:", sn); - for (int i = 0; i < 0x30; ++i) { - if (i % 16 == 0) { - printf("\n %04x:", i); - } - #if MICROPY_PY_NETWORK_WIZNET5K == 5200 - uint32_t reg = WIZCHIP_SREG_ADDR(sn, i); - #else - uint32_t reg = _W5500_IO_BASE_ | i << 8 | WIZCHIP_SREG_BLOCK(sn) << 3; - #endif - printf(" %02x", WIZCHIP_READ(reg)); - } - } - printf("\n"); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_regs_obj, wiznet5k_regs); - -STATIC mp_obj_t wiznet5k_isconnected(mp_obj_t self_in) { - (void)self_in; - return mp_obj_new_bool(wizphy_getphylink() == PHY_LINK_ON); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_isconnected_obj, wiznet5k_isconnected); - -/// \method ifconfig([(ip, subnet, gateway, dns)]) -/// Get/set IP address, subnet mask, gateway and DNS. -STATIC mp_obj_t wiznet5k_ifconfig(size_t n_args, const mp_obj_t *args) { - wiz_NetInfo netinfo; - ctlnetwork(CN_GET_NETINFO, &netinfo); - if (n_args == 1) { - // get - mp_obj_t tuple[4] = { - netutils_format_ipv4_addr(netinfo.ip, NETUTILS_BIG), - netutils_format_ipv4_addr(netinfo.sn, NETUTILS_BIG), - netutils_format_ipv4_addr(netinfo.gw, NETUTILS_BIG), - netutils_format_ipv4_addr(netinfo.dns, NETUTILS_BIG), - }; - return mp_obj_new_tuple(4, tuple); - } else { - // set - mp_obj_t *items; - mp_obj_get_array_fixed_n(args[1], 4, &items); - netutils_parse_ipv4_addr(items[0], netinfo.ip, NETUTILS_BIG); - netutils_parse_ipv4_addr(items[1], netinfo.sn, NETUTILS_BIG); - netutils_parse_ipv4_addr(items[2], netinfo.gw, NETUTILS_BIG); - netutils_parse_ipv4_addr(items[3], netinfo.dns, NETUTILS_BIG); - ctlnetwork(CN_SET_NETINFO, &netinfo); - return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_ifconfig_obj, 1, 2, wiznet5k_ifconfig); - -STATIC const mp_rom_map_elem_t wiznet5k_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_regs), MP_ROM_PTR(&wiznet5k_regs_obj) }, - { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&wiznet5k_ifconfig_obj) }, - { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&wiznet5k_isconnected_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(wiznet5k_locals_dict, wiznet5k_locals_dict_table); - -const mod_network_nic_type_t mod_network_nic_type_wiznet5k = { - .base = { - { &mp_type_type }, - .name = MP_QSTR_WIZNET5K, - .make_new = wiznet5k_make_new, - .locals_dict = (mp_obj_dict_t *)&wiznet5k_locals_dict, - }, - .gethostbyname = wiznet5k_gethostbyname, - .socket = wiznet5k_socket_socket, - .close = wiznet5k_socket_close, - .bind = wiznet5k_socket_bind, - .listen = wiznet5k_socket_listen, - .accept = wiznet5k_socket_accept, - .connect = wiznet5k_socket_connect, - .send = wiznet5k_socket_send, - .recv = wiznet5k_socket_recv, - .sendto = wiznet5k_socket_sendto, - .recvfrom = wiznet5k_socket_recvfrom, - .setsockopt = wiznet5k_socket_setsockopt, - .settimeout = wiznet5k_socket_settimeout, - .ioctl = wiznet5k_socket_ioctl, -}; - -#endif // MICROPY_PY_NETWORK_WIZNET5K && !MICROPY_PY_LWIP diff --git a/ports/stm32/network_wiznet5k.c b/ports/stm32/network_wiznet5k.c deleted file mode 100644 index 4675f3c2c2..0000000000 --- a/ports/stm32/network_wiznet5k.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2014-2018 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 -#include - -#include "py/runtime.h" -#include "py/mphal.h" -#include "extmod/modnetwork.h" -#include "spi.h" - -#if MICROPY_PY_NETWORK_WIZNET5K && MICROPY_PY_LWIP - -#include "shared/netutils/netutils.h" -#include "drivers/wiznet5k/ethernet/socket.h" -#include "lwip/err.h" -#include "lwip/dns.h" -#include "lwip/dhcp.h" -#include "netif/etharp.h" - -#define TRACE_ETH_TX (0x0002) -#define TRACE_ETH_RX (0x0004) - -/*******************************************************************************/ -// Wiznet5k Ethernet driver in MACRAW mode - -typedef struct _wiznet5k_obj_t { - mp_obj_base_t base; - mp_uint_t cris_state; - const spi_t *spi; - mp_hal_pin_obj_t cs; - mp_hal_pin_obj_t rst; - uint8_t eth_frame[1514]; - uint32_t trace_flags; - struct netif netif; - struct dhcp dhcp_struct; -} wiznet5k_obj_t; - -// Global object holding the Wiznet5k state -STATIC wiznet5k_obj_t wiznet5k_obj; - -STATIC void wiznet5k_lwip_init(wiznet5k_obj_t *self); - -STATIC void wiz_cris_enter(void) { - wiznet5k_obj.cris_state = MICROPY_BEGIN_ATOMIC_SECTION(); -} - -STATIC void wiz_cris_exit(void) { - MICROPY_END_ATOMIC_SECTION(wiznet5k_obj.cris_state); -} - -STATIC void wiz_cs_select(void) { - mp_hal_pin_low(wiznet5k_obj.cs); -} - -STATIC void wiz_cs_deselect(void) { - mp_hal_pin_high(wiznet5k_obj.cs); -} - -STATIC void wiz_spi_read(uint8_t *buf, uint32_t len) { - HAL_StatusTypeDef status = HAL_SPI_Receive(wiznet5k_obj.spi->spi, buf, len, 5000); - (void)status; -} - -STATIC void wiz_spi_write(const uint8_t *buf, uint32_t len) { - HAL_StatusTypeDef status = HAL_SPI_Transmit(wiznet5k_obj.spi->spi, (uint8_t *)buf, len, 5000); - (void)status; -} - -STATIC void wiznet5k_init(void) { - // SPI configuration - SPI_InitTypeDef *init = &wiznet5k_obj.spi->spi->Init; - init->Mode = SPI_MODE_MASTER; - init->Direction = SPI_DIRECTION_2LINES; - init->DataSize = SPI_DATASIZE_8BIT; - init->CLKPolarity = SPI_POLARITY_LOW; // clock is low when idle - init->CLKPhase = SPI_PHASE_1EDGE; // data latched on first edge, which is rising edge for low-idle - init->NSS = SPI_NSS_SOFT; - init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; // clock freq = f_PCLK / this_prescale_value; Wiz820i can do up to 80MHz - init->FirstBit = SPI_FIRSTBIT_MSB; - init->TIMode = SPI_TIMODE_DISABLED; - init->CRCCalculation = SPI_CRCCALCULATION_DISABLED; - init->CRCPolynomial = 7; // unused - spi_init(wiznet5k_obj.spi, false); - - mp_hal_pin_output(wiznet5k_obj.cs); - mp_hal_pin_output(wiznet5k_obj.rst); - - // Reset the chip - mp_hal_pin_low(wiznet5k_obj.rst); - mp_hal_delay_ms(1); // datasheet says 2us - mp_hal_pin_high(wiznet5k_obj.rst); - mp_hal_delay_ms(150); // datasheet says 150ms - - // Set physical interface callbacks - reg_wizchip_cris_cbfunc(wiz_cris_enter, wiz_cris_exit); - reg_wizchip_cs_cbfunc(wiz_cs_select, wiz_cs_deselect); - reg_wizchip_spi_cbfunc(wiz_spi_read, wiz_spi_write); - - // Configure 16k buffers for fast MACRAW - uint8_t sn_size[16] = {16, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0}; - ctlwizchip(CW_INIT_WIZCHIP, sn_size); - - // Seems we need a small delay after init - mp_hal_delay_ms(250); - - // If the device doesn't have a MAC address then set one - uint8_t mac[6]; - getSHAR(mac); - if ((mac[0] | mac[1] | mac[2] | mac[3] | mac[4] | mac[5]) == 0) { - mp_hal_get_mac(MP_HAL_MAC_ETH0, mac); - setSHAR(mac); - } - - // Hook the Wiznet into lwIP - wiznet5k_lwip_init(&wiznet5k_obj); -} - -STATIC void wiznet5k_deinit(void) { - for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { - if (netif == &wiznet5k_obj.netif) { - netif_remove(netif); - netif->flags = 0; - break; - } - } -} - -STATIC void wiznet5k_get_mac_address(wiznet5k_obj_t *self, uint8_t mac[6]) { - (void)self; - getSHAR(mac); -} - -STATIC void wiznet5k_send_ethernet(wiznet5k_obj_t *self, size_t len, const uint8_t *buf) { - uint8_t ip[4] = {1, 1, 1, 1}; // dummy - int ret = WIZCHIP_EXPORT(sendto)(0, (byte *)buf, len, ip, 11); // dummy port - if (ret != len) { - printf("wiznet5k_send_ethernet: fatal error %d\n", ret); - netif_set_link_down(&self->netif); - netif_set_down(&self->netif); - } -} - -// Stores the frame in self->eth_frame and returns number of bytes in the frame, 0 for no frame -STATIC uint16_t wiznet5k_recv_ethernet(wiznet5k_obj_t *self) { - uint16_t len = getSn_RX_RSR(0); - if (len == 0) { - return 0; - } - - byte ip[4]; - uint16_t port; - int ret = WIZCHIP_EXPORT(recvfrom)(0, self->eth_frame, 1514, ip, &port); - if (ret <= 0) { - printf("wiznet5k_poll: fatal error len=%u ret=%d\n", len, ret); - netif_set_link_down(&self->netif); - netif_set_down(&self->netif); - return 0; - } - - return ret; -} - -/*******************************************************************************/ -// Wiznet5k lwIP interface - -STATIC err_t wiznet5k_netif_output(struct netif *netif, struct pbuf *p) { - wiznet5k_obj_t *self = netif->state; - pbuf_copy_partial(p, self->eth_frame, p->tot_len, 0); - if (self->trace_flags & TRACE_ETH_TX) { - netutils_ethernet_trace(MP_PYTHON_PRINTER, p->tot_len, self->eth_frame, NETUTILS_TRACE_IS_TX | NETUTILS_TRACE_NEWLINE); - } - wiznet5k_send_ethernet(self, p->tot_len, self->eth_frame); - return ERR_OK; -} - -STATIC err_t wiznet5k_netif_init(struct netif *netif) { - netif->linkoutput = wiznet5k_netif_output; - netif->output = etharp_output; - netif->mtu = 1500; - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP; - wiznet5k_get_mac_address(netif->state, netif->hwaddr); - netif->hwaddr_len = sizeof(netif->hwaddr); - int ret = WIZCHIP_EXPORT(socket)(0, Sn_MR_MACRAW, 0, 0); - if (ret != 0) { - printf("WIZNET fatal error in netifinit: %d\n", ret); - return ERR_IF; - } - - // Enable MAC filtering so we only get frames destined for us, to reduce load on lwIP - setSn_MR(0, getSn_MR(0) | Sn_MR_MFEN); - - return ERR_OK; -} - -STATIC void wiznet5k_lwip_init(wiznet5k_obj_t *self) { - ip_addr_t ipconfig[4]; - ipconfig[0].addr = 0; - ipconfig[1].addr = 0; - ipconfig[2].addr = 0; - ipconfig[3].addr = 0; - netif_add(&self->netif, &ipconfig[0], &ipconfig[1], &ipconfig[2], self, wiznet5k_netif_init, ethernet_input); - self->netif.name[0] = 'e'; - self->netif.name[1] = '0'; - netif_set_default(&self->netif); - dns_setserver(0, &ipconfig[3]); - dhcp_set_struct(&self->netif, &self->dhcp_struct); - // Setting NETIF_FLAG_UP then clearing it is a workaround for dhcp_start and the - // LWIP_DHCP_CHECK_LINK_UP option, so that the DHCP client schedules itself to - // automatically start when the interface later goes up. - self->netif.flags |= NETIF_FLAG_UP; - dhcp_start(&self->netif); - self->netif.flags &= ~NETIF_FLAG_UP; -} - -void wiznet5k_poll(void) { - wiznet5k_obj_t *self = &wiznet5k_obj; - if (!(self->netif.flags & NETIF_FLAG_LINK_UP)) { - return; - } - uint16_t len; - while ((len = wiznet5k_recv_ethernet(self)) > 0) { - if (self->trace_flags & TRACE_ETH_RX) { - netutils_ethernet_trace(MP_PYTHON_PRINTER, len, self->eth_frame, NETUTILS_TRACE_NEWLINE); - } - struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); - if (p != NULL) { - pbuf_take(p, self->eth_frame, len); - if (self->netif.input(p, &self->netif) != ERR_OK) { - pbuf_free(p); - } - } - } -} - -/*******************************************************************************/ -// MicroPython bindings - -// WIZNET5K([spi, pin_cs, pin_rst]) -STATIC mp_obj_t wiznet5k_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, 3, 3, false); - - const spi_t *spi = spi_from_mp_obj(args[0]); - mp_hal_pin_obj_t cs = pin_find(args[1]); - mp_hal_pin_obj_t rst = pin_find(args[2]); - - // Access the existing object, if it has been constructed with the same hardware interface - if (wiznet5k_obj.base.type == (mp_obj_type_t *)&mod_network_nic_type_wiznet5k) { - if (!(wiznet5k_obj.spi == spi && wiznet5k_obj.cs == cs && wiznet5k_obj.rst == rst - && wiznet5k_obj.netif.flags != 0)) { - wiznet5k_deinit(); - } - } - - // Init the wiznet5k object - wiznet5k_obj.base.type = (mp_obj_type_t *)&mod_network_nic_type_wiznet5k; - wiznet5k_obj.cris_state = 0; - wiznet5k_obj.spi = spi; - wiznet5k_obj.cs = cs; - wiznet5k_obj.rst = rst; - wiznet5k_obj.trace_flags = 0; - - // Return wiznet5k object - return MP_OBJ_FROM_PTR(&wiznet5k_obj); -} - -STATIC mp_obj_t wiznet5k_regs(mp_obj_t self_in) { - (void)self_in; - printf("Wiz CREG:"); - for (int i = 0; i < 0x50; ++i) { - if (i % 16 == 0) { - printf("\n %04x:", i); - } - #if MICROPY_PY_NETWORK_WIZNET5K == 5200 - uint32_t reg = i; - #else - uint32_t reg = _W5500_IO_BASE_ | i << 8; - #endif - printf(" %02x", WIZCHIP_READ(reg)); - } - for (int sn = 0; sn < 4; ++sn) { - printf("\nWiz SREG[%d]:", sn); - for (int i = 0; i < 0x30; ++i) { - if (i % 16 == 0) { - printf("\n %04x:", i); - } - #if MICROPY_PY_NETWORK_WIZNET5K == 5200 - uint32_t reg = WIZCHIP_SREG_ADDR(sn, i); - #else - uint32_t reg = _W5500_IO_BASE_ | i << 8 | WIZCHIP_SREG_BLOCK(sn) << 3; - #endif - printf(" %02x", WIZCHIP_READ(reg)); - } - } - printf("\n"); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_regs_obj, wiznet5k_regs); - -STATIC mp_obj_t wiznet5k_isconnected(mp_obj_t self_in) { - wiznet5k_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_bool( - wizphy_getphylink() == PHY_LINK_ON - && (self->netif.flags & NETIF_FLAG_UP) - && self->netif.ip_addr.addr != 0 - ); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_isconnected_obj, wiznet5k_isconnected); - -STATIC mp_obj_t wiznet5k_active(size_t n_args, const mp_obj_t *args) { - wiznet5k_obj_t *self = MP_OBJ_TO_PTR(args[0]); - if (n_args == 1) { - return mp_obj_new_bool(self->netif.flags & NETIF_FLAG_UP); - } else { - if (mp_obj_is_true(args[1])) { - if (!(self->netif.flags & NETIF_FLAG_UP)) { - wiznet5k_init(); - netif_set_link_up(&self->netif); - netif_set_up(&self->netif); - } - } else { - if (self->netif.flags & NETIF_FLAG_UP) { - netif_set_down(&self->netif); - netif_set_link_down(&self->netif); - wiznet5k_deinit(); - } - } - return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_active_obj, 1, 2, wiznet5k_active); - -STATIC mp_obj_t wiznet5k_ifconfig(size_t n_args, const mp_obj_t *args) { - wiznet5k_obj_t *self = MP_OBJ_TO_PTR(args[0]); - return mod_network_nic_ifconfig(&self->netif, n_args - 1, args + 1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_ifconfig_obj, 1, 2, wiznet5k_ifconfig); - -STATIC mp_obj_t wiznet5k_status(size_t n_args, const mp_obj_t *args) { - wiznet5k_obj_t *self = MP_OBJ_TO_PTR(args[0]); - (void)self; - - if (n_args == 1) { - // No arguments: return link status - if (self->netif.flags && wizphy_getphylink() == PHY_LINK_ON) { - if ((self->netif.flags & NETIF_FLAG_UP) && self->netif.ip_addr.addr != 0) { - return MP_OBJ_NEW_SMALL_INT(2); - } else { - return MP_OBJ_NEW_SMALL_INT(1); - } - } else { - return MP_OBJ_NEW_SMALL_INT(0); - } - } - - mp_raise_ValueError(MP_ERROR_TEXT("unknown config param")); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_status_obj, 1, 2, wiznet5k_status); - -STATIC mp_obj_t wiznet5k_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { - wiznet5k_obj_t *self = MP_OBJ_TO_PTR(args[0]); - - if (kwargs->used == 0) { - // Get config value - if (n_args != 2) { - mp_raise_TypeError(MP_ERROR_TEXT("must query one param")); - } - - switch (mp_obj_str_get_qstr(args[1])) { - case MP_QSTR_mac: { - uint8_t buf[6]; - wiznet5k_get_mac_address(self, buf); - return mp_obj_new_bytes(buf, 6); - } - default: - mp_raise_ValueError(MP_ERROR_TEXT("unknown config param")); - } - } else { - // Set config value(s) - if (n_args != 1) { - mp_raise_TypeError(MP_ERROR_TEXT("can't specify pos and kw args")); - } - - for (size_t i = 0; i < kwargs->alloc; ++i) { - if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) { - mp_map_elem_t *e = &kwargs->table[i]; - switch (mp_obj_str_get_qstr(e->key)) { - case MP_QSTR_mac: { - mp_buffer_info_t buf; - mp_get_buffer_raise(e->value, &buf, MP_BUFFER_READ); - if (buf.len != 6) { - mp_raise_ValueError(NULL); - } - setSHAR(buf.buf); - memcpy(self->netif.hwaddr, buf.buf, 6); - break; - } - case MP_QSTR_trace: { - self->trace_flags = mp_obj_get_int(e->value); - break; - } - default: - mp_raise_ValueError(MP_ERROR_TEXT("unknown config param")); - } - } - } - - return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wiznet5k_config_obj, 1, wiznet5k_config); - -STATIC mp_obj_t send_ethernet_wrapper(mp_obj_t self_in, mp_obj_t buf_in) { - wiznet5k_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_buffer_info_t buf; - mp_get_buffer_raise(buf_in, &buf, MP_BUFFER_READ); - wiznet5k_send_ethernet(self, buf.len, buf.buf); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(send_ethernet_obj, send_ethernet_wrapper); - -STATIC const mp_rom_map_elem_t wiznet5k_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_regs), MP_ROM_PTR(&wiznet5k_regs_obj) }, - { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&wiznet5k_isconnected_obj) }, - { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&wiznet5k_active_obj) }, - { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&wiznet5k_ifconfig_obj) }, - { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&wiznet5k_status_obj) }, - { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&wiznet5k_config_obj) }, - - { MP_ROM_QSTR(MP_QSTR_send_ethernet), MP_ROM_PTR(&send_ethernet_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(wiznet5k_locals_dict, wiznet5k_locals_dict_table); - -const mp_obj_type_t mod_network_nic_type_wiznet5k = { - { &mp_type_type }, - .name = MP_QSTR_WIZNET5K, - .make_new = wiznet5k_make_new, - .locals_dict = (mp_obj_dict_t *)&wiznet5k_locals_dict, -}; - -#endif // MICROPY_PY_NETWORK_WIZNET5K && MICROPY_PY_LWIP From c3305c49e422369119ab211dc8fb2366aa6d7d53 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 4 Aug 2022 20:19:57 +0200 Subject: [PATCH 0305/1041] stm32: Add definitions required for lwIP version of Wiznet NIC. --- ports/stm32/mphalport.h | 8 ++++++++ ports/stm32/mpnetworkport.c | 5 +++++ ports/stm32/pendsv.h | 3 +++ 3 files changed, 16 insertions(+) diff --git a/ports/stm32/mphalport.h b/ports/stm32/mphalport.h index 47bb1f8c84..8028782a90 100644 --- a/ports/stm32/mphalport.h +++ b/ports/stm32/mphalport.h @@ -96,11 +96,19 @@ static inline mp_uint_t mp_hal_ticks_cpu(void) { #define mp_hal_pin_od_high(p) mp_hal_pin_high(p) #define mp_hal_pin_read(p) (((p)->gpio->IDR >> (p)->pin) & 1) #define mp_hal_pin_write(p, v) ((v) ? mp_hal_pin_high(p) : mp_hal_pin_low(p)) +#define mp_hal_pin_interrupt(pin, handler, trigger, hard) extint_register_pin(pin, trigger, hard, handler) + +enum mp_hal_pin_interrupt_trigger { + MP_HAL_PIN_TRIGGER_NONE, + MP_HAL_PIN_TRIGGER_FALL = GPIO_MODE_IT_FALLING, + MP_HAL_PIN_TRIGGER_RISE = GPIO_MODE_IT_RISING, +}; void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio); void mp_hal_pin_config(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, uint32_t alt); bool mp_hal_pin_config_alt(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, uint8_t fn, uint8_t unit); void mp_hal_pin_config_speed(mp_hal_pin_obj_t pin_obj, uint32_t speed); +void extint_register_pin(const pin_obj_t *pin, uint32_t mode, bool hard_irq, mp_obj_t callback_obj); enum { MP_HAL_MAC_WLAN0 = 0, diff --git a/ports/stm32/mpnetworkport.c b/ports/stm32/mpnetworkport.c index 2f49328e11..1ce758e7dd 100644 --- a/ports/stm32/mpnetworkport.c +++ b/ports/stm32/mpnetworkport.c @@ -50,6 +50,11 @@ #if MICROPY_PY_NETWORK_WIZNET5K void wiznet5k_poll(void); +void wiznet5k_deinit(void); + +void wiznet5k_try_poll(void) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_WIZNET, wiznet5k_poll); +} #endif u32_t sys_now(void) { diff --git a/ports/stm32/pendsv.h b/ports/stm32/pendsv.h index 0733d355d3..f97581e99a 100644 --- a/ports/stm32/pendsv.h +++ b/ports/stm32/pendsv.h @@ -35,6 +35,9 @@ enum { #if MICROPY_PY_NETWORK_CYW43 PENDSV_DISPATCH_CYW43, #endif + #if MICROPY_PY_NETWORK_WIZNET5K + PENDSV_DISPATCH_WIZNET, + #endif #endif #if MICROPY_PY_BLUETOOTH && !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS PENDSV_DISPATCH_BLUETOOTH_HCI, From 54eaa8c8a6c854e13f3c1b646ef44d0888628353 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 10 Aug 2022 11:04:09 +0200 Subject: [PATCH 0306/1041] stm32/mphalport: Add mp_hal_get_spi_obj() helper function. The function spi_from_mp_obj() is kept since it is used by the cc3k driver. --- ports/stm32/mphalport.h | 2 ++ ports/stm32/spi.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/ports/stm32/mphalport.h b/ports/stm32/mphalport.h index 8028782a90..358d9cd25d 100644 --- a/ports/stm32/mphalport.h +++ b/ports/stm32/mphalport.h @@ -110,6 +110,8 @@ bool mp_hal_pin_config_alt(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, u void mp_hal_pin_config_speed(mp_hal_pin_obj_t pin_obj, uint32_t speed); void extint_register_pin(const pin_obj_t *pin, uint32_t mode, bool hard_irq, mp_obj_t callback_obj); +mp_obj_base_t *mp_hal_get_spi_obj(mp_obj_t spi_in); + enum { MP_HAL_MAC_WLAN0 = 0, MP_HAL_MAC_WLAN1, diff --git a/ports/stm32/spi.c b/ports/stm32/spi.c index 188376ec06..9c031cad2e 100644 --- a/ports/stm32/spi.c +++ b/ports/stm32/spi.c @@ -30,6 +30,7 @@ #include "py/runtime.h" #include "py/mphal.h" #include "spi.h" +#include "extmod/machine_spi.h" // Possible DMA configurations for SPI buses: // SPI1_TX: DMA2_Stream3.CHANNEL_3 or DMA2_Stream5.CHANNEL_3 @@ -685,6 +686,20 @@ const spi_t *spi_from_mp_obj(mp_obj_t o) { } } +mp_obj_base_t *mp_hal_get_spi_obj(mp_obj_t o) { + if (mp_obj_is_type(o, &machine_hard_spi_type)) { + return MP_OBJ_TO_PTR(o); + } + #if MICROPY_PY_MACHINE_SOFTSPI + else if (mp_obj_is_type(o, &mp_machine_soft_spi_type)) { + return MP_OBJ_TO_PTR(o); + } + #endif + else { + mp_raise_TypeError(MP_ERROR_TEXT("expecting an SPI object")); + } +} + /******************************************************************************/ // Implementation of low-level SPI C protocol From f6ec01d1da8d316e1cdfeaf20cdc0578f943e154 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 5 Aug 2022 16:49:15 +0200 Subject: [PATCH 0307/1041] tools/ci.sh: Split the stm32 builds for wiznet5k and cc3k. - Add lib/wiznet5k into the 'make submodules' step. - Split the stm32 builds for wiznet5k and cc3k. - Run 'make .... clean' after making the wiznet5k build. --- tools/ci.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/ci.sh b/tools/ci.sh index dc2ccf775b..b7b20e3c7d 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -309,10 +309,12 @@ function ci_stm32_setup { function ci_stm32_pyb_build { make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/stm32 submodules + make ${MAKEOPTS} -C ports/stm32 MICROPY_PY_NETWORK_WIZNET5K=5200 submodules git submodule update --init lib/btstack git submodule update --init lib/mynewt-nimble - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_NETWORK_WIZNET5K=5200 MICROPY_PY_CC3K=1 USER_C_MODULES=../../examples/usercmodule + make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_NETWORK_WIZNET5K=5200 USER_C_MODULES=../../examples/usercmodule + make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 clean + make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_CC3K=1 make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF2 make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF6 NANBOX=1 MICROPY_BLUETOOTH_NIMBLE=0 MICROPY_BLUETOOTH_BTSTACK=1 make ${MAKEOPTS} -C ports/stm32/mboot BOARD=PYBV10 CFLAGS_EXTRA='-DMBOOT_FSLOAD=1 -DMBOOT_VFS_LFS2=1' From 71dcb21e24064d1150094e66a904877402cdd157 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 10 Aug 2022 11:07:35 +0200 Subject: [PATCH 0308/1041] drivers/wiznet5k: Remove old Wiznet driver. It has been replaced by the submodule lib/wiznet5k. --- drivers/wiznet5k/README.md | 6 - drivers/wiznet5k/ethernet/socket.c | 725 -------- drivers/wiznet5k/ethernet/socket.h | 472 ----- drivers/wiznet5k/ethernet/w5200/w5200.c | 215 --- drivers/wiznet5k/ethernet/w5200/w5200.h | 2092 ---------------------- drivers/wiznet5k/ethernet/w5500/w5500.c | 247 --- drivers/wiznet5k/ethernet/w5500/w5500.h | 2057 --------------------- drivers/wiznet5k/ethernet/wizchip_conf.c | 662 ------- drivers/wiznet5k/ethernet/wizchip_conf.h | 554 ------ drivers/wiznet5k/internet/dhcp/dhcp.c | 978 ---------- drivers/wiznet5k/internet/dhcp/dhcp.h | 150 -- drivers/wiznet5k/internet/dns/dns.c | 566 ------ drivers/wiznet5k/internet/dns/dns.h | 96 - 13 files changed, 8820 deletions(-) delete mode 100644 drivers/wiznet5k/README.md delete mode 100644 drivers/wiznet5k/ethernet/socket.c delete mode 100644 drivers/wiznet5k/ethernet/socket.h delete mode 100644 drivers/wiznet5k/ethernet/w5200/w5200.c delete mode 100644 drivers/wiznet5k/ethernet/w5200/w5200.h delete mode 100644 drivers/wiznet5k/ethernet/w5500/w5500.c delete mode 100644 drivers/wiznet5k/ethernet/w5500/w5500.h delete mode 100644 drivers/wiznet5k/ethernet/wizchip_conf.c delete mode 100644 drivers/wiznet5k/ethernet/wizchip_conf.h delete mode 100644 drivers/wiznet5k/internet/dhcp/dhcp.c delete mode 100644 drivers/wiznet5k/internet/dhcp/dhcp.h delete mode 100644 drivers/wiznet5k/internet/dns/dns.c delete mode 100644 drivers/wiznet5k/internet/dns/dns.h diff --git a/drivers/wiznet5k/README.md b/drivers/wiznet5k/README.md deleted file mode 100644 index 88f25a2b8d..0000000000 --- a/drivers/wiznet5k/README.md +++ /dev/null @@ -1,6 +0,0 @@ -This is the driver for the WIZnet5x00 series of Ethernet controllers. - -Adapted for MicroPython. - -Original source: https://github.com/Wiznet/W5500_EVB/tree/master/ioLibrary -Taken on: 30 August 2014 diff --git a/drivers/wiznet5k/ethernet/socket.c b/drivers/wiznet5k/ethernet/socket.c deleted file mode 100644 index 3ffda3a722..0000000000 --- a/drivers/wiznet5k/ethernet/socket.c +++ /dev/null @@ -1,725 +0,0 @@ -//***************************************************************************** -// -//! \file socket.c -//! \brief SOCKET APIs Implements file. -//! \details SOCKET APIs like as Berkeley Socket APIs. -//! \version 1.0.3 -//! \date 2013/10/21 -//! \par Revision history -//! <2014/05/01> V1.0.3. Refer to M20140501 -//! 1. Implicit type casting -> Explicit type casting. -//! 2. replace 0x01 with PACK_REMAINED in recvfrom() -//! 3. Validation a destination ip in connect() & sendto(): -//! It occurs a fatal error on converting unint32 address if uint8* addr parameter is not aligned by 4byte address. -//! Copy 4 byte addr value into temporary uint32 variable and then compares it. -//! <2013/12/20> V1.0.2 Refer to M20131220 -//! Remove Warning. -//! <2013/11/04> V1.0.1 2nd Release. Refer to "20131104". -//! In sendto(), Add to clear timeout interrupt status (Sn_IR_TIMEOUT) -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#include - -#include "py/mpthread.h" -#include "socket.h" - -#define SOCK_ANY_PORT_NUM 0xC000; - -static uint16_t sock_any_port = SOCK_ANY_PORT_NUM; -static uint16_t sock_io_mode = 0; -static uint16_t sock_is_sending = 0; -static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,}; -static uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,}; - -#if _WIZCHIP_ == 5200 - static uint16_t sock_next_rd[_WIZCHIP_SOCK_NUM_] ={0,}; -#endif - -#define CHECK_SOCKNUM() \ - do{ \ - if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \ - }while(0); \ - -#define CHECK_SOCKMODE(mode) \ - do{ \ - if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \ - }while(0); \ - -#define CHECK_SOCKINIT() \ - do{ \ - if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \ - }while(0); \ - -#define CHECK_SOCKDATA() \ - do{ \ - if(len == 0) return SOCKERR_DATALEN; \ - }while(0); \ - -void WIZCHIP_EXPORT(socket_reset)(void) { - sock_any_port = SOCK_ANY_PORT_NUM; - sock_io_mode = 0; - sock_is_sending = 0; - /* - memset(sock_remained_size, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t)); - memset(sock_pack_info, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint8_t)); - */ - -#if _WIZCHIP_ == 5200 - memset(sock_next_rd, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t)); -#endif -} - -int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag) -{ - CHECK_SOCKNUM(); - switch(protocol) - { - case Sn_MR_TCP : - case Sn_MR_UDP : - case Sn_MR_MACRAW : - break; - #if ( _WIZCHIP_ < 5200 ) - case Sn_MR_IPRAW : - case Sn_MR_PPPoE : - break; - #endif - default : - return SOCKERR_SOCKMODE; - } - if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG; -#if _WIZCHIP_ == 5200 - if(flag & 0x10) return SOCKERR_SOCKFLAG; -#endif - - if(flag != 0) - { - switch(protocol) - { - case Sn_MR_TCP: - if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG; - break; - case Sn_MR_UDP: - if(flag & SF_IGMP_VER2) - { - if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG; - } - #if _WIZCHIP_ == 5500 - if(flag & SF_UNI_BLOCK) - { - if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG; - } - #endif - break; - default: - break; - } - } - WIZCHIP_EXPORT(close)(sn); - setSn_MR(sn, (protocol | (flag & 0xF0))); - if(!port) - { - port = sock_any_port++; - if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM; - } - setSn_PORT(sn,port); - setSn_CR(sn,Sn_CR_OPEN); - while(getSn_CR(sn)); - sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn); - sock_is_sending &= ~(1< freesize) len = freesize; // check size not to exceed MAX size. - while(1) - { - freesize = getSn_TX_FSR(sn); - tmp = getSn_SR(sn); - if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT)) - { - WIZCHIP_EXPORT(close)(sn); - return SOCKERR_SOCKSTATUS; - } - if( (sock_io_mode & (1< freesize) ) return SOCK_BUSY; - if(len <= freesize) break; - MICROPY_THREAD_YIELD(); - } - wiz_send_data(sn, buf, len); - #if _WIZCHIP_ == 5200 - sock_next_rd[sn] = getSn_TX_RD(sn) + len; - #endif - setSn_CR(sn,Sn_CR_SEND); - /* wait to process the command... */ - while(getSn_CR(sn)); - sock_is_sending |= (1 << sn); - return len; -} - - -int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len) -{ - uint8_t tmp = 0; - uint16_t recvsize = 0; - CHECK_SOCKNUM(); - CHECK_SOCKMODE(Sn_MR_TCP); - CHECK_SOCKDATA(); - - recvsize = getSn_RxMAX(sn); - if(recvsize < len) len = recvsize; - while(1) - { - recvsize = getSn_RX_RSR(sn); - tmp = getSn_SR(sn); - if (tmp != SOCK_ESTABLISHED) - { - if(tmp == SOCK_CLOSE_WAIT) - { - if(recvsize != 0) break; - else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn)) - { - // dpgeorge: Getting here seems to be an orderly shutdown of the - // socket, and trying to get POSIX behaviour we return 0 because: - // "If no messages are available to be received and the peer has per‐ - // formed an orderly shutdown, recv() shall return 0". - // TODO this return value clashes with SOCK_BUSY in non-blocking mode. - WIZCHIP_EXPORT(close)(sn); - return 0; - } - } - else - { - WIZCHIP_EXPORT(close)(sn); - return SOCKERR_SOCKSTATUS; - } - } - if((sock_io_mode & (1< freesize) len = freesize; // check size not to exceed MAX size. - while(1) - { - freesize = getSn_TX_FSR(sn); - if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; - if( (sock_io_mode & (1< freesize) ) return SOCK_BUSY; - if(len <= freesize) break; - MICROPY_THREAD_YIELD(); - }; - wiz_send_data(sn, buf, len); - - #if _WIZCHIP_ == 5200 // for W5200 ARP errata - setSUBR(wizchip_getsubn()); - #endif - - setSn_CR(sn,Sn_CR_SEND); - /* wait to process the command... */ - while(getSn_CR(sn)); - while(1) - { - tmp = getSn_IR(sn); - if(tmp & Sn_IR_SENDOK) - { - setSn_IR(sn, Sn_IR_SENDOK); - break; - } - //M:20131104 - //else if(tmp & Sn_IR_TIMEOUT) return SOCKERR_TIMEOUT; - else if(tmp & Sn_IR_TIMEOUT) - { - setSn_IR(sn, Sn_IR_TIMEOUT); - #if _WIZCHIP_ == 5200 // for W5200 ARP errata - setSUBR((uint8_t*)"\x00\x00\x00\x00"); - #endif - return SOCKERR_TIMEOUT; - } - //////////// - MICROPY_THREAD_YIELD(); - } - #if _WIZCHIP_ == 5200 // for W5200 ARP errata - setSUBR((uint8_t*)"\x00\x00\x00\x00"); - #endif - return len; -} - - - -int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port) -{ - uint8_t mr; - uint8_t head[8]; - uint16_t pack_len=0; - - CHECK_SOCKNUM(); - //CHECK_SOCKMODE(Sn_MR_UDP); - switch((mr=getSn_MR(sn)) & 0x0F) - { - case Sn_MR_UDP: - case Sn_MR_MACRAW: - break; - #if ( _WIZCHIP_ < 5200 ) - case Sn_MR_IPRAW: - case Sn_MR_PPPoE: - break; - #endif - default: - return SOCKERR_SOCKMODE; - } - CHECK_SOCKDATA(); - if(sock_remained_size[sn] == 0) - { - while(1) - { - pack_len = getSn_RX_RSR(sn); - if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; - if( (sock_io_mode & (1< 1514) - { - WIZCHIP_EXPORT(close)(sn); - return SOCKFATAL_PACKLEN; - } - sock_pack_info[sn] = PACK_FIRST; - } - if(len < sock_remained_size[sn]) pack_len = len; - else pack_len = sock_remained_size[sn]; - wiz_recv_data(sn,buf,pack_len); - break; - #if ( _WIZCHIP_ < 5200 ) - case Sn_MR_IPRAW: - if(sock_remained_size[sn] == 0) - { - wiz_recv_data(sn, head, 6); - setSn_CR(sn,Sn_CR_RECV); - while(getSn_CR(sn)); - addr[0] = head[0]; - addr[1] = head[1]; - addr[2] = head[2]; - addr[3] = head[3]; - sock_remained_size[sn] = head[4]; - sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5]; - sock_pack_info[sn] = PACK_FIRST; - } - // - // Need to packet length check - // - if(len < sock_remained_size[sn]) pack_len = len; - else pack_len = sock_remained_size[sn]; - wiz_recv_data(sn, buf, pack_len); // data copy. - break; - #endif - default: - wiz_recv_ignore(sn, pack_len); // data copy. - sock_remained_size[sn] = pack_len; - break; - } - setSn_CR(sn,Sn_CR_RECV); - /* wait to process the command... */ - while(getSn_CR(sn)) ; - sock_remained_size[sn] -= pack_len; - //M20140501 : replace 0x01 with PACK_REMAINED - //if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= 0x01; - if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= PACK_REMAINED; - // - return pack_len; -} - - -int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg) -{ - uint8_t tmp = 0; - CHECK_SOCKNUM(); - switch(cstype) - { - case CS_SET_IOMODE: - tmp = *((uint8_t*)arg); - if(tmp == SOCK_IO_NONBLOCK) sock_io_mode |= (1< explict type casting - //*((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001; - *((uint8_t*)arg) = (uint8_t)((sock_io_mode >> sn) & 0x0001); - // - break; - case CS_GET_MAXTXBUF: - *((uint16_t*)arg) = getSn_TxMAX(sn); - break; - case CS_GET_MAXRXBUF: - *((uint16_t*)arg) = getSn_RxMAX(sn); - break; - case CS_CLR_INTERRUPT: - if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG; - setSn_IR(sn,*(uint8_t*)arg); - break; - case CS_GET_INTERRUPT: - *((uint8_t*)arg) = getSn_IR(sn); - break; - case CS_SET_INTMASK: - if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG; - setSn_IMR(sn,*(uint8_t*)arg); - break; - case CS_GET_INTMASK: - *((uint8_t*)arg) = getSn_IMR(sn); - default: - return SOCKERR_ARG; - } - return SOCK_OK; -} - -int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg) -{ - // M20131220 : Remove warning - //uint8_t tmp; - CHECK_SOCKNUM(); - switch(sotype) - { - case SO_TTL: - setSn_TTL(sn,*(uint8_t*)arg); - break; - case SO_TOS: - setSn_TOS(sn,*(uint8_t*)arg); - break; - case SO_MSS: - setSn_MSSR(sn,*(uint16_t*)arg); - break; - case SO_DESTIP: - setSn_DIPR(sn, (uint8_t*)arg); - break; - case SO_DESTPORT: - setSn_DPORT(sn, *(uint16_t*)arg); - break; -#if _WIZCHIP_ != 5100 - case SO_KEEPALIVESEND: - CHECK_SOCKMODE(Sn_MR_TCP); - #if _WIZCHIP_ > 5200 - if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT; - #endif - setSn_CR(sn,Sn_CR_SEND_KEEP); - while(getSn_CR(sn) != 0) - { - // M20131220 - //if ((tmp = getSn_IR(sn)) & Sn_IR_TIMEOUT) - if (getSn_IR(sn) & Sn_IR_TIMEOUT) - { - setSn_IR(sn, Sn_IR_TIMEOUT); - return SOCKERR_TIMEOUT; - } - } - break; - #if _WIZCHIP_ > 5200 - case SO_KEEPALIVEAUTO: - CHECK_SOCKMODE(Sn_MR_TCP); - setSn_KPALVTR(sn,*(uint8_t*)arg); - break; - #endif -#endif - default: - return SOCKERR_ARG; - } - return SOCK_OK; -} - -int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg) -{ - CHECK_SOCKNUM(); - switch(sotype) - { - case SO_FLAG: - *(uint8_t*)arg = getSn_MR(sn) & 0xF0; - break; - case SO_TTL: - *(uint8_t*) arg = getSn_TTL(sn); - break; - case SO_TOS: - *(uint8_t*) arg = getSn_TOS(sn); - break; - case SO_MSS: - *(uint8_t*) arg = getSn_MSSR(sn); - case SO_DESTIP: - getSn_DIPR(sn, (uint8_t*)arg); - break; - case SO_DESTPORT: - *(uint16_t*) arg = getSn_DPORT(sn); - break; - #if _WIZCHIP_ > 5200 - case SO_KEEPALIVEAUTO: - CHECK_SOCKMODE(Sn_MR_TCP); - *(uint16_t*) arg = getSn_KPALVTR(sn); - break; - #endif - case SO_SENDBUF: - *(uint16_t*) arg = getSn_TX_FSR(sn); - case SO_RECVBUF: - *(uint16_t*) arg = getSn_RX_RSR(sn); - case SO_STATUS: - *(uint8_t*) arg = getSn_SR(sn); - break; - case SO_REMAINSIZE: - if(getSn_MR(sn) == Sn_MR_TCP) - *(uint16_t*)arg = getSn_RX_RSR(sn); - else - *(uint16_t*)arg = sock_remained_size[sn]; - break; - case SO_PACKINFO: - CHECK_SOCKMODE(Sn_MR_TCP); - *(uint8_t*)arg = sock_pack_info[sn]; - break; - default: - return SOCKERR_SOCKOPT; - } - return SOCK_OK; -} diff --git a/drivers/wiznet5k/ethernet/socket.h b/drivers/wiznet5k/ethernet/socket.h deleted file mode 100644 index 2f03a34eba..0000000000 --- a/drivers/wiznet5k/ethernet/socket.h +++ /dev/null @@ -1,472 +0,0 @@ -//***************************************************************************** -// -//! \file socket.h -//! \brief SOCKET APIs Header file. -//! \details SOCKET APIs like as berkeley socket api. -//! \version 1.0.2 -//! \date 2013/10/21 -//! \par Revision history -//! <2014/05/01> V1.0.2. Refer to M20140501 -//! 1. Modify the comment : SO_REMAINED -> PACK_REMAINED -//! 2. Add the comment as zero byte udp data reception in getsockopt(). -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** -/** - * @defgroup WIZnet_socket_APIs 1. WIZnet socket APIs - * @brief WIZnet socket APIs are based on Berkeley socket APIs, thus it has much similar name and interface. - * But there is a little bit of difference. - * @details - * Comparison between WIZnet and Berkeley SOCKET APIs - * - * - * - * - * - * - * - * - * - * - * - * - *
API WIZnet Berkeley
socket() O O
bind() X O
listen() O O
connect() O O
accept() X O
recv() O O
send() O O
recvfrom() O O
sendto() O O
closesocket() O
close() & disconnect()
O
- * There are @b bind() and @b accept() functions in @b Berkeley SOCKET API but, - * not in @b WIZnet SOCKET API. Because socket() of WIZnet is not only creating a SOCKET but also binding a local port number, - * and listen() of WIZnet is not only listening to connection request from client but also accepting the connection request. \n - * When you program "TCP SERVER" with Berkeley SOCKET API, you can use only one listen port. - * When the listen SOCKET accepts a connection request from a client, it keeps listening. - * After accepting the connection request, a new SOCKET is created and the new SOCKET is used in communication with the client. \n - * Following figure shows network flow diagram by Berkeley SOCKET API. - * @image html Berkeley_SOCKET.jpg "" - * But, When you program "TCP SERVER" with WIZnet SOCKET API, you can use as many as 8 listen SOCKET with same port number. \n - * Because there's no accept() in WIZnet SOCKET APIs, when the listen SOCKET accepts a connection request from a client, - * it is changed in order to communicate with the client. - * And the changed SOCKET is not listening any more and is dedicated for communicating with the client. \n - * If there're many listen SOCKET with same listen port number and a client requests a connection, - * the SOCKET which has the smallest SOCKET number accepts the request and is changed as communication SOCKET. \n - * Following figure shows network flow diagram by WIZnet SOCKET API. - * @image html WIZnet_SOCKET.jpg "" - */ -#ifndef _WIZCHIP_SOCKET_H_ -#define _WIZCHIP_SOCKET_H_ - -// use this macro for exported names to avoid name clashes -#define WIZCHIP_EXPORT(name) wizchip_ ## name - -#include "wizchip_conf.h" - -#define SOCKET uint8_t ///< SOCKET type define for legacy driver - -#define SOCK_OK 1 ///< Result is OK about socket process. -#define SOCK_BUSY 0 ///< Socket is busy on processing the operation. Valid only Non-block IO Mode. -#define SOCK_FATAL -1000 ///< Result is fatal error about socket process. - -#define SOCK_ERROR 0 -#define SOCKERR_SOCKNUM (SOCK_ERROR - 1) ///< Invalid socket number -#define SOCKERR_SOCKOPT (SOCK_ERROR - 2) ///< Invalid socket option -#define SOCKERR_SOCKINIT (SOCK_ERROR - 3) ///< Socket is not initialized -#define SOCKERR_SOCKCLOSED (SOCK_ERROR - 4) ///< Socket unexpectedly closed. -#define SOCKERR_SOCKMODE (SOCK_ERROR - 5) ///< Invalid socket mode for socket operation. -#define SOCKERR_SOCKFLAG (SOCK_ERROR - 6) ///< Invalid socket flag -#define SOCKERR_SOCKSTATUS (SOCK_ERROR - 7) ///< Invalid socket status for socket operation. -#define SOCKERR_ARG (SOCK_ERROR - 10) ///< Invalid argument. -#define SOCKERR_PORTZERO (SOCK_ERROR - 11) ///< Port number is zero -#define SOCKERR_IPINVALID (SOCK_ERROR - 12) ///< Invalid IP address -#define SOCKERR_TIMEOUT (SOCK_ERROR - 13) ///< Timeout occurred -#define SOCKERR_DATALEN (SOCK_ERROR - 14) ///< Data length is zero or greater than buffer max size. -#define SOCKERR_BUFFER (SOCK_ERROR - 15) ///< Socket buffer is not enough for data communication. - -#define SOCKFATAL_PACKLEN (SOCK_FATAL - 1) ///< Invalid packet length. Fatal Error. - -/* - * SOCKET FLAG - */ -#define SF_ETHER_OWN (Sn_MR_MFEN) ///< In \ref Sn_MR_MACRAW, Receive only the packet as broadcast, multicast and own packet -#define SF_IGMP_VER2 (Sn_MR_MC) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE, Select IGMP version 2. -#define SF_TCP_NODELAY (Sn_MR_ND) ///< In \ref Sn_MR_TCP, Use to nodelayed ack. -#define SF_MULTI_ENABLE (Sn_MR_MULTI) ///< In \ref Sn_MR_UDP, Enable multicast mode. - -#if _WIZCHIP_ == 5500 - #define SF_BROAD_BLOCK (Sn_MR_BCASTB) ///< In \ref Sn_MR_UDP or \ref Sn_MR_MACRAW, Block broadcast packet. Valid only in W5500 - #define SF_MULTI_BLOCK (Sn_MR_MMB) ///< In \ref Sn_MR_MACRAW, Block multicast packet. Valid only in W5500 - #define SF_IPv6_BLOCK (Sn_MR_MIP6B) ///< In \ref Sn_MR_MACRAW, Block IPv6 packet. Valid only in W5500 - #define SF_UNI_BLOCK (Sn_MR_UCASTB) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE. Valid only in W5500 -#endif - -#define SF_IO_NONBLOCK 0x01 ///< Socket nonblock io mode. It used parameter in \ref socket(). - -/* - * UDP & MACRAW Packet Infomation - */ -#define PACK_FIRST 0x80 ///< In Non-TCP packet, It indicates to start receiving a packet. -#define PACK_REMAINED 0x01 ///< In Non-TCP packet, It indicates to remain a packet to be received. -#define PACK_COMPLETED 0x00 ///< In Non-TCP packet, It indicates to complete to receive a packet. - -// resets all global state associated with the socket interface -void WIZCHIP_EXPORT(socket_reset)(void); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Open a socket. - * @details Initializes the socket with 'sn' passed as parameter and open. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param protocol Protocol type to operate such as TCP, UDP and MACRAW. - * @param port Port number to be bined. - * @param flag Socket flags as \ref SF_ETHER_OWN, \ref SF_IGMP_VER2, \ref SF_TCP_NODELAY, \ref SF_MULTI_ENABLE, \ref SF_IO_NONBLOCK and so on.\n - * Valid flags only in W5500 : @ref SF_BROAD_BLOCK, @ref SF_MULTI_BLOCK, @ref SF_IPv6_BLOCK, and @ref SF_UNI_BLOCK. - * @sa Sn_MR - * - * @return @b Success : The socket number @b 'sn' passed as parameter\n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n - * @ref SOCKERR_SOCKMODE - Not support socket mode as TCP, UDP, and so on. \n - * @ref SOCKERR_SOCKFLAG - Invaild socket flag. - */ -int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Close a socket. - * @details It closes the socket with @b'sn' passed as parameter. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * - * @return @b Success : @ref SOCK_OK \n - * @b Fail : @ref SOCKERR_SOCKNUM - Invalid socket number - */ -int8_t WIZCHIP_EXPORT(close)(uint8_t sn); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Listen to a connection request from a client. - * @details It is listening to a connection request from a client. - * If connection request is accepted successfully, the connection is established. Socket sn is used in passive(server) mode. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @return @b Success : @ref SOCK_OK \n - * @b Fail :\n @ref SOCKERR_SOCKINIT - Socket is not initialized \n - * @ref SOCKERR_SOCKCLOSED - Socket closed unexpectedly. - */ -int8_t WIZCHIP_EXPORT(listen)(uint8_t sn); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Try to connect a server. - * @details It requests connection to the server with destination IP address and port number passed as parameter.\n - * @note It is valid only in TCP client mode. - * In block io mode, it does not return until connection is completed. - * In Non-block io mode, it return @ref SOCK_BUSY immediately. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. - * @param port Destination port number. - * - * @return @b Success : @ref SOCK_OK \n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n - * @ref SOCKERR_SOCKMODE - Invalid socket mode\n - * @ref SOCKERR_SOCKINIT - Socket is not initialized\n - * @ref SOCKERR_IPINVALID - Wrong server IP address\n - * @ref SOCKERR_PORTZERO - Server port zero\n - * @ref SOCKERR_TIMEOUT - Timeout occurred during request connection\n - * @ref SOCK_BUSY - In non-block io mode, it returned immediately\n - */ -int8_t WIZCHIP_EXPORT(connect)(uint8_t sn, uint8_t * addr, uint16_t port); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Try to disconnect a connection socket. - * @details It sends request message to disconnect the TCP socket 'sn' passed as parameter to the server or client. - * @note It is valid only in TCP server or client mode. \n - * In block io mode, it does not return until disconnection is completed. \n - * In Non-block io mode, it return @ref SOCK_BUSY immediately. \n - - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @return @b Success : @ref SOCK_OK \n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_TIMEOUT - Timeout occurred \n - * @ref SOCK_BUSY - Socket is busy. - */ -int8_t WIZCHIP_EXPORT(disconnect)(uint8_t sn); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Send data to the connected peer in TCP socket. - * @details It is used to send outgoing data to the connected socket. - * @note It is valid only in TCP server or client mode. It can't send data greater than socket buffer size. \n - * In block io mode, It doesn't return until data send is completed - socket buffer size is greater than data. \n - * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. \n - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param buf Pointer buffer containing data to be sent. - * @param len The byte length of data in buf. - * @return @b Success : The sent data size \n - * @b Fail : \n @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n - * @ref SOCKERR_TIMEOUT - Timeout occurred \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCK_BUSY - Socket is busy. - */ -int32_t WIZCHIP_EXPORT(send)(uint8_t sn, uint8_t * buf, uint16_t len); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Receive data from the connected peer. - * @details It is used to read incoming data from the connected socket.\n - * It waits for data as much as the application wants to receive. - * @note It is valid only in TCP server or client mode. It can't receive data greater than socket buffer size. \n - * In block io mode, it doesn't return until data reception is completed - data is filled as len in socket buffer. \n - * In non-block io mode, it return @ref SOCK_BUSY immediately when len is greater than data size in socket buffer. \n - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param buf Pointer buffer to read incoming data. - * @param len The max data length of data in buf. - * @return @b Success : The real received data size \n - * @b Fail :\n - * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCK_BUSY - Socket is busy. - */ -int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Sends datagram to the peer with destination IP address and port number passed as parameter. - * @details It sends datagram of UDP or MACRAW to the peer with destination IP address and port number passed as parameter.\n - * Even if the connectionless socket has been previously connected to a specific address, - * the address and port number parameters override the destination address for that particular datagram only. - * @note In block io mode, It doesn't return until data send is completed - socket buffer size is greater than len. - * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param buf Pointer buffer to send outgoing data. - * @param len The byte length of data in buf. - * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. - * @param port Destination port number. - * - * @return @b Success : The sent data size \n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n - * @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCKERR_IPINVALID - Wrong server IP address\n - * @ref SOCKERR_PORTZERO - Server port zero\n - * @ref SOCKERR_SOCKCLOSED - Socket unexpectedly closed \n - * @ref SOCKERR_TIMEOUT - Timeout occurred \n - * @ref SOCK_BUSY - Socket is busy. - */ -int32_t WIZCHIP_EXPORT(sendto)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Receive datagram of UDP or MACRAW - * @details This function is an application I/F function which is used to receive the data in other then TCP mode. \n - * This function is used to receive UDP and MAC_RAW mode, and handle the header as well. - * This function can divide to received the packet data. - * On the MACRAW SOCKET, the addr and port parameters are ignored. - * @note In block io mode, it doesn't return until data reception is completed - data is filled as len in socket buffer - * In non-block io mode, it return @ref SOCK_BUSY immediately when len is greater than data size in socket buffer. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param buf Pointer buffer to read incoming data. - * @param len The max data length of data in buf. - * When the received packet size <= len, receives data as packet sized. - * When others, receives data as len. - * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. - * It is valid only when the first call recvfrom for receiving the packet. - * When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo). - * @param port Pointer variable of destination port number. - * It is valid only when the first call recvform for receiving the packet. -* When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo). - * - * @return @b Success : This function return real received data size for success.\n - * @b Fail : @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKBUSY - Socket is busy. - */ -int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); - - -///////////////////////////// -// SOCKET CONTROL & OPTION // -///////////////////////////// -#define SOCK_IO_BLOCK 0 ///< Socket Block IO Mode in @ref setsockopt(). -#define SOCK_IO_NONBLOCK 1 ///< Socket Non-block IO Mode in @ref setsockopt(). - -/** - * @defgroup DATA_TYPE DATA TYPE - */ - -/** - * @ingroup DATA_TYPE - * @brief The kind of Socket Interrupt. - * @sa Sn_IR, Sn_IMR, setSn_IR(), getSn_IR(), setSn_IMR(), getSn_IMR() - */ -typedef enum -{ - SIK_CONNECTED = (1 << 0), ///< connected - SIK_DISCONNECTED = (1 << 1), ///< disconnected - SIK_RECEIVED = (1 << 2), ///< data received - SIK_TIMEOUT = (1 << 3), ///< timeout occurred - SIK_SENT = (1 << 4), ///< send ok - SIK_ALL = 0x1F, ///< all interrupt -}sockint_kind; - -/** - * @ingroup DATA_TYPE - * @brief The type of @ref ctlsocket(). - */ -typedef enum -{ - CS_SET_IOMODE, ///< set socket IO mode with @ref SOCK_IO_BLOCK or @ref SOCK_IO_NONBLOCK - CS_GET_IOMODE, ///< get socket IO mode - CS_GET_MAXTXBUF, ///< get the size of socket buffer allocated in TX memory - CS_GET_MAXRXBUF, ///< get the size of socket buffer allocated in RX memory - CS_CLR_INTERRUPT, ///< clear the interrupt of socket with @ref sockint_kind - CS_GET_INTERRUPT, ///< get the socket interrupt. refer to @ref sockint_kind - CS_SET_INTMASK, ///< set the interrupt mask of socket with @ref sockint_kind - CS_GET_INTMASK ///< get the masked interrupt of socket. refer to @ref sockint_kind -}ctlsock_type; - - -/** - * @ingroup DATA_TYPE - * @brief The type of socket option in @ref setsockopt() or @ref getsockopt() - */ -typedef enum -{ - SO_FLAG, ///< Valid only in getsockopt(), For set flag of socket refer to flag in @ref socket(). - SO_TTL, ///< Set/Get TTL. @ref Sn_TTL ( @ref setSn_TTL(), @ref getSn_TTL() ) - SO_TOS, ///< Set/Get TOS. @ref Sn_TOS ( @ref setSn_TOS(), @ref getSn_TOS() ) - SO_MSS, ///< Set/Get MSS. @ref Sn_MSSR ( @ref setSn_MSSR(), @ref getSn_MSSR() ) - SO_DESTIP, ///< Set/Get the destination IP address. @ref Sn_DIPR ( @ref setSn_DIPR(), @ref getSn_DIPR() ) - SO_DESTPORT, ///< Set/Get the destination Port number. @ref Sn_DPORT ( @ref setSn_DPORT(), @ref getSn_DPORT() ) -#if _WIZCHIP_ != 5100 - SO_KEEPALIVESEND, ///< Valid only in setsockopt. Manually send keep-alive packet in TCP mode - #if _WIZCHIP_ > 5200 - SO_KEEPALIVEAUTO, ///< Set/Get keep-alive auto transmission timer in TCP mode - #endif -#endif - SO_SENDBUF, ///< Valid only in getsockopt. Get the free data size of Socekt TX buffer. @ref Sn_TX_FSR, @ref getSn_TX_FSR() - SO_RECVBUF, ///< Valid only in getsockopt. Get the received data size in socket RX buffer. @ref Sn_RX_RSR, @ref getSn_RX_RSR() - SO_STATUS, ///< Valid only in getsockopt. Get the socket status. @ref Sn_SR, @ref getSn_SR() - SO_REMAINSIZE, ///< Valid only in getsockopt. Get the remained packet size in other then TCP mode. - SO_PACKINFO ///< Valid only in getsockopt. Get the packet information as @ref PACK_FIRST, @ref PACK_REMAINED, and @ref PACK_COMPLETED in other then TCP mode. -}sockopt_type; - -/** - * @ingroup WIZnet_socket_APIs - * @brief Control socket. - * @details Control IO mode, Interrupt & Mask of socket and get the socket buffer information. - * Refer to @ref ctlsock_type. - * @param sn socket number - * @param cstype type of control socket. refer to @ref ctlsock_type. - * @param arg Data type and value is determined according to @ref ctlsock_type. \n - * - * - * - * - * - *
@b cstype @b data type@b value
@ref CS_SET_IOMODE \n @ref CS_GET_IOMODE uint8_t @ref SOCK_IO_BLOCK @ref SOCK_IO_NONBLOCK
@ref CS_GET_MAXTXBUF \n @ref CS_GET_MAXRXBUF uint16_t 0 ~ 16K
@ref CS_CLR_INTERRUPT \n @ref CS_GET_INTERRUPT \n @ref CS_SET_INTMASK \n @ref CS_GET_INTMASK @ref sockint_kind @ref SIK_CONNECTED, etc.
- * @return @b Success @ref SOCK_OK \n - * @b fail @ref SOCKERR_ARG - Invalid argument\n - */ -int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg); - -/** - * @ingroup WIZnet_socket_APIs - * @brief set socket options - * @details Set socket option like as TTL, MSS, TOS, and so on. Refer to @ref sockopt_type. - * - * @param sn socket number - * @param sotype socket option type. refer to @ref sockopt_type - * @param arg Data type and value is determined according to sotype. \n - * - * - * - * - * - * - * - * - * - *
@b sotype @b data type@b value
@ref SO_TTL uint8_t 0 ~ 255
@ref SO_TOS uint8_t 0 ~ 255
@ref SO_MSS uint16_t 0 ~ 65535
@ref SO_DESTIP uint8_t[4]
@ref SO_DESTPORT uint16_t 0 ~ 65535
@ref SO_KEEPALIVESEND null null
@ref SO_KEEPALIVEAUTO uint8_t 0 ~ 255
- * @return - * - @b Success : @ref SOCK_OK \n - * - @b Fail - * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n - * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n - * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n - * - @ref SOCKERR_TIMEOUT - Timeout occurred when sending keep-alive packet \n - */ -int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg); - -/** - * @ingroup WIZnet_socket_APIs - * @brief get socket options - * @details Get socket option like as FLAG, TTL, MSS, and so on. Refer to @ref sockopt_type - * @param sn socket number - * @param sotype socket option type. refer to @ref sockopt_type - * @param arg Data type and value is determined according to sotype. \n - * - * - * - * - * - * - * - * - * - * - * - * - * - *
@b sotype @b data type@b value
@ref SO_FLAG uint8_t @ref SF_ETHER_OWN, etc...
@ref SO_TOS uint8_t 0 ~ 255
@ref SO_MSS uint16_t 0 ~ 65535
@ref SO_DESTIP uint8_t[4]
@ref SO_DESTPORT uint16_t
@ref SO_KEEPALIVEAUTO uint8_t 0 ~ 255
@ref SO_SENDBUF uint16_t 0 ~ 65535
@ref SO_RECVBUF uint16_t 0 ~ 65535
@ref SO_STATUS uint8_t @ref SOCK_ESTABLISHED, etc..
@ref SO_REMAINSIZE uint16_t 0~ 65535
@ref SO_PACKINFO uint8_t @ref PACK_FIRST, etc...
- * @return - * - @b Success : @ref SOCK_OK \n - * - @b Fail - * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n - * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n - * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n - * @note - * The option as PACK_REMAINED and SO_PACKINFO is valid only in NON-TCP mode and after call @ref recvfrom(). \n - * When SO_PACKINFO value is PACK_FIRST and the return value of recvfrom() is zero, - * This means the zero byte UDP data(UDP Header only) received. - */ -int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg); - -#endif // _WIZCHIP_SOCKET_H_ diff --git a/drivers/wiznet5k/ethernet/w5200/w5200.c b/drivers/wiznet5k/ethernet/w5200/w5200.c deleted file mode 100644 index a84d3c9fa7..0000000000 --- a/drivers/wiznet5k/ethernet/w5200/w5200.c +++ /dev/null @@ -1,215 +0,0 @@ -// dpgeorge: this file taken from w5500/w5500.c and adapted to W5200 - -//***************************************************************************** -// -//! \file w5500.c -//! \brief W5500 HAL Interface. -//! \version 1.0.1 -//! \date 2013/10/21 -//! \par Revision history -//! <2014/05/01> V1.0.2 -//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501 -//! Fixed the problem on porting into under 32bit MCU -//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh -//! Thank for your interesting and serious advices. -//! <2013/10/21> 1st Release -//! <2013/12/20> V1.0.1 -//! 1. Remove warning -//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_ -//! for loop optimized(removed). refer to M20131220 -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#include "w5200.h" - -#if WIZCHIP_USE_MAX_BUFFER -// This option is intended to be used when MACRAW mode is enabled, to allow -// the single raw socket to use all the available buffer space. -#define SMASK (16 * 1024 - 1) /* tx buffer mask */ -#define RMASK (16 * 1024 - 1) /* rx buffer mask */ -#define SSIZE (16 * 1024) /* max tx buffer size */ -#define RSIZE (16 * 1024) /* max rx buffer size */ -#else -#define SMASK (0x7ff) /* tx buffer mask */ -#define RMASK (0x7ff) /* rx buffer mask */ -#define SSIZE (2048) /* max tx buffer size */ -#define RSIZE (2048) /* max rx buffer size */ -#endif - -#define TXBUF_BASE (0x8000) -#define RXBUF_BASE (0xc000) -#define SBASE(sn) (TXBUF_BASE + SSIZE * (sn)) /* tx buffer base for socket sn */ -#define RBASE(sn) (RXBUF_BASE + RSIZE * (sn)) /* rx buffer base for socket sn */ - -uint8_t WIZCHIP_READ(uint32_t AddrSel) { - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - uint8_t spi_data[4] = { - AddrSel >> 8, - AddrSel, - 0x00, - 0x01, - }; - WIZCHIP.IF.SPI._write_bytes(spi_data, 4); - uint8_t ret; - WIZCHIP.IF.SPI._read_bytes(&ret, 1); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); - - return ret; -} - -void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb) { - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - uint8_t spi_data[5] = { - AddrSel >> 8, - AddrSel, - 0x80, - 0x01, - wb, - }; - WIZCHIP.IF.SPI._write_bytes(spi_data, 5); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - -void WIZCHIP_READ_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) { - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - uint8_t spi_data[4] = { - AddrSel >> 8, - AddrSel, - 0x00 | ((len >> 8) & 0x7f), - len & 0xff, - }; - WIZCHIP.IF.SPI._write_bytes(spi_data, 4); - WIZCHIP.IF.SPI._read_bytes(pBuf, len); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - -void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) { - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - uint8_t spi_data[4] = { - AddrSel >> 8, - AddrSel, - 0x80 | ((len >> 8) & 0x7f), - len & 0xff, - }; - WIZCHIP.IF.SPI._write_bytes(spi_data, 4); - WIZCHIP.IF.SPI._write_bytes(pBuf, len); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - -uint16_t getSn_TX_FSR(uint8_t sn) { - uint16_t val = 0, val1 = 0; - do { - val1 = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1); - if (val1 != 0) { - val = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1); - } - } while (val != val1); - return val; -} - -uint16_t getSn_RX_RSR(uint8_t sn) { - uint16_t val = 0, val1 = 0; - do { - val1 = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1); - if (val1 != 0) { - val = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1); - } - } while (val != val1); - return val; -} - -void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) { - if (len == 0) { - return; - } - - uint16_t ptr = getSn_TX_WR(sn); - uint16_t offset = ptr & SMASK; - uint32_t addr = offset + SBASE(sn); - - if (offset + len > SSIZE) { - // implement wrap-around circular buffer - uint16_t size = SSIZE - offset; - WIZCHIP_WRITE_BUF(addr, wizdata, size); - WIZCHIP_WRITE_BUF(SBASE(sn), wizdata + size, len - size); - } else { - WIZCHIP_WRITE_BUF(addr, wizdata, len); - } - - ptr += len; - setSn_TX_WR(sn, ptr); -} - -void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) { - if (len == 0) { - return; - } - - uint16_t ptr = getSn_RX_RD(sn); - uint16_t offset = ptr & RMASK; - uint16_t addr = RBASE(sn) + offset; - - if (offset + len > RSIZE) { - // implement wrap-around circular buffer - uint16_t size = RSIZE - offset; - WIZCHIP_READ_BUF(addr, wizdata, size); - WIZCHIP_READ_BUF(RBASE(sn), wizdata + size, len - size); - } else { - WIZCHIP_READ_BUF(addr, wizdata, len); - } - - ptr += len; - setSn_RX_RD(sn, ptr); -} - -void wiz_recv_ignore(uint8_t sn, uint16_t len) { - uint16_t ptr = getSn_RX_RD(sn); - ptr += len; - setSn_RX_RD(sn, ptr); -} diff --git a/drivers/wiznet5k/ethernet/w5200/w5200.h b/drivers/wiznet5k/ethernet/w5200/w5200.h deleted file mode 100644 index 63561940f8..0000000000 --- a/drivers/wiznet5k/ethernet/w5200/w5200.h +++ /dev/null @@ -1,2092 +0,0 @@ -// dpgeorge: this file taken from w5500/w5500.h and adapted to W5200 - -//***************************************************************************** -// -//! \file w5500.h -//! \brief W5500 HAL Header File. -//! \version 1.0.0 -//! \date 2013/10/21 -//! \par Revision history -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#ifndef _W5200_H_ -#define _W5200_H_ - -#include -#include "../wizchip_conf.h" -//#include "board.h" - -#define _W5200_IO_BASE_ 0x00000000 - -#define WIZCHIP_CREG_ADDR(addr) (_W5200_IO_BASE_ + (addr)) - -#define WIZCHIP_CH_BASE (0x4000) -#define WIZCHIP_CH_SIZE (0x100) -#define WIZCHIP_SREG_ADDR(sn, addr) (_W5200_IO_BASE_ + WIZCHIP_CH_BASE + (sn) * WIZCHIP_CH_SIZE + (addr)) - -////////////////////////////// -//-------------------------- defgroup --------------------------------- -/** - * @defgroup W5500 W5500 - * - * @brief WHIZCHIP register defines and I/O functions of @b W5500. - * - * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group - * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function - */ - - -/** - * @defgroup WIZCHIP_register WIZCHIP register - * @ingroup W5500 - * - * @brief WHIZCHIP register defines register group of @b W5500. - * - * - @ref Common_register_group : Common register group - * - @ref Socket_register_group : \c SOCKET n register group - */ - - -/** - * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions - * @ingroup W5500 - * - * @brief This supports the basic I/O functions for @ref WIZCHIP_register. - * - * - Basic I/O function \n - * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n - * - * - @ref Common_register_group access functions \n - * -# @b Mode \n - * getMR(), setMR() - * -# @b Interrupt \n - * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL() - * -# Network Information \n - * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR() - * -# @b Retransmission \n - * getRCR(), setRCR(), getRTR(), setRTR() - * -# @b PPPoE \n - * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU() - * -# ICMP packet \n - * getUIPR(), getUPORTR() - * -# @b etc. \n - * getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n - * - * - \ref Socket_register_group access functions \n - * -# SOCKET control \n - * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR() - * -# SOCKET information \n - * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT() - * getSn_MSSR(), setSn_MSSR() - * -# SOCKET communication \n - * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n - * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n - * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n - * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR() - * -# IP header field \n - * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n - * getSn_TTL(), setSn_TTL() - */ - - - -/** - * @defgroup Common_register_group Common register - * @ingroup WIZCHIP_register - * - * @brief Common register group\n - * It set the basic for the networking\n - * It set the configuration such as interrupt, network information, ICMP, etc. - * @details - * @sa MR : Mode register. - * @sa GAR, SUBR, SHAR, SIPR - * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt. - * @sa RTR, RCR : Data retransmission. - * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE. - * @sa UIPR, UPORTR : ICMP message. - * @sa PHYCFGR, VERSIONR : etc. - */ - - - -/** - * @defgroup Socket_register_group Socket register - * @ingroup WIZCHIP_register - * - * @brief Socket register group.\n - * Socket register configures and control SOCKETn which is necessary to data communication. - * @details - * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control - * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information - * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol. - * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication - */ - - - - /** - * @defgroup Basic_IO_function Basic I/O function - * @ingroup WIZCHIP_IO_Functions - * @brief These are basic input/output functions to read values from register or write values to register. - */ - -/** - * @defgroup Common_register_access_function Common register access functions - * @ingroup WIZCHIP_IO_Functions - * @brief These are functions to access common registers. - */ - -/** - * @defgroup Socket_register_access_function Socket register access functions - * @ingroup WIZCHIP_IO_Functions - * @brief These are functions to access socket registers. - */ - -//------------------------------- defgroup end -------------------------------------------- -//----------------------------- W5500 Common Registers IOMAP ----------------------------- -/** - * @ingroup Common_register_group - * @brief Mode Register address(R/W)\n - * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc. - * @details Each bit of @ref MR defined as follows. - * - * - * - *
7 6 5 4 3 2 1 0
RST Reserved WOL PB PPPoE Reserved FARP Reserved
- * - \ref MR_RST : Reset - * - \ref MR_WOL : Wake on LAN - * - \ref MR_PB : Ping block - * - \ref MR_PPPOE : PPPoE mode - * - \ref MR_FARP : Force ARP mode - */ -#define MR WIZCHIP_CREG_ADDR(0x0000) - -/** - * @ingroup Common_register_group - * @brief Gateway IP Register address(R/W) - * @details @ref GAR configures the default gateway address. - */ -#define GAR WIZCHIP_CREG_ADDR(0x0001) - -/** - * @ingroup Common_register_group - * @brief Subnet mask Register address(R/W) - * @details @ref SUBR configures the subnet mask address. - */ -#define SUBR WIZCHIP_CREG_ADDR(0x0005) - -/** - * @ingroup Common_register_group - * @brief Source MAC Register address(R/W) - * @details @ref SHAR configures the source hardware address. - */ -#define SHAR WIZCHIP_CREG_ADDR(0x0009) - -/** - * @ingroup Common_register_group - * @brief Source IP Register address(R/W) - * @details @ref SIPR configures the source IP address. - */ -#define SIPR WIZCHIP_CREG_ADDR(0x000f) - -/** - * @ingroup Common_register_group - * @brief Set Interrupt low level timer register address(R/W) - * @details @ref INTLEVEL configures the Interrupt Assert Time. - */ -//#define INTLEVEL (_W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Interrupt Register(R/W) - * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host. - * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n - * Each bit of @ref IR defined as follows. - * - * - * - *
7 6 5 4 3 2 1 0
CONFLICT UNREACH PPPoE MP Reserved Reserved Reserved Reserved
- * - \ref IR_CONFLICT : IP conflict - * - \ref IR_UNREACH : Destination unreachable - * - \ref IR_PPPoE : PPPoE connection close - * - \ref IR_MP : Magic packet - */ -#define IR WIZCHIP_CREG_ADDR(0x0015) - -/** - * @ingroup Common_register_group - * @brief Interrupt mask register(R/W) - * @details @ref IMR is used to mask interrupts. Each bit of @ref IMR corresponds to each bit of @ref IR. - * When a bit of @ref IMR is and the corresponding bit of @ref IR is an interrupt will be issued. In other words, - * if a bit of @ref IMR is an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n - * Each bit of @ref IMR defined as the following. - * - * - * - *
7 6 5 4 3 2 1 0
IM_IR7 IM_IR6 IM_IR5 IM_IR4 Reserved Reserved Reserved Reserved
- * - \ref IM_IR7 : IP Conflict Interrupt Mask - * - \ref IM_IR6 : Destination unreachable Interrupt Mask - * - \ref IM_IR5 : PPPoE Close Interrupt Mask - * - \ref IM_IR4 : Magic Packet Interrupt Mask - */ -#define IMR WIZCHIP_CREG_ADDR(0x0016) - -/** - * @ingroup Common_register_group - * @brief Socket Interrupt Register(R/W) - * @details @ref SIR indicates the interrupt status of Socket.\n - * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n - * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */ -//#define SIR (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Socket Interrupt Mask Register(R/W) - * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR. - * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is Interrupt will be issued. - * In other words, if a bit of @ref SIMR is an interrupt will be not issued even if the corresponding bit of @ref SIR is - */ -//#define SIMR (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Timeout register address( 1 is 100us )(R/W) - * @details @ref RTR configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref RTR is x07D0or 000 - * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref RTR, W5500 waits for the peer response - * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). - * If the peer does not respond within the @ref RTR time, W5500 retransmits the packet or issues timeout. - */ -#define RTR WIZCHIP_CREG_ADDR(0x0017) - -/** - * @ingroup Common_register_group - * @brief Retry count register(R/W) - * @details @ref RCR configures the number of time of retransmission. - * When retransmission occurs as many as ref RCR+1 Timeout interrupt is issued (@ref Sn_IR[TIMEOUT] = . - */ -#define RCR WIZCHIP_CREG_ADDR(0x0019) - -/** - * @ingroup Common_register_group - * @brief PPP LCP Request Timer register in PPPoE mode(R/W) - * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms. - */ -#define PTIMER WIZCHIP_CREG_ADDR(0x0028) - -/** - * @ingroup Common_register_group - * @brief PPP LCP Magic number register in PPPoE mode(R/W) - * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation. - */ -#define PMAGIC WIZCHIP_CREG_ADDR(0x0029) - -/** - * @ingroup Common_register_group - * @brief PPP Destination MAC Register address(R/W) - * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process. - */ -//#define PHAR (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP Session Identification Register(R/W) - * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process. - */ -//#define PSID (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP Maximum Segment Size(MSS) register(R/W) - * @details @ref PMRU configures the maximum receive unit of PPPoE. - */ -//#define PMRU (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Unreachable IP register address in UDP mode(R) - * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number - * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates - * the destination IP address & port number respectively. - */ -//#define UIPR (_W5500_IO_BASE_ + (0x002a << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Unreachable Port register address in UDP mode(R) - * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number - * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR - * indicates the destination IP address & port number respectively. - */ -//#define UPORTR (_W5500_IO_BASE_ + (0x002e << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PHY Status Register(R/W) - * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link. - */ -//#define PHYCFGR (_W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3)) -#define PHYSTATUS WIZCHIP_CREG_ADDR(0x0035) - -// Reserved (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief chip version register address(R) - * @details @ref VERSIONR always indicates the W5500 version as @b 0x04. - */ -//#define VERSIONR (_W5200_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - - -//----------------------------- W5500 Socket Registers IOMAP ----------------------------- -/** - * @ingroup Socket_register_group - * @brief socket Mode register(R/W) - * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n - * Each bit of @ref Sn_MR defined as the following. - * - * - * - *
7 6 5 4 3 2 1 0
MULTI/MFEN BCASTB ND/MC/MMB UCASTB/MIP6B Protocol[3] Protocol[2] Protocol[1] Protocol[0]
- * - @ref Sn_MR_MULTI : Support UDP Multicasting - * - @ref Sn_MR_BCASTB : Broadcast block in UDP Multicasting - * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag - * - @ref Sn_MR_MC : IGMP version used in UDP mulitcasting - * - @ref Sn_MR_MMB : Multicast Blocking in @ref Sn_MR_MACRAW mode - * - @ref Sn_MR_UCASTB : Unicast Block in UDP Multicating - * - @ref Sn_MR_MIP6B : IPv6 packet Blocking in @ref Sn_MR_MACRAW mode - * - Protocol - * - * - * - * - * - * - *
Protocol[3] Protocol[2] Protocol[1] Protocol[0] @b Meaning
0 0 0 0 Closed
0 0 0 1 TCP
0 0 1 0 UDP
0 1 0 0 MACRAW
- * - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n - * - @ref Sn_MR_UDP : UDP - * - @ref Sn_MR_TCP : TCP - * - @ref Sn_MR_CLOSE : Unused socket - * @note MACRAW mode should be only used in Socket 0. - */ -#define Sn_MR(N) WIZCHIP_SREG_ADDR(N, 0x0000) - -/** - * @ingroup Socket_register_group - * @brief Socket command register(R/W) - * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n - * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00. - * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n - * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR. - * - @ref Sn_CR_OPEN : Initialize or open socket. - * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode) - * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode) - * - @ref Sn_CR_DISCON : Send closing request in TCP mode. - * - @ref Sn_CR_CLOSE : Close socket. - * - @ref Sn_CR_SEND : Update TX buffer pointer and send data. - * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process. - * - @ref Sn_CR_SEND_KEEP : Send keep alive message. - * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data. - */ -#define Sn_CR(N) WIZCHIP_SREG_ADDR(N, 0x0001) - -/** - * @ingroup Socket_register_group - * @brief Socket interrupt register(R) - * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n - * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n - * In order to clear the @ref Sn_IR bit, the host should write the bit to \n - * - * - * - *
7 6 5 4 3 2 1 0
Reserved Reserved Reserved SEND_OK TIMEOUT RECV DISCON CON
- * - \ref Sn_IR_SENDOK : SEND_OK Interrupt - * - \ref Sn_IR_TIMEOUT : TIMEOUT Interrupt - * - \ref Sn_IR_RECV : RECV Interrupt - * - \ref Sn_IR_DISCON : DISCON Interrupt - * - \ref Sn_IR_CON : CON Interrupt - */ -#define Sn_IR(N) WIZCHIP_SREG_ADDR(N, 0x0002) - -/** - * @ingroup Socket_register_group - * @brief Socket status register(R) - * @details @ref Sn_SR indicates the status of Socket n.\n - * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP. - * @par Normal status - * - @ref SOCK_CLOSED : Closed - * - @ref SOCK_INIT : Initiate state - * - @ref SOCK_LISTEN : Listen state - * - @ref SOCK_ESTABLISHED : Success to connect - * - @ref SOCK_CLOSE_WAIT : Closing state - * - @ref SOCK_UDP : UDP socket - * - @ref SOCK_MACRAW : MAC raw mode socket - *@par Temporary status during changing the status of Socket n. - * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer. - * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer. - * - @ref SOCK_FIN_WAIT : Connection state - * - @ref SOCK_CLOSING : Closing state - * - @ref SOCK_TIME_WAIT : Closing state - * - @ref SOCK_LAST_ACK : Closing state - */ -#define Sn_SR(N) WIZCHIP_SREG_ADDR(N, 0x0003) - -/** - * @ingroup Socket_register_group - * @brief source port register(R/W) - * @details @ref Sn_PORT configures the source port number of Socket n. - * It is valid when Socket n is used in TCP/UPD mode. It should be set before OPEN command is ordered. - */ -#define Sn_PORT(N) WIZCHIP_SREG_ADDR(N, 0x0004) - -/** - * @ingroup Socket_register_group - * @brief Peer MAC register address(R/W) - * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or - * it indicates that it is acquired in ARP-process by CONNECT/SEND command. - */ -#define Sn_DHAR(N) WIZCHIP_SREG_ADDR(N, 0x0006) - -/** - * @ingroup Socket_register_group - * @brief Peer IP register address(R/W) - * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode. - * In TCP client mode, it configures an IP address of �TCP serverbefore CONNECT command. - * In TCP server mode, it indicates an IP address of �TCP clientafter successfully establishing connection. - * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command. - */ -#define Sn_DIPR(N) WIZCHIP_SREG_ADDR(N, 0x000c) - -/** - * @ingroup Socket_register_group - * @brief Peer port register address(R/W) - * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode. - * In �TCP clientmode, it configures the listen port number of �TCP serverbefore CONNECT command. - * In �TCP Servermode, it indicates the port number of TCP client after successfully establishing connection. - * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command. - */ -#define Sn_DPORT(N) WIZCHIP_SREG_ADDR(N, 0x0010) - -/** - * @ingroup Socket_register_group - * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W) - * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n. - */ -#define Sn_MSSR(N) WIZCHIP_SREG_ADDR(N, 0x0012) - -// Reserved (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief IP Type of Service(TOS) Register(R/W) - * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n. - * It is set before OPEN command. - */ -#define Sn_TOS(N) WIZCHIP_SREG_ADDR(N, 0x0015) -/** - * @ingroup Socket_register_group - * @brief IP Time to live(TTL) Register(R/W) - * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n. - * It is set before OPEN command. - */ -#define Sn_TTL(N) WIZCHIP_SREG_ADDR(N, 0x0016) -// Reserved (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Receive memory size register(R/W) - * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n. - * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. - * If a different size is configured, the data cannot be normally received from a peer. - * Although Socket n RX Buffer Block size is initially configured to 2Kbytes, - * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes. - * When exceeded, the data reception error is occurred. - */ -#define Sn_RXBUF_SIZE(N) WIZCHIP_SREG_ADDR(N, 0x001e) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory size register(R/W) - * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. - * If a different size is configured, the data can�t be normally transmitted to a peer. - * Although Socket n TX Buffer Block size is initially configured to 2Kbytes, - * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes. - * When exceeded, the data transmission error is occurred. - */ -#define Sn_TXBUF_SIZE(N) WIZCHIP_SREG_ADDR(N, 0x001f) - -/** - * @ingroup Socket_register_group - * @brief Transmit free memory size register(R) - * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE. - * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent. - * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size, - * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size, - * transmit the data after dividing into the checked size and saving in the Socket n TX buffer. - */ -#define Sn_TX_FSR(N) WIZCHIP_SREG_ADDR(N, 0x0020) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory read pointer register address(R) - * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP. - * After its initialization, it is auto-increased by SEND command. - * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer. - * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR. - * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value. - */ -#define Sn_TX_RD(N) WIZCHIP_SREG_ADDR(N, 0x0022) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory write pointer register address(R/W) - * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n - * It should be read or be updated like as follows.\n - * 1. Read the starting address for saving the transmitting data.\n - * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n - * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size. - * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value.\n - * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command - */ -#define Sn_TX_WR(N) WIZCHIP_SREG_ADDR(N, 0x0024) - -/** - * @ingroup Socket_register_group - * @brief Received data size register(R) - * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer. - * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between - * �Socket n RX Write Pointer (@ref Sn_RX_WR)and �Socket n RX Read Pointer (@ref Sn_RX_RD) - */ -#define Sn_RX_RSR(N) WIZCHIP_SREG_ADDR(N, 0x0026) - -/** - * @ingroup Socket_register_group - * @brief Read point of Receive memory(R/W) - * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n - * 1. Read the starting save address of the received data.\n - * 2. Read data from the starting address of Socket n RX Buffer.\n - * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size. - * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs, - * update with the lower 16bits value ignored the carry bit.\n - * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500. - */ -#define Sn_RX_RD(N) WIZCHIP_SREG_ADDR(N, 0x0028) - -/** - * @ingroup Socket_register_group - * @brief Write point of Receive memory(R) - * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception. - * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value. - */ -#define Sn_RX_WR(N) WIZCHIP_SREG_ADDR(N, 0x002a) - -/** - * @ingroup Socket_register_group - * @brief socket interrupt mask register(R) - * @details @ref Sn_IMR masks the interrupt of Socket n. - * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is - * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is - * Host is interrupted by asserted INTn PIN to low. - */ -//#define Sn_IMR(N) (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Fragment field value in IP header register(R/W) - * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header). - */ -//#define Sn_FRAG(N) (_W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Keep Alive Timer register(R/W) - * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode, - * and ignored in other modes. The time unit is 5s. - * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once. - * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process). - * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate, - * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process). - * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'. - */ -//#define Sn_KPALVTR(N) (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -//#define Sn_TSR(N) (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - - -//----------------------------- W5500 Register values ----------------------------- - -/* MODE register values */ -/** - * @brief Reset - * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset. - */ -#define MR_RST 0x80 - -/** - * @brief Wake on LAN - * @details 0 : Disable WOL mode\n - * 1 : Enable WOL mode\n - * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low. - * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.) - * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and - * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode. - */ -#define MR_WOL 0x20 - -/** - * @brief Ping block - * @details 0 : Disable Ping block\n - * 1 : Enable Ping block\n - * If the bit is it blocks the response to a ping request. - */ -#define MR_PB 0x10 - -/** - * @brief Enable PPPoE - * @details 0 : DisablePPPoE mode\n - * 1 : EnablePPPoE mode\n - * If you use ADSL, this bit should be - */ -#define MR_PPPOE 0x08 - -/** - * @brief Enable UDP_FORCE_ARP CHECHK - * @details 0 : Disable Force ARP mode\n - * 1 : Enable Force ARP mode\n - * In Force ARP mode, It forces on sending ARP Request whenever data is sent. - */ -#define MR_FARP 0x02 - -/* IR register values */ -/** - * @brief Check IP conflict. - * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request. - */ -#define IR_CONFLICT 0x80 - -/** - * @brief Get the destination unreachable message in UDP sending. - * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as - * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR. - */ -#define IR_UNREACH 0x40 - -/** - * @brief Get the PPPoE close message. - * @details When PPPoE is disconnected during PPPoE mode, this bit is set. - */ -#define IR_PPPoE 0x20 - -/** - * @brief Get the magic packet interrupt. - * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set. - */ -#define IR_MP 0x10 - - -/* PHYCFGR register value */ -#define PHYCFGR_RST ~(1<<7) //< For PHY reset, must operate AND mask. -#define PHYCFGR_OPMD (1<<6) // Configre PHY with OPMDC value -#define PHYCFGR_OPMDC_ALLA (7<<3) -#define PHYCFGR_OPMDC_PDOWN (6<<3) -#define PHYCFGR_OPMDC_NA (5<<3) -#define PHYCFGR_OPMDC_100FA (4<<3) -#define PHYCFGR_OPMDC_100F (3<<3) -#define PHYCFGR_OPMDC_100H (2<<3) -#define PHYCFGR_OPMDC_10F (1<<3) -#define PHYCFGR_OPMDC_10H (0<<3) -#define PHYCFGR_DPX_FULL (1<<2) -#define PHYCFGR_DPX_HALF (0<<2) -#define PHYCFGR_SPD_100 (1<<1) -#define PHYCFGR_SPD_10 (0<<1) -#define PHYCFGR_LNK_ON (1<<0) -#define PHYCFGR_LNK_OFF (0<<0) - -// PHYSTATUS register -#define PHYSTATUS_POWERDOWN (0x08) -#define PHYSTATUS_LINK (0x20) - -/* IMR register values */ -/** - * @brief IP Conflict Interrupt Mask. - * @details 0: Disable IP Conflict Interrupt\n - * 1: Enable IP Conflict Interrupt - */ -#define IM_IR7 0x80 - -/** - * @brief Destination unreachable Interrupt Mask. - * @details 0: Disable Destination unreachable Interrupt\n - * 1: Enable Destination unreachable Interrupt - */ -#define IM_IR6 0x40 - -/** - * @brief PPPoE Close Interrupt Mask. - * @details 0: Disable PPPoE Close Interrupt\n - * 1: Enable PPPoE Close Interrupt - */ -#define IM_IR5 0x20 - -/** - * @brief Magic Packet Interrupt Mask. - * @details 0: Disable Magic Packet Interrupt\n - * 1: Enable Magic Packet Interrupt - */ -#define IM_IR4 0x10 - -/* Sn_MR Default values */ -/** - * @brief Support UDP Multicasting - * @details 0 : disable Multicasting\n - * 1 : enable Multicasting\n - * This bit is applied only during UDP mode(P[3:0] = 010.\n - * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number - * before Socket n is opened by OPEN command of @ref Sn_CR. - */ -#define Sn_MR_MULTI 0x80 - -/** - * @brief Broadcast block in UDP Multicasting. - * @details 0 : disable Broadcast Blocking\n - * 1 : enable Broadcast Blocking\n - * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m - * In addition, This bit does when MACRAW mode(P[3:0] = 100 - */ -//#define Sn_MR_BCASTB 0x40 - -/** - * @brief No Delayed Ack(TCP), Multicast flag - * @details 0 : Disable No Delayed ACK option\n - * 1 : Enable No Delayed ACK option\n - * This bit is applied only during TCP mode (P[3:0] = 001.\n - * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n - * When this bit is It sends the ACK packet after waiting for the timeout time configured by @ref RTR. - */ -#define Sn_MR_ND 0x20 - -/** - * @brief Unicast Block in UDP Multicasting - * @details 0 : disable Unicast Blocking\n - * 1 : enable Unicast Blocking\n - * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI = - */ -//#define Sn_MR_UCASTB 0x10 - -/** - * @brief MAC LAYER RAW SOCK - * @details This configures the protocol mode of Socket n. - * @note MACRAW mode should be only used in Socket 0. - */ -#define Sn_MR_MACRAW 0x04 - -#define Sn_MR_IPRAW 0x03 /**< IP LAYER RAW SOCK */ - -/** - * @brief UDP - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_UDP 0x02 - -/** - * @brief TCP - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_TCP 0x01 - -/** - * @brief Unused socket - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_CLOSE 0x00 - -/* Sn_MR values used with Sn_MR_MACRAW */ -/** - * @brief MAC filter enable in @ref Sn_MR_MACRAW mode - * @details 0 : disable MAC Filtering\n - * 1 : enable MAC Filtering\n - * This bit is applied only during MACRAW mode(P[3:0] = 100.\n - * When set as W5500 can only receive broadcasting packet or packet sent to itself. - * When this bit is W5500 can receive all packets on Ethernet. - * If user wants to implement Hybrid TCP/IP stack, - * it is recommended that this bit is set as for reducing host overhead to process the all received packets. - */ -#define Sn_MR_MFEN Sn_MR_MULTI - -/** - * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode - * @details 0 : using IGMP version 2\n - * 1 : using IGMP version 1\n - * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = - * It configures the version for IGMP messages (Join/Leave/Report). - */ -#define Sn_MR_MMB Sn_MR_ND - -/** - * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode - * @details 0 : disable IPv6 Blocking\n - * 1 : enable IPv6 Blocking\n - * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet. - */ -#define Sn_MR_MIP6B Sn_MR_UCASTB - -/* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */ -/** - * @brief IGMP version used in UDP mulitcasting - * @details 0 : disable Multicast Blocking\n - * 1 : enable Multicast Blocking\n - * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address. - */ -#define Sn_MR_MC Sn_MR_ND - -/* Sn_MR alternate values */ -/** - * @brief For Berkeley Socket API - */ -#define SOCK_STREAM Sn_MR_TCP - -/** - * @brief For Berkeley Socket API - */ -#define SOCK_DGRAM Sn_MR_UDP - - -/* Sn_CR values */ -/** - * @brief Initialize or open socket - * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0). - * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n - * - * - * - * - * - * - *
\b Sn_MR (P[3:0]) \b Sn_SR
Sn_MR_CLOSE (000
Sn_MR_TCP (001 SOCK_INIT (0x13)
Sn_MR_UDP (010 SOCK_UDP (0x22)
S0_MR_MACRAW (100 SOCK_MACRAW (0x02)
- */ -#define Sn_CR_OPEN 0x01 - -/** - * @brief Wait connection request in TCP mode(Server mode) - * @details This is valid only in TCP mode (Sn_MR(P3:P0) = Sn_MR_TCP). - * In this mode, Socket n operates as a �TCP serverand waits for connection-request (SYN packet) from any �TCP client - * The @ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN. - * When a �TCP clientconnection request is successfully established, - * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes - * But when a �TCP clientconnection request is failed, Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED. - */ -#define Sn_CR_LISTEN 0x02 - -/** - * @brief Send connection request in TCP mode(Client mode) - * @details To connect, a connect-request (SYN packet) is sent to b>TCP serverconfigured by @ref Sn_DIPR & Sn_DPORT(destination address & port). - * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n - * The connect-request fails in the following three cases.\n - * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = ) because destination hardware address is not acquired through the ARP-process.\n - * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n - * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED. - * @note This is valid only in TCP mode and operates when Socket n acts as b>TCP client - */ -#define Sn_CR_CONNECT 0x04 - -/** - * @brief Send closing request in TCP mode - * @details Regardless of b>TCP serveror b>TCP client the DISCON command processes the disconnect-process (b>Active closeor b>Passive close.\n - * @par Active close - * it transmits disconnect-request(FIN packet) to the connected peer\n - * @par Passive close - * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n - * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n - * Otherwise, TCPTO occurs (Sn_IR(3)=)= and then @ref Sn_SR is changed to @ref SOCK_CLOSED. - * @note Valid only in TCP mode. - */ -#define Sn_CR_DISCON 0x08 - -/** - * @brief Close socket - * @details Sn_SR is changed to @ref SOCK_CLOSED. - */ -#define Sn_CR_CLOSE 0x10 - -/** - * @brief Update TX buffer pointer and send data - * @details SEND transmits all the data in the Socket n TX buffer.\n - * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n, - * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD). - */ -#define Sn_CR_SEND 0x20 - -/** - * @brief Send data with MAC address, so without ARP process - * @details The basic operation is same as SEND.\n - * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n - * But SEND_MAC transmits data without the automatic ARP-process.\n - * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process. - * @note Valid only in UDP mode. - */ -#define Sn_CR_SEND_MAC 0x21 - -/** - * @brief Send keep alive message - * @details It checks the connection status by sending 1byte keep-alive packet.\n - * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur. - * @note Valid only in TCP mode. - */ -#define Sn_CR_SEND_KEEP 0x22 - -/** - * @brief Update RX buffer pointer and receive data - * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n - * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR), - * and Socket n RX Read Pointer Register (@ref Sn_RX_RD). - */ -#define Sn_CR_RECV 0x40 - -/* Sn_IR values */ -/** - * @brief SEND_OK Interrupt - * @details This is issued when SEND command is completed. - */ -#define Sn_IR_SENDOK 0x10 - -/** - * @brief TIMEOUT Interrupt - * @details This is issued when ARPTO or TCPTO occurs. - */ -#define Sn_IR_TIMEOUT 0x08 - -/** - * @brief RECV Interrupt - * @details This is issued whenever data is received from a peer. - */ -#define Sn_IR_RECV 0x04 - -/** - * @brief DISCON Interrupt - * @details This is issued when FIN or FIN/ACK packet is received from a peer. - */ -#define Sn_IR_DISCON 0x02 - -/** - * @brief CON Interrupt - * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED. - */ -#define Sn_IR_CON 0x01 - -/* Sn_SR values */ -/** - * @brief Closed - * @details This indicates that Socket n is released.\N - * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status. - */ -#define SOCK_CLOSED 0x00 - -/** - * @brief Initiate state - * @details This indicates Socket n is opened with TCP mode.\N - * It is changed to @ref SOCK_INIT when Sn_MR(P[3:0]) = 001and OPEN command is ordered.\N - * After @ref SOCK_INIT, user can use LISTEN /CONNECT command. - */ -#define SOCK_INIT 0x13 - -/** - * @brief Listen state - * @details This indicates Socket n is operating as b>TCP servermode and waiting for connection-request (SYN packet) from a peer (b>TCP client.\n - * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n - * Otherwise it will change to @ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = . - */ -#define SOCK_LISTEN 0x14 - -/** - * @brief Connection state - * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n - * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n - * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n - * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = is occurred. - */ -#define SOCK_SYNSENT 0x15 - -/** - * @brief Connection state - * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n - * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n - * If not, it changes to @ref SOCK_CLOSED after timeout occurs (@ref Sn_IR[TIMEOUT] = . - */ -#define SOCK_SYNRECV 0x16 - -/** - * @brief Success to connect - * @details This indicates the status of the connection of Socket n.\n - * It changes to @ref SOCK_ESTABLISHED when the b>TCP SERVERprocessed the SYN packet from the b>TCP CLIENTduring @ref SOCK_LISTEN, or - * when the CONNECT command is successful.\n - * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command. - */ -#define SOCK_ESTABLISHED 0x17 - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_FIN_WAIT 0x18 - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_CLOSING 0x1A - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_TIME_WAIT 0x1B - -/** - * @brief Closing state - * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n - * This is half-closing status, and data can be transferred.\n - * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used. - */ -#define SOCK_CLOSE_WAIT 0x1C - -/** - * @brief Closing state - * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n - * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (@ref Sn_IR[TIMEOUT] = . - */ -#define SOCK_LAST_ACK 0x1D - -/** - * @brief UDP socket - * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010.\n - * It changes to SOCK_UPD when Sn_MR(P[3:0]) = 010 and OPEN command is ordered.\n - * Unlike TCP mode, data can be transfered without the connection-process. - */ -#define SOCK_UDP 0x22 - -//#define SOCK_IPRAW 0x32 /**< IP raw mode socket */ - -/** - * @brief MAC raw mode socket - * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n - * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n - * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process. - */ -#define SOCK_MACRAW 0x42 - -//#define SOCK_PPPOE 0x5F - -/* IP PROTOCOL */ -#define IPPROTO_IP 0 //< Dummy for IP -#define IPPROTO_ICMP 1 //< Control message protocol -#define IPPROTO_IGMP 2 //< Internet group management protocol -#define IPPROTO_GGP 3 //< Gateway^2 (deprecated) -#define IPPROTO_TCP 6 //< TCP -#define IPPROTO_PUP 12 //< PUP -#define IPPROTO_UDP 17 //< UDP -#define IPPROTO_IDP 22 //< XNS idp -#define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol -#define IPPROTO_RAW 255 //< Raw IP packet - - -/** - * @brief Enter a critical section - * - * @details It is provided to protect your shared code which are executed without distribution. \n \n - * - * In non-OS environment, It can be just implemented by disabling whole interrupt.\n - * In OS environment, You can replace it to critical section api supported by OS. - * - * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() - * \sa WIZCHIP_CRITICAL_EXIT() - */ -#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter() - -/** - * @brief Exit a critical section - * - * @details It is provided to protect your shared code which are executed without distribution. \n\n - * - * In non-OS environment, It can be just implemented by disabling whole interrupt. \n - * In OS environment, You can replace it to critical section api supported by OS. - * - * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() - * @sa WIZCHIP_CRITICAL_ENTER() - */ -#ifdef _exit -#undef _exit -#endif -#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit() - - - -//////////////////////// -// Basic I/O Function // -//////////////////////// - -/** - * @ingroup Basic_IO_function - * @brief It reads 1 byte value from a register. - * @param AddrSel Register address - * @return The value of register - */ -uint8_t WIZCHIP_READ (uint32_t AddrSel); - -/** - * @ingroup Basic_IO_function - * @brief It writes 1 byte value to a register. - * @param AddrSel Register address - * @param wb Write data - * @return void - */ -void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ); - -/** - * @ingroup Basic_IO_function - * @brief It reads sequence data from registers. - * @param AddrSel Register address - * @param pBuf Pointer buffer to read data - * @param len Data length - */ -void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It writes sequence data to registers. - * @param AddrSel Register address - * @param pBuf Pointer buffer to write data - * @param len Data length - */ -void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len); - -///////////////////////////////// -// Common Register I/O function // -///////////////////////////////// -/** - * @ingroup Common_register_access_function - * @brief Set Mode Register - * @param (uint8_t)mr The value to be set. - * @sa getMR() - */ -#define setMR(mr) \ - WIZCHIP_WRITE(MR,mr) - - -/** - * @ingroup Common_register_access_function - * @brief Get Mode Register - * @return uint8_t. The value of Mode register. - * @sa setMR() - */ -#define getMR() \ - WIZCHIP_READ(MR) - -/** - * @ingroup Common_register_access_function - * @brief Set gateway IP address - * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes. - * @sa getGAR() - */ -#define setGAR(gar) \ - WIZCHIP_WRITE_BUF(GAR,gar,4) - -/** - * @ingroup Common_register_access_function - * @brief Get gateway IP address - * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes. - * @sa setGAR() - */ -#define getGAR(gar) \ - WIZCHIP_READ_BUF(GAR,gar,4) - -/** - * @ingroup Common_register_access_function - * @brief Set subnet mask address - * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes. - * @sa getSUBR() - */ -#define setSUBR(subr) \ - WIZCHIP_WRITE_BUF(SUBR, subr,4) - - -/** - * @ingroup Common_register_access_function - * @brief Get subnet mask address - * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes. - * @sa setSUBR() - */ -#define getSUBR(subr) \ - WIZCHIP_READ_BUF(SUBR, subr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Set local MAC address - * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes. - * @sa getSHAR() - */ -#define setSHAR(shar) \ - WIZCHIP_WRITE_BUF(SHAR, shar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Get local MAC address - * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes. - * @sa setSHAR() - */ -#define getSHAR(shar) \ - WIZCHIP_READ_BUF(SHAR, shar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Set local IP address - * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes. - * @sa getSIPR() - */ -#define setSIPR(sipr) \ - WIZCHIP_WRITE_BUF(SIPR, sipr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Get local IP address - * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes. - * @sa setSIPR() - */ -#define getSIPR(sipr) \ - WIZCHIP_READ_BUF(SIPR, sipr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Set INTLEVEL register - * @param (uint16_t)intlevel Value to set @ref INTLEVEL register. - * @sa getINTLEVEL() - */ -// dpgeorge: not yet implemented -#define setINTLEVEL(intlevel) (void)intlevel -#if 0 -#define setINTLEVEL(intlevel) {\ - WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \ - } -#endif - - -/** - * @ingroup Common_register_access_function - * @brief Get INTLEVEL register - * @return uint16_t. Value of @ref INTLEVEL register. - * @sa setINTLEVEL() - */ -// dpgeorge: not yet implemented -#define getINTLEVEL() (0) -#if 0 -#define getINTLEVEL() \ - ((WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1))) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Set @ref IR register - * @param (uint8_t)ir Value to set @ref IR register. - * @sa getIR() - */ -#define setIR(ir) \ - WIZCHIP_WRITE(IR, (ir & 0xF0)) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref IR register - * @return uint8_t. Value of @ref IR register. - * @sa setIR() - */ -#define getIR() \ - (WIZCHIP_READ(IR) & 0xF0) -/** - * @ingroup Common_register_access_function - * @brief Set @ref IMR register - * @param (uint8_t)imr Value to set @ref IMR register. - * @sa getIMR() - */ -#define setIMR(imr) \ - WIZCHIP_WRITE(IMR, imr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref IMR register - * @return uint8_t. Value of @ref IMR register. - * @sa setIMR() - */ -#define getIMR() \ - WIZCHIP_READ(IMR) - - -/** - * @ingroup Common_register_access_function - * @brief Set @ref SIR register - * @param (uint8_t)sir Value to set @ref SIR register. - * @sa getSIR() - */ -// dpgeorge: not yet implemented -#define setSIR(sir) ((void)sir) -#if 0 -#define setSIR(sir) \ - WIZCHIP_WRITE(SIR, sir) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Get @ref SIR register - * @return uint8_t. Value of @ref SIR register. - * @sa setSIR() - */ -// dpgeorge: not yet implemented -#define getSIR() (0) -#if 0 -#define getSIR() \ - WIZCHIP_READ(SIR) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Set @ref SIMR register - * @param (uint8_t)simr Value to set @ref SIMR register. - * @sa getSIMR() - */ -// dpgeorge: not yet implemented -#define setSIMR(simr) ((void)simr) -#if 0 -#define setSIMR(simr) \ - WIZCHIP_WRITE(SIMR, simr) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Get @ref SIMR register - * @return uint8_t. Value of @ref SIMR register. - * @sa setSIMR() - */ -// dpgeorge: not yet implemented -#define getSIMR() (0) -#if 0 -#define getSIMR() \ - WIZCHIP_READ(SIMR) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Set @ref RTR register - * @param (uint16_t)rtr Value to set @ref RTR register. - * @sa getRTR() - */ -#define setRTR(rtr) {\ - WIZCHIP_WRITE(RTR, (uint8_t)(rtr >> 8)); \ - WIZCHIP_WRITE(RTR + 1, (uint8_t) rtr); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref RTR register - * @return uint16_t. Value of @ref RTR register. - * @sa setRTR() - */ -#define getRTR() \ - ((WIZCHIP_READ(RTR) << 8) + WIZCHIP_READ(RTR + 1)) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref RCR register - * @param (uint8_t)rcr Value to set @ref RCR register. - * @sa getRCR() - */ -#define setRCR(rcr) \ - WIZCHIP_WRITE(RCR, rcr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref RCR register - * @return uint8_t. Value of @ref RCR register. - * @sa setRCR() - */ -#define getRCR() \ - WIZCHIP_READ(RCR) - -//================================================== test done =========================================================== - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PTIMER register - * @param (uint8_t)ptimer Value to set @ref PTIMER register. - * @sa getPTIMER() - */ -#define setPTIMER(ptimer) \ - WIZCHIP_WRITE(PTIMER, ptimer) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PTIMER register - * @return uint8_t. Value of @ref PTIMER register. - * @sa setPTIMER() - */ -#define getPTIMER() \ - WIZCHIP_READ(PTIMER) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PMAGIC register - * @param (uint8_t)pmagic Value to set @ref PMAGIC register. - * @sa getPMAGIC() - */ -#define setPMAGIC(pmagic) \ - WIZCHIP_WRITE(PMAGIC, pmagic) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PMAGIC register - * @return uint8_t. Value of @ref PMAGIC register. - * @sa setPMAGIC() - */ -#define getPMAGIC() \ - WIZCHIP_READ(PMAGIC) - -/** - * @ingroup Common_register_access_function - * @brief Set PHAR address - * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes. - * @sa getPHAR() - */ -#if 0 -#define setPHAR(phar) \ - WIZCHIP_WRITE_BUF(PHAR, phar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Get local IP address - * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes. - * @sa setPHAR() - */ -#define getPHAR(phar) \ - WIZCHIP_READ_BUF(PHAR, phar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PSID register - * @param (uint16_t)psid Value to set @ref PSID register. - * @sa getPSID() - */ -#define setPSID(psid) {\ - WIZCHIP_WRITE(PSID, (uint8_t)(psid >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PSID register - * @return uint16_t. Value of @ref PSID register. - * @sa setPSID() - */ -//uint16_t getPSID(void); -#define getPSID() \ - ((WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PMRU register - * @param (uint16_t)pmru Value to set @ref PMRU register. - * @sa getPMRU() - */ -#define setPMRU(pmru) { \ - WIZCHIP_WRITE(PMRU, (uint8_t)(pmru>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PMRU register - * @return uint16_t. Value of @ref PMRU register. - * @sa setPMRU() - */ -#define getPMRU() \ - ((WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1))) - -/** - * @ingroup Common_register_access_function - * @brief Get unreachable IP address - * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes. - */ -#define getUIPR(uipr) \ - WIZCHIP_READ_BUF(UIPR,uipr,6) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref UPORTR register - * @return uint16_t. Value of @ref UPORTR register. - */ -#define getUPORTR() \ - ((WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PHYCFGR register - * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register. - * @sa getPHYCFGR() - */ -#define setPHYCFGR(phycfgr) \ - WIZCHIP_WRITE(PHYCFGR, phycfgr) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PHYCFGR register - * @return uint8_t. Value of @ref PHYCFGR register. - * @sa setPHYCFGR() - */ -#define getPHYSTATUS() \ - WIZCHIP_READ(PHYSTATUS) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref VERSIONR register - * @return uint8_t. Value of @ref VERSIONR register. - */ -/* -#define getVERSIONR() \ - WIZCHIP_READ(VERSIONR) - */ -///////////////////////////////////// - -/////////////////////////////////// -// Socket N register I/O function // -/////////////////////////////////// -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)mr Value to set @ref Sn_MR - * @sa getSn_MR() - */ -#define setSn_MR(sn, mr) \ - WIZCHIP_WRITE(Sn_MR(sn),mr) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_MR. - * @sa setSn_MR() - */ -#define getSn_MR(sn) \ - WIZCHIP_READ(Sn_MR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_CR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)cr Value to set @ref Sn_CR - * @sa getSn_CR() - */ -#define setSn_CR(sn, cr) \ - WIZCHIP_WRITE(Sn_CR(sn), cr) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_CR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_CR. - * @sa setSn_CR() - */ -#define getSn_CR(sn) \ - WIZCHIP_READ(Sn_CR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_IR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)ir Value to set @ref Sn_IR - * @sa getSn_IR() - */ -#define setSn_IR(sn, ir) \ - WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F)) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_IR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_IR. - * @sa setSn_IR() - */ -#define getSn_IR(sn) \ - (WIZCHIP_READ(Sn_IR(sn)) & 0x1F) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_IMR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)imr Value to set @ref Sn_IMR - * @sa getSn_IMR() - */ -// dpgeorge: not yet implemented -#define setSn_IMR(sn, imr) (void)sn; (void)imr -#if 0 -#define setSn_IMR(sn, imr) \ - WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F)) -#endif - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_IMR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_IMR. - * @sa setSn_IMR() - */ -// dpgeorge: not yet implemented -#define getSn_IMR(sn) (0) -#if 0 -#define getSn_IMR(sn) \ - (WIZCHIP_READ(Sn_IMR(sn)) & 0x1F) -#endif - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_SR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_SR. - */ -#define getSn_SR(sn) \ - WIZCHIP_READ(Sn_SR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_PORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)port Value to set @ref Sn_PORT. - * @sa getSn_PORT() - */ -#define setSn_PORT(sn, port) { \ - WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \ - WIZCHIP_WRITE(Sn_PORT(sn) + 1, (uint8_t) port); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_PORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_PORT. - * @sa setSn_PORT() - */ -#define getSn_PORT(sn) \ - ((WIZCHIP_READ(Sn_PORT(sn)) << 8) | WIZCHIP_READ(Sn_PORT(sn) + 1)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DHAR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes. - * @sa getSn_DHAR() - */ -#define setSn_DHAR(sn, dhar) \ - WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes. - * @sa setSn_DHAR() - */ -#define getSn_DHAR(sn, dhar) \ - WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DIPR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes. - * @sa getSn_DIPR() - */ -#define setSn_DIPR(sn, dipr) \ - WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_DIPR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes. - * @sa SetSn_DIPR() - */ -#define getSn_DIPR(sn, dipr) \ - WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DPORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)dport Value to set @ref Sn_DPORT - * @sa getSn_DPORT() - */ -#define setSn_DPORT(sn, dport) { \ - WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \ - WIZCHIP_WRITE(Sn_DPORT(sn) + 1, (uint8_t) dport); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_DPORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_DPORT. - * @sa setSn_DPORT() - */ -#define getSn_DPORT(sn) \ - ((WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ((Sn_DPORT(sn)+1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_MSSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)mss Value to set @ref Sn_MSSR - * @sa setSn_MSSR() - */ -#define setSn_MSSR(sn, mss) { \ - WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \ - WIZCHIP_WRITE((Sn_MSSR(sn)+1), (uint8_t) mss); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MSSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_MSSR. - * @sa setSn_MSSR() - */ -#define getSn_MSSR(sn) \ - ((WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ((Sn_MSSR(sn)+1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TOS register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)tos Value to set @ref Sn_TOS - * @sa getSn_TOS() - */ -#define setSn_TOS(sn, tos) \ - WIZCHIP_WRITE(Sn_TOS(sn), tos) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TOS register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of Sn_TOS. - * @sa setSn_TOS() - */ -#define getSn_TOS(sn) \ - WIZCHIP_READ(Sn_TOS(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TTL register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)ttl Value to set @ref Sn_TTL - * @sa getSn_TTL() - */ -#define setSn_TTL(sn, ttl) \ - WIZCHIP_WRITE(Sn_TTL(sn), ttl) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TTL register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_TTL. - * @sa setSn_TTL() - */ -#define getSn_TTL(sn) \ - WIZCHIP_READ(Sn_TTL(sn)) - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_RXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE - * @sa getSn_RXBUF_SIZE() - */ -#define setSn_RXBUF_SIZE(sn, rxbufsize) \ - WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_RXBUF_SIZE. - * @sa setSn_RXBUF_SIZE() - */ -#define getSn_RXBUF_SIZE(sn) \ - WIZCHIP_READ(Sn_RXBUF_SIZE(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE - * @sa getSn_TXBUF_SIZE() - */ -#define setSn_TXBUF_SIZE(sn, txbufsize) \ - WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_TXBUF_SIZE. - * @sa setSn_TXBUF_SIZE() - */ -#define getSn_TXBUF_SIZE(sn) \ - WIZCHIP_READ(Sn_TXBUF_SIZE(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_FSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_FSR. - */ -uint16_t getSn_TX_FSR(uint8_t sn); - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_RD. - */ -#define getSn_TX_RD(sn) \ - ((WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ((Sn_TX_RD(sn)+1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)txwr Value to set @ref Sn_TX_WR - * @sa GetSn_TX_WR() - */ -#define setSn_TX_WR(sn, txwr) { \ - WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \ - WIZCHIP_WRITE((Sn_TX_WR(sn)+1), (uint8_t) txwr); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_WR. - * @sa setSn_TX_WR() - */ -#define getSn_TX_WR(sn) \ - ((WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ((Sn_TX_WR(sn)+1))) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_RSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_RX_RSR. - */ -uint16_t getSn_RX_RSR(uint8_t sn); - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_RX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD - * @sa getSn_RX_RD() - */ -#define setSn_RX_RD(sn, rxrd) { \ - WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \ - WIZCHIP_WRITE((Sn_RX_RD(sn)+1), (uint8_t) rxrd); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @regurn uint16_t. Value of @ref Sn_RX_RD. - * @sa setSn_RX_RD() - */ -#define getSn_RX_RD(sn) \ - ((WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ((Sn_RX_RD(sn)+1))) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_RX_WR. - */ -#define getSn_RX_WR(sn) \ - ((WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ((Sn_RX_WR(sn)+1))) - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_FRAG register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)frag Value to set @ref Sn_FRAG - * @sa getSn_FRAD() - */ -#if 0 // dpgeorge -#define setSn_FRAG(sn, frag) { \ - WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_FRAG register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_FRAG. - * @sa setSn_FRAG() - */ -#define getSn_FRAG(sn) \ - ((WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_KPALVTR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR - * @sa getSn_KPALVTR() - */ -#define setSn_KPALVTR(sn, kpalvt) \ - WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_KPALVTR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_KPALVTR. - * @sa setSn_KPALVTR() - */ -#define getSn_KPALVTR(sn) \ - WIZCHIP_READ(Sn_KPALVTR(sn)) - -////////////////////////////////////// -#endif - -///////////////////////////////////// -// Sn_TXBUF & Sn_RXBUF IO function // -///////////////////////////////////// -/** - * @brief Gets the max buffer size of socket sn passed as parameter. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of Socket n RX max buffer size. - */ -#define getSn_RxMAX(sn) \ - (getSn_RXBUF_SIZE(sn) << 10) - -/** - * @brief Gets the max buffer size of socket sn passed as parameters. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of Socket n TX max buffer size. - */ -//uint16_t getSn_TxMAX(uint8_t sn); -#define getSn_TxMAX(sn) \ - (getSn_TXBUF_SIZE(sn) << 10) - -void wiz_init(void); - -/** - * @ingroup Basic_IO_function - * @brief It copies data to internal TX memory - * - * @details This function reads the Tx write pointer register and after that, - * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory - * and updates the Tx write pointer register. - * This function is being called by send() and sendto() function also. - * - * @note User should read upper byte first and lower byte later to get proper value. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param wizdata Pointer buffer to write data - * @param len Data length - * @sa wiz_recv_data() - */ -void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It copies data to your buffer from internal RX memory - * - * @details This function read the Rx read pointer register and after that, - * it copies the received data from internal RX memory - * to wizdata(pointer variable) of the length of len(variable) bytes. - * This function is being called by recv() also. - * - * @note User should read upper byte first and lower byte later to get proper value. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param wizdata Pointer buffer to read data - * @param len Data length - * @sa wiz_send_data() - */ -void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It discard the received data in RX memory. - * @details It discards the data of the length of len(variable) bytes in internal RX memory. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param len Data length - */ -void wiz_recv_ignore(uint8_t sn, uint16_t len); - -#endif // _W5500_H_ diff --git a/drivers/wiznet5k/ethernet/w5500/w5500.c b/drivers/wiznet5k/ethernet/w5500/w5500.c deleted file mode 100644 index 3107b1b71a..0000000000 --- a/drivers/wiznet5k/ethernet/w5500/w5500.c +++ /dev/null @@ -1,247 +0,0 @@ -//***************************************************************************** -// -//! \file w5500.c -//! \brief W5500 HAL Interface. -//! \version 1.0.1 -//! \date 2013/10/21 -//! \par Revision history -//! <2014/05/01> V1.0.2 -//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501 -//! Fixed the problem on porting into under 32bit MCU -//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh -//! Thank for your interesting and serious advices. -//! <2013/10/21> 1st Release -//! <2013/12/20> V1.0.1 -//! 1. Remove warning -//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_ -//! for loop optimized(removed). refer to M20131220 -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** -//#include -#include "w5500.h" - -#define _W5500_SPI_VDM_OP_ 0x00 -#define _W5500_SPI_FDM_OP_LEN1_ 0x01 -#define _W5500_SPI_FDM_OP_LEN2_ 0x02 -#define _W5500_SPI_FDM_OP_LEN4_ 0x03 - -//////////////////////////////////////////////////// - -#define LPC_SSP0 (0) - -static void Chip_SSP_ReadFrames_Blocking(int dummy, uint8_t *buf, uint32_t len) { - WIZCHIP.IF.SPI._read_bytes(buf, len); -} - -static void Chip_SSP_WriteFrames_Blocking(int dummy, const uint8_t *buf, uint32_t len) { - WIZCHIP.IF.SPI._write_bytes(buf, len); -} - -uint8_t WIZCHIP_READ(uint32_t AddrSel) -{ - uint8_t ret; - uint8_t spi_data[3]; - - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_); - - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); - //ret = WIZCHIP.IF.SPI._read_byte(); - spi_data[0] = (AddrSel & 0x00FF0000) >> 16; - spi_data[1] = (AddrSel & 0x0000FF00) >> 8; - spi_data[2] = (AddrSel & 0x000000FF) >> 0; - Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3); - Chip_SSP_ReadFrames_Blocking(LPC_SSP0, &ret, 1); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); - return ret; -} - -void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ) -{ - uint8_t spi_data[4]; - - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_); - - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); - //WIZCHIP.IF.SPI._write_byte(wb); - spi_data[0] = (AddrSel & 0x00FF0000) >> 16; - spi_data[1] = (AddrSel & 0x0000FF00) >> 8; - spi_data[2] = (AddrSel & 0x000000FF) >> 0; - spi_data[3] = wb; - Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 4); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - -void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len) -{ - uint8_t spi_data[3]; - //uint16_t i; - - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_); - - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); - //for(i = 0; i < len; i++) - // pBuf[i] = WIZCHIP.IF.SPI._read_byte(); - spi_data[0] = (AddrSel & 0x00FF0000) >> 16; - spi_data[1] = (AddrSel & 0x0000FF00) >> 8; - spi_data[2] = (AddrSel & 0x000000FF) >> 0; - Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3); - Chip_SSP_ReadFrames_Blocking(LPC_SSP0, pBuf, len); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - -void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) -{ - uint8_t spi_data[3]; - //uint16_t i; - - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_); - - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); - //for(i = 0; i < len; i++) - // WIZCHIP.IF.SPI._write_byte(pBuf[i]); - spi_data[0] = (AddrSel & 0x00FF0000) >> 16; - spi_data[1] = (AddrSel & 0x0000FF00) >> 8; - spi_data[2] = (AddrSel & 0x000000FF) >> 0; - Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3); - Chip_SSP_WriteFrames_Blocking(LPC_SSP0, pBuf, len); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - - -uint16_t getSn_TX_FSR(uint8_t sn) -{ - uint16_t val=0,val1=0; - - do - { - val1 = WIZCHIP_READ(Sn_TX_FSR(sn)); - val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); - if (val1 != 0) - { - val = WIZCHIP_READ(Sn_TX_FSR(sn)); - val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); - } - }while (val != val1); - return val; -} - - -uint16_t getSn_RX_RSR(uint8_t sn) -{ - uint16_t val=0,val1=0; - - do - { - val1 = WIZCHIP_READ(Sn_RX_RSR(sn)); - val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); - if (val1 != 0) - { - val = WIZCHIP_READ(Sn_RX_RSR(sn)); - val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); - } - }while (val != val1); - return val; -} - -void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) -{ - uint16_t ptr = 0; - uint32_t addrsel = 0; - - if(len == 0) return; - ptr = getSn_TX_WR(sn); - //M20140501 : implict type casting -> explict type casting - //addrsel = (ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3); - addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3); - // - WIZCHIP_WRITE_BUF(addrsel,wizdata, len); - - ptr += len; - setSn_TX_WR(sn,ptr); -} - -void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) -{ - uint16_t ptr = 0; - uint32_t addrsel = 0; - - if(len == 0) return; - ptr = getSn_RX_RD(sn); - //M20140501 : implict type casting -> explict type casting - //addrsel = ((ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); - addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); - // - WIZCHIP_READ_BUF(addrsel, wizdata, len); - ptr += len; - - setSn_RX_RD(sn,ptr); -} - - -void wiz_recv_ignore(uint8_t sn, uint16_t len) -{ - uint16_t ptr = 0; - - ptr = getSn_RX_RD(sn); - ptr += len; - setSn_RX_RD(sn,ptr); -} - diff --git a/drivers/wiznet5k/ethernet/w5500/w5500.h b/drivers/wiznet5k/ethernet/w5500/w5500.h deleted file mode 100644 index c2afb180eb..0000000000 --- a/drivers/wiznet5k/ethernet/w5500/w5500.h +++ /dev/null @@ -1,2057 +0,0 @@ -//***************************************************************************** -// -//! \file w5500.h -//! \brief W5500 HAL Header File. -//! \version 1.0.0 -//! \date 2013/10/21 -//! \par Revision history -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#ifndef _W5500_H_ -#define _W5500_H_ - -#include -#include "../wizchip_conf.h" - -#define _W5500_IO_BASE_ 0x00000000 - -#define _W5500_SPI_READ_ (0x00 << 2) //< SPI interface Read operation in Control Phase -#define _W5500_SPI_WRITE_ (0x01 << 2) //< SPI interface Write operation in Control Phase - -#define WIZCHIP_CREG_BLOCK 0x00 //< Common register block -#define WIZCHIP_SREG_BLOCK(N) (1+4*N) //< Socket N register block -#define WIZCHIP_TXBUF_BLOCK(N) (2+4*N) //< Socket N Tx buffer address block -#define WIZCHIP_RXBUF_BLOCK(N) (3+4*N) //< Socket N Rx buffer address block - -#define WIZCHIP_OFFSET_INC(ADDR, N) (ADDR + (N<<8)) //< Increase offset address - - -/////////////////////////////////////// -// Definition For Legacy Chip Driver // -/////////////////////////////////////// -#define IINCHIP_READ(ADDR) WIZCHIP_READ(ADDR) ///< The defined for legacy chip driver -#define IINCHIP_WRITE(ADDR,VAL) WIZCHIP_WRITE(ADDR,VAL) ///< The defined for legacy chip driver -#define IINCHIP_READ_BUF(ADDR,BUF,LEN) WIZCHIP_READ_BUF(ADDR,BUF,LEN) ///< The defined for legacy chip driver -#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN) WIZCHIP_WRITE(ADDR,BUF,LEN) ///< The defined for legacy chip driver - -////////////////////////////// -//-------------------------- defgroup --------------------------------- -/** - * @defgroup W5500 W5500 - * - * @brief WHIZCHIP register defines and I/O functions of @b W5500. - * - * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group - * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function - */ - - -/** - * @defgroup WIZCHIP_register WIZCHIP register - * @ingroup W5500 - * - * @brief WHIZCHIP register defines register group of @b W5500. - * - * - @ref Common_register_group : Common register group - * - @ref Socket_register_group : \c SOCKET n register group - */ - - -/** - * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions - * @ingroup W5500 - * - * @brief This supports the basic I/O functions for @ref WIZCHIP_register. - * - * - Basic I/O function \n - * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n - * - * - @ref Common_register_group access functions \n - * -# @b Mode \n - * getMR(), setMR() - * -# @b Interrupt \n - * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL() - * -# Network Information \n - * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR() - * -# @b Retransmission \n - * getRCR(), setRCR(), getRTR(), setRTR() - * -# @b PPPoE \n - * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU() - * -# ICMP packet \n - * getUIPR(), getUPORTR() - * -# @b etc. \n - * getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n - * - * - \ref Socket_register_group access functions \n - * -# SOCKET control \n - * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR() - * -# SOCKET information \n - * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT() - * getSn_MSSR(), setSn_MSSR() - * -# SOCKET communication \n - * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n - * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n - * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n - * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR() - * -# IP header field \n - * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n - * getSn_TTL(), setSn_TTL() - */ - - - -/** - * @defgroup Common_register_group Common register - * @ingroup WIZCHIP_register - * - * @brief Common register group\n - * It set the basic for the networking\n - * It set the configuration such as interrupt, network information, ICMP, etc. - * @details - * @sa MR : Mode register. - * @sa GAR, SUBR, SHAR, SIPR - * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt. - * @sa RTR, RCR : Data retransmission. - * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE. - * @sa UIPR, UPORTR : ICMP message. - * @sa PHYCFGR, VERSIONR : etc. - */ - - - -/** - * @defgroup Socket_register_group Socket register - * @ingroup WIZCHIP_register - * - * @brief Socket register group.\n - * Socket register configures and control SOCKETn which is necessary to data communication. - * @details - * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control - * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information - * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol. - * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication - */ - - - - /** - * @defgroup Basic_IO_function Basic I/O function - * @ingroup WIZCHIP_IO_Functions - * @brief These are basic input/output functions to read values from register or write values to register. - */ - -/** - * @defgroup Common_register_access_function Common register access functions - * @ingroup WIZCHIP_IO_Functions - * @brief These are functions to access common registers. - */ - -/** - * @defgroup Socket_register_access_function Socket register access functions - * @ingroup WIZCHIP_IO_Functions - * @brief These are functions to access socket registers. - */ - -//------------------------------- defgroup end -------------------------------------------- -//----------------------------- W5500 Common Registers IOMAP ----------------------------- -/** - * @ingroup Common_register_group - * @brief Mode Register address(R/W)\n - * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc. - * @details Each bit of @ref MR defined as follows. - * - * - * - *
7 6 5 4 3 2 1 0
RST Reserved WOL PB PPPoE Reserved FARP Reserved
- * - \ref MR_RST : Reset - * - \ref MR_WOL : Wake on LAN - * - \ref MR_PB : Ping block - * - \ref MR_PPPOE : PPPoE mode - * - \ref MR_FARP : Force ARP mode - */ -#define MR (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Gateway IP Register address(R/W) - * @details @ref GAR configures the default gateway address. - */ -#define GAR (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Subnet mask Register address(R/W) - * @details @ref SUBR configures the subnet mask address. - */ -#define SUBR (_W5500_IO_BASE_ + (0x0005 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Source MAC Register address(R/W) - * @details @ref SHAR configures the source hardware address. - */ -#define SHAR (_W5500_IO_BASE_ + (0x0009 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Source IP Register address(R/W) - * @details @ref SIPR configures the source IP address. - */ -#define SIPR (_W5500_IO_BASE_ + (0x000F << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Set Interrupt low level timer register address(R/W) - * @details @ref INTLEVEL configures the Interrupt Assert Time. - */ -#define INTLEVEL (_W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Interrupt Register(R/W) - * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host. - * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n - * Each bit of @ref IR defined as follows. - * - * - * - *
7 6 5 4 3 2 1 0
CONFLICT UNREACH PPPoE MP Reserved Reserved Reserved Reserved
- * - \ref IR_CONFLICT : IP conflict - * - \ref IR_UNREACH : Destination unreachable - * - \ref IR_PPPoE : PPPoE connection close - * - \ref IR_MP : Magic packet - */ -#define IR (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Interrupt mask register(R/W) - * @details @ref IMR is used to mask interrupts. Each bit of @ref IMR corresponds to each bit of @ref IR. - * When a bit of @ref IMR is and the corresponding bit of @ref IR is an interrupt will be issued. In other words, - * if a bit of @ref IMR is an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n - * Each bit of @ref IMR defined as the following. - * - * - * - *
7 6 5 4 3 2 1 0
IM_IR7 IM_IR6 IM_IR5 IM_IR4 Reserved Reserved Reserved Reserved
- * - \ref IM_IR7 : IP Conflict Interrupt Mask - * - \ref IM_IR6 : Destination unreachable Interrupt Mask - * - \ref IM_IR5 : PPPoE Close Interrupt Mask - * - \ref IM_IR4 : Magic Packet Interrupt Mask - */ -#define IMR (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Socket Interrupt Register(R/W) - * @details @ref SIR indicates the interrupt status of Socket.\n - * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n - * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */ -#define SIR (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Socket Interrupt Mask Register(R/W) - * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR. - * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is Interrupt will be issued. - * In other words, if a bit of @ref SIMR is an interrupt will be not issued even if the corresponding bit of @ref SIR is - */ -#define SIMR (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Timeout register address( 1 is 100us )(R/W) - * @details @ref RTR configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref RTR is x07D0or 000 - * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref RTR, W5500 waits for the peer response - * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). - * If the peer does not respond within the @ref RTR time, W5500 retransmits the packet or issues timeout. - */ -#define RTR (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Retry count register(R/W) - * @details @ref RCR configures the number of time of retransmission. - * When retransmission occurs as many as ref RCR+1 Timeout interrupt is issued (@ref Sn_IR[TIMEOUT] = . - */ -#define RCR (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP LCP Request Timer register in PPPoE mode(R/W) - * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms. - */ -#define PTIMER (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP LCP Magic number register in PPPoE mode(R/W) - * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation. - */ -#define PMAGIC (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP Destination MAC Register address(R/W) - * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process. - */ -#define PHAR (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP Session Identification Register(R/W) - * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process. - */ -#define PSID (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP Maximum Segment Size(MSS) register(R/W) - * @details @ref PMRU configures the maximum receive unit of PPPoE. - */ -#define PMRU (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Unreachable IP register address in UDP mode(R) - * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number - * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates - * the destination IP address & port number respectively. - */ -#define UIPR (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Unreachable Port register address in UDP mode(R) - * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number - * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR - * indicates the destination IP address & port number respectively. - */ -#define UPORTR (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PHY Status Register(R/W) - * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link. - */ -#define PHYCFGR (_W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -// Reserved (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief chip version register address(R) - * @details @ref VERSIONR always indicates the W5500 version as @b 0x04. - */ -#define VERSIONR (_W5500_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - - -//----------------------------- W5500 Socket Registers IOMAP ----------------------------- -/** - * @ingroup Socket_register_group - * @brief socket Mode register(R/W) - * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n - * Each bit of @ref Sn_MR defined as the following. - * - * - * - *
7 6 5 4 3 2 1 0
MULTI/MFEN BCASTB ND/MC/MMB UCASTB/MIP6B Protocol[3] Protocol[2] Protocol[1] Protocol[0]
- * - @ref Sn_MR_MULTI : Support UDP Multicasting - * - @ref Sn_MR_BCASTB : Broadcast block in UDP Multicasting - * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag - * - @ref Sn_MR_MC : IGMP version used in UDP mulitcasting - * - @ref Sn_MR_MMB : Multicast Blocking in @ref Sn_MR_MACRAW mode - * - @ref Sn_MR_UCASTB : Unicast Block in UDP Multicating - * - @ref Sn_MR_MIP6B : IPv6 packet Blocking in @ref Sn_MR_MACRAW mode - * - Protocol - * - * - * - * - * - * - *
Protocol[3] Protocol[2] Protocol[1] Protocol[0] @b Meaning
0 0 0 0 Closed
0 0 0 1 TCP
0 0 1 0 UDP
0 1 0 0 MACRAW
- * - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n - * - @ref Sn_MR_UDP : UDP - * - @ref Sn_MR_TCP : TCP - * - @ref Sn_MR_CLOSE : Unused socket - * @note MACRAW mode should be only used in Socket 0. - */ -#define Sn_MR(N) (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Socket command register(R/W) - * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n - * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00. - * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n - * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR. - * - @ref Sn_CR_OPEN : Initialize or open socket. - * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode) - * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode) - * - @ref Sn_CR_DISCON : Send closing request in TCP mode. - * - @ref Sn_CR_CLOSE : Close socket. - * - @ref Sn_CR_SEND : Update TX buffer pointer and send data. - * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process. - * - @ref Sn_CR_SEND_KEEP : Send keep alive message. - * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data. - */ -#define Sn_CR(N) (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Socket interrupt register(R) - * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n - * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n - * In order to clear the @ref Sn_IR bit, the host should write the bit to \n - * - * - * - *
7 6 5 4 3 2 1 0
Reserved Reserved Reserved SEND_OK TIMEOUT RECV DISCON CON
- * - \ref Sn_IR_SENDOK : SEND_OK Interrupt - * - \ref Sn_IR_TIMEOUT : TIMEOUT Interrupt - * - \ref Sn_IR_RECV : RECV Interrupt - * - \ref Sn_IR_DISCON : DISCON Interrupt - * - \ref Sn_IR_CON : CON Interrupt - */ -#define Sn_IR(N) (_W5500_IO_BASE_ + (0x0002 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Socket status register(R) - * @details @ref Sn_SR indicates the status of Socket n.\n - * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP. - * @par Normal status - * - @ref SOCK_CLOSED : Closed - * - @ref SOCK_INIT : Initiate state - * - @ref SOCK_LISTEN : Listen state - * - @ref SOCK_ESTABLISHED : Success to connect - * - @ref SOCK_CLOSE_WAIT : Closing state - * - @ref SOCK_UDP : UDP socket - * - @ref SOCK_MACRAW : MAC raw mode socket - *@par Temporary status during changing the status of Socket n. - * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer. - * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer. - * - @ref SOCK_FIN_WAIT : Connection state - * - @ref SOCK_CLOSING : Closing state - * - @ref SOCK_TIME_WAIT : Closing state - * - @ref SOCK_LAST_ACK : Closing state - */ -#define Sn_SR(N) (_W5500_IO_BASE_ + (0x0003 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief source port register(R/W) - * @details @ref Sn_PORT configures the source port number of Socket n. - * It is valid when Socket n is used in TCP/UPD mode. It should be set before OPEN command is ordered. - */ -#define Sn_PORT(N) (_W5500_IO_BASE_ + (0x0004 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Peer MAC register address(R/W) - * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or - * it indicates that it is acquired in ARP-process by CONNECT/SEND command. - */ -#define Sn_DHAR(N) (_W5500_IO_BASE_ + (0x0006 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Peer IP register address(R/W) - * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode. - * In TCP client mode, it configures an IP address of �TCP serverbefore CONNECT command. - * In TCP server mode, it indicates an IP address of �TCP clientafter successfully establishing connection. - * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command. - */ -#define Sn_DIPR(N) (_W5500_IO_BASE_ + (0x000C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Peer port register address(R/W) - * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode. - * In �TCP clientmode, it configures the listen port number of �TCP serverbefore CONNECT command. - * In �TCP Servermode, it indicates the port number of TCP client after successfully establishing connection. - * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command. - */ -#define Sn_DPORT(N) (_W5500_IO_BASE_ + (0x0010 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W) - * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n. - */ -#define Sn_MSSR(N) (_W5500_IO_BASE_ + (0x0012 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -// Reserved (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief IP Type of Service(TOS) Register(R/W) - * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n. - * It is set before OPEN command. - */ -#define Sn_TOS(N) (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -/** - * @ingroup Socket_register_group - * @brief IP Time to live(TTL) Register(R/W) - * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n. - * It is set before OPEN command. - */ -#define Sn_TTL(N) (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Receive memory size register(R/W) - * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n. - * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. - * If a different size is configured, the data cannot be normally received from a peer. - * Although Socket n RX Buffer Block size is initially configured to 2Kbytes, - * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes. - * When exceeded, the data reception error is occurred. - */ -#define Sn_RXBUF_SIZE(N) (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory size register(R/W) - * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. - * If a different size is configured, the data can�t be normally transmitted to a peer. - * Although Socket n TX Buffer Block size is initially configured to 2Kbytes, - * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes. - * When exceeded, the data transmission error is occurred. - */ -#define Sn_TXBUF_SIZE(N) (_W5500_IO_BASE_ + (0x001F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Transmit free memory size register(R) - * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE. - * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent. - * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size, - * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size, - * transmit the data after dividing into the checked size and saving in the Socket n TX buffer. - */ -#define Sn_TX_FSR(N) (_W5500_IO_BASE_ + (0x0020 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory read pointer register address(R) - * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP. - * After its initialization, it is auto-increased by SEND command. - * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer. - * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR. - * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value. - */ -#define Sn_TX_RD(N) (_W5500_IO_BASE_ + (0x0022 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory write pointer register address(R/W) - * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n - * It should be read or be updated like as follows.\n - * 1. Read the starting address for saving the transmitting data.\n - * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n - * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size. - * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value.\n - * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command - */ -#define Sn_TX_WR(N) (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Received data size register(R) - * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer. - * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between - * �Socket n RX Write Pointer (@ref Sn_RX_WR)and �Socket n RX Read Pointer (@ref Sn_RX_RD) - */ -#define Sn_RX_RSR(N) (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Read point of Receive memory(R/W) - * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n - * 1. Read the starting save address of the received data.\n - * 2. Read data from the starting address of Socket n RX Buffer.\n - * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size. - * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs, - * update with the lower 16bits value ignored the carry bit.\n - * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500. - */ -#define Sn_RX_RD(N) (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Write point of Receive memory(R) - * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception. - * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value. - */ -#define Sn_RX_WR(N) (_W5500_IO_BASE_ + (0x002A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief socket interrupt mask register(R) - * @details @ref Sn_IMR masks the interrupt of Socket n. - * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is - * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is - * Host is interrupted by asserted INTn PIN to low. - */ -#define Sn_IMR(N) (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Fragment field value in IP header register(R/W) - * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header). - */ -#define Sn_FRAG(N) (_W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Keep Alive Timer register(R/W) - * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode, - * and ignored in other modes. The time unit is 5s. - * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once. - * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process). - * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate, - * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process). - * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'. - */ -#define Sn_KPALVTR(N) (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -//#define Sn_TSR(N) (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - - -//----------------------------- W5500 Register values ----------------------------- - -/* MODE register values */ -/** - * @brief Reset - * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset. - */ -#define MR_RST 0x80 - -/** - * @brief Wake on LAN - * @details 0 : Disable WOL mode\n - * 1 : Enable WOL mode\n - * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low. - * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.) - * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and - * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode. - */ -#define MR_WOL 0x20 - -/** - * @brief Ping block - * @details 0 : Disable Ping block\n - * 1 : Enable Ping block\n - * If the bit is it blocks the response to a ping request. - */ -#define MR_PB 0x10 - -/** - * @brief Enable PPPoE - * @details 0 : DisablePPPoE mode\n - * 1 : EnablePPPoE mode\n - * If you use ADSL, this bit should be - */ -#define MR_PPPOE 0x08 - -/** - * @brief Enable UDP_FORCE_ARP CHECHK - * @details 0 : Disable Force ARP mode\n - * 1 : Enable Force ARP mode\n - * In Force ARP mode, It forces on sending ARP Request whenever data is sent. - */ -#define MR_FARP 0x02 - -/* IR register values */ -/** - * @brief Check IP conflict. - * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request. - */ -#define IR_CONFLICT 0x80 - -/** - * @brief Get the destination unreachable message in UDP sending. - * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as - * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR. - */ -#define IR_UNREACH 0x40 - -/** - * @brief Get the PPPoE close message. - * @details When PPPoE is disconnected during PPPoE mode, this bit is set. - */ -#define IR_PPPoE 0x20 - -/** - * @brief Get the magic packet interrupt. - * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set. - */ -#define IR_MP 0x10 - - -/* PHYCFGR register value */ -#define PHYCFGR_RST ~(1<<7) //< For PHY reset, must operate AND mask. -#define PHYCFGR_OPMD (1<<6) // Configre PHY with OPMDC value -#define PHYCFGR_OPMDC_ALLA (7<<3) -#define PHYCFGR_OPMDC_PDOWN (6<<3) -#define PHYCFGR_OPMDC_NA (5<<3) -#define PHYCFGR_OPMDC_100FA (4<<3) -#define PHYCFGR_OPMDC_100F (3<<3) -#define PHYCFGR_OPMDC_100H (2<<3) -#define PHYCFGR_OPMDC_10F (1<<3) -#define PHYCFGR_OPMDC_10H (0<<3) -#define PHYCFGR_DPX_FULL (1<<2) -#define PHYCFGR_DPX_HALF (0<<2) -#define PHYCFGR_SPD_100 (1<<1) -#define PHYCFGR_SPD_10 (0<<1) -#define PHYCFGR_LNK_ON (1<<0) -#define PHYCFGR_LNK_OFF (0<<0) - -/* IMR register values */ -/** - * @brief IP Conflict Interrupt Mask. - * @details 0: Disable IP Conflict Interrupt\n - * 1: Enable IP Conflict Interrupt - */ -#define IM_IR7 0x80 - -/** - * @brief Destination unreachable Interrupt Mask. - * @details 0: Disable Destination unreachable Interrupt\n - * 1: Enable Destination unreachable Interrupt - */ -#define IM_IR6 0x40 - -/** - * @brief PPPoE Close Interrupt Mask. - * @details 0: Disable PPPoE Close Interrupt\n - * 1: Enable PPPoE Close Interrupt - */ -#define IM_IR5 0x20 - -/** - * @brief Magic Packet Interrupt Mask. - * @details 0: Disable Magic Packet Interrupt\n - * 1: Enable Magic Packet Interrupt - */ -#define IM_IR4 0x10 - -/* Sn_MR Default values */ -/** - * @brief Support UDP Multicasting - * @details 0 : disable Multicasting\n - * 1 : enable Multicasting\n - * This bit is applied only during UDP mode(P[3:0] = 010.\n - * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number - * before Socket n is opened by OPEN command of @ref Sn_CR. - */ -#define Sn_MR_MULTI 0x80 - -/** - * @brief Broadcast block in UDP Multicasting. - * @details 0 : disable Broadcast Blocking\n - * 1 : enable Broadcast Blocking\n - * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m - * In addition, This bit does when MACRAW mode(P[3:0] = 100 - */ -#define Sn_MR_BCASTB 0x40 - -/** - * @brief No Delayed Ack(TCP), Multicast flag - * @details 0 : Disable No Delayed ACK option\n - * 1 : Enable No Delayed ACK option\n - * This bit is applied only during TCP mode (P[3:0] = 001.\n - * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n - * When this bit is It sends the ACK packet after waiting for the timeout time configured by @ref RTR. - */ -#define Sn_MR_ND 0x20 - -/** - * @brief Unicast Block in UDP Multicasting - * @details 0 : disable Unicast Blocking\n - * 1 : enable Unicast Blocking\n - * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI = - */ -#define Sn_MR_UCASTB 0x10 - -/** - * @brief MAC LAYER RAW SOCK - * @details This configures the protocol mode of Socket n. - * @note MACRAW mode should be only used in Socket 0. - */ -#define Sn_MR_MACRAW 0x04 - -//#define Sn_MR_IPRAW 0x03 /**< IP LAYER RAW SOCK */ - -/** - * @brief UDP - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_UDP 0x02 - -/** - * @brief TCP - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_TCP 0x01 - -/** - * @brief Unused socket - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_CLOSE 0x00 - -/* Sn_MR values used with Sn_MR_MACRAW */ -/** - * @brief MAC filter enable in @ref Sn_MR_MACRAW mode - * @details 0 : disable MAC Filtering\n - * 1 : enable MAC Filtering\n - * This bit is applied only during MACRAW mode(P[3:0] = 100.\n - * When set as W5500 can only receive broadcasting packet or packet sent to itself. - * When this bit is W5500 can receive all packets on Ethernet. - * If user wants to implement Hybrid TCP/IP stack, - * it is recommended that this bit is set as for reducing host overhead to process the all received packets. - */ -#define Sn_MR_MFEN Sn_MR_MULTI - -/** - * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode - * @details 0 : using IGMP version 2\n - * 1 : using IGMP version 1\n - * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = - * It configures the version for IGMP messages (Join/Leave/Report). - */ -#define Sn_MR_MMB Sn_MR_ND - -/** - * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode - * @details 0 : disable IPv6 Blocking\n - * 1 : enable IPv6 Blocking\n - * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet. - */ -#define Sn_MR_MIP6B Sn_MR_UCASTB - -/* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */ -/** - * @brief IGMP version used in UDP mulitcasting - * @details 0 : disable Multicast Blocking\n - * 1 : enable Multicast Blocking\n - * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address. - */ -#define Sn_MR_MC Sn_MR_ND - -/* Sn_MR alternate values */ -/** - * @brief For Berkeley Socket API - */ -#define SOCK_STREAM Sn_MR_TCP - -/** - * @brief For Berkeley Socket API - */ -#define SOCK_DGRAM Sn_MR_UDP - - -/* Sn_CR values */ -/** - * @brief Initialize or open socket - * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0). - * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n - * - * - * - * - * - * - *
\b Sn_MR (P[3:0]) \b Sn_SR
Sn_MR_CLOSE (000
Sn_MR_TCP (001 SOCK_INIT (0x13)
Sn_MR_UDP (010 SOCK_UDP (0x22)
S0_MR_MACRAW (100 SOCK_MACRAW (0x02)
- */ -#define Sn_CR_OPEN 0x01 - -/** - * @brief Wait connection request in TCP mode(Server mode) - * @details This is valid only in TCP mode (Sn_MR(P3:P0) = Sn_MR_TCP). - * In this mode, Socket n operates as a �TCP serverand waits for connection-request (SYN packet) from any �TCP client - * The @ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN. - * When a �TCP clientconnection request is successfully established, - * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes - * But when a �TCP clientconnection request is failed, Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED. - */ -#define Sn_CR_LISTEN 0x02 - -/** - * @brief Send connection request in TCP mode(Client mode) - * @details To connect, a connect-request (SYN packet) is sent to b>TCP serverconfigured by @ref Sn_DIPR & Sn_DPORT(destination address & port). - * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n - * The connect-request fails in the following three cases.\n - * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = ) because destination hardware address is not acquired through the ARP-process.\n - * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n - * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED. - * @note This is valid only in TCP mode and operates when Socket n acts as b>TCP client - */ -#define Sn_CR_CONNECT 0x04 - -/** - * @brief Send closing request in TCP mode - * @details Regardless of b>TCP serveror b>TCP client the DISCON command processes the disconnect-process (b>Active closeor b>Passive close.\n - * @par Active close - * it transmits disconnect-request(FIN packet) to the connected peer\n - * @par Passive close - * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n - * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n - * Otherwise, TCPTO occurs (Sn_IR(3)=)= and then @ref Sn_SR is changed to @ref SOCK_CLOSED. - * @note Valid only in TCP mode. - */ -#define Sn_CR_DISCON 0x08 - -/** - * @brief Close socket - * @details Sn_SR is changed to @ref SOCK_CLOSED. - */ -#define Sn_CR_CLOSE 0x10 - -/** - * @brief Update TX buffer pointer and send data - * @details SEND transmits all the data in the Socket n TX buffer.\n - * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n, - * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD). - */ -#define Sn_CR_SEND 0x20 - -/** - * @brief Send data with MAC address, so without ARP process - * @details The basic operation is same as SEND.\n - * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n - * But SEND_MAC transmits data without the automatic ARP-process.\n - * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process. - * @note Valid only in UDP mode. - */ -#define Sn_CR_SEND_MAC 0x21 - -/** - * @brief Send keep alive message - * @details It checks the connection status by sending 1byte keep-alive packet.\n - * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur. - * @note Valid only in TCP mode. - */ -#define Sn_CR_SEND_KEEP 0x22 - -/** - * @brief Update RX buffer pointer and receive data - * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n - * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR), - * and Socket n RX Read Pointer Register (@ref Sn_RX_RD). - */ -#define Sn_CR_RECV 0x40 - -/* Sn_IR values */ -/** - * @brief SEND_OK Interrupt - * @details This is issued when SEND command is completed. - */ -#define Sn_IR_SENDOK 0x10 - -/** - * @brief TIMEOUT Interrupt - * @details This is issued when ARPTO or TCPTO occurs. - */ -#define Sn_IR_TIMEOUT 0x08 - -/** - * @brief RECV Interrupt - * @details This is issued whenever data is received from a peer. - */ -#define Sn_IR_RECV 0x04 - -/** - * @brief DISCON Interrupt - * @details This is issued when FIN or FIN/ACK packet is received from a peer. - */ -#define Sn_IR_DISCON 0x02 - -/** - * @brief CON Interrupt - * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED. - */ -#define Sn_IR_CON 0x01 - -/* Sn_SR values */ -/** - * @brief Closed - * @details This indicates that Socket n is released.\N - * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status. - */ -#define SOCK_CLOSED 0x00 - -/** - * @brief Initiate state - * @details This indicates Socket n is opened with TCP mode.\N - * It is changed to @ref SOCK_INIT when Sn_MR(P[3:0]) = 001and OPEN command is ordered.\N - * After @ref SOCK_INIT, user can use LISTEN /CONNECT command. - */ -#define SOCK_INIT 0x13 - -/** - * @brief Listen state - * @details This indicates Socket n is operating as b>TCP servermode and waiting for connection-request (SYN packet) from a peer (b>TCP client.\n - * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n - * Otherwise it will change to @ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = . - */ -#define SOCK_LISTEN 0x14 - -/** - * @brief Connection state - * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n - * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n - * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n - * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = is occurred. - */ -#define SOCK_SYNSENT 0x15 - -/** - * @brief Connection state - * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n - * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n - * If not, it changes to @ref SOCK_CLOSED after timeout occurs (@ref Sn_IR[TIMEOUT] = . - */ -#define SOCK_SYNRECV 0x16 - -/** - * @brief Success to connect - * @details This indicates the status of the connection of Socket n.\n - * It changes to @ref SOCK_ESTABLISHED when the b>TCP SERVERprocessed the SYN packet from the b>TCP CLIENTduring @ref SOCK_LISTEN, or - * when the CONNECT command is successful.\n - * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command. - */ -#define SOCK_ESTABLISHED 0x17 - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_FIN_WAIT 0x18 - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_CLOSING 0x1A - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_TIME_WAIT 0x1B - -/** - * @brief Closing state - * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n - * This is half-closing status, and data can be transferred.\n - * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used. - */ -#define SOCK_CLOSE_WAIT 0x1C - -/** - * @brief Closing state - * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n - * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (@ref Sn_IR[TIMEOUT] = . - */ -#define SOCK_LAST_ACK 0x1D - -/** - * @brief UDP socket - * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010.\n - * It changes to SOCK_UPD when Sn_MR(P[3:0]) = 010 and OPEN command is ordered.\n - * Unlike TCP mode, data can be transfered without the connection-process. - */ -#define SOCK_UDP 0x22 - -//#define SOCK_IPRAW 0x32 /**< IP raw mode socket */ - -/** - * @brief MAC raw mode socket - * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n - * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n - * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process. - */ -#define SOCK_MACRAW 0x42 - -//#define SOCK_PPPOE 0x5F - -/* IP PROTOCOL */ -#define IPPROTO_IP 0 //< Dummy for IP -#define IPPROTO_ICMP 1 //< Control message protocol -#define IPPROTO_IGMP 2 //< Internet group management protocol -#define IPPROTO_GGP 3 //< Gateway^2 (deprecated) -#define IPPROTO_TCP 6 //< TCP -#define IPPROTO_PUP 12 //< PUP -#define IPPROTO_UDP 17 //< UDP -#define IPPROTO_IDP 22 //< XNS idp -#define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol -#define IPPROTO_RAW 255 //< Raw IP packet - - -/** - * @brief Enter a critical section - * - * @details It is provided to protect your shared code which are executed without distribution. \n \n - * - * In non-OS environment, It can be just implemented by disabling whole interrupt.\n - * In OS environment, You can replace it to critical section api supported by OS. - * - * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() - * \sa WIZCHIP_CRITICAL_EXIT() - */ -#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter() - -/** - * @brief Exit a critical section - * - * @details It is provided to protect your shared code which are executed without distribution. \n\n - * - * In non-OS environment, It can be just implemented by disabling whole interrupt. \n - * In OS environment, You can replace it to critical section api supported by OS. - * - * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() - * @sa WIZCHIP_CRITICAL_ENTER() - */ -#ifdef _exit -#undef _exit -#endif -#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit() - - - -//////////////////////// -// Basic I/O Function // -//////////////////////// - -/** - * @ingroup Basic_IO_function - * @brief It reads 1 byte value from a register. - * @param AddrSel Register address - * @return The value of register - */ -uint8_t WIZCHIP_READ (uint32_t AddrSel); - -/** - * @ingroup Basic_IO_function - * @brief It writes 1 byte value to a register. - * @param AddrSel Register address - * @param wb Write data - * @return void - */ -void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ); - -/** - * @ingroup Basic_IO_function - * @brief It reads sequence data from registers. - * @param AddrSel Register address - * @param pBuf Pointer buffer to read data - * @param len Data length - */ -void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It writes sequence data to registers. - * @param AddrSel Register address - * @param pBuf Pointer buffer to write data - * @param len Data length - */ -void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len); - -///////////////////////////////// -// Common Register I/O function // -///////////////////////////////// -/** - * @ingroup Common_register_access_function - * @brief Set Mode Register - * @param (uint8_t)mr The value to be set. - * @sa getMR() - */ -#define setMR(mr) \ - WIZCHIP_WRITE(MR,mr) - - -/** - * @ingroup Common_register_access_function - * @brief Get Mode Register - * @return uint8_t. The value of Mode register. - * @sa setMR() - */ -#define getMR() \ - WIZCHIP_READ(MR) - -/** - * @ingroup Common_register_access_function - * @brief Set gateway IP address - * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes. - * @sa getGAR() - */ -#define setGAR(gar) \ - WIZCHIP_WRITE_BUF(GAR,gar,4) - -/** - * @ingroup Common_register_access_function - * @brief Get gateway IP address - * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes. - * @sa setGAR() - */ -#define getGAR(gar) \ - WIZCHIP_READ_BUF(GAR,gar,4) - -/** - * @ingroup Common_register_access_function - * @brief Set subnet mask address - * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes. - * @sa getSUBR() - */ -#define setSUBR(subr) \ - WIZCHIP_WRITE_BUF(SUBR, subr,4) - - -/** - * @ingroup Common_register_access_function - * @brief Get subnet mask address - * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes. - * @sa setSUBR() - */ -#define getSUBR(subr) \ - WIZCHIP_READ_BUF(SUBR, subr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Set local MAC address - * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes. - * @sa getSHAR() - */ -#define setSHAR(shar) \ - WIZCHIP_WRITE_BUF(SHAR, shar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Get local MAC address - * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes. - * @sa setSHAR() - */ -#define getSHAR(shar) \ - WIZCHIP_READ_BUF(SHAR, shar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Set local IP address - * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes. - * @sa getSIPR() - */ -#define setSIPR(sipr) \ - WIZCHIP_WRITE_BUF(SIPR, sipr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Get local IP address - * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes. - * @sa setSIPR() - */ -#define getSIPR(sipr) \ - WIZCHIP_READ_BUF(SIPR, sipr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Set INTLEVEL register - * @param (uint16_t)intlevel Value to set @ref INTLEVEL register. - * @sa getINTLEVEL() - */ -#define setINTLEVEL(intlevel) {\ - WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \ - } - - -/** - * @ingroup Common_register_access_function - * @brief Get INTLEVEL register - * @return uint16_t. Value of @ref INTLEVEL register. - * @sa setINTLEVEL() - */ -#define getINTLEVEL() \ - ((WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref IR register - * @param (uint8_t)ir Value to set @ref IR register. - * @sa getIR() - */ -#define setIR(ir) \ - WIZCHIP_WRITE(IR, (ir & 0xF0)) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref IR register - * @return uint8_t. Value of @ref IR register. - * @sa setIR() - */ -#define getIR() \ - (WIZCHIP_READ(IR) & 0xF0) -/** - * @ingroup Common_register_access_function - * @brief Set @ref IMR register - * @param (uint8_t)imr Value to set @ref IMR register. - * @sa getIMR() - */ -#define setIMR(imr) \ - WIZCHIP_WRITE(IMR, imr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref IMR register - * @return uint8_t. Value of @ref IMR register. - * @sa setIMR() - */ -#define getIMR() \ - WIZCHIP_READ(IMR) - - -/** - * @ingroup Common_register_access_function - * @brief Set @ref SIR register - * @param (uint8_t)sir Value to set @ref SIR register. - * @sa getSIR() - */ -#define setSIR(sir) \ - WIZCHIP_WRITE(SIR, sir) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref SIR register - * @return uint8_t. Value of @ref SIR register. - * @sa setSIR() - */ -#define getSIR() \ - WIZCHIP_READ(SIR) -/** - * @ingroup Common_register_access_function - * @brief Set @ref SIMR register - * @param (uint8_t)simr Value to set @ref SIMR register. - * @sa getSIMR() - */ -#define setSIMR(simr) \ - WIZCHIP_WRITE(SIMR, simr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref SIMR register - * @return uint8_t. Value of @ref SIMR register. - * @sa setSIMR() - */ -#define getSIMR() \ - WIZCHIP_READ(SIMR) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref RTR register - * @param (uint16_t)rtr Value to set @ref RTR register. - * @sa getRTR() - */ -#define setRTR(rtr) {\ - WIZCHIP_WRITE(RTR, (uint8_t)(rtr >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(RTR,1), (uint8_t) rtr); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref RTR register - * @return uint16_t. Value of @ref RTR register. - * @sa setRTR() - */ -#define getRTR() \ - ((WIZCHIP_READ(RTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(RTR,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref RCR register - * @param (uint8_t)rcr Value to set @ref RCR register. - * @sa getRCR() - */ -#define setRCR(rcr) \ - WIZCHIP_WRITE(RCR, rcr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref RCR register - * @return uint8_t. Value of @ref RCR register. - * @sa setRCR() - */ -#define getRCR() \ - WIZCHIP_READ(RCR) - -//================================================== test done =========================================================== - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PTIMER register - * @param (uint8_t)ptimer Value to set @ref PTIMER register. - * @sa getPTIMER() - */ -#define setPTIMER(ptimer) \ - WIZCHIP_WRITE(PTIMER, ptimer) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PTIMER register - * @return uint8_t. Value of @ref PTIMER register. - * @sa setPTIMER() - */ -#define getPTIMER() \ - WIZCHIP_READ(PTIMER) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PMAGIC register - * @param (uint8_t)pmagic Value to set @ref PMAGIC register. - * @sa getPMAGIC() - */ -#define setPMAGIC(pmagic) \ - WIZCHIP_WRITE(PMAGIC, pmagic) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PMAGIC register - * @return uint8_t. Value of @ref PMAGIC register. - * @sa setPMAGIC() - */ -#define getPMAGIC() \ - WIZCHIP_READ(PMAGIC) - -/** - * @ingroup Common_register_access_function - * @brief Set PHAR address - * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes. - * @sa getPHAR() - */ -#define setPHAR(phar) \ - WIZCHIP_WRITE_BUF(PHAR, phar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Get local IP address - * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes. - * @sa setPHAR() - */ -#define getPHAR(phar) \ - WIZCHIP_READ_BUF(PHAR, phar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PSID register - * @param (uint16_t)psid Value to set @ref PSID register. - * @sa getPSID() - */ -#define setPSID(psid) {\ - WIZCHIP_WRITE(PSID, (uint8_t)(psid >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PSID register - * @return uint16_t. Value of @ref PSID register. - * @sa setPSID() - */ -//uint16_t getPSID(void); -#define getPSID() \ - ((WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PMRU register - * @param (uint16_t)pmru Value to set @ref PMRU register. - * @sa getPMRU() - */ -#define setPMRU(pmru) { \ - WIZCHIP_WRITE(PMRU, (uint8_t)(pmru>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PMRU register - * @return uint16_t. Value of @ref PMRU register. - * @sa setPMRU() - */ -#define getPMRU() \ - ((WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1))) - -/** - * @ingroup Common_register_access_function - * @brief Get unreachable IP address - * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes. - */ -#define getUIPR(uipr) \ - WIZCHIP_READ_BUF(UIPR,uipr,6) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref UPORTR register - * @return uint16_t. Value of @ref UPORTR register. - */ -#define getUPORTR() \ - ((WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PHYCFGR register - * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register. - * @sa getPHYCFGR() - */ -#define setPHYCFGR(phycfgr) \ - WIZCHIP_WRITE(PHYCFGR, phycfgr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PHYCFGR register - * @return uint8_t. Value of @ref PHYCFGR register. - * @sa setPHYCFGR() - */ -#define getPHYCFGR() \ - WIZCHIP_READ(PHYCFGR) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref VERSIONR register - * @return uint8_t. Value of @ref VERSIONR register. - */ -#define getVERSIONR() \ - WIZCHIP_READ(VERSIONR) - -///////////////////////////////////// - -/////////////////////////////////// -// Socket N register I/O function // -/////////////////////////////////// -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)mr Value to set @ref Sn_MR - * @sa getSn_MR() - */ -#define setSn_MR(sn, mr) \ - WIZCHIP_WRITE(Sn_MR(sn),mr) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_MR. - * @sa setSn_MR() - */ -#define getSn_MR(sn) \ - WIZCHIP_READ(Sn_MR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_CR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)cr Value to set @ref Sn_CR - * @sa getSn_CR() - */ -#define setSn_CR(sn, cr) \ - WIZCHIP_WRITE(Sn_CR(sn), cr) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_CR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_CR. - * @sa setSn_CR() - */ -#define getSn_CR(sn) \ - WIZCHIP_READ(Sn_CR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_IR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)ir Value to set @ref Sn_IR - * @sa getSn_IR() - */ -#define setSn_IR(sn, ir) \ - WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F)) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_IR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_IR. - * @sa setSn_IR() - */ -#define getSn_IR(sn) \ - (WIZCHIP_READ(Sn_IR(sn)) & 0x1F) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_IMR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)imr Value to set @ref Sn_IMR - * @sa getSn_IMR() - */ -#define setSn_IMR(sn, imr) \ - WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F)) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_IMR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_IMR. - * @sa setSn_IMR() - */ -#define getSn_IMR(sn) \ - (WIZCHIP_READ(Sn_IMR(sn)) & 0x1F) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_SR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_SR. - */ -#define getSn_SR(sn) \ - WIZCHIP_READ(Sn_SR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_PORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)port Value to set @ref Sn_PORT. - * @sa getSn_PORT() - */ -#define setSn_PORT(sn, port) { \ - WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1), (uint8_t) port); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_PORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_PORT. - * @sa setSn_PORT() - */ -#define getSn_PORT(sn) \ - ((WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DHAR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes. - * @sa getSn_DHAR() - */ -#define setSn_DHAR(sn, dhar) \ - WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes. - * @sa setSn_DHAR() - */ -#define getSn_DHAR(sn, dhar) \ - WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DIPR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes. - * @sa getSn_DIPR() - */ -#define setSn_DIPR(sn, dipr) \ - WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_DIPR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes. - * @sa SetSn_DIPR() - */ -#define getSn_DIPR(sn, dipr) \ - WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DPORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)dport Value to set @ref Sn_DPORT - * @sa getSn_DPORT() - */ -#define setSn_DPORT(sn, dport) { \ - WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1), (uint8_t) dport); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_DPORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_DPORT. - * @sa setSn_DPORT() - */ -#define getSn_DPORT(sn) \ - ((WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_MSSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)mss Value to set @ref Sn_MSSR - * @sa setSn_MSSR() - */ -#define setSn_MSSR(sn, mss) { \ - WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1), (uint8_t) mss); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MSSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_MSSR. - * @sa setSn_MSSR() - */ -#define getSn_MSSR(sn) \ - ((WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TOS register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)tos Value to set @ref Sn_TOS - * @sa getSn_TOS() - */ -#define setSn_TOS(sn, tos) \ - WIZCHIP_WRITE(Sn_TOS(sn), tos) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TOS register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of Sn_TOS. - * @sa setSn_TOS() - */ -#define getSn_TOS(sn) \ - WIZCHIP_READ(Sn_TOS(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TTL register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)ttl Value to set @ref Sn_TTL - * @sa getSn_TTL() - */ -#define setSn_TTL(sn, ttl) \ - WIZCHIP_WRITE(Sn_TTL(sn), ttl) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TTL register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_TTL. - * @sa setSn_TTL() - */ -#define getSn_TTL(sn) \ - WIZCHIP_READ(Sn_TTL(sn)) - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_RXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE - * @sa getSn_RXBUF_SIZE() - */ -#define setSn_RXBUF_SIZE(sn, rxbufsize) \ - WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_RXBUF_SIZE. - * @sa setSn_RXBUF_SIZE() - */ -#define getSn_RXBUF_SIZE(sn) \ - WIZCHIP_READ(Sn_RXBUF_SIZE(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE - * @sa getSn_TXBUF_SIZE() - */ -#define setSn_TXBUF_SIZE(sn, txbufsize) \ - WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_TXBUF_SIZE. - * @sa setSn_TXBUF_SIZE() - */ -#define getSn_TXBUF_SIZE(sn) \ - WIZCHIP_READ(Sn_TXBUF_SIZE(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_FSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_FSR. - */ -uint16_t getSn_TX_FSR(uint8_t sn); - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_RD. - */ -#define getSn_TX_RD(sn) \ - ((WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)txwr Value to set @ref Sn_TX_WR - * @sa GetSn_TX_WR() - */ -#define setSn_TX_WR(sn, txwr) { \ - WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1), (uint8_t) txwr); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_WR. - * @sa setSn_TX_WR() - */ -#define getSn_TX_WR(sn) \ - ((WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1))) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_RSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_RX_RSR. - */ -uint16_t getSn_RX_RSR(uint8_t sn); - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_RX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD - * @sa getSn_RX_RD() - */ -#define setSn_RX_RD(sn, rxrd) { \ - WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1), (uint8_t) rxrd); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @regurn uint16_t. Value of @ref Sn_RX_RD. - * @sa setSn_RX_RD() - */ -#define getSn_RX_RD(sn) \ - ((WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_RX_WR. - */ -#define getSn_RX_WR(sn) \ - ((WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1))) - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_FRAG register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)frag Value to set @ref Sn_FRAG - * @sa getSn_FRAD() - */ -#define setSn_FRAG(sn, frag) { \ - WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_FRAG register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_FRAG. - * @sa setSn_FRAG() - */ -#define getSn_FRAG(sn) \ - ((WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_KPALVTR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR - * @sa getSn_KPALVTR() - */ -#define setSn_KPALVTR(sn, kpalvt) \ - WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_KPALVTR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_KPALVTR. - * @sa setSn_KPALVTR() - */ -#define getSn_KPALVTR(sn) \ - WIZCHIP_READ(Sn_KPALVTR(sn)) - -////////////////////////////////////// - -///////////////////////////////////// -// Sn_TXBUF & Sn_RXBUF IO function // -///////////////////////////////////// -/** - * @brief Gets the max buffer size of socket sn passed as parameter. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of Socket n RX max buffer size. - */ -#define getSn_RxMAX(sn) \ - (getSn_RXBUF_SIZE(sn) << 10) - -/** - * @brief Gets the max buffer size of socket sn passed as parameters. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of Socket n TX max buffer size. - */ -//uint16_t getSn_TxMAX(uint8_t sn); -#define getSn_TxMAX(sn) \ - (getSn_TXBUF_SIZE(sn) << 10) - -/** - * @ingroup Basic_IO_function - * @brief It copies data to internal TX memory - * - * @details This function reads the Tx write pointer register and after that, - * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory - * and updates the Tx write pointer register. - * This function is being called by send() and sendto() function also. - * - * @note User should read upper byte first and lower byte later to get proper value. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param wizdata Pointer buffer to write data - * @param len Data length - * @sa wiz_recv_data() - */ -void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It copies data to your buffer from internal RX memory - * - * @details This function read the Rx read pointer register and after that, - * it copies the received data from internal RX memory - * to wizdata(pointer variable) of the length of len(variable) bytes. - * This function is being called by recv() also. - * - * @note User should read upper byte first and lower byte later to get proper value. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param wizdata Pointer buffer to read data - * @param len Data length - * @sa wiz_send_data() - */ -void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It discard the received data in RX memory. - * @details It discards the data of the length of len(variable) bytes in internal RX memory. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param len Data length - */ -void wiz_recv_ignore(uint8_t sn, uint16_t len); - -#endif // _W5500_H_ diff --git a/drivers/wiznet5k/ethernet/wizchip_conf.c b/drivers/wiznet5k/ethernet/wizchip_conf.c deleted file mode 100644 index 3e54d2c90b..0000000000 --- a/drivers/wiznet5k/ethernet/wizchip_conf.c +++ /dev/null @@ -1,662 +0,0 @@ -//****************************************************************************/ -//! -//! \file wizchip_conf.c -//! \brief WIZCHIP Config Header File. -//! \version 1.0.1 -//! \date 2013/10/21 -//! \par Revision history -//! <2014/05/01> V1.0.1 Refer to M20140501 -//! 1. Explicit type casting in wizchip_bus_readbyte() & wizchip_bus_writebyte() -// Issued by Mathias ClauBen. -//! uint32_t type converts into ptrdiff_t first. And then recoverting it into uint8_t* -//! For remove the warning when pointer type size is not 32bit. -//! If ptrdiff_t doesn't support in your complier, You should must replace ptrdiff_t into your suitable pointer type. -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//*****************************************************************************/ -//A20140501 : for use the type - ptrdiff_t -#include -// - -#include "wizchip_conf.h" -#include "socket.h" - -/** - * @brief Default function to enable interrupt. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_cris_enter(void) {}; -/** - * @brief Default function to disable interrupt. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_cris_exit(void) {}; -/** - * @brief Default function to select chip. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_cs_select(void) {}; -/** - * @brief Default function to deselect chip. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_cs_deselect(void) {}; -/** - * @brief Default function to read in direct or indirect interface. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ - //M20140501 : Explict pointer type casting -//uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *) AddrSel); }; -uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *)((ptrdiff_t) AddrSel)); }; -/** - * @brief Default function to write in direct or indirect interface. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ - -//M20140501 : Explict pointer type casting -//void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*) AddrSel) = wb; }; -void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*)((ptrdiff_t)AddrSel)) = wb; }; - -/** - * @brief Default function to read in SPI interface. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_spi_readbytes(uint8_t *buf, uint32_t len) {} -/** - * @brief Default function to write in SPI interface. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_spi_writebytes(const uint8_t *buf, uint32_t len) {} - -/** - * @\ref _WIZCHIP instance - */ -_WIZCHIP WIZCHIP = - { - .id = _WIZCHIP_ID_, - .if_mode = _WIZCHIP_IO_MODE_, - .CRIS._enter = wizchip_cris_enter, - .CRIS._exit = wizchip_cris_exit, - .CS._select = wizchip_cs_select, - .CS._deselect = wizchip_cs_deselect, - .IF.BUS._read_byte = wizchip_bus_readbyte, - .IF.BUS._write_byte = wizchip_bus_writebyte -// .IF.SPI._read_byte = wizchip_spi_readbyte, -// .IF.SPI._write_byte = wizchip_spi_writebyte - }; - -#if _WIZCHIP_ == 5200 // for W5200 ARP errata -static uint8_t _SUBN_[4]; // subnet -#endif -static uint8_t _DNS_[4]; // DNS server ip address -static dhcp_mode _DHCP_; // DHCP mode - -void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void)) -{ - if(!cris_en || !cris_ex) - { - WIZCHIP.CRIS._enter = wizchip_cris_enter; - WIZCHIP.CRIS._exit = wizchip_cris_exit; - } - else - { - WIZCHIP.CRIS._enter = cris_en; - WIZCHIP.CRIS._exit = cris_ex; - } -} - -void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void)) -{ - if(!cs_sel || !cs_desel) - { - WIZCHIP.CS._select = wizchip_cs_select; - WIZCHIP.CS._deselect = wizchip_cs_deselect; - } - else - { - WIZCHIP.CS._select = cs_sel; - WIZCHIP.CS._deselect = cs_desel; - } -} - -void reg_wizchip_bus_cbfunc(uint8_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb)) -{ - while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_BUS_)); - - if(!bus_rb || !bus_wb) - { - WIZCHIP.IF.BUS._read_byte = wizchip_bus_readbyte; - WIZCHIP.IF.BUS._write_byte = wizchip_bus_writebyte; - } - else - { - WIZCHIP.IF.BUS._read_byte = bus_rb; - WIZCHIP.IF.BUS._write_byte = bus_wb; - } -} - -void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t)) -{ - while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_)); - - if(!spi_rb || !spi_wb) - { - WIZCHIP.IF.SPI._read_bytes = wizchip_spi_readbytes; - WIZCHIP.IF.SPI._write_bytes = wizchip_spi_writebytes; - } - else - { - WIZCHIP.IF.SPI._read_bytes = spi_rb; - WIZCHIP.IF.SPI._write_bytes = spi_wb; - } -} - -int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg) -{ - uint8_t tmp = 0; - uint8_t* ptmp[2] = {0,0}; - switch(cwtype) - { - case CW_RESET_WIZCHIP: - wizchip_sw_reset(); - break; - case CW_INIT_WIZCHIP: - if(arg != 0) - { - ptmp[0] = (uint8_t*)arg; - ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_; - } - return wizchip_init(ptmp[0], ptmp[1]); - case CW_CLR_INTERRUPT: - wizchip_clrinterrupt(*((intr_kind*)arg)); - break; - case CW_GET_INTERRUPT: - *((intr_kind*)arg) = wizchip_getinterrupt(); - break; - case CW_SET_INTRMASK: - wizchip_setinterruptmask(*((intr_kind*)arg)); - break; - case CW_GET_INTRMASK: - *((intr_kind*)arg) = wizchip_getinterruptmask(); - break; - #if _WIZCHIP_ > 5100 - case CW_SET_INTRTIME: - setINTLEVEL(*(uint16_t*)arg); - break; - case CW_GET_INTRTIME: - *(uint16_t*)arg = getINTLEVEL(); - break; - #endif - case CW_GET_ID: - ((uint8_t*)arg)[0] = WIZCHIP.id[0]; - ((uint8_t*)arg)[1] = WIZCHIP.id[1]; - ((uint8_t*)arg)[2] = WIZCHIP.id[2]; - ((uint8_t*)arg)[3] = WIZCHIP.id[3]; - ((uint8_t*)arg)[4] = WIZCHIP.id[4]; - ((uint8_t*)arg)[5] = 0; - break; - #if _WIZCHIP_ == 5500 - case CW_RESET_PHY: - wizphy_reset(); - break; - case CW_SET_PHYCONF: - wizphy_setphyconf((wiz_PhyConf*)arg); - break; - case CW_GET_PHYCONF: - wizphy_getphyconf((wiz_PhyConf*)arg); - break; - case CW_GET_PHYSTATUS: - break; - case CW_SET_PHYPOWMODE: - return wizphy_setphypmode(*(uint8_t*)arg); - #endif - case CW_GET_PHYPOWMODE: - tmp = wizphy_getphypmode(); - if((int8_t)tmp == -1) return -1; - *(uint8_t*)arg = tmp; - break; - case CW_GET_PHYLINK: - tmp = wizphy_getphylink(); - if((int8_t)tmp == -1) return -1; - *(uint8_t*)arg = tmp; - break; - default: - return -1; - } - return 0; -} - - -int8_t ctlnetwork(ctlnetwork_type cntype, void* arg) -{ - - switch(cntype) - { - case CN_SET_NETINFO: - wizchip_setnetinfo((wiz_NetInfo*)arg); - break; - case CN_GET_NETINFO: - wizchip_getnetinfo((wiz_NetInfo*)arg); - break; - case CN_SET_NETMODE: - return wizchip_setnetmode(*(netmode_type*)arg); - case CN_GET_NETMODE: - *(netmode_type*)arg = wizchip_getnetmode(); - break; - case CN_SET_TIMEOUT: - wizchip_settimeout((wiz_NetTimeout*)arg); - break; - case CN_GET_TIMEOUT: - wizchip_gettimeout((wiz_NetTimeout*)arg); - break; - default: - return -1; - } - return 0; -} - -void wizchip_sw_reset(void) -{ - uint8_t gw[4], sn[4], sip[4]; - uint8_t mac[6]; - getSHAR(mac); - getGAR(gw); getSUBR(sn); getSIPR(sip); - setMR(MR_RST); - getMR(); // for delay - setSHAR(mac); - setGAR(gw); - setSUBR(sn); - setSIPR(sip); -} - -int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize) -{ - int8_t i; - int8_t tmp = 0; - wizchip_sw_reset(); - if(txsize) - { - tmp = 0; - for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) - tmp += txsize[i]; - if(tmp > 16) return -1; - for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) - setSn_TXBUF_SIZE(i, txsize[i]); - } - if(rxsize) - { - tmp = 0; - for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) - tmp += rxsize[i]; - if(tmp > 16) return -1; - for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) - setSn_RXBUF_SIZE(i, rxsize[i]); - } - - WIZCHIP_EXPORT(socket_reset)(); - - return 0; -} - -void wizchip_clrinterrupt(intr_kind intr) -{ - uint8_t ir = (uint8_t)intr; - uint8_t sir = (uint8_t)((uint16_t)intr >> 8); -#if _WIZCHIP_ < 5500 - ir |= (1<<4); // IK_WOL -#endif -#if _WIZCHIP_ == 5200 - ir |= (1 << 6); -#endif - -#if _WIZCHIP_ < 5200 - sir &= 0x0F; -#endif - -#if _WIZCHIP_ == 5100 - ir |= sir; - setIR(ir); -#else - setIR(ir); - setSIR(sir); -#endif -} - -intr_kind wizchip_getinterrupt(void) -{ - uint8_t ir = 0; - uint8_t sir = 0; - uint16_t ret = 0; -#if _WIZCHIP_ == 5100 - ir = getIR(); - sir = ir 0x0F; -#else - ir = getIR(); - sir = getSIR(); -#endif - -#if _WIZCHIP_ < 5500 - ir &= ~(1<<4); // IK_WOL -#endif -#if _WIZCHIP_ == 5200 - ir &= ~(1 << 6); -#endif - ret = sir; - ret = (ret << 8) + ir; - return (intr_kind)ret; -} - -void wizchip_setinterruptmask(intr_kind intr) -{ - uint8_t imr = (uint8_t)intr; - uint8_t simr = (uint8_t)((uint16_t)intr >> 8); -#if _WIZCHIP_ < 5500 - imr &= ~(1<<4); // IK_WOL -#endif -#if _WIZCHIP_ == 5200 - imr &= ~(1 << 6); -#endif - -#if _WIZCHIP_ < 5200 - simr &= 0x0F; -#endif - -#if _WIZCHIP_ == 5100 - imr |= simr; - setIMR(imr); -#else - setIMR(imr); - setSIMR(simr); -#endif -} - -intr_kind wizchip_getinterruptmask(void) -{ - uint8_t imr = 0; - uint8_t simr = 0; - uint16_t ret = 0; -#if _WIZCHIP_ == 5100 - imr = getIMR(); - simr = imr 0x0F; -#else - imr = getIMR(); - simr = getSIMR(); -#endif - -#if _WIZCHIP_ < 5500 - imr &= ~(1<<4); // IK_WOL -#endif -#if _WIZCHIP_ == 5200 - imr &= ~(1 << 6); // IK_DEST_UNREACH -#endif - ret = simr; - ret = (ret << 8) + imr; - return (intr_kind)ret; -} - -int8_t wizphy_getphylink(void) -{ - int8_t tmp; -#if _WIZCHIP_ == 5200 - if(getPHYSTATUS() & PHYSTATUS_LINK) - tmp = PHY_LINK_ON; - else - tmp = PHY_LINK_OFF; -#elif _WIZCHIP_ == 5500 - if(getPHYCFGR() & PHYCFGR_LNK_ON) - tmp = PHY_LINK_ON; - else - tmp = PHY_LINK_OFF; -#else - tmp = -1; -#endif - return tmp; -} - -#if _WIZCHIP_ > 5100 - -int8_t wizphy_getphypmode(void) -{ - int8_t tmp = 0; - #if _WIZCHIP_ == 5200 - if(getPHYSTATUS() & PHYSTATUS_POWERDOWN) - tmp = PHY_POWER_DOWN; - else - tmp = PHY_POWER_NORM; - #elif _WIZCHIP_ == 5500 - if(getPHYCFGR() & PHYCFGR_OPMDC_PDOWN) - tmp = PHY_POWER_DOWN; - else - tmp = PHY_POWER_NORM; - #else - tmp = -1; - #endif - return tmp; -} -#endif - -#if _WIZCHIP_ == 5500 -void wizphy_reset(void) -{ - uint8_t tmp = getPHYCFGR(); - tmp &= PHYCFGR_RST; - setPHYCFGR(tmp); - tmp = getPHYCFGR(); - tmp |= ~PHYCFGR_RST; - setPHYCFGR(tmp); -} - -void wizphy_setphyconf(wiz_PhyConf* phyconf) -{ - uint8_t tmp = 0; - if(phyconf->by == PHY_CONFBY_SW) - tmp |= PHYCFGR_OPMD; - else - tmp &= ~PHYCFGR_OPMD; - if(phyconf->mode == PHY_MODE_AUTONEGO) - tmp |= PHYCFGR_OPMDC_ALLA; - else - { - if(phyconf->duplex == PHY_DUPLEX_FULL) - { - if(phyconf->speed == PHY_SPEED_100) - tmp |= PHYCFGR_OPMDC_100F; - else - tmp |= PHYCFGR_OPMDC_10F; - } - else - { - if(phyconf->speed == PHY_SPEED_100) - tmp |= PHYCFGR_OPMDC_100H; - else - tmp |= PHYCFGR_OPMDC_10H; - } - } - setPHYCFGR(tmp); - wizphy_reset(); -} - -void wizphy_getphyconf(wiz_PhyConf* phyconf) -{ - uint8_t tmp = 0; - tmp = getPHYCFGR(); - phyconf->by = (tmp & PHYCFGR_OPMD) ? PHY_CONFBY_SW : PHY_CONFBY_HW; - switch(tmp & PHYCFGR_OPMDC_ALLA) - { - case PHYCFGR_OPMDC_ALLA: - case PHYCFGR_OPMDC_100FA: - phyconf->mode = PHY_MODE_AUTONEGO; - break; - default: - phyconf->mode = PHY_MODE_MANUAL; - break; - } - switch(tmp & PHYCFGR_OPMDC_ALLA) - { - case PHYCFGR_OPMDC_100FA: - case PHYCFGR_OPMDC_100F: - case PHYCFGR_OPMDC_100H: - phyconf->speed = PHY_SPEED_100; - break; - default: - phyconf->speed = PHY_SPEED_10; - break; - } - switch(tmp & PHYCFGR_OPMDC_ALLA) - { - case PHYCFGR_OPMDC_100FA: - case PHYCFGR_OPMDC_100F: - case PHYCFGR_OPMDC_10F: - phyconf->duplex = PHY_DUPLEX_FULL; - break; - default: - phyconf->duplex = PHY_DUPLEX_HALF; - break; - } -} - -void wizphy_getphystat(wiz_PhyConf* phyconf) -{ - uint8_t tmp = getPHYCFGR(); - phyconf->duplex = (tmp & PHYCFGR_DPX_FULL) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; - phyconf->speed = (tmp & PHYCFGR_SPD_100) ? PHY_SPEED_100 : PHY_SPEED_10; -} - -int8_t wizphy_setphypmode(uint8_t pmode) -{ - uint8_t tmp = 0; - tmp = getPHYCFGR(); - if((tmp & PHYCFGR_OPMD)== 0) return -1; - tmp &= ~PHYCFGR_OPMDC_ALLA; - if( pmode == PHY_POWER_DOWN) - tmp |= PHYCFGR_OPMDC_PDOWN; - else - tmp |= PHYCFGR_OPMDC_ALLA; - setPHYCFGR(tmp); - wizphy_reset(); - tmp = getPHYCFGR(); - if( pmode == PHY_POWER_DOWN) - { - if(tmp & PHYCFGR_OPMDC_PDOWN) return 0; - } - else - { - if(tmp & PHYCFGR_OPMDC_ALLA) return 0; - } - return -1; -} -#endif - - -void wizchip_setnetinfo(wiz_NetInfo* pnetinfo) -{ - setSHAR(pnetinfo->mac); - setGAR(pnetinfo->gw); - setSUBR(pnetinfo->sn); - setSIPR(pnetinfo->ip); -#if _WIZCHIP_ == 5200 // for W5200 ARP errata - _SUBN_[0] = pnetinfo->sn[0]; - _SUBN_[1] = pnetinfo->sn[1]; - _SUBN_[2] = pnetinfo->sn[2]; - _SUBN_[3] = pnetinfo->sn[3]; -#endif - _DNS_[0] = pnetinfo->dns[0]; - _DNS_[1] = pnetinfo->dns[1]; - _DNS_[2] = pnetinfo->dns[2]; - _DNS_[3] = pnetinfo->dns[3]; - _DHCP_ = pnetinfo->dhcp; -} - -void wizchip_getnetinfo(wiz_NetInfo* pnetinfo) -{ - getSHAR(pnetinfo->mac); - getGAR(pnetinfo->gw); - getSUBR(pnetinfo->sn); - getSIPR(pnetinfo->ip); -#if _WIZCHIP_ == 5200 // for W5200 ARP errata - pnetinfo->sn[0] = _SUBN_[0]; - pnetinfo->sn[1] = _SUBN_[1]; - pnetinfo->sn[2] = _SUBN_[2]; - pnetinfo->sn[3] = _SUBN_[3]; -#endif - pnetinfo->dns[0]= _DNS_[0]; - pnetinfo->dns[1]= _DNS_[1]; - pnetinfo->dns[2]= _DNS_[2]; - pnetinfo->dns[3]= _DNS_[3]; - pnetinfo->dhcp = _DHCP_; -} - -#if _WIZCHIP_ == 5200 // for W5200 ARP errata -uint8_t *wizchip_getsubn(void) { - return _SUBN_; -} -#endif - -int8_t wizchip_setnetmode(netmode_type netmode) -{ - uint8_t tmp = 0; -#if _WIZCHIP_ != 5500 - if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK)) return -1; -#else - if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK | NM_FORCEARP)) return -1; -#endif - tmp = getMR(); - tmp |= (uint8_t)netmode; - setMR(tmp); - return 0; -} - -netmode_type wizchip_getnetmode(void) -{ - return (netmode_type) getMR(); -} - -void wizchip_settimeout(wiz_NetTimeout* nettime) -{ - setRCR(nettime->retry_cnt); - setRTR(nettime->time_100us); -} - -void wizchip_gettimeout(wiz_NetTimeout* nettime) -{ - nettime->retry_cnt = getRCR(); - nettime->time_100us = getRTR(); -} diff --git a/drivers/wiznet5k/ethernet/wizchip_conf.h b/drivers/wiznet5k/ethernet/wizchip_conf.h deleted file mode 100644 index 4a7a7bd691..0000000000 --- a/drivers/wiznet5k/ethernet/wizchip_conf.h +++ /dev/null @@ -1,554 +0,0 @@ -//***************************************************************************** -// -//! \file wizchip_conf.h -//! \brief WIZCHIP Config Header File. -//! \version 1.0.0 -//! \date 2013/10/21 -//! \par Revision history -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -/** - * @defgroup extra_functions 2. WIZnet Extra Functions - * - * @brief These functions is optional function. It could be replaced at WIZCHIP I/O function because they were made by WIZCHIP I/O functions. - * @details There are functions of configuring WIZCHIP, network, interrupt, phy, network information and timer. \n - * - */ - -#ifndef _WIZCHIP_CONF_H_ -#define _WIZCHIP_CONF_H_ - -#include -/** - * @brief Select WIZCHIP. - * @todo You should select one, \b 5100, \b 5200 ,\b 5500 or etc. \n\n - * ex> #define \_WIZCHIP_ 5500 - */ -#ifndef _WIZCHIP_ -#define _WIZCHIP_ 5200 // 5100, 5200, 5500 -#endif - -#define _WIZCHIP_IO_MODE_NONE_ 0x0000 -#define _WIZCHIP_IO_MODE_BUS_ 0x0100 /**< Bus interface mode */ -#define _WIZCHIP_IO_MODE_SPI_ 0x0200 /**< SPI interface mode */ -//#define _WIZCHIP_IO_MODE_IIC_ 0x0400 -//#define _WIZCHIP_IO_MODE_SDIO_ 0x0800 -// Add to -// - -#define _WIZCHIP_IO_MODE_BUS_DIR_ (_WIZCHIP_IO_MODE_BUS_ + 1) /**< BUS interface mode for direct */ -#define _WIZCHIP_IO_MODE_BUS_INDIR_ (_WIZCHIP_IO_MODE_BUS_ + 2) /**< BUS interface mode for indirect */ - -#define _WIZCHIP_IO_MODE_SPI_VDM_ (_WIZCHIP_IO_MODE_SPI_ + 1) /**< SPI interface mode for variable length data*/ -#define _WIZCHIP_IO_MODE_SPI_FDM_ (_WIZCHIP_IO_MODE_SPI_ + 2) /**< SPI interface mode for fixed length data mode*/ - - -#if (_WIZCHIP_ == 5100) - #define _WIZCHIP_ID_ "W5100\0" -/** - * @brief Define interface mode. - * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ - */ - -// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_DIR_ -// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_ - #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_ - -#elif (_WIZCHIP_ == 5200) - #define _WIZCHIP_ID_ "W5200\0" -/** - * @brief Define interface mode. - * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ - */ -// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_ - #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_ - #include "w5200/w5200.h" -#elif (_WIZCHIP_ == 5500) - #define _WIZCHIP_ID_ "W5500\0" - -/** - * @brief Define interface mode. \n - * @todo Should select interface mode as chip. - * - @ref \_WIZCHIP_IO_MODE_SPI_ \n - * -@ref \_WIZCHIP_IO_MODE_SPI_VDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n - * -@ref \_WIZCHIP_IO_MODE_SPI_FDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n - * - @ref \_WIZCHIP_IO_MODE_BUS_ \n - * - @ref \_WIZCHIP_IO_MODE_BUS_DIR_ \n - * - @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ \n - * - Others will be defined in future. \n\n - * ex> #define \_WIZCHIP_IO_MODE_ \_WIZCHIP_IO_MODE_SPI_VDM_ - * - */ - //#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_FDM_ - #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_VDM_ - #include "w5500/w5500.h" -#else - #error "Unknown defined _WIZCHIP_. You should define one of 5100, 5200, and 5500 !!!" -#endif - -#ifndef _WIZCHIP_IO_MODE_ - #error "Undefined _WIZCHIP_IO_MODE_. You should define it !!!" -#endif - -/** - * @brief Define I/O base address when BUS IF mode. - * @todo Should re-define it to fit your system when BUS IF Mode (@ref \_WIZCHIP_IO_MODE_BUS_, - * @ref \_WIZCHIP_IO_MODE_BUS_DIR_, @ref \_WIZCHIP_IO_MODE_BUS_INDIR_). \n\n - * ex> #define \_WIZCHIP_IO_BASE_ 0x00008000 - */ -#define _WIZCHIP_IO_BASE_ 0x00000000 // - -#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS - #ifndef _WIZCHIP_IO_BASE_ - #error "You should be define _WIZCHIP_IO_BASE to fit your system memory map." - #endif -#endif - -#if _WIZCHIP_ > 5100 - #define _WIZCHIP_SOCK_NUM_ 8 ///< The count of independant socket of @b WIZCHIP -#else - #define _WIZCHIP_SOCK_NUM_ 4 ///< The count of independant socket of @b WIZCHIP -#endif - - -/******************************************************** -* WIZCHIP BASIC IF functions for SPI, SDIO, I2C , ETC. -*********************************************************/ -/** - * @ingroup DATA_TYPE - * @brief The set of callback functions for W5500:@ref WIZCHIP_IO_Functions W5200:@ref WIZCHIP_IO_Functions_W5200 - */ -typedef struct __WIZCHIP -{ - uint16_t if_mode; ///< host interface mode - uint8_t id[6]; ///< @b WIZCHIP ID such as @b 5100, @b 5200, @b 5500, and so on. - /** - * The set of critical section callback func. - */ - struct _CRIS - { - void (*_enter) (void); ///< crtical section enter - void (*_exit) (void); ///< critial section exit - }CRIS; - /** - * The set of @ref\_WIZCHIP_ select control callback func. - */ - struct _CS - { - void (*_select) (void); ///< @ref \_WIZCHIP_ selected - void (*_deselect)(void); ///< @ref \_WIZCHIP_ deselected - }CS; - /** - * The set of interface IO callback func. - */ - union _IF - { - /** - * For BUS interface IO - */ - struct - { - uint8_t (*_read_byte) (uint32_t AddrSel); - void (*_write_byte) (uint32_t AddrSel, uint8_t wb); - }BUS; - /** - * For SPI interface IO - */ - struct - { - void (*_read_bytes) (uint8_t *buf, uint32_t len); - void (*_write_bytes) (const uint8_t *buf, uint32_t len); - }SPI; - // To be added - // - }IF; -}_WIZCHIP; - -extern _WIZCHIP WIZCHIP; - -/** - * @ingroup DATA_TYPE - * WIZCHIP control type enumration used in @ref ctlwizchip(). - */ -typedef enum -{ - CW_RESET_WIZCHIP, ///< Resets WIZCHIP by softly - CW_INIT_WIZCHIP, ///< Inializes to WIZCHIP with SOCKET buffer size 2 or 1 dimension array typed uint8_t. - CW_GET_INTERRUPT, ///< Get Interrupt status of WIZCHIP - CW_CLR_INTERRUPT, ///< Clears interrupt - CW_SET_INTRMASK, ///< Masks interrupt - CW_GET_INTRMASK, ///< Get interrupt mask - CW_SET_INTRTIME, ///< Set interval time between the current and next interrupt. - CW_GET_INTRTIME, ///< Set interval time between the current and next interrupt. - CW_GET_ID, ///< Gets WIZCHIP name. - -#if _WIZCHIP_ == 5500 - CW_RESET_PHY, ///< Resets internal PHY. Valid Only W5000 - CW_SET_PHYCONF, ///< When PHY configured by interal register, PHY operation mode (Manual/Auto, 10/100, Half/Full). Valid Only W5000 - CW_GET_PHYCONF, ///< Get PHY operation mode in interal register. Valid Only W5000 - CW_GET_PHYSTATUS, ///< Get real PHY status on operating. Valid Only W5000 - CW_SET_PHYPOWMODE, ///< Set PHY power mode as noraml and down when PHYSTATUS.OPMD == 1. Valid Only W5000 -#endif - CW_GET_PHYPOWMODE, ///< Get PHY Power mode as down or normal - CW_GET_PHYLINK ///< Get PHY Link status -}ctlwizchip_type; - -/** - * @ingroup DATA_TYPE - * Network control type enumration used in @ref ctlnetwork(). - */ -typedef enum -{ - CN_SET_NETINFO, ///< Set Network with @ref wiz_NetInfo - CN_GET_NETINFO, ///< Get Network with @ref wiz_NetInfo - CN_SET_NETMODE, ///< Set network mode as WOL, PPPoE, Ping Block, and Force ARP mode - CN_GET_NETMODE, ///< Get network mode as WOL, PPPoE, Ping Block, and Force ARP mode - CN_SET_TIMEOUT, ///< Set network timeout as retry count and time. - CN_GET_TIMEOUT, ///< Get network timeout as retry count and time. -}ctlnetwork_type; - -/** - * @ingroup DATA_TYPE - * Interrupt kind when CW_SET_INTRRUPT, CW_GET_INTERRUPT, CW_SET_INTRMASK - * and CW_GET_INTRMASK is used in @ref ctlnetwork(). - * It can be used with OR operation. - */ -typedef enum -{ -#if _WIZCHIP_ > 5200 - IK_WOL = (1 << 4), ///< Wake On Lan by receiving the magic packet. Valid in W500. -#endif - - IK_PPPOE_TERMINATED = (1 << 5), ///< PPPoE Disconnected - -#if _WIZCHIP_ != 5200 - IK_DEST_UNREACH = (1 << 6), ///< Destination IP & Port Unreable, No use in W5200 -#endif - - IK_IP_CONFLICT = (1 << 7), ///< IP conflict occurred - - IK_SOCK_0 = (1 << 8), ///< Socket 0 interrupt - IK_SOCK_1 = (1 << 9), ///< Socket 1 interrupt - IK_SOCK_2 = (1 << 10), ///< Socket 2 interrupt - IK_SOCK_3 = (1 << 11), ///< Socket 3 interrupt -#if _WIZCHIP_ > 5100 - IK_SOCK_4 = (1 << 12), ///< Socket 4 interrupt, No use in 5100 - IK_SOCK_5 = (1 << 13), ///< Socket 5 interrupt, No use in 5100 - IK_SOCK_6 = (1 << 14), ///< Socket 6 interrupt, No use in 5100 - IK_SOCK_7 = (1 << 15), ///< Socket 7 interrupt, No use in 5100 -#endif - -#if _WIZCHIP_ > 5100 - IK_SOCK_ALL = (0xFF << 8) ///< All Socket interrpt -#else - IK_SOCK_ALL = (0x0F << 8) ///< All Socket interrpt -#endif -}intr_kind; - -#define PHY_CONFBY_HW 0 ///< Configured PHY operation mode by HW pin -#define PHY_CONFBY_SW 1 ///< Configured PHY operation mode by SW register -#define PHY_MODE_MANUAL 0 ///< Configured PHY operation mode with user setting. -#define PHY_MODE_AUTONEGO 1 ///< Configured PHY operation mode with auto-negotiation -#define PHY_SPEED_10 0 ///< Link Speed 10 -#define PHY_SPEED_100 1 ///< Link Speed 100 -#define PHY_DUPLEX_HALF 0 ///< Link Half-Duplex -#define PHY_DUPLEX_FULL 1 ///< Link Full-Duplex -#define PHY_LINK_OFF 0 ///< Link Off -#define PHY_LINK_ON 1 ///< Link On -#define PHY_POWER_NORM 0 ///< PHY power normal mode -#define PHY_POWER_DOWN 1 ///< PHY power down mode - - -#if _WIZCHIP_ == 5500 -/** - * @ingroup DATA_TYPE - * It configures PHY configuration when CW_SET PHYCONF or CW_GET_PHYCONF in W5500, - * and it indicates the real PHY status configured by HW or SW in all WIZCHIP. \n - * Valid only in W5500. - */ -typedef struct wiz_PhyConf_t -{ - uint8_t by; ///< set by @ref PHY_CONFBY_HW or @ref PHY_CONFBY_SW - uint8_t mode; ///< set by @ref PHY_MODE_MANUAL or @ref PHY_MODE_AUTONEGO - uint8_t speed; ///< set by @ref PHY_SPEED_10 or @ref PHY_SPEED_100 - uint8_t duplex; ///< set by @ref PHY_DUPLEX_HALF @ref PHY_DUPLEX_FULL - //uint8_t power; ///< set by @ref PHY_POWER_NORM or @ref PHY_POWER_DOWN - //uint8_t link; ///< Valid only in CW_GET_PHYSTATUS. set by @ref PHY_LINK_ON or PHY_DUPLEX_OFF - }wiz_PhyConf; -#endif - -/** - * @ingroup DATA_TYPE - * It used in setting dhcp_mode of @ref wiz_NetInfo. - */ -typedef enum -{ - NETINFO_STATIC = 1, ///< Static IP configuration by manually. - NETINFO_DHCP ///< Dynamic IP configruation from a DHCP sever -}dhcp_mode; - -/** - * @ingroup DATA_TYPE - * Network Information for WIZCHIP - */ -typedef struct wiz_NetInfo_t -{ - uint8_t mac[6]; ///< Source Mac Address - uint8_t ip[4]; ///< Source IP Address - uint8_t sn[4]; ///< Subnet Mask - uint8_t gw[4]; ///< Gateway IP Address - uint8_t dns[4]; ///< DNS server IP Address - dhcp_mode dhcp; ///< 1 - Static, 2 - DHCP -}wiz_NetInfo; - -/** - * @ingroup DATA_TYPE - * Network mode - */ -typedef enum -{ -#if _WIZCHIP_ == 5500 - NM_FORCEARP = (1<<1), ///< Force to APP send whenever udp data is sent. Valid only in W5500 -#endif - NM_WAKEONLAN = (1<<5), ///< Wake On Lan - NM_PINGBLOCK = (1<<4), ///< Block ping-request - NM_PPPOE = (1<<3), ///< PPPoE mode -}netmode_type; - -/** - * @ingroup DATA_TYPE - * Used in CN_SET_TIMEOUT or CN_GET_TIMEOUT of @ref ctlwizchip() for timeout configruation. - */ -typedef struct wiz_NetTimeout_t -{ - uint8_t retry_cnt; ///< retry count - uint16_t time_100us; ///< time unit 100us -}wiz_NetTimeout; - -/** - *@brief Registers call back function for critical section of I/O functions such as - *\ref WIZCHIP_READ, @ref WIZCHIP_WRITE, @ref WIZCHIP_READ_BUF and @ref WIZCHIP_WRITE_BUF. - *@param cris_en : callback function for critical section enter. - *@param cris_ex : callback function for critical section exit. - *@todo Describe @ref WIZCHIP_CRITICAL_ENTER and @ref WIZCHIP_CRITICAL_EXIT marco or register your functions. - *@note If you do not describe or register, default functions(@ref wizchip_cris_enter & @ref wizchip_cris_exit) is called. - */ -void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void)); - - -/** - *@brief Registers call back function for WIZCHIP select & deselect. - *@param cs_sel : callback function for WIZCHIP select - *@param cs_desel : callback fucntion for WIZCHIP deselect - *@todo Describe @ref wizchip_cs_select and @ref wizchip_cs_deselect function or register your functions. - *@note If you do not describe or register, null function is called. - */ -void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void)); - -/** - *@brief Registers call back function for bus interface. - *@param bus_rb : callback function to read byte data using system bus - *@param bus_wb : callback function to write byte data using system bus - *@todo Describe @ref wizchip_bus_readbyte and @ref wizchip_bus_writebyte function - *or register your functions. - *@note If you do not describe or register, null function is called. - */ -void reg_wizchip_bus_cbfunc(uint8_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb)); - -/** - *@brief Registers call back function for SPI interface. - *@param spi_rb : callback function to read byte usig SPI - *@param spi_wb : callback function to write byte usig SPI - *@todo Describe \ref wizchip_spi_readbyte and \ref wizchip_spi_writebyte function - *or register your functions. - *@note If you do not describe or register, null function is called. - */ -void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t)); - -/** - * @ingroup extra_functions - * @brief Controls to the WIZCHIP. - * @details Resets WIZCHIP & internal PHY, Configures PHY mode, Monitor PHY(Link,Speed,Half/Full/Auto), - * controls interrupt & mask and so on. - * @param cwtype : Decides to the control type - * @param arg : arg type is dependent on cwtype. - * @return 0 : Success \n - * -1 : Fail because of invalid \ref ctlwizchip_type or unsupported \ref ctlwizchip_type in WIZCHIP - */ -int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg); - -/** - * @ingroup extra_functions - * @brief Controls to network. - * @details Controls to network environment, mode, timeout and so on. - * @param cntype : Input. Decides to the control type - * @param arg : Inout. arg type is dependent on cntype. - * @return -1 : Fail because of invalid \ref ctlnetwork_type or unsupported \ref ctlnetwork_type in WIZCHIP \n - * 0 : Success - */ -int8_t ctlnetwork(ctlnetwork_type cntype, void* arg); - - -/* - * The following functions are implemented for internal use. - * but You can call these functions for code size reduction instead of ctlwizchip() and ctlnetwork(). - */ - -/** - * @ingroup extra_functions - * @brief Reset WIZCHIP by softly. - */ -void wizchip_sw_reset(void); - -/** - * @ingroup extra_functions - * @brief Initializes WIZCHIP with socket buffer size - * @param txsize Socket tx buffer sizes. If null, initialized the default size 2KB. - * @param rxsize Socket rx buffer sizes. If null, initialized the default size 2KB. - * @return 0 : succcess \n - * -1 : fail. Invalid buffer size - */ -int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize); - -/** - * @ingroup extra_functions - * @brief Clear Interrupt of WIZCHIP. - * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t. - */ -void wizchip_clrinterrupt(intr_kind intr); - -/** - * @ingroup extra_functions - * @brief Get Interrupt of WIZCHIP. - * @return @ref intr_kind value operated OR. It can type-cast to uint16_t. - */ -intr_kind wizchip_getinterrupt(void); - -/** - * @ingroup extra_functions - * @brief Mask or Unmask Interrupt of WIZCHIP. - * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t. - */ -void wizchip_setinterruptmask(intr_kind intr); - -/** - * @ingroup extra_functions - * @brief Get Interrupt mask of WIZCHIP. - * @return : The operated OR vaule of @ref intr_kind. It can type-cast to uint16_t. - */ -intr_kind wizchip_getinterruptmask(void); - -#if _WIZCHIP_ > 5100 - int8_t wizphy_getphylink(void); ///< get the link status of phy in WIZCHIP. No use in W5100 - int8_t wizphy_getphypmode(void); ///< get the power mode of PHY in WIZCHIP. No use in W5100 -#endif - -#if _WIZCHIP_ == 5500 - void wizphy_reset(void); ///< Reset phy. Vailid only in W5500 -/** - * @ingroup extra_functions - * @brief Set the phy information for WIZCHIP without power mode - * @param phyconf : @ref wiz_PhyConf - */ - void wizphy_setphyconf(wiz_PhyConf* phyconf); - /** - * @ingroup extra_functions - * @brief Get phy configuration information. - * @param phyconf : @ref wiz_PhyConf - */ - void wizphy_getphyconf(wiz_PhyConf* phyconf); - /** - * @ingroup extra_functions - * @brief Get phy status. - * @param phyconf : @ref wiz_PhyConf - */ - void wizphy_getphystat(wiz_PhyConf* phyconf); - /** - * @ingroup extra_functions - * @brief set the power mode of phy inside WIZCHIP. Refer to @ref PHYCFGR in W5500, @ref PHYSTATUS in W5200 - * @param pmode Settig value of power down mode. - */ - int8_t wizphy_setphypmode(uint8_t pmode); -#endif - -/** -* @ingroup extra_functions - * @brief Set the network information for WIZCHIP - * @param pnetinfo : @ref wizNetInfo - */ -void wizchip_setnetinfo(wiz_NetInfo* pnetinfo); - -/** - * @ingroup extra_functions - * @brief Get the network information for WIZCHIP - * @param pnetinfo : @ref wizNetInfo - */ -void wizchip_getnetinfo(wiz_NetInfo* pnetinfo); - -#if _WIZCHIP_ == 5200 // for W5200 ARP errata -uint8_t *wizchip_getsubn(void); -#endif - -/** - * @ingroup extra_functions - * @brief Set the network mode such WOL, PPPoE, Ping Block, and etc. - * @param pnetinfo Value of network mode. Refer to @ref netmode_type. - */ -int8_t wizchip_setnetmode(netmode_type netmode); - -/** - * @ingroup extra_functions - * @brief Get the network mode such WOL, PPPoE, Ping Block, and etc. - * @return Value of network mode. Refer to @ref netmode_type. - */ -netmode_type wizchip_getnetmode(void); - -/** - * @ingroup extra_functions - * @brief Set retry time value(@ref RTR) and retry count(@ref RCR). - * @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission. - * @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout. - */ -void wizchip_settimeout(wiz_NetTimeout* nettime); - -/** - * @ingroup extra_functions - * @brief Get retry time value(@ref RTR) and retry count(@ref RCR). - * @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission. - * @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout. - */ -void wizchip_gettimeout(wiz_NetTimeout* nettime); - -#endif // _WIZCHIP_CONF_H_ diff --git a/drivers/wiznet5k/internet/dhcp/dhcp.c b/drivers/wiznet5k/internet/dhcp/dhcp.c deleted file mode 100644 index 5747582599..0000000000 --- a/drivers/wiznet5k/internet/dhcp/dhcp.c +++ /dev/null @@ -1,978 +0,0 @@ -//***************************************************************************** -// -//! \file dhcp.c -//! \brief DHCP APIs implement file. -//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE. -//! \version 1.1.0 -//! \date 2013/11/18 -//! \par Revision history -//! <2013/11/18> 1st Release -//! <2012/12/20> V1.1.0 -//! 1. Optimize code -//! 2. Add reg_dhcp_cbfunc() -//! 3. Add DHCP_stop() -//! 4. Integrate check_DHCP_state() & DHCP_run() to DHCP_run() -//! 5. Don't care system endian -//! 6. Add comments -//! <2012/12/26> V1.1.1 -//! 1. Modify variable declaration: dhcp_tick_1s is declared volatile for code optimization -//! \author Eric Jung & MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -//#include "Ethernet/socket.h" -//#include "Internet/DHCP/dhcp.h" -#include "../../Ethernet/socket.h" -#include "dhcp.h" - -/* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */ - -#ifdef _DHCP_DEBUG_ - #include -#endif - -/* DHCP state machine. */ -#define STATE_DHCP_INIT 0 ///< Initialize -#define STATE_DHCP_DISCOVER 1 ///< send DISCOVER and wait OFFER -#define STATE_DHCP_REQUEST 2 ///< send REQEUST and wait ACK or NACK -#define STATE_DHCP_LEASED 3 ///< ReceiveD ACK and IP leased -#define STATE_DHCP_REREQUEST 4 ///< send REQUEST for maintaining leased IP -#define STATE_DHCP_RELEASE 5 ///< No use -#define STATE_DHCP_STOP 6 ///< Stop processing DHCP - -#define DHCP_FLAGSBROADCAST 0x8000 ///< The broadcast value of flags in @ref RIP_MSG -#define DHCP_FLAGSUNICAST 0x0000 ///< The unicast value of flags in @ref RIP_MSG - -/* DHCP message OP code */ -#define DHCP_BOOTREQUEST 1 ///< Request Message used in op of @ref RIP_MSG -#define DHCP_BOOTREPLY 2 ///< Reply Message used i op of @ref RIP_MSG - -/* DHCP message type */ -#define DHCP_DISCOVER 1 ///< DISCOVER message in OPT of @ref RIP_MSG -#define DHCP_OFFER 2 ///< OFFER message in OPT of @ref RIP_MSG -#define DHCP_REQUEST 3 ///< REQUEST message in OPT of @ref RIP_MSG -#define DHCP_DECLINE 4 ///< DECLINE message in OPT of @ref RIP_MSG -#define DHCP_ACK 5 ///< ACK message in OPT of @ref RIP_MSG -#define DHCP_NAK 6 ///< NACK message in OPT of @ref RIP_MSG -#define DHCP_RELEASE 7 ///< RELEASE message in OPT of @ref RIP_MSG. No use -#define DHCP_INFORM 8 ///< INFORM message in OPT of @ref RIP_MSG. No use - -#define DHCP_HTYPE10MB 1 ///< Used in type of @ref RIP_MSG -#define DHCP_HTYPE100MB 2 ///< Used in type of @ref RIP_MSG - -#define DHCP_HLENETHERNET 6 ///< Used in hlen of @ref RIP_MSG -#define DHCP_HOPS 0 ///< Used in hops of @ref RIP_MSG -#define DHCP_SECS 0 ///< Used in secs of @ref RIP_MSG - -#define INFINITE_LEASETIME 0xffffffff ///< Infinite lease time - -#define OPT_SIZE 312 /// Max OPT size of @ref RIP_MSG -#define RIP_MSG_SIZE (236+OPT_SIZE) /// Max size of @ref RIP_MSG - -/* - * @brief DHCP option and value (cf. RFC1533) - */ -enum -{ - padOption = 0, - subnetMask = 1, - timerOffset = 2, - routersOnSubnet = 3, - timeServer = 4, - nameServer = 5, - dns = 6, - logServer = 7, - cookieServer = 8, - lprServer = 9, - impressServer = 10, - resourceLocationServer = 11, - hostName = 12, - bootFileSize = 13, - meritDumpFile = 14, - domainName = 15, - swapServer = 16, - rootPath = 17, - extentionsPath = 18, - IPforwarding = 19, - nonLocalSourceRouting = 20, - policyFilter = 21, - maxDgramReasmSize = 22, - defaultIPTTL = 23, - pathMTUagingTimeout = 24, - pathMTUplateauTable = 25, - ifMTU = 26, - allSubnetsLocal = 27, - broadcastAddr = 28, - performMaskDiscovery = 29, - maskSupplier = 30, - performRouterDiscovery = 31, - routerSolicitationAddr = 32, - staticRoute = 33, - trailerEncapsulation = 34, - arpCacheTimeout = 35, - ethernetEncapsulation = 36, - tcpDefaultTTL = 37, - tcpKeepaliveInterval = 38, - tcpKeepaliveGarbage = 39, - nisDomainName = 40, - nisServers = 41, - ntpServers = 42, - vendorSpecificInfo = 43, - netBIOSnameServer = 44, - netBIOSdgramDistServer = 45, - netBIOSnodeType = 46, - netBIOSscope = 47, - xFontServer = 48, - xDisplayManager = 49, - dhcpRequestedIPaddr = 50, - dhcpIPaddrLeaseTime = 51, - dhcpOptionOverload = 52, - dhcpMessageType = 53, - dhcpServerIdentifier = 54, - dhcpParamRequest = 55, - dhcpMsg = 56, - dhcpMaxMsgSize = 57, - dhcpT1value = 58, - dhcpT2value = 59, - dhcpClassIdentifier = 60, - dhcpClientIdentifier = 61, - endOption = 255 -}; - -/* - * @brief DHCP message format - */ -typedef struct { - uint8_t op; ///< @ref DHCP_BOOTREQUEST or @ref DHCP_BOOTREPLY - uint8_t htype; ///< @ref DHCP_HTYPE10MB or @ref DHCP_HTYPE100MB - uint8_t hlen; ///< @ref DHCP_HLENETHERNET - uint8_t hops; ///< @ref DHCP_HOPS - uint32_t xid; ///< @ref DHCP_XID This increase one every DHCP transaction. - uint16_t secs; ///< @ref DHCP_SECS - uint16_t flags; ///< @ref DHCP_FLAGSBROADCAST or @ref DHCP_FLAGSUNICAST - uint8_t ciaddr[4]; ///< @ref Request IP to DHCP sever - uint8_t yiaddr[4]; ///< @ref Offered IP from DHCP server - uint8_t siaddr[4]; ///< No use - uint8_t giaddr[4]; ///< No use - uint8_t chaddr[16]; ///< DHCP client 6bytes MAC address. Others is filled to zero - uint8_t sname[64]; ///< No use - uint8_t file[128]; ///< No use - uint8_t OPT[OPT_SIZE]; ///< Option -} RIP_MSG; - - - -uint8_t DHCP_SOCKET; // Socket number for DHCP - -uint8_t DHCP_SIP[4]; // DHCP Server IP address - -// Network information from DHCP Server -uint8_t OLD_allocated_ip[4] = {0, }; // Previous IP address -uint8_t DHCP_allocated_ip[4] = {0, }; // IP address from DHCP -uint8_t DHCP_allocated_gw[4] = {0, }; // Gateway address from DHCP -uint8_t DHCP_allocated_sn[4] = {0, }; // Subnet mask from DHCP -uint8_t DHCP_allocated_dns[4] = {0, }; // DNS address from DHCP - - -int8_t dhcp_state = STATE_DHCP_INIT; // DHCP state -int8_t dhcp_retry_count = 0; - -uint32_t dhcp_lease_time = INFINITE_LEASETIME; -volatile uint32_t dhcp_tick_1s = 0; // unit 1 second -uint32_t dhcp_tick_next = DHCP_WAIT_TIME ; - -uint32_t DHCP_XID; // Any number - -RIP_MSG* pDHCPMSG; // Buffer pointer for DHCP processing - -uint8_t HOST_NAME[] = DCHP_HOST_NAME; - -uint8_t DHCP_CHADDR[6]; // DHCP Client MAC address. - -/* The default callback function */ -void default_ip_assign(void); -void default_ip_update(void); -void default_ip_conflict(void); - -/* Callback handler */ -void (*dhcp_ip_assign)(void) = default_ip_assign; /* handler to be called when the IP address from DHCP server is first assigned */ -void (*dhcp_ip_update)(void) = default_ip_update; /* handler to be called when the IP address from DHCP server is updated */ -void (*dhcp_ip_conflict)(void) = default_ip_conflict; /* handler to be called when the IP address from DHCP server is conflict */ - -void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)); - - -/* send DISCOVER message to DHCP server */ -void send_DHCP_DISCOVER(void); - -/* send REQEUST message to DHCP server */ -void send_DHCP_REQUEST(void); - -/* send DECLINE message to DHCP server */ -void send_DHCP_DECLINE(void); - -/* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */ -int8_t check_DHCP_leasedIP(void); - -/* check the timeout in DHCP process */ -uint8_t check_DHCP_timeout(void); - -/* Intialize to timeout process. */ -void reset_DHCP_timeout(void); - -/* Parse message as OFFER and ACK and NACK from DHCP server.*/ -int8_t parseDHCPCMSG(void); - -/* The default handler of ip assign first */ -void default_ip_assign(void) -{ - setSIPR(DHCP_allocated_ip); - setSUBR(DHCP_allocated_sn); - setGAR (DHCP_allocated_gw); -} - -/* The default handler of ip changed */ -void default_ip_update(void) -{ - /* WIZchip Software Reset */ - setMR(MR_RST); - getMR(); // for delay - default_ip_assign(); - setSHAR(DHCP_CHADDR); -} - -/* The default handler of ip changed */ -void default_ip_conflict(void) -{ - // WIZchip Software Reset - setMR(MR_RST); - getMR(); // for delay - setSHAR(DHCP_CHADDR); -} - -/* register the call back func. */ -void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)) -{ - dhcp_ip_assign = default_ip_assign; - dhcp_ip_update = default_ip_update; - dhcp_ip_conflict = default_ip_conflict; - if(ip_assign) dhcp_ip_assign = ip_assign; - if(ip_update) dhcp_ip_update = ip_update; - if(ip_conflict) dhcp_ip_conflict = ip_conflict; -} - -/* make the common DHCP message */ -void makeDHCPMSG(void) -{ - uint8_t bk_mac[6]; - uint8_t* ptmp; - uint8_t i; - getSHAR(bk_mac); - pDHCPMSG->op = DHCP_BOOTREQUEST; - pDHCPMSG->htype = DHCP_HTYPE10MB; - pDHCPMSG->hlen = DHCP_HLENETHERNET; - pDHCPMSG->hops = DHCP_HOPS; - ptmp = (uint8_t*)(&pDHCPMSG->xid); - *(ptmp+0) = (uint8_t)((DHCP_XID & 0xFF000000) >> 24); - *(ptmp+1) = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16); - *(ptmp+2) = (uint8_t)((DHCP_XID & 0x0000FF00) >> 8); - *(ptmp+3) = (uint8_t)((DHCP_XID & 0x000000FF) >> 0); - pDHCPMSG->secs = DHCP_SECS; - ptmp = (uint8_t*)(&pDHCPMSG->flags); - *(ptmp+0) = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8); - *(ptmp+1) = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0); - - pDHCPMSG->ciaddr[0] = 0; - pDHCPMSG->ciaddr[1] = 0; - pDHCPMSG->ciaddr[2] = 0; - pDHCPMSG->ciaddr[3] = 0; - - pDHCPMSG->yiaddr[0] = 0; - pDHCPMSG->yiaddr[1] = 0; - pDHCPMSG->yiaddr[2] = 0; - pDHCPMSG->yiaddr[3] = 0; - - pDHCPMSG->siaddr[0] = 0; - pDHCPMSG->siaddr[1] = 0; - pDHCPMSG->siaddr[2] = 0; - pDHCPMSG->siaddr[3] = 0; - - pDHCPMSG->giaddr[0] = 0; - pDHCPMSG->giaddr[1] = 0; - pDHCPMSG->giaddr[2] = 0; - pDHCPMSG->giaddr[3] = 0; - - pDHCPMSG->chaddr[0] = DHCP_CHADDR[0]; - pDHCPMSG->chaddr[1] = DHCP_CHADDR[1]; - pDHCPMSG->chaddr[2] = DHCP_CHADDR[2]; - pDHCPMSG->chaddr[3] = DHCP_CHADDR[3]; - pDHCPMSG->chaddr[4] = DHCP_CHADDR[4]; - pDHCPMSG->chaddr[5] = DHCP_CHADDR[5]; - - for (i = 6; i < 16; i++) pDHCPMSG->chaddr[i] = 0; - for (i = 0; i < 64; i++) pDHCPMSG->sname[i] = 0; - for (i = 0; i < 128; i++) pDHCPMSG->file[i] = 0; - - // MAGIC_COOKIE - pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24); - pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16); - pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >> 8); - pDHCPMSG->OPT[3] = (uint8_t) (MAGIC_COOKIE & 0x000000FF) >> 0; -} - -/* SEND DHCP DISCOVER */ -void send_DHCP_DISCOVER(void) -{ - uint16_t i; - uint8_t ip[4]; - uint16_t k = 0; - - makeDHCPMSG(); - - k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() - - // Option Request Param - pDHCPMSG->OPT[k++] = dhcpMessageType; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_DISCOVER; - - // Client identifier - pDHCPMSG->OPT[k++] = dhcpClientIdentifier; - pDHCPMSG->OPT[k++] = 0x07; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - - // host name - pDHCPMSG->OPT[k++] = hostName; - pDHCPMSG->OPT[k++] = 0; // fill zero length of hostname - for(i = 0 ; HOST_NAME[i] != 0; i++) - pDHCPMSG->OPT[k++] = HOST_NAME[i]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname - - pDHCPMSG->OPT[k++] = dhcpParamRequest; - pDHCPMSG->OPT[k++] = 0x06; // length of request - pDHCPMSG->OPT[k++] = subnetMask; - pDHCPMSG->OPT[k++] = routersOnSubnet; - pDHCPMSG->OPT[k++] = dns; - pDHCPMSG->OPT[k++] = domainName; - pDHCPMSG->OPT[k++] = dhcpT1value; - pDHCPMSG->OPT[k++] = dhcpT2value; - pDHCPMSG->OPT[k++] = endOption; - - for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; - - // send broadcasting packet - ip[0] = 255; - ip[1] = 255; - ip[2] = 255; - ip[3] = 255; - -#ifdef _DHCP_DEBUG_ - printf("> Send DHCP_DISCOVER\r\n"); -#endif - - sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); -} - -/* SEND DHCP REQUEST */ -void send_DHCP_REQUEST(void) -{ - int i; - uint8_t ip[4]; - uint16_t k = 0; - - makeDHCPMSG(); - - if(dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST) - { - *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8); - *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF); - pDHCPMSG->ciaddr[0] = DHCP_allocated_ip[0]; - pDHCPMSG->ciaddr[1] = DHCP_allocated_ip[1]; - pDHCPMSG->ciaddr[2] = DHCP_allocated_ip[2]; - pDHCPMSG->ciaddr[3] = DHCP_allocated_ip[3]; - ip[0] = DHCP_SIP[0]; - ip[1] = DHCP_SIP[1]; - ip[2] = DHCP_SIP[2]; - ip[3] = DHCP_SIP[3]; - } - else - { - ip[0] = 255; - ip[1] = 255; - ip[2] = 255; - ip[3] = 255; - } - - k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() - - // Option Request Param. - pDHCPMSG->OPT[k++] = dhcpMessageType; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_REQUEST; - - pDHCPMSG->OPT[k++] = dhcpClientIdentifier; - pDHCPMSG->OPT[k++] = 0x07; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - - if(ip[3] == 255) // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE) - { - pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr; - pDHCPMSG->OPT[k++] = 0x04; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3]; - - pDHCPMSG->OPT[k++] = dhcpServerIdentifier; - pDHCPMSG->OPT[k++] = 0x04; - pDHCPMSG->OPT[k++] = DHCP_SIP[0]; - pDHCPMSG->OPT[k++] = DHCP_SIP[1]; - pDHCPMSG->OPT[k++] = DHCP_SIP[2]; - pDHCPMSG->OPT[k++] = DHCP_SIP[3]; - } - - // host name - pDHCPMSG->OPT[k++] = hostName; - pDHCPMSG->OPT[k++] = 0; // length of hostname - for(i = 0 ; HOST_NAME[i] != 0; i++) - pDHCPMSG->OPT[k++] = HOST_NAME[i]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname - - pDHCPMSG->OPT[k++] = dhcpParamRequest; - pDHCPMSG->OPT[k++] = 0x08; - pDHCPMSG->OPT[k++] = subnetMask; - pDHCPMSG->OPT[k++] = routersOnSubnet; - pDHCPMSG->OPT[k++] = dns; - pDHCPMSG->OPT[k++] = domainName; - pDHCPMSG->OPT[k++] = dhcpT1value; - pDHCPMSG->OPT[k++] = dhcpT2value; - pDHCPMSG->OPT[k++] = performRouterDiscovery; - pDHCPMSG->OPT[k++] = staticRoute; - pDHCPMSG->OPT[k++] = endOption; - - for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; - -#ifdef _DHCP_DEBUG_ - printf("> Send DHCP_REQUEST\r\n"); -#endif - - sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); - -} - -/* SEND DHCP DHCPDECLINE */ -void send_DHCP_DECLINE(void) -{ - int i; - uint8_t ip[4]; - uint16_t k = 0; - - makeDHCPMSG(); - - k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() - - *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8); - *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF); - - // Option Request Param. - pDHCPMSG->OPT[k++] = dhcpMessageType; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_DECLINE; - - pDHCPMSG->OPT[k++] = dhcpClientIdentifier; - pDHCPMSG->OPT[k++] = 0x07; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - - pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr; - pDHCPMSG->OPT[k++] = 0x04; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3]; - - pDHCPMSG->OPT[k++] = dhcpServerIdentifier; - pDHCPMSG->OPT[k++] = 0x04; - pDHCPMSG->OPT[k++] = DHCP_SIP[0]; - pDHCPMSG->OPT[k++] = DHCP_SIP[1]; - pDHCPMSG->OPT[k++] = DHCP_SIP[2]; - pDHCPMSG->OPT[k++] = DHCP_SIP[3]; - - pDHCPMSG->OPT[k++] = endOption; - - for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; - - //send broadcasting packet - ip[0] = 0xFF; - ip[1] = 0xFF; - ip[2] = 0xFF; - ip[3] = 0xFF; - -#ifdef _DHCP_DEBUG_ - printf("\r\n> Send DHCP_DECLINE\r\n"); -#endif - - sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); -} - -/* PARSE REPLY pDHCPMSG */ -int8_t parseDHCPMSG(void) -{ - uint8_t svr_addr[6]; - uint16_t svr_port; - uint16_t len; - - uint8_t * p; - uint8_t * e; - uint8_t type; - uint8_t opt_len; - - if((len = getSn_RX_RSR(DHCP_SOCKET)) > 0) - { - len = recvfrom(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port); - #ifdef _DHCP_DEBUG_ - printf("DHCP message : %d.%d.%d.%d(%d) %d received. \r\n",svr_addr[0],svr_addr[1],svr_addr[2], svr_addr[3],svr_port, len); - #endif - } - else return 0; - if (svr_port == DHCP_SERVER_PORT) { - // compare mac address - if ( (pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) || - (pDHCPMSG->chaddr[2] != DHCP_CHADDR[2]) || (pDHCPMSG->chaddr[3] != DHCP_CHADDR[3]) || - (pDHCPMSG->chaddr[4] != DHCP_CHADDR[4]) || (pDHCPMSG->chaddr[5] != DHCP_CHADDR[5]) ) - return 0; - type = 0; - p = (uint8_t *)(&pDHCPMSG->op); - p = p + 240; // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt) - e = p + (len - 240); - - while ( p < e ) { - - switch ( *p ) { - - case endOption : - p = e; // for break while(p < e) - break; - case padOption : - p++; - break; - case dhcpMessageType : - p++; - p++; - type = *p++; - break; - case subnetMask : - p++; - p++; - DHCP_allocated_sn[0] = *p++; - DHCP_allocated_sn[1] = *p++; - DHCP_allocated_sn[2] = *p++; - DHCP_allocated_sn[3] = *p++; - break; - case routersOnSubnet : - p++; - opt_len = *p++; - DHCP_allocated_gw[0] = *p++; - DHCP_allocated_gw[1] = *p++; - DHCP_allocated_gw[2] = *p++; - DHCP_allocated_gw[3] = *p++; - p = p + (opt_len - 4); - break; - case dns : - p++; - opt_len = *p++; - DHCP_allocated_dns[0] = *p++; - DHCP_allocated_dns[1] = *p++; - DHCP_allocated_dns[2] = *p++; - DHCP_allocated_dns[3] = *p++; - p = p + (opt_len - 4); - break; - case dhcpIPaddrLeaseTime : - p++; - opt_len = *p++; - dhcp_lease_time = *p++; - dhcp_lease_time = (dhcp_lease_time << 8) + *p++; - dhcp_lease_time = (dhcp_lease_time << 8) + *p++; - dhcp_lease_time = (dhcp_lease_time << 8) + *p++; - #ifdef _DHCP_DEBUG_ - dhcp_lease_time = 10; - #endif - break; - case dhcpServerIdentifier : - p++; - opt_len = *p++; - DHCP_SIP[0] = *p++; - DHCP_SIP[1] = *p++; - DHCP_SIP[2] = *p++; - DHCP_SIP[3] = *p++; - break; - default : - p++; - opt_len = *p++; - p += opt_len; - break; - } // switch - } // while - } // if - return type; -} - -uint8_t DHCP_run(void) -{ - uint8_t type; - uint8_t ret; - - if(dhcp_state == STATE_DHCP_STOP) return DHCP_STOPPED; - - if(getSn_SR(DHCP_SOCKET) != SOCK_UDP) - socket(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00); - - ret = DHCP_RUNNING; - type = parseDHCPMSG(); - - switch ( dhcp_state ) { - case STATE_DHCP_INIT : - DHCP_allocated_ip[0] = 0; - DHCP_allocated_ip[1] = 0; - DHCP_allocated_ip[2] = 0; - DHCP_allocated_ip[3] = 0; - send_DHCP_DISCOVER(); - dhcp_state = STATE_DHCP_DISCOVER; - break; - case STATE_DHCP_DISCOVER : - if (type == DHCP_OFFER){ -#ifdef _DHCP_DEBUG_ - printf("> Receive DHCP_OFFER\r\n"); -#endif - DHCP_allocated_ip[0] = pDHCPMSG->yiaddr[0]; - DHCP_allocated_ip[1] = pDHCPMSG->yiaddr[1]; - DHCP_allocated_ip[2] = pDHCPMSG->yiaddr[2]; - DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3]; - - send_DHCP_REQUEST(); - dhcp_state = STATE_DHCP_REQUEST; - } else ret = check_DHCP_timeout(); - break; - - case STATE_DHCP_REQUEST : - if (type == DHCP_ACK) { - -#ifdef _DHCP_DEBUG_ - printf("> Receive DHCP_ACK\r\n"); -#endif - if (check_DHCP_leasedIP()) { - // Network info assignment from DHCP - dhcp_ip_assign(); - reset_DHCP_timeout(); - - dhcp_state = STATE_DHCP_LEASED; - } else { - // IP address conflict occurred - reset_DHCP_timeout(); - dhcp_ip_conflict(); - dhcp_state = STATE_DHCP_INIT; - } - } else if (type == DHCP_NAK) { - -#ifdef _DHCP_DEBUG_ - printf("> Receive DHCP_NACK\r\n"); -#endif - - reset_DHCP_timeout(); - - dhcp_state = STATE_DHCP_DISCOVER; - } else ret = check_DHCP_timeout(); - break; - - case STATE_DHCP_LEASED : - ret = DHCP_IP_LEASED; - if ((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time/2) < dhcp_tick_1s)) { - -#ifdef _DHCP_DEBUG_ - printf("> Maintains the IP address \r\n"); -#endif - - type = 0; - OLD_allocated_ip[0] = DHCP_allocated_ip[0]; - OLD_allocated_ip[1] = DHCP_allocated_ip[1]; - OLD_allocated_ip[2] = DHCP_allocated_ip[2]; - OLD_allocated_ip[3] = DHCP_allocated_ip[3]; - - DHCP_XID++; - - send_DHCP_REQUEST(); - - reset_DHCP_timeout(); - - dhcp_state = STATE_DHCP_REREQUEST; - } - break; - - case STATE_DHCP_REREQUEST : - ret = DHCP_IP_LEASED; - if (type == DHCP_ACK) { - dhcp_retry_count = 0; - if (OLD_allocated_ip[0] != DHCP_allocated_ip[0] || - OLD_allocated_ip[1] != DHCP_allocated_ip[1] || - OLD_allocated_ip[2] != DHCP_allocated_ip[2] || - OLD_allocated_ip[3] != DHCP_allocated_ip[3]) - { - ret = DHCP_IP_CHANGED; - dhcp_ip_update(); - #ifdef _DHCP_DEBUG_ - printf(">IP changed.\r\n"); - #endif - - } - #ifdef _DHCP_DEBUG_ - else printf(">IP is continued.\r\n"); - #endif - reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_LEASED; - } else if (type == DHCP_NAK) { - -#ifdef _DHCP_DEBUG_ - printf("> Receive DHCP_NACK, Failed to maintain ip\r\n"); -#endif - - reset_DHCP_timeout(); - - dhcp_state = STATE_DHCP_DISCOVER; - } else ret = check_DHCP_timeout(); - break; - default : - break; - } - - return ret; -} - -void DHCP_stop(void) -{ - close(DHCP_SOCKET); - dhcp_state = STATE_DHCP_STOP; -} - -uint8_t check_DHCP_timeout(void) -{ - uint8_t ret = DHCP_RUNNING; - - if (dhcp_retry_count < MAX_DHCP_RETRY) { - if (dhcp_tick_next < dhcp_tick_1s) { - - switch ( dhcp_state ) { - case STATE_DHCP_DISCOVER : -// printf("<> state : STATE_DHCP_DISCOVER\r\n"); - send_DHCP_DISCOVER(); - break; - - case STATE_DHCP_REQUEST : -// printf("<> state : STATE_DHCP_REQUEST\r\n"); - - send_DHCP_REQUEST(); - break; - - case STATE_DHCP_REREQUEST : -// printf("<> state : STATE_DHCP_REREQUEST\r\n"); - - send_DHCP_REQUEST(); - break; - - default : - break; - } - - dhcp_tick_1s = 0; - dhcp_tick_next = dhcp_tick_1s + DHCP_WAIT_TIME; - dhcp_retry_count++; - } - } else { // timeout occurred - - switch(dhcp_state) { - case STATE_DHCP_DISCOVER: - dhcp_state = STATE_DHCP_INIT; - ret = DHCP_FAILED; - break; - case STATE_DHCP_REQUEST: - case STATE_DHCP_REREQUEST: - send_DHCP_DISCOVER(); - dhcp_state = STATE_DHCP_DISCOVER; - break; - default : - break; - } - reset_DHCP_timeout(); - } - return ret; -} - -int8_t check_DHCP_leasedIP(void) -{ - uint8_t tmp; - int32_t ret; - - //WIZchip RCR value changed for ARP Timeout count control - tmp = getRCR(); - setRCR(0x03); - - // IP conflict detection : ARP request - ARP reply - // Broadcasting ARP Request for check the IP conflict using UDP sendto() function - ret = sendto(DHCP_SOCKET, (uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000); - - // RCR value restore - setRCR(tmp); - - if(ret == SOCKERR_TIMEOUT) { - // UDP send Timeout occurred : allocated IP address is unique, DHCP Success - -#ifdef _DHCP_DEBUG_ - printf("\r\n> Check leased IP - OK\r\n"); -#endif - - return 1; - } else { - // Received ARP reply or etc : IP address conflict occur, DHCP Failed - send_DHCP_DECLINE(); - - ret = dhcp_tick_1s; - while((dhcp_tick_1s - ret) < 2) ; // wait for 1s over; wait to complete to send DECLINE message; - - return 0; - } -} - -void DHCP_init(uint8_t s, uint8_t * buf) -{ - uint8_t zeroip[4] = {0,0,0,0}; - getSHAR(DHCP_CHADDR); - if((DHCP_CHADDR[0] | DHCP_CHADDR[1] | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] | DHCP_CHADDR[5]) == 0x00) - { - // assign temporary mac address, you should be set SHAR before call this function. - DHCP_CHADDR[0] = 0x00; - DHCP_CHADDR[1] = 0x08; - DHCP_CHADDR[2] = 0xdc; - DHCP_CHADDR[3] = 0x00; - DHCP_CHADDR[4] = 0x00; - DHCP_CHADDR[5] = 0x00; - setSHAR(DHCP_CHADDR); - } - - DHCP_SOCKET = s; // SOCK_DHCP - pDHCPMSG = (RIP_MSG*)buf; - DHCP_XID = 0x12345678; - - // WIZchip Netinfo Clear - setSIPR(zeroip); - setSIPR(zeroip); - setGAR(zeroip); - - reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_INIT; -} - - -/* Rset the DHCP timeout count and retry count. */ -void reset_DHCP_timeout(void) -{ - dhcp_tick_1s = 0; - dhcp_tick_next = DHCP_WAIT_TIME; - dhcp_retry_count = 0; -} - -void DHCP_time_handler(void) -{ - dhcp_tick_1s++; -} - -void getIPfromDHCP(uint8_t* ip) -{ - ip[0] = DHCP_allocated_ip[0]; - ip[1] = DHCP_allocated_ip[1]; - ip[2] = DHCP_allocated_ip[2]; - ip[3] = DHCP_allocated_ip[3]; -} - -void getGWfromDHCP(uint8_t* ip) -{ - ip[0] =DHCP_allocated_gw[0]; - ip[1] =DHCP_allocated_gw[1]; - ip[2] =DHCP_allocated_gw[2]; - ip[3] =DHCP_allocated_gw[3]; -} - -void getSNfromDHCP(uint8_t* ip) -{ - ip[0] = DHCP_allocated_sn[0]; - ip[1] = DHCP_allocated_sn[1]; - ip[2] = DHCP_allocated_sn[2]; - ip[3] = DHCP_allocated_sn[3]; -} - -void getDNSfromDHCP(uint8_t* ip) -{ - ip[0] = DHCP_allocated_dns[0]; - ip[1] = DHCP_allocated_dns[1]; - ip[2] = DHCP_allocated_dns[2]; - ip[3] = DHCP_allocated_dns[3]; -} - -uint32_t getDHCPLeasetime(void) -{ - return dhcp_lease_time; -} - - - - diff --git a/drivers/wiznet5k/internet/dhcp/dhcp.h b/drivers/wiznet5k/internet/dhcp/dhcp.h deleted file mode 100644 index ee154d506a..0000000000 --- a/drivers/wiznet5k/internet/dhcp/dhcp.h +++ /dev/null @@ -1,150 +0,0 @@ -//***************************************************************************** -// -//! \file dhcp.h -//! \brief DHCP APIs Header file. -//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE. -//! \version 1.1.0 -//! \date 2013/11/18 -//! \par Revision history -//! <2013/11/18> 1st Release -//! <2012/12/20> V1.1.0 -//! 1. Move unreferenced DEFINE to dhcp.c -//! <2012/12/26> V1.1.1 -//! \author Eric Jung & MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** -#ifndef _DHCP_H_ -#define _DHCP_H_ - -/* - * @brief - * @details If you want to display debug & processing message, Define _DHCP_DEBUG_ - * @note If defined, it depends on - */ - -//#define _DHCP_DEBUG_ - -/* Retry to processing DHCP */ -#define MAX_DHCP_RETRY 2 ///< Maximum retry count -#define DHCP_WAIT_TIME 10 ///< Wait Time 10s - -/* UDP port numbers for DHCP */ -#define DHCP_SERVER_PORT 67 ///< DHCP server port number -#define DHCP_CLIENT_PORT 68 ///< DHCP client port number - -#define MAGIC_COOKIE 0x63825363 ///< Any number. You can be modified it any number - -#define DCHP_HOST_NAME "WIZnet\0" - -/* - * @brief return value of @ref DHCP_run() - */ -enum -{ - DHCP_FAILED = 0, ///< Processing Fail - DHCP_RUNNING, ///< Processing DHCP protocol - DHCP_IP_ASSIGN, ///< First Occupy IP from DHPC server (if cbfunc == null, act as default default_ip_assign) - DHCP_IP_CHANGED, ///< Change IP address by new IP address from DHCP (if cbfunc == null, act as default default_ip_update) - DHCP_IP_LEASED, ///< Stand by - DHCP_STOPPED ///< Stop processing DHCP protocol -}; - -/* - * @brief DHCP client initialization (outside of the main loop) - * @param s - socket number - * @param buf - buffer for processing DHCP message - */ -void DHCP_init(uint8_t s, uint8_t * buf); - -/* - * @brief DHCP 1s Tick Timer handler - * @note SHOULD BE register to your system 1s Tick timer handler - */ -void DHCP_time_handler(void); - -/* - * @brief Register call back function - * @param ip_assign - callback func when IP is assigned from DHCP server first - * @param ip_update - callback func when IP is changed - * @prarm ip_conflict - callback func when the assigned IP is conflict with others. - */ -void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)); - -/* - * @brief DHCP client in the main loop - * @return The value is as the follow \n - * @ref DHCP_FAILED \n - * @ref DHCP_RUNNING \n - * @ref DHCP_IP_ASSIGN \n - * @ref DHCP_IP_CHANGED \n - * @ref DHCP_IP_LEASED \n - * @ref DHCP_STOPPED \n - * - * @note This function is always called by you main task. - */ -uint8_t DHCP_run(void); - -/* - * @brief Stop DHCP processing - * @note If you want to restart. call DHCP_init() and DHCP_run() - */ -void DHCP_stop(void); - -/* Get Network information assigned from DHCP server */ -/* - * @brief Get IP address - * @param ip - IP address to be returned - */ -void getIPfromDHCP(uint8_t* ip); -/* - * @brief Get Gateway address - * @param ip - Gateway address to be returned - */ -void getGWfromDHCP(uint8_t* ip); -/* - * @brief Get Subnet mask value - * @param ip - Subnet mask to be returned - */ -void getSNfromDHCP(uint8_t* ip); -/* - * @brief Get DNS address - * @param ip - DNS address to be returned - */ -void getDNSfromDHCP(uint8_t* ip); - -/* - * @brief Get the leased time by DHCP sever - * @return unit 1s - */ -uint32_t getDHCPLeasetime(void); - -#endif /* _DHCP_H_ */ diff --git a/drivers/wiznet5k/internet/dns/dns.c b/drivers/wiznet5k/internet/dns/dns.c deleted file mode 100644 index c0ad570c00..0000000000 --- a/drivers/wiznet5k/internet/dns/dns.c +++ /dev/null @@ -1,566 +0,0 @@ -//***************************************************************************** -// -//! \file dns.c -//! \brief DNS APIs Implement file. -//! \details Send DNS query & Receive DNS reponse. \n -//! It depends on stdlib.h & string.h in ansi-c library -//! \version 1.1.0 -//! \date 2013/11/18 -//! \par Revision history -//! <2013/10/21> 1st Release -//! <2013/12/20> V1.1.0 -//! 1. Remove secondary DNS server in DNS_run -//! If 1st DNS_run failed, call DNS_run with 2nd DNS again -//! 2. DNS_timerHandler -> DNS_time_handler -//! 3. Remove the unused define -//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c -//! <2013/12/20> V1.1.0 -//! -//! \author Eric Jung & MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#include -#include - -//#include "Ethernet/socket.h" -//#include "Internet/DNS/dns.h" -#include "../../ethernet/socket.h" -#include "dns.h" - -#ifdef _DNS_DEBUG_ - #include -#endif - -#define INITRTT 2000L /* Initial smoothed response time */ -#define MAXCNAME (MAX_DOMAIN_NAME + (MAX_DOMAIN_NAME>>1)) /* Maximum amount of cname recursion */ - -#define TYPE_A 1 /* Host address */ -#define TYPE_NS 2 /* Name server */ -#define TYPE_MD 3 /* Mail destination (obsolete) */ -#define TYPE_MF 4 /* Mail forwarder (obsolete) */ -#define TYPE_CNAME 5 /* Canonical name */ -#define TYPE_SOA 6 /* Start of Authority */ -#define TYPE_MB 7 /* Mailbox name (experimental) */ -#define TYPE_MG 8 /* Mail group member (experimental) */ -#define TYPE_MR 9 /* Mail rename name (experimental) */ -#define TYPE_NULL 10 /* Null (experimental) */ -#define TYPE_WKS 11 /* Well-known sockets */ -#define TYPE_PTR 12 /* Pointer record */ -#define TYPE_HINFO 13 /* Host information */ -#define TYPE_MINFO 14 /* Mailbox information (experimental)*/ -#define TYPE_MX 15 /* Mail exchanger */ -#define TYPE_TXT 16 /* Text strings */ -#define TYPE_ANY 255 /* Matches any type */ - -#define CLASS_IN 1 /* The ARPA Internet */ - -/* Round trip timing parameters */ -#define AGAIN 8 /* Average RTT gain = 1/8 */ -#define LAGAIN 3 /* Log2(AGAIN) */ -#define DGAIN 4 /* Mean deviation gain = 1/4 */ -#define LDGAIN 2 /* log2(DGAIN) */ - -/* Header for all domain messages */ -struct dhdr -{ - uint16_t id; /* Identification */ - uint8_t qr; /* Query/Response */ -#define QUERY 0 -#define RESPONSE 1 - uint8_t opcode; -#define IQUERY 1 - uint8_t aa; /* Authoratative answer */ - uint8_t tc; /* Truncation */ - uint8_t rd; /* Recursion desired */ - uint8_t ra; /* Recursion available */ - uint8_t rcode; /* Response code */ -#define NO_ERROR 0 -#define FORMAT_ERROR 1 -#define SERVER_FAIL 2 -#define NAME_ERROR 3 -#define NOT_IMPL 4 -#define REFUSED 5 - uint16_t qdcount; /* Question count */ - uint16_t ancount; /* Answer count */ - uint16_t nscount; /* Authority (name server) count */ - uint16_t arcount; /* Additional record count */ -}; - - -uint8_t* pDNSMSG; // DNS message buffer -uint8_t DNS_SOCKET; // SOCKET number for DNS -uint16_t DNS_MSGID; // DNS message ID - -extern uint32_t HAL_GetTick(void); -uint32_t hal_sys_tick; - -/* converts uint16_t from network buffer to a host byte order integer. */ -uint16_t get16(uint8_t * s) -{ - uint16_t i; - i = *s++ << 8; - i = i + *s; - return i; -} - -/* copies uint16_t to the network buffer with network byte order. */ -uint8_t * put16(uint8_t * s, uint16_t i) -{ - *s++ = i >> 8; - *s++ = i; - return s; -} - - -/* - * CONVERT A DOMAIN NAME TO THE HUMAN-READABLE FORM - * - * Description : This function converts a compressed domain name to the human-readable form - * Arguments : msg - is a pointer to the reply message - * compressed - is a pointer to the domain name in reply message. - * buf - is a pointer to the buffer for the human-readable form name. - * len - is the MAX. size of buffer. - * Returns : the length of compressed message - */ -int parse_name(uint8_t * msg, uint8_t * compressed, char * buf, int16_t len) -{ - uint16_t slen; /* Length of current segment */ - uint8_t * cp; - int clen = 0; /* Total length of compressed name */ - int indirect = 0; /* Set if indirection encountered */ - int nseg = 0; /* Total number of segments in name */ - - cp = compressed; - - for (;;) - { - slen = *cp++; /* Length of this segment */ - - if (!indirect) clen++; - - if ((slen & 0xc0) == 0xc0) - { - if (!indirect) - clen++; - indirect = 1; - /* Follow indirection */ - cp = &msg[((slen & 0x3f)<<8) + *cp]; - slen = *cp++; - } - - if (slen == 0) /* zero length == all done */ - break; - - len -= slen + 1; - - if (len < 0) return -1; - - if (!indirect) clen += slen; - - while (slen-- != 0) *buf++ = (char)*cp++; - *buf++ = '.'; - nseg++; - } - - if (nseg == 0) - { - /* Root name; represent as single dot */ - *buf++ = '.'; - len--; - } - - *buf++ = '\0'; - len--; - - return clen; /* Length of compressed message */ -} - -/* - * PARSE QUESTION SECTION - * - * Description : This function parses the question record of the reply message. - * Arguments : msg - is a pointer to the reply message - * cp - is a pointer to the question record. - * Returns : a pointer the to next record. - */ -uint8_t * dns_question(uint8_t * msg, uint8_t * cp) -{ - int len; - char name[MAXCNAME]; - - len = parse_name(msg, cp, name, MAXCNAME); - - - if (len == -1) return 0; - - cp += len; - cp += 2; /* type */ - cp += 2; /* class */ - - return cp; -} - - -/* - * PARSE ANSER SECTION - * - * Description : This function parses the answer record of the reply message. - * Arguments : msg - is a pointer to the reply message - * cp - is a pointer to the answer record. - * Returns : a pointer the to next record. - */ -uint8_t * dns_answer(uint8_t * msg, uint8_t * cp, uint8_t * ip_from_dns) -{ - int len, type; - char name[MAXCNAME]; - - len = parse_name(msg, cp, name, MAXCNAME); - - if (len == -1) return 0; - - cp += len; - type = get16(cp); - cp += 2; /* type */ - cp += 2; /* class */ - cp += 4; /* ttl */ - cp += 2; /* len */ - - - switch (type) - { - case TYPE_A: - /* Just read the address directly into the structure */ - ip_from_dns[0] = *cp++; - ip_from_dns[1] = *cp++; - ip_from_dns[2] = *cp++; - ip_from_dns[3] = *cp++; - break; - case TYPE_CNAME: - case TYPE_MB: - case TYPE_MG: - case TYPE_MR: - case TYPE_NS: - case TYPE_PTR: - /* These types all consist of a single domain name */ - /* convert it to ASCII format */ - len = parse_name(msg, cp, name, MAXCNAME); - if (len == -1) return 0; - - cp += len; - break; - case TYPE_HINFO: - len = *cp++; - cp += len; - - len = *cp++; - cp += len; - break; - case TYPE_MX: - cp += 2; - /* Get domain name of exchanger */ - len = parse_name(msg, cp, name, MAXCNAME); - if (len == -1) return 0; - - cp += len; - break; - case TYPE_SOA: - /* Get domain name of name server */ - len = parse_name(msg, cp, name, MAXCNAME); - if (len == -1) return 0; - - cp += len; - - /* Get domain name of responsible person */ - len = parse_name(msg, cp, name, MAXCNAME); - if (len == -1) return 0; - - cp += len; - - cp += 4; - cp += 4; - cp += 4; - cp += 4; - cp += 4; - break; - case TYPE_TXT: - /* Just stash */ - break; - default: - /* Ignore */ - break; - } - - return cp; -} - -/* - * PARSE THE DNS REPLY - * - * Description : This function parses the reply message from DNS server. - * Arguments : dhdr - is a pointer to the header for DNS message - * buf - is a pointer to the reply message. - * len - is the size of reply message. - * Returns : -1 - Domain name length is too big - * 0 - Fail (Timeout or parse error) - * 1 - Success, - */ -int8_t parseDNSMSG(struct dhdr * pdhdr, uint8_t * pbuf, uint8_t * ip_from_dns) -{ - uint16_t tmp; - uint16_t i; - uint8_t * msg; - uint8_t * cp; - - msg = pbuf; - memset(pdhdr, 0, sizeof(*pdhdr)); - - pdhdr->id = get16(&msg[0]); - tmp = get16(&msg[2]); - if (tmp & 0x8000) pdhdr->qr = 1; - - pdhdr->opcode = (tmp >> 11) & 0xf; - - if (tmp & 0x0400) pdhdr->aa = 1; - if (tmp & 0x0200) pdhdr->tc = 1; - if (tmp & 0x0100) pdhdr->rd = 1; - if (tmp & 0x0080) pdhdr->ra = 1; - - pdhdr->rcode = tmp & 0xf; - pdhdr->qdcount = get16(&msg[4]); - pdhdr->ancount = get16(&msg[6]); - pdhdr->nscount = get16(&msg[8]); - pdhdr->arcount = get16(&msg[10]); - - - /* Now parse the variable length sections */ - cp = &msg[12]; - - /* Question section */ - for (i = 0; i < pdhdr->qdcount; i++) - { - cp = dns_question(msg, cp); - if(!cp) - { -#ifdef _DNS_DEBUG_ - printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n"); -#endif - return -1; - } - } - - /* Answer section */ - for (i = 0; i < pdhdr->ancount; i++) - { - cp = dns_answer(msg, cp, ip_from_dns); - if(!cp) - { -#ifdef _DNS_DEBUG_ - printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n"); -#endif - return -1; - } - - } - - /* Name server (authority) section */ - for (i = 0; i < pdhdr->nscount; i++) - { - ; - } - - /* Additional section */ - for (i = 0; i < pdhdr->arcount; i++) - { - ; - } - - if(pdhdr->rcode == 0) return 1; // No error - else return 0; -} - - -/* - * MAKE DNS QUERY MESSAGE - * - * Description : This function makes DNS query message. - * Arguments : op - Recursion desired - * name - is a pointer to the domain name. - * buf - is a pointer to the buffer for DNS message. - * len - is the MAX. size of buffer. - * Returns : the pointer to the DNS message. - */ -int16_t dns_makequery(uint16_t op, char * name, uint8_t * buf, uint16_t len) -{ - uint8_t *cp; - char *cp1; - char sname[MAXCNAME]; - char *dname; - uint16_t p; - uint16_t dlen; - - cp = buf; - - DNS_MSGID++; - cp = put16(cp, DNS_MSGID); - p = (op << 11) | 0x0100; /* Recursion desired */ - cp = put16(cp, p); - cp = put16(cp, 1); - cp = put16(cp, 0); - cp = put16(cp, 0); - cp = put16(cp, 0); - - strcpy(sname, name); - dname = sname; - dlen = strlen(dname); - for (;;) - { - /* Look for next dot */ - cp1 = strchr(dname, '.'); - - if (cp1 != NULL) len = cp1 - dname; /* More to come */ - else len = dlen; /* Last component */ - - *cp++ = len; /* Write length of component */ - if (len == 0) break; - - /* Copy component up to (but not including) dot */ - memcpy(cp, dname, len); - cp += len; - if (cp1 == NULL) - { - *cp++ = 0; /* Last one; write null and finish */ - break; - } - dname += len+1; - dlen -= len+1; - } - - cp = put16(cp, 0x0001); /* type */ - cp = put16(cp, 0x0001); /* class */ - - return ((int16_t)((uint32_t)(cp) - (uint32_t)(buf))); -} - -/* - * CHECK DNS TIMEOUT - * - * Description : This function check the DNS timeout - * Arguments : None. - * Returns : -1 - timeout occurred, 0 - timer over, but no timeout, 1 - no timer over, no timeout occur - * Note : timeout : retry count and timer both over. - */ - -int8_t check_DNS_timeout(void) -{ - static uint8_t retry_count; - - uint32_t tick = HAL_GetTick(); - if(tick - hal_sys_tick >= DNS_WAIT_TIME * 1000) - { - hal_sys_tick = tick; - if(retry_count >= MAX_DNS_RETRY) { - retry_count = 0; - return -1; // timeout occurred - } - retry_count++; - return 0; // timer over, but no timeout - } - - return 1; // no timer over, no timeout occur -} - - - -/* DNS CLIENT INIT */ -void DNS_init(uint8_t s, uint8_t * buf) -{ - DNS_SOCKET = s; // SOCK_DNS - pDNSMSG = buf; // User's shared buffer - DNS_MSGID = DNS_MSG_ID; -} - -/* DNS CLIENT RUN */ -int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns) -{ - int8_t ret; - struct dhdr dhp; - uint8_t ip[4]; - uint16_t len, port; - int8_t ret_check_timeout; - - hal_sys_tick = HAL_GetTick(); - - // Socket open - WIZCHIP_EXPORT(socket)(DNS_SOCKET, Sn_MR_UDP, 0, 0); - -#ifdef _DNS_DEBUG_ - printf("> DNS Query to DNS Server : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]); -#endif - - len = dns_makequery(0, (char *)name, pDNSMSG, MAX_DNS_BUF_SIZE); - WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN); - - while (1) - { - if ((len = getSn_RX_RSR(DNS_SOCKET)) > 0) - { - if (len > MAX_DNS_BUF_SIZE) len = MAX_DNS_BUF_SIZE; - len = WIZCHIP_EXPORT(recvfrom)(DNS_SOCKET, pDNSMSG, len, ip, &port); - #ifdef _DNS_DEBUG_ - printf("> Receive DNS message from %d.%d.%d.%d(%d). len = %d\r\n", ip[0], ip[1], ip[2], ip[3],port,len); - #endif - ret = parseDNSMSG(&dhp, pDNSMSG, ip_from_dns); - break; - } - // Check Timeout - ret_check_timeout = check_DNS_timeout(); - if (ret_check_timeout < 0) { - -#ifdef _DNS_DEBUG_ - printf("> DNS Server is not responding : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]); -#endif - return 0; // timeout occurred - } - else if (ret_check_timeout == 0) { - -#ifdef _DNS_DEBUG_ - printf("> DNS Timeout\r\n"); -#endif - WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN); - } - } - WIZCHIP_EXPORT(close)(DNS_SOCKET); - // Return value - // 0 > : failed / 1 - success - return ret; -} diff --git a/drivers/wiznet5k/internet/dns/dns.h b/drivers/wiznet5k/internet/dns/dns.h deleted file mode 100644 index de0039515e..0000000000 --- a/drivers/wiznet5k/internet/dns/dns.h +++ /dev/null @@ -1,96 +0,0 @@ -//***************************************************************************** -// -//! \file dns.h -//! \brief DNS APIs Header file. -//! \details Send DNS query & Receive DNS reponse. -//! \version 1.1.0 -//! \date 2013/11/18 -//! \par Revision history -//! <2013/10/21> 1st Release -//! <2013/12/20> V1.1.0 -//! 1. Remove secondary DNS server in DNS_run -//! If 1st DNS_run failed, call DNS_run with 2nd DNS again -//! 2. DNS_timerHandler -> DNS_time_handler -//! 3. Move the no reference define to dns.c -//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c -//! <2013/12/20> V1.1.0 -//! -//! \author Eric Jung & MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#ifndef _DNS_H_ -#define _DNS_H_ - -#include -/* - * @brief Define it for Debug & Monitor DNS processing. - * @note If defined, it depends on - */ - -//#define _DNS_DEBUG_ - -#define MAX_DNS_BUF_SIZE 256 ///< maximum size of DNS buffer. */ -/* - * @brief Maximum length of your queried Domain name - * @todo SHOULD BE defined it equal as or greater than your Domain name length + null character(1) - * @note SHOULD BE careful to stack overflow because it is allocated 1.5 times as MAX_DOMAIN_NAME in stack. - */ -#define MAX_DOMAIN_NAME 32 // for example "www.google.com" - -#define MAX_DNS_RETRY 2 ///< Requery Count -#define DNS_WAIT_TIME 4 ///< Wait response time. unit 1s. - -#define IPPORT_DOMAIN 53 ///< DNS server port number - -#define DNS_MSG_ID 0x1122 ///< ID for DNS message. You can be modified it any number -/* - * @brief DNS process initialize - * @param s : Socket number for DNS - * @param buf : Buffer for DNS message - */ -void DNS_init(uint8_t s, uint8_t * buf); - -/* - * @brief DNS process - * @details Send DNS query and receive DNS response - * @param dns_ip : DNS server ip address - * @param name : Domain name to be queried - * @param ip_from_dns : IP address from DNS server - * @return -1 : failed. @ref MAX_DOMIN_NAME is too small \n - * 0 : failed (Timeout or Parse error)\n - * 1 : success - * @note This function blocks until success or fail. max time = @ref MAX_DNS_RETRY * @ref DNS_WAIT_TIME - */ -int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns); - -#endif /* _DNS_H_ */ From 8308f9c977adf322b264e5fbec6dd84315231eb4 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 20 Aug 2022 11:25:34 +0200 Subject: [PATCH 0309/1041] extmod/network_wiznet5k: Use the configured DNS address if available. Instead of the default 8.8.8.8. The change was suggested by @omogenot. --- extmod/network_wiznet5k.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extmod/network_wiznet5k.c b/extmod/network_wiznet5k.c index 89c933c2d4..95c852d7f7 100644 --- a/extmod/network_wiznet5k.c +++ b/extmod/network_wiznet5k.c @@ -397,6 +397,9 @@ STATIC int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t dns_ip[MOD_NETWORK_IPADDR_BUF_SIZE] = {8, 8, 8, 8}; uint8_t *buf = m_new(uint8_t, MAX_DNS_BUF_SIZE); DNS_init(2, buf); + if (wiznet5k_obj.netinfo.dns[0]) { + memcpy(dns_ip, wiznet5k_obj.netinfo.dns, MOD_NETWORK_IPADDR_BUF_SIZE); + } mp_int_t ret = DNS_run(dns_ip, (uint8_t *)name, out_ip); m_del(uint8_t, buf, MAX_DNS_BUF_SIZE); if (ret == 1) { From 47c45d0e7fda10f4a62b7017d48ae452203b22f0 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 22 Aug 2022 08:09:02 +0200 Subject: [PATCH 0310/1041] rp2/machine_wdt: Check for the maximum timeout value of watchdog. The value will be checked for timeout <= 8388. Notes were added to the documentation. --- docs/library/machine.WDT.rst | 5 +++-- docs/rp2/quickref.rst | 1 + ports/rp2/machine_wdt.c | 9 ++++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/library/machine.WDT.rst b/docs/library/machine.WDT.rst index 8c81e10ea5..95893cec36 100644 --- a/docs/library/machine.WDT.rst +++ b/docs/library/machine.WDT.rst @@ -15,7 +15,7 @@ Example usage:: wdt = WDT(timeout=2000) # enable it with a timeout of 2s wdt.feed() -Availability of this class: pyboard, WiPy, esp8266, esp32. +Availability of this class: pyboard, WiPy, esp8266, esp32, rp2040, mimxrt. Constructors ------------ @@ -26,7 +26,8 @@ Constructors Once it is running the timeout cannot be changed and the WDT cannot be stopped either. Notes: On the esp32 the minimum timeout is 1 second. On the esp8266 a timeout - cannot be specified, it is determined by the underlying system. + cannot be specified, it is determined by the underlying system. On rp2040 devices, + the maximum timeout is 8388 ms. Methods ------- diff --git a/docs/rp2/quickref.rst b/docs/rp2/quickref.rst index 4824f390eb..430c130c6e 100644 --- a/docs/rp2/quickref.rst +++ b/docs/rp2/quickref.rst @@ -296,6 +296,7 @@ See :ref:`machine.WDT `. :: wdt = WDT(timeout=5000) wdt.feed() +The maximum value for timeout is 8388 ms. OneWire driver -------------- diff --git a/ports/rp2/machine_wdt.c b/ports/rp2/machine_wdt.c index 38e0597018..d6914a4f26 100644 --- a/ports/rp2/machine_wdt.c +++ b/ports/rp2/machine_wdt.c @@ -29,6 +29,9 @@ #include "hardware/watchdog.h" +// The maximum timeout in milliseconds is: 0xffffff / 2 / 1000 +#define WDT_TIMEOUT_MAX 8388 + typedef struct _machine_wdt_obj_t { mp_obj_base_t base; } machine_wdt_obj_t; @@ -53,7 +56,11 @@ STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type, size_t n_args, s } // Start the watchdog (timeout is in milliseconds). - watchdog_enable(args[ARG_timeout].u_int, false); + uint32_t timeout = args[ARG_timeout].u_int; + if (timeout > WDT_TIMEOUT_MAX) { + mp_raise_ValueError(MP_ERROR_TEXT("timeout exceeds " MP_STRINGIFY(WDT_TIMEOUT_MAX))); + } + watchdog_enable(timeout, false); return MP_OBJ_FROM_PTR(&machine_wdt); } From 98d1c50159fe9427d72ec358ba0219eaebb1d991 Mon Sep 17 00:00:00 2001 From: glenn20 Date: Sun, 31 Jul 2022 16:36:10 +1000 Subject: [PATCH 0311/1041] esp32/network_wlan: Use esp_wifi_set/get_channel to config wifi channel. Set the channel with esp_wifi_set_channel(), which adds support for setting the channel of the STA interface Get the channel with esp_wifi_get_channel() which returns the actual wifi channel of the radio, rather than the configured channel. --- ports/esp32/network_wlan.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/ports/esp32/network_wlan.c b/ports/esp32/network_wlan.c index 9b2200e4ff..501dc40f27 100644 --- a/ports/esp32/network_wlan.c +++ b/ports/esp32/network_wlan.c @@ -448,8 +448,22 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_ break; } case MP_QSTR_channel: { - req_if = WIFI_IF_AP; - cfg.ap.channel = mp_obj_get_int(kwargs->table[i].value); + uint8_t primary; + wifi_second_chan_t secondary; + // Get the current value of secondary + esp_exceptions(esp_wifi_get_channel(&primary, &secondary)); + primary = mp_obj_get_int(kwargs->table[i].value); + esp_err_t err = esp_wifi_set_channel(primary, secondary); + if (err == ESP_ERR_INVALID_ARG) { + // May need to swap secondary channel above to below or below to above + secondary = ( + (secondary == WIFI_SECOND_CHAN_ABOVE) + ? WIFI_SECOND_CHAN_BELOW + : (secondary == WIFI_SECOND_CHAN_BELOW) + ? WIFI_SECOND_CHAN_ABOVE + : WIFI_SECOND_CHAN_NONE); + esp_exceptions(esp_wifi_set_channel(primary, secondary)); + } break; } case MP_QSTR_hostname: @@ -535,10 +549,13 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_ req_if = WIFI_IF_AP; val = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode); break; - case MP_QSTR_channel: - req_if = WIFI_IF_AP; - val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel); + case MP_QSTR_channel: { + uint8_t channel; + wifi_second_chan_t second; + esp_exceptions(esp_wifi_get_channel(&channel, &second)); + val = MP_OBJ_NEW_SMALL_INT(channel); break; + } case MP_QSTR_hostname: case MP_QSTR_dhcp_hostname: { const char *s; From 76f2e3e62bd2bc177a62649bae34b67d9bd2c8b1 Mon Sep 17 00:00:00 2001 From: glenn20 Date: Sun, 31 Jul 2022 18:17:40 +1000 Subject: [PATCH 0312/1041] esp32/network_wlan: Add support to set/get the wifi protocol. Add 'protocol' option to WLAN.config() to support setting/getting the wifi protocol modes: MODE_11G|MODE_11G|MODE_11N. --- ports/esp32/network_wlan.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ports/esp32/network_wlan.c b/ports/esp32/network_wlan.c index 501dc40f27..4f74262afc 100644 --- a/ports/esp32/network_wlan.c +++ b/ports/esp32/network_wlan.c @@ -490,6 +490,10 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_ esp_exceptions(esp_wifi_set_max_tx_power(power)); break; } + case MP_QSTR_protocol: { + esp_exceptions(esp_wifi_set_protocol(self->if_id, mp_obj_get_int(kwargs->table[i].value))); + break; + } default: goto unknown; } @@ -578,6 +582,12 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_ val = mp_obj_new_float(power * 0.25); break; } + case MP_QSTR_protocol: { + uint8_t protocol_bitmap; + esp_exceptions(esp_wifi_get_protocol(self->if_id, &protocol_bitmap)); + val = MP_OBJ_NEW_SMALL_INT(protocol_bitmap); + break; + } default: goto unknown; } From 0507f239e812fa7ae57c1e172c53eae8fc37cd18 Mon Sep 17 00:00:00 2001 From: glenn20 Date: Sun, 31 Jul 2022 18:19:18 +1000 Subject: [PATCH 0313/1041] esp32/modnetwork: Add network.MODE_LR constant. Adds the MODE_LR constant to the network module to support Espressif's long-range communication protocol. --- ports/esp32/modnetwork.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/esp32/modnetwork.c b/ports/esp32/modnetwork.c index 45231c4230..7429274c15 100644 --- a/ports/esp32/modnetwork.c +++ b/ports/esp32/modnetwork.c @@ -244,6 +244,7 @@ STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_MODE_11B), MP_ROM_INT(WIFI_PROTOCOL_11B) }, { MP_ROM_QSTR(MP_QSTR_MODE_11G), MP_ROM_INT(WIFI_PROTOCOL_11G) }, { MP_ROM_QSTR(MP_QSTR_MODE_11N), MP_ROM_INT(WIFI_PROTOCOL_11N) }, + { MP_ROM_QSTR(MP_QSTR_MODE_LR), MP_ROM_INT(WIFI_PROTOCOL_LR) }, { MP_ROM_QSTR(MP_QSTR_AUTH_OPEN), MP_ROM_INT(WIFI_AUTH_OPEN) }, { MP_ROM_QSTR(MP_QSTR_AUTH_WEP), MP_ROM_INT(WIFI_AUTH_WEP) }, From e6e60f4330c176e1a9443a994ba29ea155d7aca7 Mon Sep 17 00:00:00 2001 From: glenn20 Date: Fri, 12 Aug 2022 16:53:48 +1000 Subject: [PATCH 0314/1041] esp8266/modnetwork: Add support for WLAN.config(protocol=XX) option. Following esp32. This is preferred to using the phy_mode() function. --- ports/esp8266/modnetwork.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ports/esp8266/modnetwork.c b/ports/esp8266/modnetwork.c index dbc12f74d4..5240d3b320 100644 --- a/ports/esp8266/modnetwork.c +++ b/ports/esp8266/modnetwork.c @@ -406,6 +406,10 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs } break; } + case MP_QSTR_protocol: { + wifi_set_phy_mode(mp_obj_get_int(kwargs->table[i].value)); + break; + } default: goto unknown; } @@ -473,6 +477,10 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs } break; } + case MP_QSTR_protocol: { + val = mp_obj_new_int(wifi_get_phy_mode()); + break; + } default: goto unknown; } From 13dceaa4ea4336eddb763985c2274cfa497c8e82 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 12 Jul 2022 18:25:41 +0200 Subject: [PATCH 0315/1041] esp32/machine_uart: Change sendbreak time to be at least 15 bit times. It used to be 10 bit times, which is too short. The break state must be longer than a regular character time, at least 13 bit times. This is now implemented by reducing the baudrate while sending the "0". The break time will now vary with data length and parity setting, but will at least be 15 bit times. Tested with a GENERIC_SPIRAM, GENERIC_C3 and UM_TINYS2 board. --- ports/esp32/machine_uart.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/ports/esp32/machine_uart.c b/ports/esp32/machine_uart.c index 49ce78b1b2..28110e39f3 100644 --- a/ports/esp32/machine_uart.c +++ b/ports/esp32/machine_uart.c @@ -399,28 +399,19 @@ STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); // Save settings - uart_word_length_t word_length; - uart_parity_t parity; - uart_get_word_length(self->uart_num, &word_length); - uart_get_parity(self->uart_num, &parity); + uint32_t baudrate; + uart_get_baudrate(self->uart_num, &baudrate); - // Synthesise the break condition by either a longer word or using even parity + // Synthesise the break condition by reducing the baud rate, + // and cater for the worst case of 5 data bits, no parity. uart_wait_tx_done(self->uart_num, pdMS_TO_TICKS(1000)); - if (word_length != UART_DATA_8_BITS) { - uart_set_word_length(self->uart_num, UART_DATA_8_BITS); - } else if (parity == UART_PARITY_DISABLE) { - uart_set_parity(self->uart_num, UART_PARITY_EVEN); - } else { - // Cannot synthesise break - mp_raise_OSError(MP_EPERM); - } + uart_set_baudrate(self->uart_num, baudrate * 6 / 15); char buf[1] = {0}; uart_write_bytes(self->uart_num, buf, 1); uart_wait_tx_done(self->uart_num, pdMS_TO_TICKS(1000)); - // Restore original settings - uart_set_word_length(self->uart_num, word_length); - uart_set_parity(self->uart_num, parity); + // Restore original setting + uart_set_baudrate(self->uart_num, baudrate); return mp_const_none; } From 8139cbcf6bfad3f9b14865a5315bc83b5c5ecc7a Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 17 Aug 2022 08:44:03 +0200 Subject: [PATCH 0316/1041] esp32/machine_timer: Support all init arguments in Timer constructor. Following the usual style of instantiation and init(). --- ports/esp32/machine_timer.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/ports/esp32/machine_timer.c b/ports/esp32/machine_timer.c index 8541bcbfdb..66969b3a95 100644 --- a/ports/esp32/machine_timer.c +++ b/ports/esp32/machine_timer.c @@ -68,6 +68,7 @@ typedef struct _machine_timer_obj_t { const mp_obj_type_t machine_timer_type; STATIC void machine_timer_disable(machine_timer_obj_t *self); +STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); void machine_timer_deinit_all(void) { // Disable, deallocate and remove all timers from list @@ -94,24 +95,35 @@ STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_pr } STATIC mp_obj_t machine_timer_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, 1, false); + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); mp_uint_t group = (mp_obj_get_int(args[0]) >> 1) & 1; mp_uint_t index = mp_obj_get_int(args[0]) & 1; - // Check whether the timer is already initialized, if so return it + machine_timer_obj_t *self = NULL; + + // Check whether the timer is already initialized, if so use it for (machine_timer_obj_t *t = MP_STATE_PORT(machine_timer_obj_head); t; t = t->next) { if (t->group == group && t->index == index) { - return t; + self = t; + break; } } + // The timer does not exist, create it. + if (self == NULL) { + self = mp_obj_malloc(machine_timer_obj_t, &machine_timer_type); + self->group = group; + self->index = index; - machine_timer_obj_t *self = mp_obj_malloc(machine_timer_obj_t, &machine_timer_type); - self->group = group; - self->index = index; + // Add the timer to the linked-list of timers + self->next = MP_STATE_PORT(machine_timer_obj_head); + MP_STATE_PORT(machine_timer_obj_head) = self; + } - // Add the timer to the linked-list of timers - self->next = MP_STATE_PORT(machine_timer_obj_head); - MP_STATE_PORT(machine_timer_obj_head) = self; + if (n_args > 1 || n_kw > 0) { + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + machine_timer_init_helper(self, n_args - 1, args + 1, &kw_args); + } return self; } From 1fbf0efaebd597207f32a910d635a94ec9f6ef69 Mon Sep 17 00:00:00 2001 From: Damiano Mazzella Date: Tue, 23 Aug 2022 16:50:24 +0200 Subject: [PATCH 0317/1041] stm32/sdram: Enable MPU for unaligned access on H7 MCUs. So that SDRAM can be used as the heap on ARDUINO_PORTENTA_H7, for example. Fixes issue #9087. --- ports/stm32/sdram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/sdram.c b/ports/stm32/sdram.c index a94b802ea4..fb0e5a8688 100644 --- a/ports/stm32/sdram.c +++ b/ports/stm32/sdram.c @@ -244,7 +244,7 @@ static void sdram_init_seq(SDRAM_HandleTypeDef #define REFRESH_COUNT (MICROPY_HW_SDRAM_REFRESH_RATE * 90000 / 8192 - 20) HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT); - #if defined(STM32F7) + #if defined(STM32F7) || defined(STM32H7) /* Enable MPU for the SDRAM Memory Region to allow non-aligned accesses (hard-fault otherwise) Initially disable all access for the entire SDRAM memory space, From 923375380b29aca68b50b3ec685c6d83465fd63d Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 30 Mar 2022 10:50:18 +1100 Subject: [PATCH 0318/1041] stm32/boards: Increase mboot region to 32k for WB55 boards. If mboot is built with support for packing (signing/encryption) it needs up to 32KiB. So for simplicity increase the mboot region to 32KiB unconditionally for WB55 boards (custom WB55 board configurations can still provide their own linker scripts to override this). --- ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk | 2 +- ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk | 2 +- ports/stm32/boards/stm32wb55xg.ld | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk index 349ce46d79..2e6ce1fe8f 100644 --- a/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk @@ -6,7 +6,7 @@ STARTUP_FILE = $(STM32LIB_CMSIS_BASE)/Source/Templates/gcc/startup_stm32wb55xx_c ifeq ($(USE_MBOOT),1) # When using Mboot all the text goes together after the bootloader LD_FILES = boards/stm32wb55xg.ld boards/common_bl.ld -TEXT0_ADDR = 0x08004000 +TEXT0_ADDR = 0x08008000 else # When not using Mboot the text goes at the start of flash LD_FILES = boards/stm32wb55xg.ld boards/common_basic.ld diff --git a/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk index 349ce46d79..2e6ce1fe8f 100644 --- a/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk +++ b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk @@ -6,7 +6,7 @@ STARTUP_FILE = $(STM32LIB_CMSIS_BASE)/Source/Templates/gcc/startup_stm32wb55xx_c ifeq ($(USE_MBOOT),1) # When using Mboot all the text goes together after the bootloader LD_FILES = boards/stm32wb55xg.ld boards/common_bl.ld -TEXT0_ADDR = 0x08004000 +TEXT0_ADDR = 0x08008000 else # When not using Mboot the text goes at the start of flash LD_FILES = boards/stm32wb55xg.ld boards/common_basic.ld diff --git a/ports/stm32/boards/stm32wb55xg.ld b/ports/stm32/boards/stm32wb55xg.ld index 841c32b8a0..9b1e5bca14 100644 --- a/ports/stm32/boards/stm32wb55xg.ld +++ b/ports/stm32/boards/stm32wb55xg.ld @@ -6,7 +6,7 @@ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* sectors 0-127 */ - FLASH_APP (rx) : ORIGIN = 0x08004000, LENGTH = 496K /* sectors 4-127 */ + FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 480K /* sectors 8-127 */ FLASH_FS (r) : ORIGIN = 0x08080000, LENGTH = 256K /* sectors 128-191 */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K /* SRAM1 */ RAM2A (xrw) : ORIGIN = 0x20030000, LENGTH = 10K /* SRAM2A */ From 492ba5eaf2c6e1e9fe8e31fd2e8f47fac6188673 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 15 Aug 2022 16:20:40 +1000 Subject: [PATCH 0319/1041] stm32: Move board variant config to mpconfigboard.mk. Rather than having the autobuild know about the particular variants, have the mpconfigboard.mk describe them and make autobuild discover them automatically. Adds a "query-variants" target to stm32/Makefile to allow the set of possible variants to be queried. Removes pybv3 from the autobuild as this isn't use by the downloads page. Signed-off-by: Jim Mussared --- ports/stm32/Makefile | 3 ++ .../stm32/boards/PYBLITEV10/mpconfigboard.mk | 21 ++++++++++++ ports/stm32/boards/PYBV10/mpconfigboard.mk | 21 ++++++++++++ ports/stm32/boards/PYBV11/mpconfigboard.mk | 21 ++++++++++++ tools/autobuild/build-stm32-extra.sh | 34 +++++++------------ 5 files changed, 79 insertions(+), 21 deletions(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 7c912f4f0b..f981f8f3eb 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -37,6 +37,9 @@ include $(TOP)/extmod/extmod.mk GIT_SUBMODULES += lib/libhydrogen lib/lwip lib/mbedtls lib/stm32lib +query-variants: + $(ECHO) "VARIANTS:" $(BOARD_VARIANTS) + LD_DIR=boards USBDEV_DIR=usbdev #USBHOST_DIR=usbhost diff --git a/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk b/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk index df95065225..89977b74ea 100644 --- a/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk +++ b/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk @@ -4,3 +4,24 @@ AF_FILE = boards/stm32f411_af.csv LD_FILES = boards/stm32f411.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 + +# Provide different variants for the downloads page. +BOARD_VARIANTS += "dp thread dp-thread network" + +ifeq ($(BOARD_VARIANT),"dp") +MICROPY_FLOAT_IMPL=double +endif + +ifeq ($(BOARD_VARIANT),"thread") +CFLAGS += -DMICROPY_PY_THREAD=1 +endif + +ifeq ($(BOARD_VARIANT),"dp-thread") +MICROPY_FLOAT_IMPL=double +CFLAGS += -DMICROPY_PY_THREAD=1 +endif + +ifeq ($(BOARD_VARIANT),"network") +MICROPY_PY_NETWORK_WIZNET5K=5200 +MICROPY_PY_CC3K=1 +endif diff --git a/ports/stm32/boards/PYBV10/mpconfigboard.mk b/ports/stm32/boards/PYBV10/mpconfigboard.mk index cb78a7846d..071ae6eb7c 100644 --- a/ports/stm32/boards/PYBV10/mpconfigboard.mk +++ b/ports/stm32/boards/PYBV10/mpconfigboard.mk @@ -14,3 +14,24 @@ endif # MicroPython settings MICROPY_VFS_LFS2 = 1 + +# Provide different variants for the downloads page. +BOARD_VARIANTS += "dp thread dp-thread network" + +ifeq ($(BOARD_VARIANT),"dp") +MICROPY_FLOAT_IMPL=double +endif + +ifeq ($(BOARD_VARIANT),"thread") +CFLAGS += -DMICROPY_PY_THREAD=1 +endif + +ifeq ($(BOARD_VARIANT),"dp-thread") +MICROPY_FLOAT_IMPL=double +CFLAGS += -DMICROPY_PY_THREAD=1 +endif + +ifeq ($(BOARD_VARIANT),"network") +MICROPY_PY_NETWORK_WIZNET5K=5200 +MICROPY_PY_CC3K=1 +endif diff --git a/ports/stm32/boards/PYBV11/mpconfigboard.mk b/ports/stm32/boards/PYBV11/mpconfigboard.mk index cb78a7846d..071ae6eb7c 100644 --- a/ports/stm32/boards/PYBV11/mpconfigboard.mk +++ b/ports/stm32/boards/PYBV11/mpconfigboard.mk @@ -14,3 +14,24 @@ endif # MicroPython settings MICROPY_VFS_LFS2 = 1 + +# Provide different variants for the downloads page. +BOARD_VARIANTS += "dp thread dp-thread network" + +ifeq ($(BOARD_VARIANT),"dp") +MICROPY_FLOAT_IMPL=double +endif + +ifeq ($(BOARD_VARIANT),"thread") +CFLAGS += -DMICROPY_PY_THREAD=1 +endif + +ifeq ($(BOARD_VARIANT),"dp-thread") +MICROPY_FLOAT_IMPL=double +CFLAGS += -DMICROPY_PY_THREAD=1 +endif + +ifeq ($(BOARD_VARIANT),"network") +MICROPY_PY_NETWORK_WIZNET5K=5200 +MICROPY_PY_CC3K=1 +endif diff --git a/tools/autobuild/build-stm32-extra.sh b/tools/autobuild/build-stm32-extra.sh index 80c6f42f5e..feb269e356 100755 --- a/tools/autobuild/build-stm32-extra.sh +++ b/tools/autobuild/build-stm32-extra.sh @@ -7,12 +7,15 @@ function do_build() { board=$2 shift shift - echo "building $descr $board" - build_dir=/tmp/stm-build-$board - $MICROPY_AUTOBUILD_MAKE $@ BOARD=$board BUILD=$build_dir || exit 1 - mv $build_dir/firmware.dfu $dest_dir/$descr$fw_tag.dfu - mv $build_dir/firmware.hex $dest_dir/$descr$fw_tag.hex - rm -rf $build_dir + for variant in `$MICROPY_AUTOBUILD_MAKE BOARD=$board query-variants | grep VARIANTS: | cut -d' ' -f2-`; do + target=$descr-$variant + echo "building $target $board" + build_dir=/tmp/stm-build-$board + $MICROPY_AUTOBUILD_MAKE $@ BOARD=$board BOARD_VARIANT=$variant BUILD=$build_dir || exit 1 + mv $build_dir/firmware.dfu $dest_dir/$target$fw_tag.dfu + mv $build_dir/firmware.hex $dest_dir/$target$fw_tag.hex + rm -rf $build_dir + done } # check/get parameters @@ -30,18 +33,7 @@ if [ ! -r modpyb.c ]; then exit 1 fi -# build the versions -do_build pybv3 PYBV3 -do_build pybv3-network PYBV3 MICROPY_PY_NETWORK_WIZNET5K=5200 MICROPY_PY_CC3K=1 -do_build pybv10-dp PYBV10 MICROPY_FLOAT_IMPL=double -do_build pybv10-thread PYBV10 CFLAGS_EXTRA='-DMICROPY_PY_THREAD=1' -do_build pybv10-dp-thread PYBV10 MICROPY_FLOAT_IMPL=double CFLAGS_EXTRA='-DMICROPY_PY_THREAD=1' -do_build pybv10-network PYBV10 MICROPY_PY_NETWORK_WIZNET5K=5200 MICROPY_PY_CC3K=1 -do_build pybv11-dp PYBV11 MICROPY_FLOAT_IMPL=double -do_build pybv11-thread PYBV11 CFLAGS_EXTRA='-DMICROPY_PY_THREAD=1' -do_build pybv11-dp-thread PYBV11 MICROPY_FLOAT_IMPL=double CFLAGS_EXTRA='-DMICROPY_PY_THREAD=1' -do_build pybv11-network PYBV11 MICROPY_PY_NETWORK_WIZNET5K=5200 MICROPY_PY_CC3K=1 -do_build pyblitev10-dp PYBLITEV10 MICROPY_FLOAT_IMPL=double -do_build pyblitev10-thread PYBLITEV10 CFLAGS_EXTRA='-DMICROPY_PY_THREAD=1' -do_build pyblitev10-dp-thread PYBLITEV10 MICROPY_FLOAT_IMPL=double CFLAGS_EXTRA='-DMICROPY_PY_THREAD=1' -do_build pyblitev10-network PYBLITEV10 MICROPY_PY_NETWORK_WIZNET5K=5200 MICROPY_PY_CC3K=1 +# build the variants for each board +do_build pybv10 PYBV10 +do_build pybv11 PYBV11 +do_build pyblitev10 PYBLITEV10 From 986ad6bf1d35cbc6f8073e847aa6b87156eefc4b Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 25 Aug 2022 12:27:49 +1000 Subject: [PATCH 0320/1041] stm32/boardctrl: Use HAL_Delay instead of mp_hal_delay_ms. Not safe to use mp_hal_delay_ms before boot if threading is enabled, because threading will not have been initialised, and MICROPY_EVENT_POLL_HOOK assumes threading is initialised. HAL_Delay doesn't call MICROPY_EVENT_POLL_HOOK, but is still power-efficient like mp_hal_delay_ms (unlike mp_hal_delay_us). Fixes #7816. Signed-off-by: Jim Mussared --- ports/stm32/boardctrl.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/ports/stm32/boardctrl.c b/ports/stm32/boardctrl.c index 406a983814..85a42a240f 100644 --- a/ports/stm32/boardctrl.c +++ b/ports/stm32/boardctrl.c @@ -89,6 +89,9 @@ void boardctrl_maybe_enter_mboot(size_t n_args, const void *args_in) { #if !MICROPY_HW_USES_BOOTLOADER STATIC uint update_reset_mode(uint reset_mode) { + // Note: Must use HAL_Delay here as MicroPython is not yet initialised + // and mp_hal_delay_ms will attempt to invoke the scheduler. + #if MICROPY_HW_HAS_SWITCH if (switch_get()) { @@ -100,7 +103,7 @@ STATIC uint update_reset_mode(uint reset_mode) { led_state(3, reset_mode & 2); led_state(4, reset_mode & 4); for (uint j = 0; j < 30; ++j) { - mp_hal_delay_ms(20); + HAL_Delay(20); if (!switch_get()) { goto select_mode; } @@ -115,13 +118,13 @@ STATIC uint update_reset_mode(uint reset_mode) { led_state(2, 0); led_state(3, 0); led_state(4, 0); - mp_hal_delay_ms(50); + HAL_Delay(50); led_state(2, reset_mode & 1); led_state(3, reset_mode & 2); led_state(4, reset_mode & 4); - mp_hal_delay_ms(50); + HAL_Delay(50); } - mp_hal_delay_ms(400); + HAL_Delay(400); #elif defined(MICROPY_HW_LED1) @@ -134,11 +137,11 @@ STATIC uint update_reset_mode(uint reset_mode) { break; } led_state(1, 1); - mp_hal_delay_ms(100); + HAL_Delay(100); led_state(1, 0); - mp_hal_delay_ms(200); + HAL_Delay(200); } - mp_hal_delay_ms(400); + HAL_Delay(400); if (!switch_get()) { break; } @@ -150,11 +153,11 @@ STATIC uint update_reset_mode(uint reset_mode) { for (uint i = 0; i < 2; i++) { for (uint j = 0; j < reset_mode; j++) { led_state(1, 1); - mp_hal_delay_ms(100); + HAL_Delay(100); led_state(1, 0); - mp_hal_delay_ms(200); + HAL_Delay(200); } - mp_hal_delay_ms(400); + HAL_Delay(400); } #else #error Need a reset mode update method From 1855df6361ad4ade62aa46ad08f3202a6a5b1bd1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 24 Aug 2022 10:44:35 +1000 Subject: [PATCH 0321/1041] stm32: Remove support for CC3000 WiFi driver. It has been about 8 years since support for this chip was added. Reasons to remove it are: - It is no longer easy to obtain this part. - There are now many other options for WiFi. - It's not a good use of developer time to maintain it. Signed-off-by: Damien George --- ports/stm32/Makefile | 23 - ports/stm32/boards/PYBLITEV10/board.md | 2 +- .../stm32/boards/PYBLITEV10/mpconfigboard.mk | 1 - ports/stm32/boards/PYBV10/board.md | 2 +- ports/stm32/boards/PYBV10/mpconfigboard.mk | 1 - ports/stm32/boards/PYBV11/board.md | 2 +- ports/stm32/boards/PYBV11/mpconfigboard.mk | 1 - ports/stm32/modnwcc3k.c | 608 ------------------ ports/stm32/mpconfigport.h | 8 - ports/stm32/mpconfigport.mk | 3 - tools/ci.sh | 2 - 11 files changed, 3 insertions(+), 650 deletions(-) delete mode 100644 ports/stm32/modnwcc3k.c diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index f981f8f3eb..ee00d77173 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -482,29 +482,6 @@ SRC_MOD += $(addprefix $(WIZNET5K_DIR)/,\ ) endif -# for CC3000 module -ifeq ($(MICROPY_PY_CC3K),1) -CC3000_DIR=drivers/cc3000 -INC += -I$(TOP)/$(CC3000_DIR)/inc -CFLAGS_MOD += -DMICROPY_PY_CC3K=1 -SRC_MOD += modnwcc3k.c -SRC_MOD += $(addprefix $(CC3000_DIR)/src/,\ - cc3000_common.c \ - evnt_handler.c \ - hci.c \ - netapp.c \ - nvmem.c \ - security.c \ - socket.c \ - wlan.c \ - ccspi.c \ - inet_ntop.c \ - inet_pton.c \ - patch.c \ - patch_prog.c \ - ) -endif - ifeq ($(MICROPY_SSL_MBEDTLS),1) CFLAGS_MOD += -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' SRC_MOD += mbedtls/mbedtls_port.c diff --git a/ports/stm32/boards/PYBLITEV10/board.md b/ports/stm32/boards/PYBLITEV10/board.md index 1511ffcf51..b490d54046 100644 --- a/ports/stm32/boards/PYBLITEV10/board.md +++ b/ports/stm32/boards/PYBLITEV10/board.md @@ -1 +1 @@ -The "standard" build is listed first and is the default firmware that the pyboards are shipped with. Use this firmware if you are uncertain. The "double FP" builds use double-precision floating point instead of the standard single precision. The "threading" builds contain the \_thread module and allow multithreading. The "network" builds have network drivers for CC3000 and WIZ820io included. All these different firmware are completely interchangeable and you can freely change from one to the other without losing the filesystem on your pyboard. +The "standard" build is listed first and is the default firmware that the pyboards are shipped with. Use this firmware if you are uncertain. The "double FP" builds use double-precision floating point instead of the standard single precision. The "threading" builds contain the \_thread module and allow multithreading. The "network" builds have network drivers for WIZ820io included. All these different firmware are completely interchangeable and you can freely change from one to the other without losing the filesystem on your pyboard. diff --git a/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk b/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk index 89977b74ea..8aeaf0e40c 100644 --- a/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk +++ b/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk @@ -23,5 +23,4 @@ endif ifeq ($(BOARD_VARIANT),"network") MICROPY_PY_NETWORK_WIZNET5K=5200 -MICROPY_PY_CC3K=1 endif diff --git a/ports/stm32/boards/PYBV10/board.md b/ports/stm32/boards/PYBV10/board.md index 1511ffcf51..b490d54046 100644 --- a/ports/stm32/boards/PYBV10/board.md +++ b/ports/stm32/boards/PYBV10/board.md @@ -1 +1 @@ -The "standard" build is listed first and is the default firmware that the pyboards are shipped with. Use this firmware if you are uncertain. The "double FP" builds use double-precision floating point instead of the standard single precision. The "threading" builds contain the \_thread module and allow multithreading. The "network" builds have network drivers for CC3000 and WIZ820io included. All these different firmware are completely interchangeable and you can freely change from one to the other without losing the filesystem on your pyboard. +The "standard" build is listed first and is the default firmware that the pyboards are shipped with. Use this firmware if you are uncertain. The "double FP" builds use double-precision floating point instead of the standard single precision. The "threading" builds contain the \_thread module and allow multithreading. The "network" builds have network drivers for WIZ820io included. All these different firmware are completely interchangeable and you can freely change from one to the other without losing the filesystem on your pyboard. diff --git a/ports/stm32/boards/PYBV10/mpconfigboard.mk b/ports/stm32/boards/PYBV10/mpconfigboard.mk index 071ae6eb7c..97af22b5e1 100644 --- a/ports/stm32/boards/PYBV10/mpconfigboard.mk +++ b/ports/stm32/boards/PYBV10/mpconfigboard.mk @@ -33,5 +33,4 @@ endif ifeq ($(BOARD_VARIANT),"network") MICROPY_PY_NETWORK_WIZNET5K=5200 -MICROPY_PY_CC3K=1 endif diff --git a/ports/stm32/boards/PYBV11/board.md b/ports/stm32/boards/PYBV11/board.md index 1511ffcf51..b490d54046 100644 --- a/ports/stm32/boards/PYBV11/board.md +++ b/ports/stm32/boards/PYBV11/board.md @@ -1 +1 @@ -The "standard" build is listed first and is the default firmware that the pyboards are shipped with. Use this firmware if you are uncertain. The "double FP" builds use double-precision floating point instead of the standard single precision. The "threading" builds contain the \_thread module and allow multithreading. The "network" builds have network drivers for CC3000 and WIZ820io included. All these different firmware are completely interchangeable and you can freely change from one to the other without losing the filesystem on your pyboard. +The "standard" build is listed first and is the default firmware that the pyboards are shipped with. Use this firmware if you are uncertain. The "double FP" builds use double-precision floating point instead of the standard single precision. The "threading" builds contain the \_thread module and allow multithreading. The "network" builds have network drivers for WIZ820io included. All these different firmware are completely interchangeable and you can freely change from one to the other without losing the filesystem on your pyboard. diff --git a/ports/stm32/boards/PYBV11/mpconfigboard.mk b/ports/stm32/boards/PYBV11/mpconfigboard.mk index 071ae6eb7c..97af22b5e1 100644 --- a/ports/stm32/boards/PYBV11/mpconfigboard.mk +++ b/ports/stm32/boards/PYBV11/mpconfigboard.mk @@ -33,5 +33,4 @@ endif ifeq ($(BOARD_VARIANT),"network") MICROPY_PY_NETWORK_WIZNET5K=5200 -MICROPY_PY_CC3K=1 endif diff --git a/ports/stm32/modnwcc3k.c b/ports/stm32/modnwcc3k.c deleted file mode 100644 index 952e535c2d..0000000000 --- a/ports/stm32/modnwcc3k.c +++ /dev/null @@ -1,608 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2014 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 -#include - -// CC3000 defines its own ENOBUFS (different to standard one!) -#undef ENOBUFS - -#include "py/objtuple.h" -#include "py/objlist.h" -#include "py/stream.h" -#include "py/runtime.h" -#include "py/mperrno.h" -#include "py/mphal.h" -#include "shared/netutils/netutils.h" -#include "extmod/modnetwork.h" -#include "pin.h" -#include "spi.h" - -#include "hci.h" -#include "socket.h" -#include "inet_ntop.h" -#include "inet_pton.h" -#include "ccspi.h" -#include "wlan.h" -#include "nvmem.h" -#include "netapp.h" -#include "patch_prog.h" - -#define MAX_ADDRSTRLEN (128) -#define MAX_RX_PACKET (CC3000_RX_BUFFER_SIZE - CC3000_MINIMAL_RX_SIZE - 1) -#define MAX_TX_PACKET (CC3000_TX_BUFFER_SIZE - CC3000_MINIMAL_TX_SIZE - 1) - -#define MAKE_SOCKADDR(addr, ip, port) \ - sockaddr addr; \ - addr.sa_family = AF_INET; \ - addr.sa_data[0] = port >> 8; \ - addr.sa_data[1] = port; \ - addr.sa_data[2] = ip[0]; \ - addr.sa_data[3] = ip[1]; \ - addr.sa_data[4] = ip[2]; \ - addr.sa_data[5] = ip[3]; - -#define UNPACK_SOCKADDR(addr, ip, port) \ - port = (addr.sa_data[0] << 8) | addr.sa_data[1]; \ - ip[0] = addr.sa_data[2]; \ - ip[1] = addr.sa_data[3]; \ - ip[2] = addr.sa_data[4]; \ - ip[3] = addr.sa_data[5]; - -STATIC int cc3k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno); - -int CC3000_EXPORT(errno); // for cc3000 driver - -STATIC volatile uint32_t fd_closed_state = 0; -STATIC volatile bool wlan_connected = false; -STATIC volatile bool ip_obtained = false; - -STATIC int cc3k_get_fd_closed_state(int fd) { - return fd_closed_state & (1 << fd); -} - -STATIC void cc3k_set_fd_closed_state(int fd) { - fd_closed_state |= 1 << fd; -} - -STATIC void cc3k_reset_fd_closed_state(int fd) { - fd_closed_state &= ~(1 << fd); -} - -STATIC void cc3k_callback(long event_type, char *data, unsigned char length) { - switch (event_type) { - case HCI_EVNT_WLAN_UNSOL_CONNECT: - wlan_connected = true; - break; - case HCI_EVNT_WLAN_UNSOL_DISCONNECT: - // link down - wlan_connected = false; - ip_obtained = false; - break; - case HCI_EVNT_WLAN_UNSOL_DHCP: - ip_obtained = true; - break; - case HCI_EVNT_BSD_TCP_CLOSE_WAIT: - // mark socket for closure - cc3k_set_fd_closed_state(data[0]); - break; - } -} - -STATIC int cc3k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) { - uint32_t ip; - // CC3000 gethostbyname is unreliable and usually returns -95 on first call - for (int retry = 5; CC3000_EXPORT(gethostbyname)((char *)name, len, &ip) < 0; retry--) { - if (retry == 0 || CC3000_EXPORT(errno) != -95) { - return CC3000_EXPORT(errno); - } - mp_hal_delay_ms(50); - } - - if (ip == 0) { - // unknown host - return -2; - } - - out_ip[0] = ip >> 24; - out_ip[1] = ip >> 16; - out_ip[2] = ip >> 8; - out_ip[3] = ip; - - return 0; -} - -STATIC int cc3k_socket_socket(mod_network_socket_obj_t *socket, int *_errno) { - if (socket->domain != MOD_NETWORK_AF_INET) { - *_errno = MP_EAFNOSUPPORT; - return -1; - } - - mp_uint_t type; - switch (socket->type) { - case MOD_NETWORK_SOCK_STREAM: - type = SOCK_STREAM; - break; - case MOD_NETWORK_SOCK_DGRAM: - type = SOCK_DGRAM; - break; - case MOD_NETWORK_SOCK_RAW: - type = SOCK_RAW; - break; - default: - *_errno = MP_EINVAL; - return -1; - } - - // open socket - int fd = CC3000_EXPORT(socket)(AF_INET, type, 0); - if (fd < 0) { - *_errno = CC3000_EXPORT(errno); - return -1; - } - - // clear socket state - cc3k_reset_fd_closed_state(fd); - - // store state of this socket - socket->fileno = fd; - - // make accept blocking by default - int optval = SOCK_OFF; - socklen_t optlen = sizeof(optval); - CC3000_EXPORT(setsockopt)(socket->fileno, SOL_SOCKET, SOCKOPT_ACCEPT_NONBLOCK, &optval, optlen); - - return 0; -} - -STATIC void cc3k_socket_close(mod_network_socket_obj_t *socket) { - CC3000_EXPORT(closesocket)(socket->fileno); -} - -STATIC int cc3k_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) { - MAKE_SOCKADDR(addr, ip, port) - int ret = CC3000_EXPORT(bind)(socket->fileno, &addr, sizeof(addr)); - if (ret != 0) { - *_errno = ret; - return -1; - } - return 0; -} - -STATIC int cc3k_socket_listen(mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno) { - int ret = CC3000_EXPORT(listen)(socket->fileno, backlog); - if (ret != 0) { - *_errno = ret; - return -1; - } - return 0; -} - -STATIC int cc3k_socket_accept(mod_network_socket_obj_t *socket, mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno) { - // accept incoming connection - int fd; - sockaddr addr; - socklen_t addr_len = sizeof(addr); - if ((fd = CC3000_EXPORT(accept)(socket->fileno, &addr, &addr_len)) < 0) { - if (fd == SOC_IN_PROGRESS) { - *_errno = MP_EAGAIN; - } else { - *_errno = -fd; - } - return -1; - } - - // clear socket state - cc3k_reset_fd_closed_state(fd); - - // store state in new socket object - socket2->fileno = fd; - - // return ip and port - // it seems CC3000 returns little endian for accept?? - // UNPACK_SOCKADDR(addr, ip, *port); - *port = (addr.sa_data[1] << 8) | addr.sa_data[0]; - ip[3] = addr.sa_data[2]; - ip[2] = addr.sa_data[3]; - ip[1] = addr.sa_data[4]; - ip[0] = addr.sa_data[5]; - - return 0; -} - -STATIC int cc3k_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) { - MAKE_SOCKADDR(addr, ip, port) - int ret = CC3000_EXPORT(connect)(socket->fileno, &addr, sizeof(addr)); - if (ret != 0) { - *_errno = CC3000_EXPORT(errno); - return -1; - } - return 0; -} - -STATIC mp_uint_t cc3k_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) { - if (cc3k_get_fd_closed_state(socket->fileno)) { - CC3000_EXPORT(closesocket)(socket->fileno); - *_errno = MP_EPIPE; - return -1; - } - - // CC3K does not handle fragmentation, and will overflow, - // split the packet into smaller ones and send them out. - mp_int_t bytes = 0; - while (bytes < len) { - int n = MIN((len - bytes), MAX_TX_PACKET); - n = CC3000_EXPORT(send)(socket->fileno, (uint8_t *)buf + bytes, n, 0); - if (n <= 0) { - *_errno = CC3000_EXPORT(errno); - return -1; - } - bytes += n; - } - - return bytes; -} - -STATIC mp_uint_t cc3k_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) { - // check the socket is open - if (cc3k_get_fd_closed_state(socket->fileno)) { - // socket is closed, but CC3000 may have some data remaining in buffer, so check - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(socket->fileno, &rfds); - cc3000_timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 1; - int nfds = CC3000_EXPORT(select)(socket->fileno + 1, &rfds, NULL, NULL, &tv); - if (nfds == -1 || !FD_ISSET(socket->fileno, &rfds)) { - // no data waiting, so close socket and return 0 data - CC3000_EXPORT(closesocket)(socket->fileno); - return 0; - } - } - - // cap length at MAX_RX_PACKET - len = MIN(len, MAX_RX_PACKET); - - // do the recv - int ret = CC3000_EXPORT(recv)(socket->fileno, buf, len, 0); - if (ret < 0) { - *_errno = CC3000_EXPORT(errno); - return -1; - } - - return ret; -} - -STATIC mp_uint_t cc3k_socket_sendto(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) { - MAKE_SOCKADDR(addr, ip, port) - int ret = CC3000_EXPORT(sendto)(socket->fileno, (byte *)buf, len, 0, (sockaddr *)&addr, sizeof(addr)); - if (ret < 0) { - *_errno = CC3000_EXPORT(errno); - return -1; - } - return ret; -} - -STATIC mp_uint_t cc3k_socket_recvfrom(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { - sockaddr addr; - socklen_t addr_len = sizeof(addr); - mp_int_t ret = CC3000_EXPORT(recvfrom)(socket->fileno, buf, len, 0, &addr, &addr_len); - if (ret < 0) { - *_errno = CC3000_EXPORT(errno); - return -1; - } - UNPACK_SOCKADDR(addr, ip, *port); - return ret; -} - -STATIC int cc3k_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) { - int ret = CC3000_EXPORT(setsockopt)(socket->fileno, level, opt, optval, optlen); - if (ret < 0) { - *_errno = CC3000_EXPORT(errno); - return -1; - } - return 0; -} - -STATIC int cc3k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno) { - int ret; - if (timeout_ms == 0 || timeout_ms == -1) { - int optval; - socklen_t optlen = sizeof(optval); - if (timeout_ms == 0) { - // set non-blocking mode - optval = SOCK_ON; - } else { - // set blocking mode - optval = SOCK_OFF; - } - ret = CC3000_EXPORT(setsockopt)(socket->fileno, SOL_SOCKET, SOCKOPT_RECV_NONBLOCK, &optval, optlen); - if (ret == 0) { - ret = CC3000_EXPORT(setsockopt)(socket->fileno, SOL_SOCKET, SOCKOPT_ACCEPT_NONBLOCK, &optval, optlen); - } - } else { - // set timeout - socklen_t optlen = sizeof(timeout_ms); - ret = CC3000_EXPORT(setsockopt)(socket->fileno, SOL_SOCKET, SOCKOPT_RECV_TIMEOUT, &timeout_ms, optlen); - } - - if (ret != 0) { - *_errno = CC3000_EXPORT(errno); - return -1; - } - - return 0; -} - -STATIC int cc3k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno) { - mp_uint_t ret; - if (request == MP_STREAM_POLL) { - mp_uint_t flags = arg; - ret = 0; - int fd = socket->fileno; - - // init fds - fd_set rfds, wfds, xfds; - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_ZERO(&xfds); - - // set fds if needed - if (flags & MP_STREAM_POLL_RD) { - FD_SET(fd, &rfds); - - // A socked that just closed is available for reading. A call to - // recv() returns 0 which is consistent with BSD. - if (cc3k_get_fd_closed_state(fd)) { - ret |= MP_STREAM_POLL_RD; - } - } - if (flags & MP_STREAM_POLL_WR) { - FD_SET(fd, &wfds); - } - if (flags & MP_STREAM_POLL_HUP) { - FD_SET(fd, &xfds); - } - - // call cc3000 select with minimum timeout - cc3000_timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 1; - int nfds = CC3000_EXPORT(select)(fd + 1, &rfds, &wfds, &xfds, &tv); - - // check for error - if (nfds == -1) { - *_errno = CC3000_EXPORT(errno); - return -1; - } - - // check return of select - if (FD_ISSET(fd, &rfds)) { - ret |= MP_STREAM_POLL_RD; - } - if (FD_ISSET(fd, &wfds)) { - ret |= MP_STREAM_POLL_WR; - } - if (FD_ISSET(fd, &xfds)) { - ret |= MP_STREAM_POLL_HUP; - } - } else { - *_errno = MP_EINVAL; - ret = -1; - } - return ret; -} - -/******************************************************************************/ -// MicroPython bindings; CC3K class - -typedef struct _cc3k_obj_t { - mp_obj_base_t base; -} cc3k_obj_t; - -STATIC const cc3k_obj_t cc3k_obj = {{(mp_obj_type_t *)&mod_network_nic_type_cc3k}}; - -// \classmethod \constructor(spi, pin_cs, pin_en, pin_irq) -// Initialise the CC3000 using the given SPI bus and pins and return a CC3K object. -// -// Note: pins were originally hard-coded to: -// PYBv1.0: init(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3) -// [SPI on Y position; Y6=B13=SCK, Y7=B14=MISO, Y8=B15=MOSI] -// -// STM32F4DISC: init(pyb.SPI(2), pyb.Pin.cpu.A15, pyb.Pin.cpu.B10, pyb.Pin.cpu.B11) -STATIC mp_obj_t cc3k_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, 4, 4, false); - - // set the pins to use - SpiInit( - spi_from_mp_obj(args[0])->spi, - pin_find(args[1]), - pin_find(args[2]), - pin_find(args[3]) - ); - - // initialize and start the module - wlan_init(cc3k_callback, NULL, NULL, NULL, - ReadWlanInterruptPin, SpiResumeSpi, SpiPauseSpi, WriteWlanPin); - - if (wlan_start(0) != 0) { - mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("failed to init CC3000 module")); - } - - // set connection policy. this should be called explicitly by the user - // wlan_ioctl_set_connection_policy(0, 0, 0); - - // Mask out all non-required events from the CC3000 - wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE | - HCI_EVNT_WLAN_UNSOL_INIT | - HCI_EVNT_WLAN_ASYNC_PING_REPORT | - HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE); - - // register with network module - mod_network_register_nic((mp_obj_t)&cc3k_obj); - - return (mp_obj_t)&cc3k_obj; -} - -// method connect(ssid, key=None, *, security=WPA2, bssid=None) -STATIC mp_obj_t cc3k_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - static const mp_arg_t allowed_args[] = { - { MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_key, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = WLAN_SEC_WPA2} }, - { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - }; - - // parse args - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - // get ssid - size_t ssid_len; - const char *ssid = mp_obj_str_get_data(args[0].u_obj, &ssid_len); - - // get key and sec - size_t key_len = 0; - const char *key = NULL; - mp_uint_t sec = WLAN_SEC_UNSEC; - if (args[1].u_obj != mp_const_none) { - key = mp_obj_str_get_data(args[1].u_obj, &key_len); - sec = args[2].u_int; - } - - // get bssid - const char *bssid = NULL; - if (args[3].u_obj != mp_const_none) { - bssid = mp_obj_str_get_str(args[3].u_obj); - } - - // connect to AP - if (wlan_connect(sec, (char *)ssid, ssid_len, (uint8_t *)bssid, (uint8_t *)key, key_len) != 0) { - mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("could not connect to ssid=%s, sec=%d, key=%s\n"), ssid, sec, key); - } - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(cc3k_connect_obj, 1, cc3k_connect); - -STATIC mp_obj_t cc3k_disconnect(mp_obj_t self_in) { - // should we check return value? - wlan_disconnect(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(cc3k_disconnect_obj, cc3k_disconnect); - -STATIC mp_obj_t cc3k_isconnected(mp_obj_t self_in) { - return mp_obj_new_bool(wlan_connected && ip_obtained); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(cc3k_isconnected_obj, cc3k_isconnected); - -STATIC mp_obj_t cc3k_ifconfig(mp_obj_t self_in) { - tNetappIpconfigRetArgs ipconfig; - netapp_ipconfig(&ipconfig); - - // render MAC address - VSTR_FIXED(mac_vstr, 18); - const uint8_t *mac = ipconfig.uaMacAddr; - vstr_printf(&mac_vstr, "%02x:%02x:%02x:%02x:%02x:%02x", mac[5], mac[4], mac[3], mac[2], mac[1], mac[0]); - - // create and return tuple with ifconfig info - mp_obj_t tuple[7] = { - netutils_format_ipv4_addr(ipconfig.aucIP, NETUTILS_LITTLE), - netutils_format_ipv4_addr(ipconfig.aucSubnetMask, NETUTILS_LITTLE), - netutils_format_ipv4_addr(ipconfig.aucDefaultGateway, NETUTILS_LITTLE), - netutils_format_ipv4_addr(ipconfig.aucDNSServer, NETUTILS_LITTLE), - netutils_format_ipv4_addr(ipconfig.aucDHCPServer, NETUTILS_LITTLE), - mp_obj_new_str(mac_vstr.buf, mac_vstr.len), - mp_obj_new_str((const char *)ipconfig.uaSSID, strlen((const char *)ipconfig.uaSSID)), - }; - return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(cc3k_ifconfig_obj, cc3k_ifconfig); - -STATIC mp_obj_t cc3k_patch_version(mp_obj_t self_in) { - uint8_t pver[2]; - mp_obj_tuple_t *t_pver; - - nvmem_read_sp_version(pver); - t_pver = mp_obj_new_tuple(2, NULL); - t_pver->items[0] = mp_obj_new_int(pver[0]); - t_pver->items[1] = mp_obj_new_int(pver[1]); - return t_pver; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(cc3k_patch_version_obj, cc3k_patch_version); - -STATIC mp_obj_t cc3k_patch_program(mp_obj_t self_in, mp_obj_t key_in) { - const char *key = mp_obj_str_get_str(key_in); - if (key[0] == 'p' && key[1] == 'g' && key[2] == 'm' && key[3] == '\0') { - patch_prog_start(); - } else { - mp_print_str(&mp_plat_print, "pass 'pgm' as argument in order to program\n"); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(cc3k_patch_program_obj, cc3k_patch_program); - -STATIC const mp_rom_map_elem_t cc3k_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&cc3k_connect_obj) }, - { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&cc3k_disconnect_obj) }, - { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&cc3k_isconnected_obj) }, - { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&cc3k_ifconfig_obj) }, - { MP_ROM_QSTR(MP_QSTR_patch_version), MP_ROM_PTR(&cc3k_patch_version_obj) }, - { MP_ROM_QSTR(MP_QSTR_patch_program), MP_ROM_PTR(&cc3k_patch_program_obj) }, - - // class constants - { MP_ROM_QSTR(MP_QSTR_WEP), MP_ROM_INT(WLAN_SEC_WEP) }, - { MP_ROM_QSTR(MP_QSTR_WPA), MP_ROM_INT(WLAN_SEC_WPA) }, - { MP_ROM_QSTR(MP_QSTR_WPA2), MP_ROM_INT(WLAN_SEC_WPA2) }, -}; - -STATIC MP_DEFINE_CONST_DICT(cc3k_locals_dict, cc3k_locals_dict_table); - -const mod_network_nic_type_t mod_network_nic_type_cc3k = { - .base = { - { &mp_type_type }, - .name = MP_QSTR_CC3K, - .make_new = cc3k_make_new, - .locals_dict = (mp_obj_dict_t *)&cc3k_locals_dict, - }, - .gethostbyname = cc3k_gethostbyname, - .socket = cc3k_socket_socket, - .close = cc3k_socket_close, - .bind = cc3k_socket_bind, - .listen = cc3k_socket_listen, - .accept = cc3k_socket_accept, - .connect = cc3k_socket_connect, - .send = cc3k_socket_send, - .recv = cc3k_socket_recv, - .sendto = cc3k_socket_sendto, - .recvfrom = cc3k_socket_recvfrom, - .setsockopt = cc3k_socket_setsockopt, - .settimeout = cc3k_socket_settimeout, - .ioctl = cc3k_socket_ioctl, -}; diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index e06e32c0d2..69b29e8ec3 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -200,13 +200,6 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k; #define MICROPY_HW_NIC_WIZNET5K #endif -#if MICROPY_PY_CC3K -extern const struct _mod_network_nic_type_t mod_network_nic_type_cc3k; -#define MICROPY_HW_NIC_CC3K { MP_ROM_QSTR(MP_QSTR_CC3K), MP_ROM_PTR(&mod_network_nic_type_cc3k) }, -#else -#define MICROPY_HW_NIC_CC3K -#endif - // extra constants #define MICROPY_PORT_CONSTANTS \ MACHINE_BUILTIN_MODULE_CONSTANTS \ @@ -221,7 +214,6 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_cc3k; MICROPY_HW_NIC_ETH \ MICROPY_HW_NIC_CYW43 \ MICROPY_HW_NIC_WIZNET5K \ - MICROPY_HW_NIC_CC3K \ MICROPY_BOARD_NETWORK_INTERFACES \ #define MP_STATE_PORT MP_STATE_VM diff --git a/ports/stm32/mpconfigport.mk b/ports/stm32/mpconfigport.mk index 830ccf0312..737ff9d3d2 100644 --- a/ports/stm32/mpconfigport.mk +++ b/ports/stm32/mpconfigport.mk @@ -6,9 +6,6 @@ # 5500 : support for W5500 module MICROPY_PY_NETWORK_WIZNET5K ?= 0 -# cc3k module for wifi support -MICROPY_PY_CC3K ?= 0 - # VFS FAT FS support MICROPY_VFS_FAT ?= 1 diff --git a/tools/ci.sh b/tools/ci.sh index b7b20e3c7d..b4cb7dc2e3 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -313,8 +313,6 @@ function ci_stm32_pyb_build { git submodule update --init lib/btstack git submodule update --init lib/mynewt-nimble make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_NETWORK_WIZNET5K=5200 USER_C_MODULES=../../examples/usercmodule - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 clean - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_CC3K=1 make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF2 make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF6 NANBOX=1 MICROPY_BLUETOOTH_NIMBLE=0 MICROPY_BLUETOOTH_BTSTACK=1 make ${MAKEOPTS} -C ports/stm32/mboot BOARD=PYBV10 CFLAGS_EXTRA='-DMBOOT_FSLOAD=1 -DMBOOT_VFS_LFS2=1' From 7d3f4b23dc26bd26477a2ef6d7b25b3af73453f4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 24 Aug 2022 10:48:27 +1000 Subject: [PATCH 0322/1041] drivers/cc3000: Remove CC3000 WiFi driver files. It's no longer used by any port. Signed-off-by: Damien George --- LICENSE | 1 - docs/library/network.CC3K.rst | 89 -- docs/library/network.rst | 1 - drivers/cc3000/inc/cc3000_common.h | 365 ------- drivers/cc3000/inc/ccspi.h | 84 -- drivers/cc3000/inc/data_types.h | 107 -- drivers/cc3000/inc/evnt_handler.h | 166 --- drivers/cc3000/inc/hci.h | 330 ------ drivers/cc3000/inc/host_driver_version.h | 40 - drivers/cc3000/inc/inet_ntop.h | 4 - drivers/cc3000/inc/inet_pton.h | 4 - drivers/cc3000/inc/netapp.h | 343 ------ drivers/cc3000/inc/nvmem.h | 248 ----- drivers/cc3000/inc/patch_prog.h | 11 - drivers/cc3000/inc/security.h | 130 --- drivers/cc3000/inc/socket.h | 676 ------------ drivers/cc3000/inc/wlan.h | 518 --------- drivers/cc3000/src/cc3000_common.c | 164 --- drivers/cc3000/src/ccspi.c | 455 -------- drivers/cc3000/src/evnt_handler.c | 849 --------------- drivers/cc3000/src/hci.c | 225 ---- drivers/cc3000/src/inet_ntop.c | 200 ---- drivers/cc3000/src/inet_pton.c | 216 ---- drivers/cc3000/src/netapp.c | 459 -------- drivers/cc3000/src/nvmem.c | 334 ------ drivers/cc3000/src/patch.c | 117 -- drivers/cc3000/src/patch_prog.c | 414 ------- drivers/cc3000/src/security.c | 530 --------- drivers/cc3000/src/socket.c | 1182 -------------------- drivers/cc3000/src/wlan.c | 1252 ---------------------- 30 files changed, 9514 deletions(-) delete mode 100644 docs/library/network.CC3K.rst delete mode 100644 drivers/cc3000/inc/cc3000_common.h delete mode 100644 drivers/cc3000/inc/ccspi.h delete mode 100644 drivers/cc3000/inc/data_types.h delete mode 100644 drivers/cc3000/inc/evnt_handler.h delete mode 100644 drivers/cc3000/inc/hci.h delete mode 100644 drivers/cc3000/inc/host_driver_version.h delete mode 100644 drivers/cc3000/inc/inet_ntop.h delete mode 100644 drivers/cc3000/inc/inet_pton.h delete mode 100644 drivers/cc3000/inc/netapp.h delete mode 100644 drivers/cc3000/inc/nvmem.h delete mode 100644 drivers/cc3000/inc/patch_prog.h delete mode 100644 drivers/cc3000/inc/security.h delete mode 100644 drivers/cc3000/inc/socket.h delete mode 100644 drivers/cc3000/inc/wlan.h delete mode 100644 drivers/cc3000/src/cc3000_common.c delete mode 100644 drivers/cc3000/src/ccspi.c delete mode 100644 drivers/cc3000/src/evnt_handler.c delete mode 100644 drivers/cc3000/src/hci.c delete mode 100644 drivers/cc3000/src/inet_ntop.c delete mode 100644 drivers/cc3000/src/inet_pton.c delete mode 100644 drivers/cc3000/src/netapp.c delete mode 100644 drivers/cc3000/src/nvmem.c delete mode 100644 drivers/cc3000/src/patch.c delete mode 100644 drivers/cc3000/src/patch_prog.c delete mode 100644 drivers/cc3000/src/security.c delete mode 100644 drivers/cc3000/src/socket.c delete mode 100644 drivers/cc3000/src/wlan.c diff --git a/LICENSE b/LICENSE index 2b9a64b89a..5a91df195f 100644 --- a/LICENSE +++ b/LICENSE @@ -35,7 +35,6 @@ used during the build process and is not part of the compiled source code. / (MIT) /drivers - /cc3000 (BSD-3-clause) /cc3100 (BSD-3-clause) /wiznet5k (BSD-3-clause) /lib diff --git a/docs/library/network.CC3K.rst b/docs/library/network.CC3K.rst deleted file mode 100644 index 41d3fb437e..0000000000 --- a/docs/library/network.CC3K.rst +++ /dev/null @@ -1,89 +0,0 @@ -.. currentmodule:: network -.. _network.CC3K: - -class CC3K -- control CC3000 WiFi modules -========================================= - -This class provides a driver for CC3000 WiFi modules. Example usage:: - - import network - nic = network.CC3K(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3) - nic.connect('your-ssid', 'your-password') - while not nic.isconnected(): - pyb.delay(50) - print(nic.ifconfig()) - - # now use socket as usual - ... - -For this example to work the CC3000 module must have the following connections: - - - MOSI connected to Y8 - - MISO connected to Y7 - - CLK connected to Y6 - - CS connected to Y5 - - VBEN connected to Y4 - - IRQ connected to Y3 - -It is possible to use other SPI buses and other pins for CS, VBEN and IRQ. - -Constructors ------------- - -.. class:: CC3K(spi, pin_cs, pin_en, pin_irq) - - Create a CC3K driver object, initialise the CC3000 module using the given SPI bus - and pins, and return the CC3K object. - - Arguments are: - - - *spi* is an :ref:`SPI object ` which is the SPI bus that the CC3000 is - connected to (the MOSI, MISO and CLK pins). - - *pin_cs* is a :ref:`Pin object ` which is connected to the CC3000 CS pin. - - *pin_en* is a :ref:`Pin object ` which is connected to the CC3000 VBEN pin. - - *pin_irq* is a :ref:`Pin object ` which is connected to the CC3000 IRQ pin. - - All of these objects will be initialised by the driver, so there is no need to - initialise them yourself. For example, you can use:: - - nic = network.CC3K(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3) - -Methods -------- - -.. method:: CC3K.connect(ssid, key=None, *, security=WPA2, bssid=None) - - Connect to a WiFi access point using the given SSID, and other security - parameters. - -.. method:: CC3K.disconnect() - - Disconnect from the WiFi access point. - -.. method:: CC3K.isconnected() - - Returns True if connected to a WiFi access point and has a valid IP address, - False otherwise. - -.. method:: CC3K.ifconfig() - - Returns a 7-tuple with (ip, subnet mask, gateway, DNS server, DHCP server, - MAC address, SSID). - -.. method:: CC3K.patch_version() - - Return the version of the patch program (firmware) on the CC3000. - -.. method:: CC3K.patch_program('pgm') - - Upload the current firmware to the CC3000. You must pass 'pgm' as the first - argument in order for the upload to proceed. - -Constants ---------- - -.. data:: CC3K.WEP -.. data:: CC3K.WPA -.. data:: CC3K.WPA2 - - security type to use diff --git a/docs/library/network.rst b/docs/library/network.rst index 6742a2e073..0a6f5506ea 100644 --- a/docs/library/network.rst +++ b/docs/library/network.rst @@ -150,7 +150,6 @@ provide a way to control networking interfaces of various kinds. network.WLAN.rst network.WLANWiPy.rst - network.CC3K.rst network.WIZNET5K.rst network.LAN.rst diff --git a/drivers/cc3000/inc/cc3000_common.h b/drivers/cc3000/inc/cc3000_common.h deleted file mode 100644 index d0c4b1d4b9..0000000000 --- a/drivers/cc3000/inc/cc3000_common.h +++ /dev/null @@ -1,365 +0,0 @@ -/***************************************************************************** -* -* cc3000_common.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_COMMON_H__ -#define __CC3000_COMMON_H__ - -#include "data_types.h" - -//****************************************************************************** -// Include files -//****************************************************************************** -#include -#include - -//***************************************************************************** -// Prefix exported names to avoid name clash -//***************************************************************************** -#define CC3000_EXPORT(name) cc3000_ ## name - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -extern int CC3000_EXPORT(errno); - -//***************************************************************************** -// ERROR CODES -//***************************************************************************** -#define ESUCCESS 0 -#define EFAIL -1 -#define EERROR EFAIL - -//***************************************************************************** -// COMMON DEFINES -//***************************************************************************** -#define ERROR_SOCKET_INACTIVE -57 - -#define WLAN_ENABLE (1) -#define WLAN_DISABLE (0) - -#define MAC_ADDR_LEN (6) - -#define SP_PORTION_SIZE (32) - -/*Defines for minimal and maximal RX buffer size. This size includes the spi - header and hci header. - The maximal buffer size derives from: - MTU + HCI header + SPI header + sendto() agrs size - The minimum buffer size derives from: - HCI header + SPI header + max args size - - This buffer is used for receiving events and data. - The packet can not be longer than MTU size and CC3000 does not support - fragmentation. Note that the same buffer is used for reception of the data - and events from CC3000. That is why the minimum is defined. - The calculation for the actual size of buffer for reception is: - Given the maximal data size MAX_DATA that is expected to be received by - application, the required buffer is: - Using recv() or recvfrom(): - - max(CC3000_MINIMAL_RX_SIZE, MAX_DATA + HEADERS_SIZE_DATA + fromlen - + ucArgsize + 1) - - Using gethostbyname() with minimal buffer size will limit the host name - returned to 99 bytes only. - The 1 is used for the overrun detection - - Buffer size increased to 130 following the add_profile() with WEP security - which requires TX buffer size of 130 bytes: - HEADERS_SIZE_EVNT + WLAN_ADD_PROFILE_WEP_PARAM_LEN + MAX SSID LEN + 4 * MAX KEY LEN = 130 - MAX SSID LEN = 32 - MAX SSID LEN = 13 (with add_profile only ascii key setting is supported, - therfore maximum key size is 13) -*/ - -#define CC3000_MINIMAL_RX_SIZE (130 + 1) -#define CC3000_MAXIMAL_RX_SIZE (1519 + 1) - -/*Defines for minimal and maximal TX buffer size. - This buffer is used for sending events and data. - The packet can not be longer than MTU size and CC3000 does not support - fragmentation. Note that the same buffer is used for transmission of the data - and commands. That is why the minimum is defined. - The calculation for the actual size of buffer for transmission is: - Given the maximal data size MAX_DATA, the required buffer is: - Using Sendto(): - - max(CC3000_MINIMAL_TX_SIZE, MAX_DATA + SPI_HEADER_SIZE - + SOCKET_SENDTO_PARAMS_LEN + SIMPLE_LINK_HCI_DATA_HEADER_SIZE + 1) - - Using Send(): - - max(CC3000_MINIMAL_TX_SIZE, MAX_DATA + SPI_HEADER_SIZE - + HCI_CMND_SEND_ARG_LENGTH + SIMPLE_LINK_HCI_DATA_HEADER_SIZE + 1) - - The 1 is used for the overrun detection */ - -#define CC3000_MINIMAL_TX_SIZE (130 + 1) -#define CC3000_MAXIMAL_TX_SIZE (1519 + 1) - -//TX and RX buffer sizes, allow to receive and transmit maximum data at length 8. -#ifdef CC3000_TINY_DRIVER -#define TINY_CC3000_MAXIMAL_RX_SIZE 44 -#define TINY_CC3000_MAXIMAL_TX_SIZE 59 -#endif - -/*In order to determine your preferred buffer size, - change CC3000_MAXIMAL_RX_SIZE and CC3000_MAXIMAL_TX_SIZE to a value between - the minimal and maximal specified above. - Note that the buffers are allocated by SPI. - In case you change the size of those buffers, you might need also to change - the linker file, since for example on MSP430 FRAM devices the buffers are - allocated in the FRAM section that is allocated manually and not by IDE. -*/ - -#ifndef CC3000_TINY_DRIVER - - #define CC3000_RX_BUFFER_SIZE (CC3000_MAXIMAL_RX_SIZE) - #define CC3000_TX_BUFFER_SIZE (CC3000_MAXIMAL_TX_SIZE) - -//if defined TINY DRIVER we use smaller RX and TX buffer in order to minimize RAM consumption -#else - #define CC3000_RX_BUFFER_SIZE (TINY_CC3000_MAXIMAL_RX_SIZE) - #define CC3000_TX_BUFFER_SIZE (TINY_CC3000_MAXIMAL_TX_SIZE) - -#endif - -//***************************************************************************** -// Compound Types -//***************************************************************************** -typedef INT32 cc3000_time_t; -typedef UINT32 clock_t; -typedef INT32 suseconds_t; - -typedef struct cc3000_timeval cc3000_timeval; - -struct cc3000_timeval -{ - cc3000_time_t tv_sec; /* seconds */ - suseconds_t tv_usec; /* microseconds */ -}; - -typedef CHAR *(*tFWPatches)(UINT32 *usLength); - -typedef CHAR *(*tDriverPatches)(UINT32 *usLength); - -typedef CHAR *(*tBootLoaderPatches)(UINT32 *usLength); - -typedef void (*tWlanCB)(INT32 event_type, CHAR * data, UINT8 length ); - -typedef INT32 (*tWlanReadInteruptPin)(void); - -typedef void (*tWlanInterruptEnable)(void); - -typedef void (*tWlanInterruptDisable)(void); - -typedef void (*tWriteWlanPin)(UINT8 val); - -typedef struct -{ - UINT16 usRxEventOpcode; - UINT16 usEventOrDataReceived; - UINT8 *pucReceivedData; - UINT8 *pucTxCommandBuffer; - - tFWPatches sFWPatches; - tDriverPatches sDriverPatches; - tBootLoaderPatches sBootLoaderPatches; - tWlanCB sWlanCB; - tWlanReadInteruptPin ReadWlanInterruptPin; - tWlanInterruptEnable WlanInterruptEnable; - tWlanInterruptDisable WlanInterruptDisable; - tWriteWlanPin WriteWlanPin; - - INT32 slTransmitDataError; - UINT16 usNumberOfFreeBuffers; - UINT16 usSlBufferLength; - UINT16 usBufferSize; - UINT16 usRxDataPending; - - UINT32 NumberOfSentPackets; - UINT32 NumberOfReleasedPackets; - - UINT8 InformHostOnTxComplete; -}sSimplLinkInformation; - -extern volatile sSimplLinkInformation tSLInformation; - - -//***************************************************************************** -// Prototypes for the APIs. -//***************************************************************************** - - - -//***************************************************************************** -// -//! SimpleLinkWaitEvent -//! -//! @param usOpcode command operation code -//! @param pRetParams command return parameters -//! -//! @return none -//! -//! @brief Wait for event, pass it to the hci_event_handler and -//! update the event opcode in a global variable. -// -//***************************************************************************** - -extern void SimpleLinkWaitEvent(UINT16 usOpcode, void *pRetParams); - -//***************************************************************************** -// -//! SimpleLinkWaitData -//! -//! @param pBuf data buffer -//! @param from from information -//! @param fromlen from information length -//! -//! @return none -//! -//! @brief Wait for data, pass it to the hci_event_handler -//! and update in a global variable that there is -//! data to read. -// -//***************************************************************************** - -extern void SimpleLinkWaitData(UINT8 *pBuf, UINT8 *from, UINT8 *fromlen); - -//***************************************************************************** -// -//! UINT32_TO_STREAM_f -//! -//! \param p pointer to the new stream -//! \param u32 pointer to the 32 bit -//! -//! \return pointer to the new stream -//! -//! \brief This function is used for copying 32 bit to stream -//! while converting to little endian format. -// -//***************************************************************************** - -extern UINT8* UINT32_TO_STREAM_f (UINT8 *p, UINT32 u32); - -//***************************************************************************** -// -//! UINT16_TO_STREAM_f -//! -//! \param p pointer to the new stream -//! \param u32 pointer to the 16 bit -//! -//! \return pointer to the new stream -//! -//! \brief This function is used for copying 16 bit to stream -//! while converting to little endian format. -// -//***************************************************************************** - -extern UINT8* UINT16_TO_STREAM_f (UINT8 *p, UINT16 u16); - -//***************************************************************************** -// -//! STREAM_TO_UINT16_f -//! -//! \param p pointer to the stream -//! \param offset offset in the stream -//! -//! \return pointer to the new 16 bit -//! -//! \brief This function is used for copying received stream to -//! 16 bit in little endian format. -// -//***************************************************************************** - -extern UINT16 STREAM_TO_UINT16_f(CHAR* p, UINT16 offset); - -//***************************************************************************** -// -//! STREAM_TO_UINT32_f -//! -//! \param p pointer to the stream -//! \param offset offset in the stream -//! -//! \return pointer to the new 32 bit -//! -//! \brief This function is used for copying received stream to -//! 32 bit in little endian format. -// -//***************************************************************************** - -extern UINT32 STREAM_TO_UINT32_f(CHAR* p, UINT16 offset); - - -//***************************************************************************** -// COMMON MACROs -//***************************************************************************** - - -//This macro is used for copying 8 bit to stream while converting to little endian format. -#define UINT8_TO_STREAM(_p, _val) {*(_p)++ = (_val);} -//This macro is used for copying 16 bit to stream while converting to little endian format. -#define UINT16_TO_STREAM(_p, _u16) (UINT16_TO_STREAM_f(_p, _u16)) -//This macro is used for copying 32 bit to stream while converting to little endian format. -#define UINT32_TO_STREAM(_p, _u32) (UINT32_TO_STREAM_f(_p, _u32)) -//This macro is used for copying a specified value length bits (l) to stream while converting to little endian format. -#define ARRAY_TO_STREAM(p, a, l) {register INT16 _i; for (_i = 0; _i < l; _i++) *(p)++ = ((UINT8 *) a)[_i];} -//This macro is used for copying received stream to 8 bit in little endian format. -#define STREAM_TO_UINT8(_p, _offset, _u8) {_u8 = (UINT8)(*(_p + _offset));} -//This macro is used for copying received stream to 16 bit in little endian format. -#define STREAM_TO_UINT16(_p, _offset, _u16) {_u16 = STREAM_TO_UINT16_f(_p, _offset);} -//This macro is used for copying received stream to 32 bit in little endian format. -#define STREAM_TO_UINT32(_p, _offset, _u32) {_u32 = STREAM_TO_UINT32_f(_p, _offset);} -#define STREAM_TO_STREAM(p, a, l) {register INT16 _i; for (_i = 0; _i < l; _i++) *(a)++= ((UINT8 *) p)[_i];} - - - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_COMMON_H__ diff --git a/drivers/cc3000/inc/ccspi.h b/drivers/cc3000/inc/ccspi.h deleted file mode 100644 index 8fa3ecd10c..0000000000 --- a/drivers/cc3000/inc/ccspi.h +++ /dev/null @@ -1,84 +0,0 @@ -/***************************************************************************** -* -* spi.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - - -#ifndef __CC3000_SPI_H__ -#define __CC3000_SPI_H__ - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -typedef void (*gcSpiHandleRx)(void *p); -typedef void (*gcSpiHandleTx)(void); -extern unsigned char wlan_tx_buffer[]; - -//***************************************************************************** -// -// Prototypes for the APIs. -// -//***************************************************************************** - -// the arguments must be of type pin_obj_t* and SPI_HandleTypeDef* -extern void SpiInit(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq); - -extern void SpiOpen(gcSpiHandleRx pfRxHandler); -extern void SpiClose(void); -extern void SpiPauseSpi(void); -extern void SpiResumeSpi(void); -extern long SpiWrite(unsigned char *pUserBuffer, unsigned short usLength); -extern void SpiConfigureHwMapping(void); -extern void SpiCleanGPIOISR(void); -extern void SSIConfigure(unsigned long ulSSIFreq, unsigned long bForceGpioConfiguration, unsigned long uiReconfigureSysClock); -extern int init_spi(void); -extern long ReadWlanInterruptPin(void); -extern void WriteWlanPin(unsigned char val); -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif - diff --git a/drivers/cc3000/inc/data_types.h b/drivers/cc3000/inc/data_types.h deleted file mode 100644 index 0520a9202f..0000000000 --- a/drivers/cc3000/inc/data_types.h +++ /dev/null @@ -1,107 +0,0 @@ -/***************************************************************************** -* -* data_types.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_DATA_TYPES__ -#define __CC3000_DATA_TYPES__ - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - - -#ifndef NULL -#define NULL (0) -#endif - -#ifndef FALSE -#define FALSE (0) -#endif - -#ifndef TRUE -#define TRUE (!FALSE) -#endif - -#ifndef OK -#define OK (0) -#endif - -#ifndef _INT8 -#define _INT8 -typedef signed char INT8; -#endif - -#ifndef _UINT8 -#define _UINT8 -typedef unsigned char UINT8; -#endif - -#ifndef _INT16 -#define _INT16 -typedef signed short INT16; -#endif - -#ifndef _UINT16 -#define _UINT16 -typedef unsigned short UINT16; -#endif - -#ifndef _BOOLEAN -#define _BOOLEAN -typedef unsigned char BOOLEAN; -#endif - -#ifndef _INT32 -#define _INT32 -typedef signed long INT32; -#endif - -#ifndef _UINT32 -#define _UINT32 -typedef unsigned long UINT32; -#endif - -typedef int INT; -typedef char CHAR; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CC3000_DATA_TYPES__ */ diff --git a/drivers/cc3000/inc/evnt_handler.h b/drivers/cc3000/inc/evnt_handler.h deleted file mode 100644 index d05a442f05..0000000000 --- a/drivers/cc3000/inc/evnt_handler.h +++ /dev/null @@ -1,166 +0,0 @@ -/***************************************************************************** -* -* evnt_handler.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_EVENT_HANDLER_H__ -#define __CC3000_EVENT_HANDLER_H__ -#include "hci.h" -#include "socket.h" - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -//***************************************************************************** -// -// Prototypes for the APIs. -// -//***************************************************************************** - -//***************************************************************************** -// -//! hci_event_handler -//! -//! @param pRetParams incoming data buffer -//! @param from from information (in case of data received) -//! @param fromlen from information length (in case of data received) -//! -//! @return none -//! -//! @brief Parse the incoming events packets and issues corresponding -//! event handler from global array of handlers pointers -// -//***************************************************************************** -extern UINT8 *hci_event_handler(void *pRetParams, UINT8 *from, UINT8 *fromlen); - -//***************************************************************************** -// -//! hci_unsol_event_handler -//! -//! @param event_hdr event header -//! -//! @return 1 if event supported and handled -//! 0 if event is not supported -//! -//! @brief Handle unsolicited events -// -//***************************************************************************** -extern INT32 hci_unsol_event_handler(CHAR *event_hdr); - -//***************************************************************************** -// -//! hci_unsolicited_event_handler -//! -//! @param None -//! -//! @return ESUCCESS if successful, EFAIL if an error occurred -//! -//! @brief Parse the incoming unsolicited event packets and issues -//! corresponding event handler. -// -//***************************************************************************** -extern INT32 hci_unsolicited_event_handler(void); - -#define M_BSD_RESP_PARAMS_OFFSET(hci_event_hdr)((CHAR *)(hci_event_hdr) + HCI_EVENT_HEADER_SIZE) - -#define SOCKET_STATUS_ACTIVE 0 -#define SOCKET_STATUS_INACTIVE 1 -/* Init socket_active_status = 'all ones': init all sockets with SOCKET_STATUS_INACTIVE. - Will be changed by 'set_socket_active_status' upon 'connect' and 'accept' calls */ -#define SOCKET_STATUS_INIT_VAL 0xFFFF -#define M_IS_VALID_SD(sd) ((0 <= (sd)) && ((sd) <= 7)) -#define M_IS_VALID_STATUS(status) (((status) == SOCKET_STATUS_ACTIVE)||((status) == SOCKET_STATUS_INACTIVE)) - -extern UINT32 socket_active_status; - -extern void set_socket_active_status(INT32 Sd, INT32 Status); -extern INT32 get_socket_active_status(INT32 Sd); - -typedef struct _bsd_accept_return_t -{ - INT32 iSocketDescriptor; - INT32 iStatus; - sockaddr tSocketAddress; - -} tBsdReturnParams; - - -typedef struct _bsd_read_return_t -{ - INT32 iSocketDescriptor; - INT32 iNumberOfBytes; - UINT32 uiFlags; -} tBsdReadReturnParams; - -#define BSD_RECV_FROM_FROMLEN_OFFSET (4) -#define BSD_RECV_FROM_FROM_OFFSET (16) - - -typedef struct _bsd_select_return_t -{ - INT32 iStatus; - UINT32 uiRdfd; - UINT32 uiWrfd; - UINT32 uiExfd; -} tBsdSelectRecvParams; - - -typedef struct _bsd_getsockopt_return_t -{ - UINT8 ucOptValue[4]; - CHAR iStatus; -} tBsdGetSockOptReturnParams; - -typedef struct _bsd_gethostbyname_return_t -{ - INT32 retVal; - INT32 outputAddress; -} tBsdGethostbynameParams; - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_EVENT_HANDLER_H__ - diff --git a/drivers/cc3000/inc/hci.h b/drivers/cc3000/inc/hci.h deleted file mode 100644 index f12b00e918..0000000000 --- a/drivers/cc3000/inc/hci.h +++ /dev/null @@ -1,330 +0,0 @@ -/***************************************************************************** -* -* hci.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_HCI_H__ -#define __CC3000_HCI_H__ - -#include "cc3000_common.h" - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - - -#define SPI_HEADER_SIZE (5) -#define SIMPLE_LINK_HCI_CMND_HEADER_SIZE (4) -#define HEADERS_SIZE_CMD (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE) -#define SIMPLE_LINK_HCI_DATA_CMND_HEADER_SIZE (5) -#define SIMPLE_LINK_HCI_DATA_HEADER_SIZE (5) -#define SIMPLE_LINK_HCI_PATCH_HEADER_SIZE (2) - - -//***************************************************************************** -// -// Values that can be used as HCI Commands and HCI Packet header defines -// -//***************************************************************************** -#define HCI_TYPE_CMND 0x1 -#define HCI_TYPE_DATA 0x2 -#define HCI_TYPE_PATCH 0x3 -#define HCI_TYPE_EVNT 0x4 - - -#define HCI_EVENT_PATCHES_DRV_REQ (1) -#define HCI_EVENT_PATCHES_FW_REQ (2) -#define HCI_EVENT_PATCHES_BOOTLOAD_REQ (3) - - -#define HCI_CMND_WLAN_BASE (0x0000) -#define HCI_CMND_WLAN_CONNECT 0x0001 -#define HCI_CMND_WLAN_DISCONNECT 0x0002 -#define HCI_CMND_WLAN_IOCTL_SET_SCANPARAM 0x0003 -#define HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY 0x0004 -#define HCI_CMND_WLAN_IOCTL_ADD_PROFILE 0x0005 -#define HCI_CMND_WLAN_IOCTL_DEL_PROFILE 0x0006 -#define HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS 0x0007 -#define HCI_CMND_EVENT_MASK 0x0008 -#define HCI_CMND_WLAN_IOCTL_STATUSGET 0x0009 -#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START 0x000A -#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP 0x000B -#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX 0x000C -#define HCI_CMND_WLAN_CONFIGURE_PATCH 0x000D - - -#define HCI_CMND_SOCKET_BASE 0x1000 -#define HCI_CMND_SOCKET 0x1001 -#define HCI_CMND_BIND 0x1002 -#define HCI_CMND_RECV 0x1004 -#define HCI_CMND_ACCEPT 0x1005 -#define HCI_CMND_LISTEN 0x1006 -#define HCI_CMND_CONNECT 0x1007 -#define HCI_CMND_BSD_SELECT 0x1008 -#define HCI_CMND_SETSOCKOPT 0x1009 -#define HCI_CMND_GETSOCKOPT 0x100A -#define HCI_CMND_CLOSE_SOCKET 0x100B -#define HCI_CMND_RECVFROM 0x100D -#define HCI_CMND_GETHOSTNAME 0x1010 -#define HCI_CMND_MDNS_ADVERTISE 0x1011 -#define HCI_CMND_GETMSSVALUE 0x1012 - - -#define HCI_DATA_BASE 0x80 - -#define HCI_CMND_SEND (0x01 + HCI_DATA_BASE) -#define HCI_CMND_SENDTO (0x03 + HCI_DATA_BASE) -#define HCI_DATA_BSD_RECVFROM (0x04 + HCI_DATA_BASE) -#define HCI_DATA_BSD_RECV (0x05 + HCI_DATA_BASE) - - -#define HCI_CMND_NVMEM_CBASE (0x0200) - - -#define HCI_CMND_NVMEM_CREATE_ENTRY (0x0203) -#define HCI_CMND_NVMEM_SWAP_ENTRY (0x0205) -#define HCI_CMND_NVMEM_READ (0x0201) -#define HCI_CMND_NVMEM_WRITE (0x0090) -#define HCI_CMND_NVMEM_WRITE_PATCH (0x0204) -#define HCI_CMND_READ_SP_VERSION (0x0207) - -#define HCI_CMND_READ_BUFFER_SIZE 0x400B -#define HCI_CMND_SIMPLE_LINK_START 0x4000 - -#define HCI_CMND_NETAPP_BASE 0x2000 - -#define HCI_NETAPP_DHCP (0x0001 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_PING_SEND (0x0002 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_PING_REPORT (0x0003 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_PING_STOP (0x0004 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_IPCONFIG (0x0005 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_ARP_FLUSH (0x0006 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_SET_DEBUG_LEVEL (0x0008 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_SET_TIMERS (0x0009 + HCI_CMND_NETAPP_BASE) - - - - - - -//***************************************************************************** -// -// Values that can be used as HCI Events defines -// -//***************************************************************************** -#define HCI_EVNT_WLAN_BASE 0x0000 -#define HCI_EVNT_WLAN_CONNECT 0x0001 -#define HCI_EVNT_WLAN_DISCONNECT \ - 0x0002 -#define HCI_EVNT_WLAN_IOCTL_ADD_PROFILE \ - 0x0005 - - -#define HCI_EVNT_SOCKET HCI_CMND_SOCKET -#define HCI_EVNT_BIND HCI_CMND_BIND -#define HCI_EVNT_RECV HCI_CMND_RECV -#define HCI_EVNT_ACCEPT HCI_CMND_ACCEPT -#define HCI_EVNT_LISTEN HCI_CMND_LISTEN -#define HCI_EVNT_CONNECT HCI_CMND_CONNECT -#define HCI_EVNT_SELECT HCI_CMND_BSD_SELECT -#define HCI_EVNT_CLOSE_SOCKET HCI_CMND_CLOSE_SOCKET -#define HCI_EVNT_RECVFROM HCI_CMND_RECVFROM -#define HCI_EVNT_SETSOCKOPT HCI_CMND_SETSOCKOPT -#define HCI_EVNT_GETSOCKOPT HCI_CMND_GETSOCKOPT -#define HCI_EVNT_BSD_GETHOSTBYNAME HCI_CMND_GETHOSTNAME -#define HCI_EVNT_MDNS_ADVERTISE HCI_CMND_MDNS_ADVERTISE -#define HCI_EVNT_GETMSSVALUE HCI_CMND_GETMSSVALUE - -#define HCI_EVNT_SEND 0x1003 -#define HCI_EVNT_WRITE 0x100E -#define HCI_EVNT_SENDTO 0x100F - -#define HCI_EVNT_PATCHES_REQ 0x1000 - -#define HCI_EVNT_UNSOL_BASE 0x4000 - -#define HCI_EVNT_WLAN_UNSOL_BASE (0x8000) - -#define HCI_EVNT_WLAN_UNSOL_CONNECT (0x0001 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_UNSOL_DISCONNECT (0x0002 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_UNSOL_INIT (0x0004 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_TX_COMPLETE (0x0008 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_UNSOL_DHCP (0x0010 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_ASYNC_PING_REPORT (0x0040 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE (0x0080 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_KEEPALIVE (0x0200 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_BSD_TCP_CLOSE_WAIT (0x0800 + HCI_EVNT_WLAN_UNSOL_BASE) - -#define HCI_EVNT_DATA_UNSOL_FREE_BUFF \ - 0x4100 - -#define HCI_EVNT_NVMEM_CREATE_ENTRY \ - HCI_CMND_NVMEM_CREATE_ENTRY -#define HCI_EVNT_NVMEM_SWAP_ENTRY HCI_CMND_NVMEM_SWAP_ENTRY - -#define HCI_EVNT_NVMEM_READ HCI_CMND_NVMEM_READ -#define HCI_EVNT_NVMEM_WRITE (0x0202) - -#define HCI_EVNT_READ_SP_VERSION \ - HCI_CMND_READ_SP_VERSION - -#define HCI_EVNT_INPROGRESS 0xFFFF - - -#define HCI_DATA_RECVFROM 0x84 -#define HCI_DATA_RECV 0x85 -#define HCI_DATA_NVMEM 0x91 - -#define HCI_EVENT_CC3000_CAN_SHUT_DOWN 0x99 - -//***************************************************************************** -// -// Prototypes for the structures for APIs. -// -//***************************************************************************** - -#define HCI_DATA_HEADER_SIZE (5) -#define HCI_EVENT_HEADER_SIZE (5) -#define HCI_DATA_CMD_HEADER_SIZE (5) -#define HCI_PATCH_HEADER_SIZE (6) - -#define HCI_PACKET_TYPE_OFFSET (0) -#define HCI_PACKET_ARGSIZE_OFFSET (2) -#define HCI_PACKET_LENGTH_OFFSET (3) - - -#define HCI_EVENT_OPCODE_OFFSET (1) -#define HCI_EVENT_LENGTH_OFFSET (3) -#define HCI_EVENT_STATUS_OFFSET (4) -#define HCI_DATA_LENGTH_OFFSET (3) - - - - -//***************************************************************************** -// -// Prototypes for the APIs. -// -//***************************************************************************** - -//***************************************************************************** -// -//! hci_command_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the command's arguments buffer -//! @param ucArgsLength length of the arguments -//! -//! @return none -//! -//! @brief Initiate an HCI command. -// -//***************************************************************************** -extern UINT16 hci_command_send(UINT16 usOpcode, - UINT8 *ucArgs, - UINT8 ucArgsLength); - - -//***************************************************************************** -// -//! hci_data_send -//! -//! @param usOpcode command operation code -//! @param ucArgs pointer to the command's arguments buffer -//! @param usArgsLength length of the arguments -//! @param ucTail pointer to the data buffer -//! @param usTailLength buffer length -//! -//! @return none -//! -//! @brief Initiate an HCI data write operation -// -//***************************************************************************** -extern INT32 hci_data_send(UINT8 ucOpcode, - UINT8 *ucArgs, - UINT16 usArgsLength, - UINT16 usDataLength, - const UINT8 *ucTail, - UINT16 usTailLength); - - -//***************************************************************************** -// -//! hci_data_command_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the data buffer -//! @param ucArgsLength arguments length -//! @param ucDataLength data length -//! -//! @return none -//! -//! @brief Prepare HCI header and initiate an HCI data write operation -// -//***************************************************************************** -extern void hci_data_command_send(UINT16 usOpcode, UINT8 *pucBuff, - UINT8 ucArgsLength, UINT16 ucDataLength); - -//***************************************************************************** -// -//! hci_patch_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the command's arguments buffer -//! @param patch pointer to patch content buffer -//! @param usDataLength data length -//! -//! @return none -//! -//! @brief Prepare HCI header and initiate an HCI patch write operation -// -//***************************************************************************** -extern void hci_patch_send(UINT8 ucOpcode, UINT8 *pucBuff, CHAR *patch, UINT16 usDataLength); - - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_HCI_H__ diff --git a/drivers/cc3000/inc/host_driver_version.h b/drivers/cc3000/inc/host_driver_version.h deleted file mode 100644 index a28d21f1be..0000000000 --- a/drivers/cc3000/inc/host_driver_version.h +++ /dev/null @@ -1,40 +0,0 @@ -/***************************************************************************** -* -* host_driver_version.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_HOST_DRIVER_VERSION_H__ -#define __CC3000_HOST_DRIVER_VERSION_H__ - -#define DRIVER_VERSION_NUMBER 15 - -#endif // __CC3000_HOST_DRIVER_VERSION_H__ diff --git a/drivers/cc3000/inc/inet_ntop.h b/drivers/cc3000/inc/inet_ntop.h deleted file mode 100644 index fa70806206..0000000000 --- a/drivers/cc3000/inc/inet_ntop.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __INET_NTOP_H -#define __INET_NTOP_H -char *inet_ntop(int af, const void *addr, char *buf, size_t size); -#endif /* __INET_NTOP_H */ diff --git a/drivers/cc3000/inc/inet_pton.h b/drivers/cc3000/inc/inet_pton.h deleted file mode 100644 index 0896d5d29f..0000000000 --- a/drivers/cc3000/inc/inet_pton.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __INET_PTON_H -#define __INET_PTON_H -int inet_pton(int, const char *, void *); -#endif /* __INET_PTON_H */ diff --git a/drivers/cc3000/inc/netapp.h b/drivers/cc3000/inc/netapp.h deleted file mode 100644 index 1e4f265896..0000000000 --- a/drivers/cc3000/inc/netapp.h +++ /dev/null @@ -1,343 +0,0 @@ -/***************************************************************************** -* -* netapp.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_NETAPP_H__ -#define __CC3000_NETAPP_H__ - -#include "data_types.h" - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -//***************************************************************************** -// -//! \addtogroup netapp_api -//! @{ -// -//***************************************************************************** - -typedef struct _netapp_dhcp_ret_args_t -{ - UINT8 aucIP[4]; - UINT8 aucSubnetMask[4]; - UINT8 aucDefaultGateway[4]; - UINT8 aucDHCPServer[4]; - UINT8 aucDNSServer[4]; -}tNetappDhcpParams; - -typedef struct _netapp_ipconfig_ret_args_t -{ - UINT8 aucIP[4]; - UINT8 aucSubnetMask[4]; - UINT8 aucDefaultGateway[4]; - UINT8 aucDHCPServer[4]; - UINT8 aucDNSServer[4]; - UINT8 uaMacAddr[6]; - UINT8 uaSSID[32]; -}tNetappIpconfigRetArgs; - - -/*Ping send report parameters*/ -typedef struct _netapp_pingreport_args -{ - UINT32 packets_sent; - UINT32 packets_received; - UINT32 min_round_time; - UINT32 max_round_time; - UINT32 avg_round_time; -} netapp_pingreport_args_t; - - -//***************************************************************************** -// -//! netapp_config_mac_adrress -//! -//! @param mac device mac address, 6 bytes. Saved: yes -//! -//! @return return on success 0, otherwise error. -//! -//! @brief Configure device MAC address and store it in NVMEM. -//! The value of the MAC address configured through the API will -//! be stored in CC3000 non volatile memory, thus preserved -//! over resets. -// -//***************************************************************************** -extern INT32 netapp_config_mac_adrress( UINT8 *mac ); - -//***************************************************************************** -// -//! netapp_dhcp -//! -//! @param aucIP device mac address, 6 bytes. Saved: yes -//! @param aucSubnetMask device mac address, 6 bytes. Saved: yes -//! @param aucDefaultGateway device mac address, 6 bytes. Saved: yes -//! @param aucDNSServer device mac address, 6 bytes. Saved: yes -//! -//! @return return on success 0, otherwise error. -//! -//! @brief netapp_dhcp is used to configure the network interface, -//! static or dynamic (DHCP).\n In order to activate DHCP mode, -//! aucIP, aucSubnetMask, aucDefaultGateway must be 0. -//! The default mode of CC3000 is DHCP mode. -//! Note that the configuration is saved in non volatile memory -//! and thus preserved over resets. -//! -//! @note If the mode is altered a reset of CC3000 device is required -//! in order to apply changes.\nAlso note that asynchronous event -//! of DHCP_EVENT, which is generated when an IP address is -//! allocated either by the DHCP server or due to static -//! allocation is generated only upon a connection to the -//! AP was established. -//! -//***************************************************************************** -extern INT32 netapp_dhcp(UINT32 *aucIP, UINT32 *aucSubnetMask,UINT32 *aucDefaultGateway, UINT32 *aucDNSServer); - - - -//***************************************************************************** -// -//! netapp_timeout_values -//! -//! @param aucDHCP DHCP lease time request, also impact -//! the DHCP renew timeout. Range: [0-0xffffffff] seconds, -//! 0 or 0xffffffff == infinity lease timeout. -//! Resolution:10 seconds. Influence: only after -//! reconnecting to the AP. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds. -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 14400 seconds. -//! -//! @param aucARP ARP refresh timeout, if ARP entry is not updated by -//! incoming packet, the ARP entry will be deleted by -//! the end of the timeout. -//! Range: [0-0xffffffff] seconds, 0 == infinity ARP timeout -//! Resolution: 10 seconds. Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 3600 seconds. -//! -//! @param aucKeepalive Keepalive event sent by the end of keepalive timeout -//! Range: [0-0xffffffff] seconds, 0 == infinity timeout -//! Resolution: 10 seconds. -//! Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 10 seconds. -//! -//! @param aucInactivity Socket inactivity timeout, socket timeout is -//! refreshed by incoming or outgoing packet, by the -//! end of the socket timeout the socket will be closed -//! Range: [0-0xffffffff] sec, 0 == infinity timeout. -//! Resolution: 10 seconds. Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 60 seconds. -//! -//! @return return on success 0, otherwise error. -//! -//! @brief Set new timeout values. Function set new timeout values for: -//! DHCP lease timeout, ARP refresh timeout, keepalive event -//! timeout and socket inactivity timeout -//! -//! @note If a parameter set to non zero value which is less than 10s, -//! it will be set automatically to 10s. -//! -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern INT32 netapp_timeout_values(UINT32 *aucDHCP, UINT32 *aucARP, UINT32 *aucKeepalive, UINT32 *aucInactivity); -#endif - -//***************************************************************************** -// -//! netapp_ping_send -//! -//! @param ip destination IP address -//! @param pingAttempts number of echo requests to send -//! @param pingSize send buffer size which may be up to 1400 bytes -//! @param pingTimeout Time to wait for a response,in milliseconds. -//! -//! @return return on success 0, otherwise error. -//! -//! @brief send ICMP ECHO_REQUEST to network hosts -//! -//! @note If an operation finished successfully asynchronous ping report -//! event will be generated. The report structure is as defined -//! by structure netapp_pingreport_args_t. -//! -//! @warning Calling this function while a previous Ping Requests are in -//! progress will stop the previous ping request. -//***************************************************************************** - - #ifndef CC3000_TINY_DRIVER -extern INT32 netapp_ping_send(UINT32 *ip, UINT32 ulPingAttempts, UINT32 ulPingSize, UINT32 ulPingTimeout); -#endif - -//***************************************************************************** -// -//! netapp_ping_stop -//! -//! @param none -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief Stop any ping request. -//! -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -extern INT32 netapp_ping_stop(); -#endif -//***************************************************************************** -// -//! netapp_ping_report -//! -//! @param none -//! -//! @return none -//! -//! @brief Request for ping status. This API triggers the CC3000 to send -//! asynchronous events: HCI_EVNT_WLAN_ASYNC_PING_REPORT. -//! This event will carry the report structure: -//! netapp_pingreport_args_t. This structure is filled in with ping -//! results up till point of triggering API. -//! netapp_pingreport_args_t:\n packets_sent - echo sent, -//! packets_received - echo reply, min_round_time - minimum -//! round time, max_round_time - max round time, -//! avg_round_time - average round time -//! -//! @note When a ping operation is not active, the returned structure -//! fields are 0. -//! -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern void netapp_ping_report(); -#endif - - -//***************************************************************************** -// -//! netapp_ipconfig -//! -//! @param[out] ipconfig This argument is a pointer to a -//! tNetappIpconfigRetArgs structure. This structure is -//! filled in with the network interface configuration. -//! tNetappIpconfigRetArgs:\n aucIP - ip address, -//! aucSubnetMask - mask, aucDefaultGateway - default -//! gateway address, aucDHCPServer - dhcp server address -//! aucDNSServer - dns server address, uaMacAddr - mac -//! address, uaSSID - connected AP ssid -//! -//! @return none -//! -//! @brief Obtain the CC3000 Network interface information. -//! Note that the information is available only after the WLAN -//! connection was established. Calling this function before -//! associated, will cause non-defined values to be returned. -//! -//! @note The function is useful for figuring out the IP Configuration of -//! the device when DHCP is used and for figuring out the SSID of -//! the Wireless network the device is associated with. -//! -//***************************************************************************** - -extern void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig ); - - -//***************************************************************************** -// -//! netapp_arp_flush -//! -//! @param none -//! -//! @return none -//! -//! @brief Flushes ARP table -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -extern INT32 netapp_arp_flush(); -#endif - - -//***************************************************************************** -// -//! netapp_set_debug_level -//! -//! @param[in] level debug level. Bitwise [0-8], -//! 0(disable)or 1(enable).\n Bitwise map: 0 - Critical -//! message, 1 information message, 2 - core messages, 3 - -//! HCI messages, 4 - Network stack messages, 5 - wlan -//! messages, 6 - wlan driver messages, 7 - epprom messages, -//! 8 - general messages. Default: 0x13f. Saved: no -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Debug messages sent via the UART debug channel, this function -//! enable/disable the debug level -//! -//***************************************************************************** - - -#ifndef CC3000_TINY_DRIVER -INT32 netapp_set_debug_level(UINT32 ulLevel); -#endif -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** - - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_NETAPP_H__ - diff --git a/drivers/cc3000/inc/nvmem.h b/drivers/cc3000/inc/nvmem.h deleted file mode 100644 index b99a2e7b9e..0000000000 --- a/drivers/cc3000/inc/nvmem.h +++ /dev/null @@ -1,248 +0,0 @@ -/***************************************************************************** -* -* nvmem.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_NVRAM_H__ -#define __CC3000_NVRAM_H__ - -#include "cc3000_common.h" - - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - - -//***************************************************************************** -// -//! \addtogroup nvmem_api -//! @{ -// -//***************************************************************************** - -/**************************************************************************** -** -** Definitions for File IDs -** -****************************************************************************/ -/* NVMEM file ID - system files*/ -#define NVMEM_NVS_FILEID (0) -#define NVMEM_NVS_SHADOW_FILEID (1) -#define NVMEM_WLAN_CONFIG_FILEID (2) -#define NVMEM_WLAN_CONFIG_SHADOW_FILEID (3) -#define NVMEM_WLAN_DRIVER_SP_FILEID (4) -#define NVMEM_WLAN_FW_SP_FILEID (5) -#define NVMEM_MAC_FILEID (6) -#define NVMEM_FRONTEND_VARS_FILEID (7) -#define NVMEM_IP_CONFIG_FILEID (8) -#define NVMEM_IP_CONFIG_SHADOW_FILEID (9) -#define NVMEM_BOOTLOADER_SP_FILEID (10) -#define NVMEM_RM_FILEID (11) - -/* NVMEM file ID - user files*/ -#define NVMEM_AES128_KEY_FILEID (12) -#define NVMEM_SHARED_MEM_FILEID (13) - -/* max entry in order to invalid nvmem */ -#define NVMEM_MAX_ENTRY (16) - - -//***************************************************************************** -// -//! nvmem_read -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_NVS_FILEID, NVMEM_NVS_SHADOW_FILEID, -//! NVMEM_WLAN_CONFIG_FILEID, NVMEM_WLAN_CONFIG_SHADOW_FILEID, -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! NVMEM_MAC_FILEID, NVMEM_FRONTEND_VARS_FILEID, -//! NVMEM_IP_CONFIG_FILEID, NVMEM_IP_CONFIG_SHADOW_FILEID, -//! NVMEM_BOOTLOADER_SP_FILEID, NVMEM_RM_FILEID, -//! and user files 12-15. -//! @param ulLength number of bytes to read -//! @param ulOffset ulOffset in file from where to read -//! @param buff output buffer pointer -//! -//! @return on success 0, error otherwise. -//! -//! @brief Reads data from the file referred by the ulFileId parameter. -//! Reads data from file ulOffset till length. Err if the file can't -//! be used, is invalid, or if the read is out of bounds. -//! -//***************************************************************************** - -extern INT32 nvmem_read(UINT32 file_id, UINT32 length, UINT32 offset, UINT8 *buff); - -//***************************************************************************** -// -//! nvmem_write -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! NVMEM_MAC_FILEID, NVMEM_BOOTLOADER_SP_FILEID, -//! and user files 12-15. -//! @param ulLength number of bytes to write -//! @param ulEntryOffset offset in file to start write operation from -//! @param buff data to write -//! -//! @return on success 0, error otherwise. -//! -//! @brief Write data to nvmem. -//! writes data to file referred by the ulFileId parameter. -//! Writes data to file ulOffset till ulLength.The file id will be -//! marked invalid till the write is done. The file entry doesn't -//! need to be valid - only allocated. -//! -//***************************************************************************** - -extern INT32 nvmem_write(UINT32 ulFileId, UINT32 ulLength, UINT32 ulEntryOffset, UINT8 *buff); - - -//***************************************************************************** -// -//! nvmem_set_mac_address -//! -//! @param mac mac address to be set -//! -//! @return on success 0, error otherwise. -//! -//! @brief Write MAC address to EEPROM. -//! mac address as appears over the air (OUI first) -//! -//***************************************************************************** -extern UINT8 nvmem_set_mac_address(UINT8 *mac); - - -//***************************************************************************** -// -//! nvmem_get_mac_address -//! -//! @param[out] mac mac address -//! -//! @return on success 0, error otherwise. -//! -//! @brief Read MAC address from EEPROM. -//! mac address as appears over the air (OUI first) -//! -//***************************************************************************** -extern UINT8 nvmem_get_mac_address(UINT8 *mac); - - -//***************************************************************************** -// -//! nvmem_write_patch -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! @param spLength number of bytes to write -//! @param spData SP data to write -//! -//! @return on success 0, error otherwise. -//! -//! @brief program a patch to a specific file ID. -//! The SP data is assumed to be organized in 2-dimensional. -//! Each line is SP_PORTION_SIZE bytes long. Actual programming is -//! applied in SP_PORTION_SIZE bytes portions. -//! -//***************************************************************************** -extern UINT8 nvmem_write_patch(UINT32 ulFileId, UINT32 spLength, const UINT8 *spData); - - -//***************************************************************************** -// -//! nvmem_read_sp_version -//! -//! @param[out] patchVer first number indicates package ID and the second -//! number indicates package build number -//! -//! @return on success 0, error otherwise. -//! -//! @brief Read patch version. read package version (WiFi FW patch, -//! driver-supplicant-NS patch, bootloader patch) -//! -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern UINT8 nvmem_read_sp_version(UINT8* patchVer); -#endif - -//***************************************************************************** -// -//! nvmem_create_entry -//! -//! @param ulFileId nvmem file Id:\n -//! * NVMEM_AES128_KEY_FILEID: 12 -//! * NVMEM_SHARED_MEM_FILEID: 13 -//! * and fileIDs 14 and 15 -//! @param ulNewLen entry ulLength -//! -//! @return on success 0, error otherwise. -//! -//! @brief Create new file entry and allocate space on the NVMEM. -//! Applies only to user files. -//! Modify the size of file. -//! If the entry is unallocated - allocate it to size -//! ulNewLen (marked invalid). -//! If it is allocated then deallocate it first. -//! To just mark the file as invalid without resizing - -//! set ulNewLen=0. -//! -//***************************************************************************** -extern INT32 nvmem_create_entry(UINT32 file_id, UINT32 newlen); - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** - - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** - - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_NVRAM_H__ diff --git a/drivers/cc3000/inc/patch_prog.h b/drivers/cc3000/inc/patch_prog.h deleted file mode 100644 index 0a141a0cb5..0000000000 --- a/drivers/cc3000/inc/patch_prog.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __CC3000_PATCH_PROG_H__ -#define __CC3000_PATCH_PROG_H__ -extern unsigned short fw_length; -extern const unsigned char fw_patch[]; - -extern unsigned short drv_length; -extern const unsigned char wlan_drv_patch[]; -extern const unsigned char cRMdefaultParams[128]; - -void patch_prog_start(); -#endif //__CC3000_PATCH_PROG_H__ diff --git a/drivers/cc3000/inc/security.h b/drivers/cc3000/inc/security.h deleted file mode 100644 index cd1baf5541..0000000000 --- a/drivers/cc3000/inc/security.h +++ /dev/null @@ -1,130 +0,0 @@ -/***************************************************************************** -* -* security.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_SECURITY__ -#define __CC3000_SECURITY__ - -#include "nvmem.h" - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - - -#define AES128_KEY_SIZE 16 - -#ifndef CC3000_UNENCRYPTED_SMART_CONFIG - - -//***************************************************************************** -// -//! aes_encrypt -//! -//! @param[in] key AES128 key of size 16 bytes -//! @param[in\out] state 16 bytes of plain text and cipher text -//! -//! @return none -//! -//! @brief AES128 encryption: -//! Given AES128 key and 16 bytes plain text, cipher text of 16 bytes -//! is computed. The AES implementation is in mode ECB (Electronic -//! Code Book). -//! -//! -//***************************************************************************** -extern void aes_encrypt(UINT8 *state, UINT8 *key); - -//***************************************************************************** -// -//! aes_decrypt -//! -//! @param[in] key AES128 key of size 16 bytes -//! @param[in\out] state 16 bytes of cipher text and plain text -//! -//! @return none -//! -//! @brief AES128 decryption: -//! Given AES128 key and 16 bytes cipher text, plain text of 16 bytes -//! is computed The AES implementation is in mode ECB -//! (Electronic Code Book). -//! -//! -//***************************************************************************** -extern void aes_decrypt(UINT8 *state, UINT8 *key); - - -//***************************************************************************** -// -//! aes_read_key -//! -//! @param[out] key AES128 key of size 16 bytes -//! -//! @return on success 0, error otherwise. -//! -//! @brief Reads AES128 key from EEPROM -//! Reads the AES128 key from fileID #12 in EEPROM -//! returns an error if the key does not exist. -//! -//! -//***************************************************************************** -extern INT32 aes_read_key(UINT8 *key); - -//***************************************************************************** -// -//! aes_write_key -//! -//! @param[out] key AES128 key of size 16 bytes -//! -//! @return on success 0, error otherwise. -//! -//! @brief writes AES128 key from EEPROM -//! Writes the AES128 key to fileID #12 in EEPROM -//! -//! -//***************************************************************************** -extern INT32 aes_write_key(UINT8 *key); - -#endif //CC3000_UNENCRYPTED_SMART_CONFIG - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif diff --git a/drivers/cc3000/inc/socket.h b/drivers/cc3000/inc/socket.h deleted file mode 100644 index 96c814bf77..0000000000 --- a/drivers/cc3000/inc/socket.h +++ /dev/null @@ -1,676 +0,0 @@ -/***************************************************************************** -* -* socket.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_SOCKET_H__ -#define __CC3000_SOCKET_H__ - -#include "cc3000_common.h" - -//***************************************************************************** -// -//! \addtogroup socket_api -//! @{ -// -//***************************************************************************** - - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -#define HOSTNAME_MAX_LENGTH (230) // 230 bytes + header shouldn't exceed 8 bit value - -//--------- Address Families -------- - -#define AF_INET 2 -#define AF_INET6 23 - -//------------ Socket Types ------------ - -#define SOCK_STREAM 1 -#define SOCK_DGRAM 2 -#define SOCK_RAW 3 // Raw sockets allow new IPv4 protocols to be implemented in user space. A raw socket receives or sends the raw datagram not including link level headers -#define SOCK_RDM 4 -#define SOCK_SEQPACKET 5 - -//----------- Socket Protocol ---------- - -#define IPPROTO_IP 0 // dummy for IP -#define IPPROTO_ICMP 1 // control message protocol -#define IPPROTO_IPV4 IPPROTO_IP // IP inside IP -#define IPPROTO_TCP 6 // tcp -#define IPPROTO_UDP 17 // user datagram protocol -#define IPPROTO_IPV6 41 // IPv6 in IPv6 -#define IPPROTO_NONE 59 // No next header -#define IPPROTO_RAW 255 // raw IP packet -#define IPPROTO_MAX 256 - -//----------- Socket retunr codes ----------- - -#define SOC_ERROR (-1) // error -#define SOC_IN_PROGRESS (-2) // socket in progress - -//----------- Socket Options ----------- -#define SOL_SOCKET 0xffff // socket level -#define SOCKOPT_RECV_NONBLOCK 0 // recv non block mode, set SOCK_ON or SOCK_OFF (default block mode) -#define SOCKOPT_RECV_TIMEOUT 1 // optname to configure recv and recvfromtimeout -#define SOCKOPT_ACCEPT_NONBLOCK 2 // accept non block mode, set SOCK_ON or SOCK_OFF (default block mode) -#define SOCK_ON 0 // socket non-blocking mode is enabled -#define SOCK_OFF 1 // socket blocking mode is enabled - -#define MAX_PACKET_SIZE 1500 -#define MAX_LISTEN_QUEUE 4 - -#define IOCTL_SOCKET_EVENTMASK - -#define ENOBUFS 55 // No buffer space available - -#define __FD_SETSIZE 32 - -#define ASIC_ADDR_LEN 8 - -#define NO_QUERY_RECIVED -3 - - -typedef struct _in_addr_t -{ - UINT32 s_addr; // load with inet_aton() -} in_addr; - -typedef struct _sockaddr_t -{ - UINT16 sa_family; - UINT8 sa_data[14]; -} sockaddr; - -typedef struct _sockaddr_in_t -{ - INT16 sin_family; // e.g. AF_INET - UINT16 sin_port; // e.g. htons(3490) - in_addr sin_addr; // see struct in_addr, below - CHAR sin_zero[8]; // zero this if you want to -} sockaddr_in; - -typedef UINT32 socklen_t; - -// The fd_set member is required to be an array of INT32s. -typedef INT32 __fd_mask; - -// It's easier to assume 8-bit bytes than to get CHAR_BIT. -#define __NFDBITS (8 * sizeof (__fd_mask)) -#define __FDELT(d) ((d) / __NFDBITS) -#define __FDMASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS)) - -// fd_set for select and pselect. -typedef struct -{ - __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS]; -#define __FDS_BITS(set) ((set)->fds_bits) -} fd_set; - -// We don't use `memset' because this would require a prototype and -// the array isn't too big. -#define __FD_ZERO(set) \ - do { \ - UINT16 __i; \ - fd_set *__arr = (set); \ - for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \ - __FDS_BITS (__arr)[__i] = 0; \ - } while (0) -#define __FD_SET(d, set) (__FDS_BITS (set)[__FDELT (d)] |= __FDMASK (d)) -#define __FD_CLR(d, set) (__FDS_BITS (set)[__FDELT (d)] &= ~__FDMASK (d)) -#define __FD_ISSET(d, set) (__FDS_BITS (set)[__FDELT (d)] & __FDMASK (d)) - -// Access macros for 'fd_set'. -#define FD_SET(fd, fdsetp) __FD_SET (fd, fdsetp) -#define FD_CLR(fd, fdsetp) __FD_CLR (fd, fdsetp) -#define FD_ISSET(fd, fdsetp) __FD_ISSET (fd, fdsetp) -#define FD_ZERO(fdsetp) __FD_ZERO (fdsetp) - -//Use in case of Big Endian only - -#define htonl(A) ((((UINT32)(A) & 0xff000000) >> 24) | \ - (((UINT32)(A) & 0x00ff0000) >> 8) | \ - (((UINT32)(A) & 0x0000ff00) << 8) | \ - (((UINT32)(A) & 0x000000ff) << 24)) - -#define ntohl htonl - -//Use in case of Big Endian only -#define htons(A) ((((UINT32)(A) & 0xff00) >> 8) | \ - (((UINT32)(A) & 0x00ff) << 8)) - - -#define ntohs htons - -// mDNS port - 5353 mDNS multicast address - 224.0.0.251 -#define SET_mDNS_ADD(sockaddr) sockaddr.sa_data[0] = 0x14; \ - sockaddr.sa_data[1] = 0xe9; \ - sockaddr.sa_data[2] = 0xe0; \ - sockaddr.sa_data[3] = 0x0; \ - sockaddr.sa_data[4] = 0x0; \ - sockaddr.sa_data[5] = 0xfb; - - -//***************************************************************************** -// -// Prototypes for the APIs. -// -//***************************************************************************** - -//***************************************************************************** -// -//! socket -//! -//! @param domain selects the protocol family which will be used for -//! communication. On this version only AF_INET is supported -//! @param type specifies the communication semantics. On this version -//! only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported -//! @param protocol specifies a particular protocol to be used with the -//! socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are -//! supported. -//! -//! @return On success, socket handle that is used for consequent socket -//! operations. On error, -1 is returned. -//! -//! @brief create an endpoint for communication -//! The socket function creates a socket that is bound to a specific -//! transport service provider. This function is called by the -//! application layer to obtain a socket handle. -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(socket)(INT32 domain, INT32 type, INT32 protocol); - -//***************************************************************************** -// -//! closesocket -//! -//! @param sd socket handle. -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief The socket function closes a created socket. -// -//***************************************************************************** -extern INT32 CC3000_EXPORT(closesocket)(INT32 sd); - -//***************************************************************************** -// -//! accept -//! -//! @param[in] sd socket descriptor (handle) -//! @param[out] addr the argument addr is a pointer to a sockaddr structure -//! This structure is filled in with the address of the -//! peer socket, as known to the communications layer. -//! determined. The exact format of the address returned -//! addr is by the socket's address sockaddr. -//! On this version only AF_INET is supported. -//! This argument returns in network order. -//! @param[out] addrlen the addrlen argument is a value-result argument: -//! it should initially contain the size of the structure -//! pointed to by addr. -//! -//! @return For socket in blocking mode: -//! On success, socket handle. on failure negative -//! For socket in non-blocking mode: -//! - On connection establishment, socket handle -//! - On connection pending, SOC_IN_PROGRESS (-2) -//! - On failure, SOC_ERROR (-1) -//! -//! @brief accept a connection on a socket: -//! This function is used with connection-based socket types -//! (SOCK_STREAM). It extracts the first connection request on the -//! queue of pending connections, creates a new connected socket, and -//! returns a new file descriptor referring to that socket. -//! The newly created socket is not in the listening state. -//! The original socket sd is unaffected by this call. -//! The argument sd is a socket that has been created with socket(), -//! bound to a local address with bind(), and is listening for -//! connections after a listen(). The argument addr is a pointer -//! to a sockaddr structure. This structure is filled in with the -//! address of the peer socket, as known to the communications layer. -//! The exact format of the address returned addr is determined by the -//! socket's address family. The addrlen argument is a value-result -//! argument: it should initially contain the size of the structure -//! pointed to by addr, on return it will contain the actual -//! length (in bytes) of the address returned. -//! -//! @sa socket ; bind ; listen -// -//***************************************************************************** -extern INT32 CC3000_EXPORT(accept)(INT32 sd, sockaddr *addr, socklen_t *addrlen); - -//***************************************************************************** -// -//! bind -//! -//! @param[in] sd socket descriptor (handle) -//! @param[out] addr specifies the destination address. On this version -//! only AF_INET is supported. -//! @param[out] addrlen contains the size of the structure pointed to by addr. -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief assign a name to a socket -//! This function gives the socket the local address addr. -//! addr is addrlen bytes long. Traditionally, this is called when a -//! socket is created with socket, it exists in a name space (address -//! family) but has no name assigned. -//! It is necessary to assign a local address before a SOCK_STREAM -//! socket may receive connections. -//! -//! @sa socket ; accept ; listen -// -//***************************************************************************** -extern INT32 CC3000_EXPORT(bind)(INT32 sd, const sockaddr *addr, INT32 addrlen); - -//***************************************************************************** -// -//! listen -//! -//! @param[in] sd socket descriptor (handle) -//! @param[in] backlog specifies the listen queue depth. On this version -//! backlog is not supported. -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief listen for connections on a socket -//! The willingness to accept incoming connections and a queue -//! limit for incoming connections are specified with listen(), -//! and then the connections are accepted with accept. -//! The listen() call applies only to sockets of type SOCK_STREAM -//! The backlog parameter defines the maximum length the queue of -//! pending connections may grow to. -//! -//! @sa socket ; accept ; bind -//! -//! @note On this version, backlog is not supported -// -//***************************************************************************** -extern INT32 CC3000_EXPORT(listen)(INT32 sd, INT32 backlog); - -//***************************************************************************** -// -//! gethostbyname -//! -//! @param[in] hostname host name -//! @param[in] usNameLen name length -//! @param[out] out_ip_addr This parameter is filled in with host IP address. -//! In case that host name is not resolved, -//! out_ip_addr is zero. -//! @return On success, positive is returned. On error, negative is returned -//! -//! @brief Get host IP by name. Obtain the IP Address of machine on network, -//! by its name. -//! -//! @note On this version, only blocking mode is supported. Also note that -//! the function requires DNS server to be configured prior to its usage. -// -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern INT16 CC3000_EXPORT(gethostbyname)(CHAR * hostname, UINT16 usNameLen, UINT32* out_ip_addr); -#endif - - -//***************************************************************************** -// -//! connect -//! -//! @param[in] sd socket descriptor (handle) -//! @param[in] addr specifies the destination addr. On this version -//! only AF_INET is supported. -//! @param[out] addrlen contains the size of the structure pointed to by addr -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief initiate a connection on a socket -//! Function connects the socket referred to by the socket descriptor -//! sd, to the address specified by addr. The addrlen argument -//! specifies the size of addr. The format of the address in addr is -//! determined by the address space of the socket. If it is of type -//! SOCK_DGRAM, this call specifies the peer with which the socket is -//! to be associated; this address is that to which datagrams are to be -//! sent, and the only address from which datagrams are to be received. -//! If the socket is of type SOCK_STREAM, this call attempts to make a -//! connection to another socket. The other socket is specified by -//! address, which is an address in the communications space of the -//! socket. Note that the function implements only blocking behavior -//! thus the caller will be waiting either for the connection -//! establishment or for the connection establishment failure. -//! -//! @sa socket -// -//***************************************************************************** -extern INT32 CC3000_EXPORT(connect)(INT32 sd, const sockaddr *addr, INT32 addrlen); - -//***************************************************************************** -// -//! select -//! -//! @param[in] nfds the highest-numbered file descriptor in any of the -//! three sets, plus 1. -//! @param[out] writesds socket descriptors list for write monitoring -//! @param[out] readsds socket descriptors list for read monitoring -//! @param[out] exceptsds socket descriptors list for exception monitoring -//! @param[in] timeout is an upper bound on the amount of time elapsed -//! before select() returns. Null means infinity -//! timeout. The minimum timeout is 5 milliseconds, -//! less than 5 milliseconds will be set -//! automatically to 5 milliseconds. -//! @return On success, select() returns the number of file descriptors -//! contained in the three returned descriptor sets (that is, the -//! total number of bits that are set in readfds, writefds, -//! exceptfds) which may be zero if the timeout expires before -//! anything interesting happens. -//! On error, -1 is returned. -//! *readsds - return the sockets on which Read request will -//! return without delay with valid data. -//! *writesds - return the sockets on which Write request -//! will return without delay. -//! *exceptsds - return the sockets which closed recently. -//! -//! @brief Monitor socket activity -//! Select allow a program to monitor multiple file descriptors, -//! waiting until one or more of the file descriptors become -//! "ready" for some class of I/O operation -//! -//! @Note If the timeout value set to less than 5ms it will automatically set -//! to 5ms to prevent overload of the system -//! -//! @sa socket -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(select)(INT32 nfds, fd_set *readsds, fd_set *writesds, - fd_set *exceptsds, struct cc3000_timeval *timeout); - -//***************************************************************************** -// -//! setsockopt -//! -//! @param[in] sd socket handle -//! @param[in] level defines the protocol level for this option -//! @param[in] optname defines the option name to Interrogate -//! @param[in] optval specifies a value for the option -//! @param[in] optlen specifies the length of the option value -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief set socket options -//! This function manipulate the options associated with a socket. -//! Options may exist at multiple protocol levels; they are always -//! present at the uppermost socket level. -//! When manipulating socket options the level at which the option -//! resides and the name of the option must be specified. -//! To manipulate options at the socket level, level is specified as -//! SOL_SOCKET. To manipulate options at any other level the protocol -//! number of the appropriate protocol controlling the option is -//! supplied. For example, to indicate that an option is to be -//! interpreted by the TCP protocol, level should be set to the -//! protocol number of TCP; -//! The parameters optval and optlen are used to access optval - -//! use for setsockopt(). For getsockopt() they identify a buffer -//! in which the value for the requested option(s) are to -//! be returned. For getsockopt(), optlen is a value-result -//! parameter, initially containing the size of the buffer -//! pointed to by option_value, and modified on return to -//! indicate the actual size of the value returned. If no option -//! value is to be supplied or returned, option_value may be NULL. -//! -//! @Note On this version the following two socket options are enabled: -//! The only protocol level supported in this version -//! is SOL_SOCKET (level). -//! 1. SOCKOPT_RECV_TIMEOUT (optname) -//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout -//! in milliseconds. -//! In that case optval should be pointer to UINT32. -//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on -//! or off. -//! In that case optval should be SOCK_ON or SOCK_OFF (optval). -//! -//! @sa getsockopt -// -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern INT16 CC3000_EXPORT(setsockopt)(INT32 sd, INT32 level, INT32 optname, const void *optval, - socklen_t optlen); -#endif -//***************************************************************************** -// -//! getsockopt -//! -//! @param[in] sd socket handle -//! @param[in] level defines the protocol level for this option -//! @param[in] optname defines the option name to Interrogate -//! @param[out] optval specifies a value for the option -//! @param[out] optlen specifies the length of the option value -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief set socket options -//! This function manipulate the options associated with a socket. -//! Options may exist at multiple protocol levels; they are always -//! present at the uppermost socket level. -//! When manipulating socket options the level at which the option -//! resides and the name of the option must be specified. -//! To manipulate options at the socket level, level is specified as -//! SOL_SOCKET. To manipulate options at any other level the protocol -//! number of the appropriate protocol controlling the option is -//! supplied. For example, to indicate that an option is to be -//! interpreted by the TCP protocol, level should be set to the -//! protocol number of TCP; -//! The parameters optval and optlen are used to access optval - -//! use for setsockopt(). For getsockopt() they identify a buffer -//! in which the value for the requested option(s) are to -//! be returned. For getsockopt(), optlen is a value-result -//! parameter, initially containing the size of the buffer -//! pointed to by option_value, and modified on return to -//! indicate the actual size of the value returned. If no option -//! value is to be supplied or returned, option_value may be NULL. -//! -//! @Note On this version the following two socket options are enabled: -//! The only protocol level supported in this version -//! is SOL_SOCKET (level). -//! 1. SOCKOPT_RECV_TIMEOUT (optname) -//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout -//! in milliseconds. -//! In that case optval should be pointer to UINT32. -//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on -//! or off. -//! In that case optval should be SOCK_ON or SOCK_OFF (optval). -//! -//! @sa setsockopt -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(getsockopt)(INT32 sd, INT32 level, INT32 optname, void *optval, - socklen_t *optlen); - -//***************************************************************************** -// -//! recv -//! -//! @param[in] sd socket handle -//! @param[out] buf Points to the buffer where the message should be stored -//! @param[in] len Specifies the length in bytes of the buffer pointed to -//! by the buffer argument. -//! @param[in] flags Specifies the type of message reception. -//! On this version, this parameter is not supported. -//! -//! @return Return the number of bytes received, or -1 if an error -//! occurred -//! -//! @brief function receives a message from a connection-mode socket -//! -//! @sa recvfrom -//! -//! @Note On this version, only blocking mode is supported. -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(recv)(INT32 sd, void *buf, INT32 len, INT32 flags); - -//***************************************************************************** -// -//! recvfrom -//! -//! @param[in] sd socket handle -//! @param[out] buf Points to the buffer where the message should be stored -//! @param[in] len Specifies the length in bytes of the buffer pointed to -//! by the buffer argument. -//! @param[in] flags Specifies the type of message reception. -//! On this version, this parameter is not supported. -//! @param[in] from pointer to an address structure indicating the source -//! address: sockaddr. On this version only AF_INET is -//! supported. -//! @param[in] fromlen source address structure size -//! -//! @return Return the number of bytes received, or -1 if an error -//! occurred -//! -//! @brief read data from socket -//! function receives a message from a connection-mode or -//! connectionless-mode socket. Note that raw sockets are not -//! supported. -//! -//! @sa recv -//! -//! @Note On this version, only blocking mode is supported. -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(recvfrom)(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from, - socklen_t *fromlen); - -//***************************************************************************** -// -//! send -//! -//! @param sd socket handle -//! @param buf Points to a buffer containing the message to be sent -//! @param len message size in bytes -//! @param flags On this version, this parameter is not supported -//! -//! @return Return the number of bytes transmitted, or -1 if an -//! error occurred -//! -//! @brief Write data to TCP socket -//! This function is used to transmit a message to another -//! socket. -//! -//! @Note On this version, only blocking mode is supported. -//! -//! @sa sendto -// -//***************************************************************************** - -extern INT16 CC3000_EXPORT(send)(INT32 sd, const void *buf, INT32 len, INT32 flags); - -//***************************************************************************** -// -//! sendto -//! -//! @param sd socket handle -//! @param buf Points to a buffer containing the message to be sent -//! @param len message size in bytes -//! @param flags On this version, this parameter is not supported -//! @param to pointer to an address structure indicating the destination -//! address: sockaddr. On this version only AF_INET is -//! supported. -//! @param tolen destination address structure size -//! -//! @return Return the number of bytes transmitted, or -1 if an -//! error occurred -//! -//! @brief Write data to TCP socket -//! This function is used to transmit a message to another -//! socket. -//! -//! @Note On this version, only blocking mode is supported. -//! -//! @sa send -// -//***************************************************************************** - -extern INT16 CC3000_EXPORT(sendto)(INT32 sd, const void *buf, INT32 len, INT32 flags, - const sockaddr *to, socklen_t tolen); - -//***************************************************************************** -// -//! mdnsAdvertiser -//! -//! @param[in] mdnsEnabled flag to enable/disable the mDNS feature -//! @param[in] deviceServiceName Service name as part of the published -//! canonical domain name -//! @param[in] deviceServiceNameLength Length of the service name - up to 32 chars -//! -//! -//! @return On success, zero is returned, return SOC_ERROR if socket was not -//! opened successfully, or if an error occurred. -//! -//! @brief Set CC3000 in mDNS advertiser mode in order to advertise itself. -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(mdnsAdvertiser)(UINT16 mdnsEnabled, CHAR * deviceServiceName, UINT16 deviceServiceNameLength); - - -//***************************************************************************** -// -//! getmssvalue -//! -//! @param[in] sd socket descriptor -//! -//! @return On success, returns the MSS value of a TCP connection -//! -//! @brief Returns the MSS value of a TCP connection according to the socket descriptor -// -//***************************************************************************** -extern UINT16 CC3000_EXPORT(getmssvalue) (INT32 sd); - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __SOCKET_H__ diff --git a/drivers/cc3000/inc/wlan.h b/drivers/cc3000/inc/wlan.h deleted file mode 100644 index 48d195b32a..0000000000 --- a/drivers/cc3000/inc/wlan.h +++ /dev/null @@ -1,518 +0,0 @@ -/***************************************************************************** -* -* wlan.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_WLAN_H__ -#define __CC3000_WLAN_H__ - -#include "cc3000_common.h" - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -#define WLAN_SEC_UNSEC (0) -#define WLAN_SEC_WEP (1) -#define WLAN_SEC_WPA (2) -#define WLAN_SEC_WPA2 (3) -//***************************************************************************** -// -//! \addtogroup wlan_api -//! @{ -// -//***************************************************************************** - - -//***************************************************************************** -// -//! wlan_init -//! -//! @param sWlanCB Asynchronous events callback. -//! 0 no event call back. -//! -call back parameters: -//! 1) event_type: HCI_EVNT_WLAN_UNSOL_CONNECT connect event, -//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event, -//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE config done, -//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp report, -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report OR -//! HCI_EVNT_WLAN_KEEPALIVE keepalive. -//! 2) data: pointer to extra data that received by the event -//! (NULL no data). -//! 3) length: data length. -//! -Events with extra data: -//! HCI_EVNT_WLAN_UNSOL_DHCP: 4 bytes IP, 4 bytes Mask, -//! 4 bytes default gateway, 4 bytes DHCP server and 4 bytes -//! for DNS server. -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT: 4 bytes Packets sent, -//! 4 bytes Packets received, 4 bytes Min round time, -//! 4 bytes Max round time and 4 bytes for Avg round time. -//! -//! @param sFWPatches 0 no patch or pointer to FW patches -//! @param sDriverPatches 0 no patch or pointer to driver patches -//! @param sBootLoaderPatches 0 no patch or pointer to bootloader patches -//! @param sReadWlanInterruptPin init callback. the callback read wlan -//! interrupt status. -//! @param sWlanInterruptEnable init callback. the callback enable wlan -//! interrupt. -//! @param sWlanInterruptDisable init callback. the callback disable wlan -//! interrupt. -//! @param sWriteWlanPin init callback. the callback write value -//! to device pin. -//! -//! @return none -//! -//! @sa wlan_set_event_mask , wlan_start , wlan_stop -//! -//! @brief Initialize wlan driver -//! -//! @warning This function must be called before ANY other wlan driver function -// -//***************************************************************************** -extern void wlan_init( tWlanCB sWlanCB, - tFWPatches sFWPatches, - tDriverPatches sDriverPatches, - tBootLoaderPatches sBootLoaderPatches, - tWlanReadInteruptPin sReadWlanInterruptPin, - tWlanInterruptEnable sWlanInterruptEnable, - tWlanInterruptDisable sWlanInterruptDisable, - tWriteWlanPin sWriteWlanPin); - - - -//***************************************************************************** -// -//! wlan_start -//! -//! @param usPatchesAvailableAtHost - flag to indicate if patches available -//! from host or from EEPROM. Due to the -//! fact the patches are burn to the EEPROM -//! using the patch programmer utility, the -//! patches will be available from the EEPROM -//! and not from the host. -//! -//! @return none -//! -//! @brief Start WLAN device. This function asserts the enable pin of -//! the device (WLAN_EN), starting the HW initialization process. -//! The function blocked until device Initialization is completed. -//! Function also configure patches (FW, driver or bootloader) -//! and calls appropriate device callbacks. -//! -//! @Note Prior calling the function wlan_init shall be called. -//! @Warning This function must be called after wlan_init and before any -//! other wlan API -//! @sa wlan_init , wlan_stop -//! -// -//***************************************************************************** -extern int wlan_start(UINT16 usPatchesAvailableAtHost); - -//***************************************************************************** -// -//! wlan_stop -//! -//! @param none -//! -//! @return none -//! -//! @brief Stop WLAN device by putting it into reset state. -//! -//! @sa wlan_start -// -//***************************************************************************** -extern void wlan_stop(void); - -//***************************************************************************** -// -//! wlan_connect -//! -//! @param sec_type security options: -//! WLAN_SEC_UNSEC, -//! WLAN_SEC_WEP (ASCII support only), -//! WLAN_SEC_WPA or WLAN_SEC_WPA2 -//! @param ssid up to 32 bytes and is ASCII SSID of the AP -//! @param ssid_len length of the SSID -//! @param bssid 6 bytes specified the AP bssid -//! @param key up to 32 bytes specified the AP security key -//! @param key_len key length -//! -//! @return On success, zero is returned. On error, negative is returned. -//! Note that even though a zero is returned on success to trigger -//! connection operation, it does not mean that CCC3000 is already -//! connected. An asynchronous "Connected" event is generated when -//! actual association process finishes and CC3000 is connected to -//! the AP. If DHCP is set, An asynchronous "DHCP" event is -//! generated when DHCP process is finish. -//! -//! -//! @brief Connect to AP -//! @warning Please Note that when connection to AP configured with security -//! type WEP, please confirm that the key is set as ASCII and not -//! as HEX. -//! @sa wlan_disconnect -// -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern INT32 wlan_connect(UINT32 ulSecType, CHAR *ssid, INT32 ssid_len, - UINT8 *bssid, UINT8 *key, INT32 key_len); -#else -extern INT32 wlan_connect(CHAR *ssid, INT32 ssid_len); - -#endif - -//***************************************************************************** -// -//! wlan_disconnect -//! -//! @return 0 disconnected done, other CC3000 already disconnected -//! -//! @brief Disconnect connection from AP. -//! -//! @sa wlan_connect -// -//***************************************************************************** - -extern INT32 wlan_disconnect(void); - -//***************************************************************************** -// -//! wlan_add_profile -//! -//! @param ulSecType WLAN_SEC_UNSEC,WLAN_SEC_WEP,WLAN_SEC_WPA,WLAN_SEC_WPA2 -//! @param ucSsid ssid SSID up to 32 bytes -//! @param ulSsidLen ssid length -//! @param ucBssid bssid 6 bytes -//! @param ulPriority ulPriority profile priority. Lowest priority:0. -//! @param ulPairwiseCipher_Or_TxKeyLen key length for WEP security -//! @param ulGroupCipher_TxKeyIndex key index -//! @param ulKeyMgmt KEY management -//! @param ucPf_OrKey security key -//! @param ulPassPhraseLen security key length for WPA\WPA2 -//! -//! @return On success, index (1-7) of the stored profile is returned. -//! On error, -1 is returned. -//! -//! @brief When auto start is enabled, the device connects to -//! station from the profiles table. Up to 7 profiles are supported. -//! If several profiles configured the device choose the highest -//! priority profile, within each priority group, device will choose -//! profile based on security policy, signal strength, etc -//! parameters. All the profiles are stored in CC3000 NVMEM. -//! -//! @sa wlan_ioctl_del_profile -// -//***************************************************************************** - -extern INT32 wlan_add_profile(UINT32 ulSecType, UINT8* ucSsid, - UINT32 ulSsidLen, - UINT8 *ucBssid, - UINT32 ulPriority, - UINT32 ulPairwiseCipher_Or_Key, - UINT32 ulGroupCipher_TxKeyLen, - UINT32 ulKeyMgmt, - UINT8* ucPf_OrKey, - UINT32 ulPassPhraseLen); - - - -//***************************************************************************** -// -//! wlan_ioctl_del_profile -//! -//! @param index number of profile to delete -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Delete WLAN profile -//! -//! @Note In order to delete all stored profile, set index to 255. -//! -//! @sa wlan_add_profile -// -//***************************************************************************** -extern INT32 wlan_ioctl_del_profile(UINT32 ulIndex); - -//***************************************************************************** -// -//! wlan_set_event_mask -//! -//! @param mask mask option: -//! HCI_EVNT_WLAN_UNSOL_CONNECT connect event -//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event -//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE smart config done -//! HCI_EVNT_WLAN_UNSOL_INIT init done -//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp event report -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report -//! HCI_EVNT_WLAN_KEEPALIVE keepalive -//! HCI_EVNT_WLAN_TX_COMPLETE - disable information on end of transmission -//! Saved: no. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Mask event according to bit mask. In case that event is -//! masked (1), the device will not send the masked event to host. -// -//***************************************************************************** -extern INT32 wlan_set_event_mask(UINT32 ulMask); - -//***************************************************************************** -// -//! wlan_ioctl_statusget -//! -//! @param none -//! -//! @return WLAN_STATUS_DISCONNECTED, WLAN_STATUS_SCANING, -//! STATUS_CONNECTING or WLAN_STATUS_CONNECTED -//! -//! @brief get wlan status: disconnected, scanning, connecting or connected -// -//***************************************************************************** -extern INT32 wlan_ioctl_statusget(void); - - -//***************************************************************************** -// -//! wlan_ioctl_set_connection_policy -//! -//! @param should_connect_to_open_ap enable(1), disable(0) connect to any -//! available AP. This parameter corresponds to the configuration of -//! item # 3 in the brief description. -//! @param should_use_fast_connect enable(1), disable(0). if enabled, tries -//! to connect to the last connected AP. This parameter corresponds -//! to the configuration of item # 1 in the brief description. -//! @param auto_start enable(1), disable(0) auto connect -//! after reset and periodically reconnect if needed. This -//! configuration configures option 2 in the above description. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief When auto is enabled, the device tries to connect according -//! the following policy: -//! 1) If fast connect is enabled and last connection is valid, -//! the device will try to connect to it without the scanning -//! procedure (fast). The last connection will be marked as -//! invalid, due to adding/removing profile. -//! 2) If profile exists, the device will try to connect it -//! (Up to seven profiles). -//! 3) If fast and profiles are not found, and open mode is -//! enabled, the device will try to connect to any AP. -//! * Note that the policy settings are stored in the CC3000 NVMEM. -//! -//! @sa wlan_add_profile , wlan_ioctl_del_profile -// -//***************************************************************************** -extern INT32 wlan_ioctl_set_connection_policy( - UINT32 should_connect_to_open_ap, - UINT32 should_use_fast_connect, - UINT32 ulUseProfiles); - -//***************************************************************************** -// -//! wlan_ioctl_get_scan_results -//! -//! @param[in] scan_timeout parameter not supported -//! @param[out] ucResults scan result (_wlan_full_scan_results_args_t) -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Gets entry from scan result table. -//! The scan results are returned one by one, and each entry -//! represents a single AP found in the area. The following is a -//! format of the scan result: -//! - 4 Bytes: number of networks found -//! - 4 Bytes: The status of the scan: 0 - aged results, -//! 1 - results valid, 2 - no results -//! - 42 bytes: Result entry, where the bytes are arranged as follows: -//! -//! - 1 bit isValid - is result valid or not -//! - 7 bits rssi - RSSI value; -//! - 2 bits: securityMode - security mode of the AP: -//! 0 - Open, 1 - WEP, 2 WPA, 3 WPA2 -//! - 6 bits: SSID name length -//! - 2 bytes: the time at which the entry has entered into -//! scans result table -//! - 32 bytes: SSID name -//! - 6 bytes: BSSID -//! -//! @Note scan_timeout, is not supported on this version. -//! -//! @sa wlan_ioctl_set_scan_params -// -//***************************************************************************** - - -extern INT32 wlan_ioctl_get_scan_results(UINT32 ulScanTimeout, - UINT8 *ucResults); - -//***************************************************************************** -// -//! wlan_ioctl_set_scan_params -//! -//! @param uiEnable - start/stop application scan: -//! 1 = start scan with default interval value of 10 min. -//! in order to set a different scan interval value apply the value -//! in milliseconds. minimum 1 second. 0=stop). Wlan reset -//! (wlan_stop() wlan_start()) is needed when changing scan interval -//! value. Saved: No -//! @param uiMinDwellTime minimum dwell time value to be used for each -//! channel, in milliseconds. Saved: yes -//! Recommended Value: 100 (Default: 20) -//! @param uiMaxDwellTime maximum dwell time value to be used for each -//! channel, in milliseconds. Saved: yes -//! Recommended Value: 100 (Default: 30) -//! @param uiNumOfProbeRequests max probe request between dwell time. -//! Saved: yes. Recommended Value: 5 (Default:2) -//! @param uiChannelMask bitwise, up to 13 channels (0x1fff). -//! Saved: yes. Default: 0x7ff -//! @param uiRSSIThreshold RSSI threshold. Saved: yes (Default: -80) -//! @param uiSNRThreshold NSR threshold. Saved: yes (Default: 0) -//! @param uiDefaultTxPower probe Tx power. Saved: yes (Default: 205) -//! @param aiIntervalList pointer to array with 16 entries (16 channels) -//! each entry (UINT32) holds timeout between periodic scan -//! (connection scan) - in milliseconds. Saved: yes. Default 2000ms. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief start and stop scan procedure. Set scan parameters. -//! -//! @Note uiDefaultTxPower, is not supported on this version. -//! -//! @sa wlan_ioctl_get_scan_results -// -//***************************************************************************** -extern INT32 wlan_ioctl_set_scan_params(UINT32 uiEnable, UINT32 - uiMinDwellTime,UINT32 uiMaxDwellTime, - UINT32 uiNumOfProbeRequests, - UINT32 uiChannelMask, - INT32 iRSSIThreshold,UINT32 uiSNRThreshold, - UINT32 uiDefaultTxPower, - UINT32 *aiIntervalList); - - -//***************************************************************************** -// -//! wlan_smart_config_start -//! -//! @param algoEncryptedFlag indicates whether the information is encrypted -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Start to acquire device profile. The device acquire its own -//! profile, if profile message is found. The acquired AP information -//! is stored in CC3000 EEPROM only in case AES128 encryption is used. -//! In case AES128 encryption is not used, a profile is created by -//! CC3000 internally. -//! -//! @Note An asynchronous event - Smart Config Done will be generated as soon -//! as the process finishes successfully. -//! -//! @sa wlan_smart_config_set_prefix , wlan_smart_config_stop -// -//***************************************************************************** -extern INT32 wlan_smart_config_start(UINT32 algoEncryptedFlag); - - -//***************************************************************************** -// -//! wlan_smart_config_stop -//! -//! @param algoEncryptedFlag indicates whether the information is encrypted -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Stop the acquire profile procedure -//! -//! @sa wlan_smart_config_start , wlan_smart_config_set_prefix -// -//***************************************************************************** -extern INT32 wlan_smart_config_stop(void); - -//***************************************************************************** -// -//! wlan_smart_config_set_prefix -//! -//! @param newPrefix 3 bytes identify the SSID prefix for the Smart Config. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Configure station ssid prefix. The prefix is used internally -//! in CC3000. It should always be TTT. -//! -//! @Note The prefix is stored in CC3000 NVMEM -//! -//! @sa wlan_smart_config_start , wlan_smart_config_stop -// -//***************************************************************************** -extern INT32 wlan_smart_config_set_prefix(CHAR* cNewPrefix); - -//***************************************************************************** -// -//! wlan_smart_config_process -//! -//! @param none -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief process the acquired data and store it as a profile. The acquired -//! AP information is stored in CC3000 EEPROM encrypted. -//! The encrypted data is decrypted and stored as a profile. -//! behavior is as defined by connection policy. -// -//***************************************************************************** -extern INT32 wlan_smart_config_process(void); - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** - - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_WLAN_H__ diff --git a/drivers/cc3000/src/cc3000_common.c b/drivers/cc3000/src/cc3000_common.c deleted file mode 100644 index b4c87848cf..0000000000 --- a/drivers/cc3000/src/cc3000_common.c +++ /dev/null @@ -1,164 +0,0 @@ -/***************************************************************************** -* -* cc3000_common.c.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -//***************************************************************************** -// -//! \addtogroup common_api -//! @{ -// -//***************************************************************************** -/****************************************************************************** -* -* Include files -* -*****************************************************************************/ - -#include "cc3000_common.h" -#include "socket.h" -#include "wlan.h" -#include "evnt_handler.h" - -//***************************************************************************** -// -//! __error__ -//! -//! @param pcFilename - file name, where error occurred -//! @param ulLine - line number, where error occurred -//! -//! @return none -//! -//! @brief stub function for ASSERT macro -// -//***************************************************************************** -void __error__(CHAR *pcFilename, UINT32 ulLine) -{ - //TODO full up function -} - - - -//***************************************************************************** -// -//! UINT32_TO_STREAM_f -//! -//! @param p pointer to the new stream -//! @param u32 pointer to the 32 bit -//! -//! @return pointer to the new stream -//! -//! @brief This function is used for copying 32 bit to stream -//! while converting to little endian format. -// -//***************************************************************************** - -UINT8* UINT32_TO_STREAM_f (UINT8 *p, UINT32 u32) -{ - *(p)++ = (UINT8)(u32); - *(p)++ = (UINT8)((u32) >> 8); - *(p)++ = (UINT8)((u32) >> 16); - *(p)++ = (UINT8)((u32) >> 24); - return p; -} - -//***************************************************************************** -// -//! UINT16_TO_STREAM_f -//! -//! @param p pointer to the new stream -//! @param u32 pointer to the 16 bit -//! -//! @return pointer to the new stream -//! -//! @brief This function is used for copying 16 bit to stream -//! while converting to little endian format. -// -//***************************************************************************** - -UINT8* UINT16_TO_STREAM_f (UINT8 *p, UINT16 u16) -{ - *(p)++ = (UINT8)(u16); - *(p)++ = (UINT8)((u16) >> 8); - return p; -} - -//***************************************************************************** -// -//! STREAM_TO_UINT16_f -//! -//! @param p pointer to the stream -//! @param offset offset in the stream -//! -//! @return pointer to the new 16 bit -//! -//! @brief This function is used for copying received stream to -//! 16 bit in little endian format. -// -//***************************************************************************** - -UINT16 STREAM_TO_UINT16_f(CHAR* p, UINT16 offset) -{ - return (UINT16)((UINT16)((UINT16) - (*(p + offset + 1)) << 8) + (UINT16)(*(p + offset))); -} - -//***************************************************************************** -// -//! STREAM_TO_UINT32_f -//! -//! @param p pointer to the stream -//! @param offset offset in the stream -//! -//! @return pointer to the new 32 bit -//! -//! @brief This function is used for copying received stream to -//! 32 bit in little endian format. -// -//***************************************************************************** - -UINT32 STREAM_TO_UINT32_f(CHAR* p, UINT16 offset) -{ - return (UINT32)((UINT32)((UINT32) - (*(p + offset + 3)) << 24) + (UINT32)((UINT32) - (*(p + offset + 2)) << 16) + (UINT32)((UINT32) - (*(p + offset + 1)) << 8) + (UINT32)(*(p + offset))); -} - - - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** diff --git a/drivers/cc3000/src/ccspi.c b/drivers/cc3000/src/ccspi.c deleted file mode 100644 index 1dcd618840..0000000000 --- a/drivers/cc3000/src/ccspi.c +++ /dev/null @@ -1,455 +0,0 @@ -/***************************************************************************** - * - * spi.c - CC3000 Host Driver Implementation. - * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ - -#include - -#include "py/runtime.h" -#include "pin.h" -#include "led.h" -#include "extint.h" -#include "spi.h" -#include "ccspi.h" -#include "evnt_handler.h" - -#if 0 // print debugging info -#include -#define DEBUG_printf(args...) printf(args) -#else // don't print debugging info -#define DEBUG_printf(args...) (void)0 -#endif - -// these need to be set to valid values before anything in this file will work -STATIC const spi_t *SPI_HANDLE = NULL; -STATIC const pin_obj_t *PIN_CS = NULL; -STATIC const pin_obj_t *PIN_EN = NULL; -STATIC const pin_obj_t *PIN_IRQ = NULL; - -#define CS_LOW() HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_RESET) -#define CS_HIGH() HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_SET) - -#define READ 3 -#define WRITE 1 - -#define HI(value) (((value) & 0xFF00) >> 8) -#define LO(value) ((value) & 0x00FF) - -#define SPI_TIMEOUT (1000) -#define HEADERS_SIZE_EVNT (SPI_HEADER_SIZE + 5) - -/* SPI bus states */ -#define eSPI_STATE_POWERUP (0) -#define eSPI_STATE_INITIALIZED (1) -#define eSPI_STATE_IDLE (2) -#define eSPI_STATE_WRITE_IRQ (3) -#define eSPI_STATE_WRITE_FIRST_PORTION (4) -#define eSPI_STATE_WRITE_EOT (5) -#define eSPI_STATE_READ_IRQ (6) -#define eSPI_STATE_READ_FIRST_PORTION (7) -#define eSPI_STATE_READ_EOT (8) - -// The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size) -// for the purpose of detection of the overrun. The location of the memory where the magic number -// resides shall never be written. In case it is written - the overrun occured and either recevie function -// or send function will stuck forever. -#define CC3000_BUFFER_MAGIC_NUMBER (0xDE) - -typedef struct { - gcSpiHandleRx SPIRxHandler; - unsigned short usTxPacketLength; - unsigned short usRxPacketLength; - unsigned long ulSpiState; - unsigned char *pTxPacket; - unsigned char *pRxPacket; -} tSpiInformation; -STATIC tSpiInformation sSpiInformation; - -STATIC char spi_buffer[CC3000_RX_BUFFER_SIZE]; -unsigned char wlan_tx_buffer[CC3000_TX_BUFFER_SIZE]; - -STATIC const mp_obj_fun_builtin_fixed_t irq_callback_obj; - -// set the pins to use to communicate with the CC3000 -// the arguments must be of type pin_obj_t* and SPI_HandleTypeDef* -void SpiInit(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq) { - SPI_HANDLE = spi; - PIN_CS = pin_cs; - PIN_EN = pin_en; - PIN_IRQ = pin_irq; -} - -void SpiClose(void) -{ - if (sSpiInformation.pRxPacket) { - sSpiInformation.pRxPacket = 0; - } - - tSLInformation.WlanInterruptDisable(); - - //HAL_SPI_DeInit(SPI_HANDLE); -} - -void SpiOpen(gcSpiHandleRx pfRxHandler) -{ - DEBUG_printf("SpiOpen\n"); - - /* initialize SPI state */ - sSpiInformation.ulSpiState = eSPI_STATE_POWERUP; - sSpiInformation.SPIRxHandler = pfRxHandler; - sSpiInformation.usTxPacketLength = 0; - sSpiInformation.pTxPacket = NULL; - sSpiInformation.pRxPacket = (unsigned char *)spi_buffer; - sSpiInformation.usRxPacketLength = 0; - spi_buffer[CC3000_RX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER; - wlan_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER; - - /* SPI configuration */ - SPI_InitTypeDef *init = &SPI_HANDLE->spi->Init; - init->Mode = SPI_MODE_MASTER; - init->Direction = SPI_DIRECTION_2LINES; - init->DataSize = SPI_DATASIZE_8BIT; - init->CLKPolarity = SPI_POLARITY_LOW; - init->CLKPhase = SPI_PHASE_2EDGE; - init->NSS = SPI_NSS_SOFT; - init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; - init->FirstBit = SPI_FIRSTBIT_MSB; - init->TIMode = SPI_TIMODE_DISABLED; - init->CRCCalculation = SPI_CRCCALCULATION_DISABLED; - init->CRCPolynomial = 7; - spi_init(SPI_HANDLE, false); - - // configure wlan CS and EN pins - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.Speed = GPIO_SPEED_FAST; - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Alternate = 0; - - GPIO_InitStructure.Pin = PIN_CS->pin_mask; - HAL_GPIO_Init(PIN_CS->gpio, &GPIO_InitStructure); - - GPIO_InitStructure.Pin = PIN_EN->pin_mask; - HAL_GPIO_Init(PIN_EN->gpio, &GPIO_InitStructure); - - HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_SET); - HAL_GPIO_WritePin(PIN_EN->gpio, PIN_EN->pin_mask, GPIO_PIN_RESET); - - /* do a dummy read, this ensures SCLK is low before - actual communications start, it might be required */ - CS_LOW(); - uint8_t buf[1]; - HAL_SPI_Receive(SPI_HANDLE->spi, buf, sizeof(buf), SPI_TIMEOUT); - CS_HIGH(); - - // register EXTI - extint_register((mp_obj_t)PIN_IRQ, GPIO_MODE_IT_FALLING, GPIO_PULLUP, (mp_obj_t)&irq_callback_obj, true); - extint_enable(PIN_IRQ->pin); - - DEBUG_printf("SpiOpen finished; IRQ.pin=%d IRQ_LINE=%d\n", PIN_IRQ->pin, PIN_IRQ->pin); -} - -long ReadWlanInterruptPin(void) -{ - return HAL_GPIO_ReadPin(PIN_IRQ->gpio, PIN_IRQ->pin_mask); -} - -void WriteWlanPin(unsigned char val) -{ - HAL_GPIO_WritePin(PIN_EN->gpio, PIN_EN->pin_mask, - (WLAN_ENABLE)? GPIO_PIN_SET:GPIO_PIN_RESET); -} - -STATIC void SpiWriteDataSynchronous(unsigned char *data, unsigned short size) -{ - DEBUG_printf("SpiWriteDataSynchronous(data=%p [%x %x %x %x], size=%u)\n", data, data[0], data[1], data[2], data[3], size); - __disable_irq(); - if (HAL_SPI_TransmitReceive(SPI_HANDLE->spi, data, data, size, SPI_TIMEOUT) != HAL_OK) { - //BREAK(); - } - __enable_irq(); - DEBUG_printf(" - rx data = [%x %x %x %x]\n", data[0], data[1], data[2], data[3]); -} - -STATIC void SpiReadDataSynchronous(unsigned char *data, unsigned short size) -{ - memset(data, READ, size); - __disable_irq(); - if (HAL_SPI_TransmitReceive(SPI_HANDLE->spi, data, data, size, SPI_TIMEOUT) != HAL_OK) { - //BREAK(); - } - __enable_irq(); -} - -STATIC void __delay_cycles(volatile int x) -{ - x *= 6; // for 168 MHz CPU - while (x--); -} - -STATIC long SpiFirstWrite(unsigned char *ucBuf, unsigned short usLength) -{ - DEBUG_printf("SpiFirstWrite %lu\n", sSpiInformation.ulSpiState); - - CS_LOW(); - - // Assuming we are running on 24 MHz ~50 micro delay is 1200 cycles; - __delay_cycles(1200); - - // SPI writes first 4 bytes of data - SpiWriteDataSynchronous(ucBuf, 4); - - __delay_cycles(1200); - - SpiWriteDataSynchronous(ucBuf + 4, usLength - 4); - - // From this point on - operate in a regular way - sSpiInformation.ulSpiState = eSPI_STATE_IDLE; - - CS_HIGH(); - - return(0); -} - -long SpiWrite(unsigned char *pUserBuffer, unsigned short usLength) -{ - DEBUG_printf("SpiWrite %lu\n", sSpiInformation.ulSpiState); - - unsigned char ucPad = 0; - - // Figure out the total length of the packet in order to figure out if there - // is padding or not - if(!(usLength & 0x0001)) { - ucPad++; - } - - pUserBuffer[0] = WRITE; - pUserBuffer[1] = HI(usLength + ucPad); - pUserBuffer[2] = LO(usLength + ucPad); - pUserBuffer[3] = 0; - pUserBuffer[4] = 0; - - usLength += (SPI_HEADER_SIZE + ucPad); - - // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size) - // for the purpose of detection of the overrun. If the magic number is overriten - buffer overrun - // occurred - and we will stuck here forever! - if (wlan_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) { - while (1); - } - - if (sSpiInformation.ulSpiState == eSPI_STATE_POWERUP) { - while (sSpiInformation.ulSpiState != eSPI_STATE_INITIALIZED); - } - - if (sSpiInformation.ulSpiState == eSPI_STATE_INITIALIZED) { - // This is time for first TX/RX transactions over SPI: - // the IRQ is down - so need to send read buffer size command - SpiFirstWrite(pUserBuffer, usLength); - } else { - // - // We need to prevent here race that can occur in case 2 back to back packets are sent to the - // device, so the state will move to IDLE and once again to not IDLE due to IRQ - // - tSLInformation.WlanInterruptDisable(); - - while (sSpiInformation.ulSpiState != eSPI_STATE_IDLE); - - sSpiInformation.ulSpiState = eSPI_STATE_WRITE_IRQ; - sSpiInformation.pTxPacket = pUserBuffer; - sSpiInformation.usTxPacketLength = usLength; - - // Assert the CS line and wait till SSI IRQ line is active and then initialize write operation - CS_LOW(); - - // Re-enable IRQ - if it was not disabled - this is not a problem... - tSLInformation.WlanInterruptEnable(); - - // check for a missing interrupt between the CS assertion and enabling back the interrupts - if (tSLInformation.ReadWlanInterruptPin() == 0) { - SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength); - - sSpiInformation.ulSpiState = eSPI_STATE_IDLE; - - CS_HIGH(); - } - } - - // Due to the fact that we are currently implementing a blocking situation - // here we will wait till end of transaction - while (eSPI_STATE_IDLE != sSpiInformation.ulSpiState); - - return(0); -} - -#if 0 -unused -STATIC void SpiReadPacket(void) -{ - int length; - - /* read SPI header */ - SpiReadDataSynchronous(sSpiInformation.pRxPacket, SPI_HEADER_SIZE); - - /* parse data length */ - STREAM_TO_UINT8(sSpiInformation.pRxPacket, SPI_HEADER_SIZE-1, length); - - /* read the remainder of the packet */ - SpiReadDataSynchronous(sSpiInformation.pRxPacket + SPI_HEADER_SIZE, length); - - sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT; -} -#endif - -STATIC void SpiReadHeader(void) -{ - SpiReadDataSynchronous(sSpiInformation.pRxPacket, 10); -} - -STATIC void SpiTriggerRxProcessing(void) -{ - SpiPauseSpi(); - CS_HIGH(); - - // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size) - // for the purpose of detection of the overrun. If the magic number is overriten - buffer overrun - // occurred - and we will stuck here forever! - if (sSpiInformation.pRxPacket[CC3000_RX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) { - while (1); - } - - sSpiInformation.ulSpiState = eSPI_STATE_IDLE; - sSpiInformation.SPIRxHandler(sSpiInformation.pRxPacket + SPI_HEADER_SIZE); -} - - -STATIC long SpiReadDataCont(void) -{ - long data_to_recv=0; - unsigned char *evnt_buff, type; - - //determine what type of packet we have - evnt_buff = sSpiInformation.pRxPacket; - STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET, type); - - switch (type) { - case HCI_TYPE_DATA:{ - // We need to read the rest of data.. - STREAM_TO_UINT16((char *)(evnt_buff + SPI_HEADER_SIZE), - HCI_DATA_LENGTH_OFFSET, data_to_recv); - if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1)) { - data_to_recv++; - } - - if (data_to_recv) { - SpiReadDataSynchronous(evnt_buff + 10, data_to_recv); - } - break; - } - case HCI_TYPE_EVNT: { - // Calculate the rest length of the data - STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), - HCI_EVENT_LENGTH_OFFSET, data_to_recv); - data_to_recv -= 1; - - // Add padding byte if needed - if ((HEADERS_SIZE_EVNT + data_to_recv) & 1) { - data_to_recv++; - } - - if (data_to_recv) { - SpiReadDataSynchronous(evnt_buff + 10, data_to_recv); - } - - sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT; - break; - } - } - - return 0; -} - -STATIC void SSIContReadOperation(void) -{ - // The header was read - continue with the payload read - if (!SpiReadDataCont()) { - /* All the data was read - finalize handling by switching - to the task and calling from task Event Handler */ - SpiTriggerRxProcessing(); - } -} - -STATIC mp_obj_t irq_callback(mp_obj_t line) { - DEBUG_printf("<< IRQ; state=%lu >>\n", sSpiInformation.ulSpiState); - switch (sSpiInformation.ulSpiState) { - case eSPI_STATE_POWERUP: - /* This means IRQ line was low call a callback of HCI Layer to inform on event */ - DEBUG_printf(" - POWERUP\n"); - sSpiInformation.ulSpiState = eSPI_STATE_INITIALIZED; - break; - case eSPI_STATE_IDLE: - DEBUG_printf(" - IDLE\n"); - sSpiInformation.ulSpiState = eSPI_STATE_READ_IRQ; - - /* IRQ line goes down - we are start reception */ - CS_LOW(); - - // Wait for TX/RX Compete which will come as DMA interrupt - SpiReadHeader(); - - sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT; - - SSIContReadOperation(); - break; - case eSPI_STATE_WRITE_IRQ: - DEBUG_printf(" - WRITE IRQ\n"); - SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength); - - sSpiInformation.ulSpiState = eSPI_STATE_IDLE; - - CS_HIGH(); - break; - } - return mp_const_none; -} - -STATIC MP_DEFINE_CONST_FUN_OBJ_1(irq_callback_obj, irq_callback); - -void SpiPauseSpi(void) { - DEBUG_printf("SpiPauseSpi\n"); - extint_disable(PIN_IRQ->pin); -} - -void SpiResumeSpi(void) { - DEBUG_printf("SpiResumeSpi\n"); - extint_enable(PIN_IRQ->pin); -} diff --git a/drivers/cc3000/src/evnt_handler.c b/drivers/cc3000/src/evnt_handler.c deleted file mode 100644 index d430bbfdad..0000000000 --- a/drivers/cc3000/src/evnt_handler.c +++ /dev/null @@ -1,849 +0,0 @@ -/***************************************************************************** -* -* evnt_handler.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -//***************************************************************************** -// -//! \addtogroup evnt_handler_api -//! @{ -// -//****************************************************************************** - -//****************************************************************************** -// INCLUDE FILES -//****************************************************************************** - -#include "cc3000_common.h" -#include "string.h" -#include "hci.h" -#include "evnt_handler.h" -#include "wlan.h" -#include "socket.h" -#include "netapp.h" -#include "ccspi.h" - - - -//***************************************************************************** -// COMMON DEFINES -//***************************************************************************** - -#define FLOW_CONTROL_EVENT_HANDLE_OFFSET (0) -#define FLOW_CONTROL_EVENT_BLOCK_MODE_OFFSET (1) -#define FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET (2) -#define FLOW_CONTROL_EVENT_SIZE (4) - -#define BSD_RSP_PARAMS_SOCKET_OFFSET (0) -#define BSD_RSP_PARAMS_STATUS_OFFSET (4) - -#define GET_HOST_BY_NAME_RETVAL_OFFSET (0) -#define GET_HOST_BY_NAME_ADDR_OFFSET (4) - -#define ACCEPT_SD_OFFSET (0) -#define ACCEPT_RETURN_STATUS_OFFSET (4) -#define ACCEPT_ADDRESS__OFFSET (8) - -#define SL_RECEIVE_SD_OFFSET (0) -#define SL_RECEIVE_NUM_BYTES_OFFSET (4) -#define SL_RECEIVE__FLAGS__OFFSET (8) - - -#define SELECT_STATUS_OFFSET (0) -#define SELECT_READFD_OFFSET (4) -#define SELECT_WRITEFD_OFFSET (8) -#define SELECT_EXFD_OFFSET (12) - - -#define NETAPP_IPCONFIG_IP_OFFSET (0) -#define NETAPP_IPCONFIG_SUBNET_OFFSET (4) -#define NETAPP_IPCONFIG_GW_OFFSET (8) -#define NETAPP_IPCONFIG_DHCP_OFFSET (12) -#define NETAPP_IPCONFIG_DNS_OFFSET (16) -#define NETAPP_IPCONFIG_MAC_OFFSET (20) -#define NETAPP_IPCONFIG_SSID_OFFSET (26) - -#define NETAPP_IPCONFIG_IP_LENGTH (4) -#define NETAPP_IPCONFIG_MAC_LENGTH (6) -#define NETAPP_IPCONFIG_SSID_LENGTH (32) - - -#define NETAPP_PING_PACKETS_SENT_OFFSET (0) -#define NETAPP_PING_PACKETS_RCVD_OFFSET (4) -#define NETAPP_PING_MIN_RTT_OFFSET (8) -#define NETAPP_PING_MAX_RTT_OFFSET (12) -#define NETAPP_PING_AVG_RTT_OFFSET (16) - -#define GET_SCAN_RESULTS_TABlE_COUNT_OFFSET (0) -#define GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET (4) -#define GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET (8) -#define GET_SCAN_RESULTS_FRAME_TIME_OFFSET (10) -#define GET_SCAN_RESULTS_SSID_MAC_LENGTH (38) - -#define GET_MSS_VAL_RETVAL_OFFSET (0) - -//***************************************************************************** -// GLOBAL VARAIABLES -//***************************************************************************** - -UINT32 socket_active_status = SOCKET_STATUS_INIT_VAL; - - -//***************************************************************************** -// Prototypes for the static functions -//***************************************************************************** - -static INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent); - -static void update_socket_active_status(CHAR *resp_params); - - -//***************************************************************************** -// -//! hci_unsol_handle_patch_request -//! -//! @param event_hdr event header -//! -//! @return none -//! -//! @brief Handle unsolicited event from type patch request -// -//***************************************************************************** -void hci_unsol_handle_patch_request(CHAR *event_hdr) -{ - CHAR *params = (CHAR *)(event_hdr) + HCI_EVENT_HEADER_SIZE; - UINT32 ucLength = 0; - CHAR *patch; - - switch (*params) - { - case HCI_EVENT_PATCHES_DRV_REQ: - - if (tSLInformation.sDriverPatches) - { - patch = tSLInformation.sDriverPatches(&ucLength); - - if (patch) - { - hci_patch_send(HCI_EVENT_PATCHES_DRV_REQ, - tSLInformation.pucTxCommandBuffer, patch, ucLength); - return; - } - } - - // Send 0 length Patches response event - hci_patch_send(HCI_EVENT_PATCHES_DRV_REQ, - tSLInformation.pucTxCommandBuffer, 0, 0); - break; - - case HCI_EVENT_PATCHES_FW_REQ: - - if (tSLInformation.sFWPatches) - { - patch = tSLInformation.sFWPatches(&ucLength); - - // Build and send a patch - if (patch) - { - hci_patch_send(HCI_EVENT_PATCHES_FW_REQ, - tSLInformation.pucTxCommandBuffer, patch, ucLength); - return; - } - } - - // Send 0 length Patches response event - hci_patch_send(HCI_EVENT_PATCHES_FW_REQ, - tSLInformation.pucTxCommandBuffer, 0, 0); - break; - - case HCI_EVENT_PATCHES_BOOTLOAD_REQ: - - if (tSLInformation.sBootLoaderPatches) - { - patch = tSLInformation.sBootLoaderPatches(&ucLength); - - if (patch) - { - hci_patch_send(HCI_EVENT_PATCHES_BOOTLOAD_REQ, - tSLInformation.pucTxCommandBuffer, patch, ucLength); - return; - } - } - - // Send 0 length Patches response event - hci_patch_send(HCI_EVENT_PATCHES_BOOTLOAD_REQ, - tSLInformation.pucTxCommandBuffer, 0, 0); - break; - } -} - - - -//***************************************************************************** -// -//! hci_event_handler -//! -//! @param pRetParams incoming data buffer -//! @param from from information (in case of data received) -//! @param fromlen from information length (in case of data received) -//! -//! @return none -//! -//! @brief Parse the incoming events packets and issues corresponding -//! event handler from global array of handlers pointers -// -//***************************************************************************** - - -UINT8 * hci_event_handler(void *pRetParams, UINT8 *from, UINT8 *fromlen) -{ - UINT8 *pucReceivedData, ucArgsize; - UINT16 usLength; - UINT8 *pucReceivedParams; - UINT16 usReceivedEventOpcode = 0; - UINT32 retValue32; - UINT8 * RecvParams; - UINT8 *RetParams; - - - while (1) - { - if (tSLInformation.usEventOrDataReceived != 0) - { - pucReceivedData = (tSLInformation.pucReceivedData); - - if (*pucReceivedData == HCI_TYPE_EVNT) - { - // Event Received - STREAM_TO_UINT16((CHAR *)pucReceivedData, HCI_EVENT_OPCODE_OFFSET, - usReceivedEventOpcode); - pucReceivedParams = pucReceivedData + HCI_EVENT_HEADER_SIZE; - RecvParams = pucReceivedParams; - RetParams = pRetParams; - - // In case unsolicited event received - here the handling finished - if (hci_unsol_event_handler((CHAR *)pucReceivedData) == 0) - { - STREAM_TO_UINT8(pucReceivedData, HCI_DATA_LENGTH_OFFSET, usLength); - - switch(usReceivedEventOpcode) - { - case HCI_CMND_READ_BUFFER_SIZE: - { - STREAM_TO_UINT8((CHAR *)pucReceivedParams, 0, - tSLInformation.usNumberOfFreeBuffers); - STREAM_TO_UINT16((CHAR *)pucReceivedParams, 1, - tSLInformation.usSlBufferLength); - } - break; - - case HCI_CMND_WLAN_CONFIGURE_PATCH: - case HCI_NETAPP_DHCP: - case HCI_NETAPP_PING_SEND: - case HCI_NETAPP_PING_STOP: - case HCI_NETAPP_ARP_FLUSH: - case HCI_NETAPP_SET_DEBUG_LEVEL: - case HCI_NETAPP_SET_TIMERS: - case HCI_EVNT_NVMEM_READ: - case HCI_EVNT_NVMEM_CREATE_ENTRY: - case HCI_CMND_NVMEM_WRITE_PATCH: - case HCI_NETAPP_PING_REPORT: - case HCI_EVNT_MDNS_ADVERTISE: - - STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET - ,*(UINT8 *)pRetParams); - break; - - case HCI_CMND_SETSOCKOPT: - case HCI_CMND_WLAN_CONNECT: - case HCI_CMND_WLAN_IOCTL_STATUSGET: - case HCI_EVNT_WLAN_IOCTL_ADD_PROFILE: - case HCI_CMND_WLAN_IOCTL_DEL_PROFILE: - case HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY: - case HCI_CMND_WLAN_IOCTL_SET_SCANPARAM: - case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START: - case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP: - case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX: - case HCI_CMND_EVENT_MASK: - case HCI_EVNT_WLAN_DISCONNECT: - case HCI_EVNT_SOCKET: - case HCI_EVNT_BIND: - case HCI_CMND_LISTEN: - case HCI_EVNT_CLOSE_SOCKET: - case HCI_EVNT_CONNECT: - case HCI_EVNT_NVMEM_WRITE: - - STREAM_TO_UINT32((CHAR *)pucReceivedParams,0 - ,*(UINT32 *)pRetParams); - break; - - case HCI_EVNT_READ_SP_VERSION: - - STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET - ,*(UINT8 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 1; - STREAM_TO_UINT32((CHAR *)pucReceivedParams, 0, retValue32); - UINT32_TO_STREAM((UINT8 *)pRetParams, retValue32); - break; - - case HCI_EVNT_BSD_GETHOSTBYNAME: - - STREAM_TO_UINT32((CHAR *)pucReceivedParams - ,GET_HOST_BY_NAME_RETVAL_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams - ,GET_HOST_BY_NAME_ADDR_OFFSET,*(UINT32 *)pRetParams); - break; - - case HCI_EVNT_GETMSSVALUE: - - STREAM_TO_UINT16((CHAR *)pucReceivedParams - ,GET_MSS_VAL_RETVAL_OFFSET,*(UINT16 *)pRetParams); - - break; - - case HCI_EVNT_ACCEPT: - { - STREAM_TO_UINT32((CHAR *)pucReceivedParams,ACCEPT_SD_OFFSET - ,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams - ,ACCEPT_RETURN_STATUS_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - - //This argument returns in network order - memcpy((UINT8 *)pRetParams, - pucReceivedParams + ACCEPT_ADDRESS__OFFSET, sizeof(sockaddr)); - break; - } - - case HCI_EVNT_RECV: - case HCI_EVNT_RECVFROM: - { - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE__FLAGS__OFFSET,*(UINT32 *)pRetParams); - - if(((tBsdReadReturnParams *)pRetParams)->iNumberOfBytes == ERROR_SOCKET_INACTIVE) - { - set_socket_active_status(((tBsdReadReturnParams *)pRetParams)->iSocketDescriptor,SOCKET_STATUS_INACTIVE); - } - break; - } - - case HCI_EVNT_SEND: - case HCI_EVNT_SENDTO: - { - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - - break; - } - - case HCI_EVNT_SELECT: - { - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_STATUS_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_READFD_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_WRITEFD_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_EXFD_OFFSET,*(UINT32 *)pRetParams); - break; - } - - case HCI_CMND_GETSOCKOPT: - - STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET,((tBsdGetSockOptReturnParams *)pRetParams)->iStatus); - //This argument returns in network order - memcpy((UINT8 *)pRetParams, pucReceivedParams, 4); - break; - - case HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS: - - STREAM_TO_UINT32((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_TABlE_COUNT_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT16((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 2; - STREAM_TO_UINT16((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_FRAME_TIME_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 2; - memcpy((UINT8 *)pRetParams, (CHAR *)(pucReceivedParams + GET_SCAN_RESULTS_FRAME_TIME_OFFSET + 2), GET_SCAN_RESULTS_SSID_MAC_LENGTH); - break; - - case HCI_CMND_SIMPLE_LINK_START: - break; - - case HCI_NETAPP_IPCONFIG: - - //Read IP address - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); - RecvParams += 4; - - //Read subnet - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); - RecvParams += 4; - - //Read default GW - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); - RecvParams += 4; - - //Read DHCP server - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); - RecvParams += 4; - - //Read DNS server - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); - RecvParams += 4; - - //Read Mac address - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_MAC_LENGTH); - RecvParams += 6; - - //Read SSID - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_SSID_LENGTH); - - } - } - - if (usReceivedEventOpcode == tSLInformation.usRxEventOpcode) - { - tSLInformation.usRxEventOpcode = 0; - } - } - else - { - pucReceivedParams = pucReceivedData; - STREAM_TO_UINT8((CHAR *)pucReceivedData, HCI_PACKET_ARGSIZE_OFFSET, ucArgsize); - - STREAM_TO_UINT16((CHAR *)pucReceivedData, HCI_PACKET_LENGTH_OFFSET, usLength); - - // Data received: note that the only case where from and from length - // are not null is in recv from, so fill the args accordingly - if (from) - { - STREAM_TO_UINT32((CHAR *)(pucReceivedData + HCI_DATA_HEADER_SIZE), BSD_RECV_FROM_FROMLEN_OFFSET, *(UINT32 *)fromlen); - memcpy(from, (pucReceivedData + HCI_DATA_HEADER_SIZE + BSD_RECV_FROM_FROM_OFFSET) ,*fromlen); - } - - memcpy(pRetParams, pucReceivedParams + HCI_DATA_HEADER_SIZE + ucArgsize, - usLength - ucArgsize); - - tSLInformation.usRxDataPending = 0; - } - - tSLInformation.usEventOrDataReceived = 0; - - SpiResumeSpi(); - - // Since we are going to TX - we need to handle this event after the - // ResumeSPi since we need interrupts - if ((*pucReceivedData == HCI_TYPE_EVNT) && - (usReceivedEventOpcode == HCI_EVNT_PATCHES_REQ)) - { - hci_unsol_handle_patch_request((CHAR *)pucReceivedData); - } - - if ((tSLInformation.usRxEventOpcode == 0) && (tSLInformation.usRxDataPending == 0)) - { - return NULL; - } - } - } - -} - -//***************************************************************************** -// -//! hci_unsol_event_handler -//! -//! @param event_hdr event header -//! -//! @return 1 if event supported and handled -//! 0 if event is not supported -//! -//! @brief Handle unsolicited events -// -//***************************************************************************** -INT32 hci_unsol_event_handler(CHAR *event_hdr) -{ - CHAR * data = NULL; - INT32 event_type; - UINT32 NumberOfReleasedPackets; - UINT32 NumberOfSentPackets; - - STREAM_TO_UINT16(event_hdr, HCI_EVENT_OPCODE_OFFSET,event_type); - - if (event_type & HCI_EVNT_UNSOL_BASE) - { - switch(event_type) - { - - case HCI_EVNT_DATA_UNSOL_FREE_BUFF: - { - hci_event_unsol_flowcontrol_handler(event_hdr); - - NumberOfReleasedPackets = tSLInformation.NumberOfReleasedPackets; - NumberOfSentPackets = tSLInformation.NumberOfSentPackets; - - if (NumberOfReleasedPackets == NumberOfSentPackets) - { - if (tSLInformation.InformHostOnTxComplete) - { - tSLInformation.sWlanCB(HCI_EVENT_CC3000_CAN_SHUT_DOWN, NULL, 0); - } - } - return 1; - - } - } - } - - if(event_type & HCI_EVNT_WLAN_UNSOL_BASE) - { - switch(event_type) - { - case HCI_EVNT_WLAN_KEEPALIVE: - case HCI_EVNT_WLAN_UNSOL_CONNECT: - case HCI_EVNT_WLAN_UNSOL_DISCONNECT: - case HCI_EVNT_WLAN_UNSOL_INIT: - case HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE: - - if( tSLInformation.sWlanCB ) - { - tSLInformation.sWlanCB(event_type, 0, 0); - } - break; - - case HCI_EVNT_WLAN_UNSOL_DHCP: - { - UINT8 params[NETAPP_IPCONFIG_MAC_OFFSET + 1]; // extra byte is for the status - UINT8 *recParams = params; - - data = (CHAR*)(event_hdr) + HCI_EVENT_HEADER_SIZE; - - //Read IP address - STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); - data += 4; - //Read subnet - STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); - data += 4; - //Read default GW - STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); - data += 4; - //Read DHCP server - STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); - data += 4; - //Read DNS server - STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); - // read the status - STREAM_TO_UINT8(event_hdr, HCI_EVENT_STATUS_OFFSET, *recParams); - - - if( tSLInformation.sWlanCB ) - { - tSLInformation.sWlanCB(event_type, (CHAR *)params, sizeof(params)); - } - } - break; - - case HCI_EVNT_WLAN_ASYNC_PING_REPORT: - { - netapp_pingreport_args_t params; - data = (CHAR*)(event_hdr) + HCI_EVENT_HEADER_SIZE; - STREAM_TO_UINT32(data, NETAPP_PING_PACKETS_SENT_OFFSET, params.packets_sent); - STREAM_TO_UINT32(data, NETAPP_PING_PACKETS_RCVD_OFFSET, params.packets_received); - STREAM_TO_UINT32(data, NETAPP_PING_MIN_RTT_OFFSET, params.min_round_time); - STREAM_TO_UINT32(data, NETAPP_PING_MAX_RTT_OFFSET, params.max_round_time); - STREAM_TO_UINT32(data, NETAPP_PING_AVG_RTT_OFFSET, params.avg_round_time); - - if( tSLInformation.sWlanCB ) - { - tSLInformation.sWlanCB(event_type, (CHAR *)¶ms, sizeof(params)); - } - } - break; - case HCI_EVNT_BSD_TCP_CLOSE_WAIT: - { - data = (CHAR *)(event_hdr) + HCI_EVENT_HEADER_SIZE; - if( tSLInformation.sWlanCB ) - { - //data[0] represents the socket id, for which FIN was received by remote. - //Upon receiving this event, the user can close the socket, or else the - //socket will be closed after inacvitity timeout (by default 60 seconds) - tSLInformation.sWlanCB(event_type, data, 1); - } - } - break; - - //'default' case which means "event not supported" - default: - return (0); - } - return(1); - } - - if ((event_type == HCI_EVNT_SEND) || (event_type == HCI_EVNT_SENDTO) - || (event_type == HCI_EVNT_WRITE)) - { - CHAR *pArg; - INT32 status; - - pArg = M_BSD_RESP_PARAMS_OFFSET(event_hdr); - STREAM_TO_UINT32(pArg, BSD_RSP_PARAMS_STATUS_OFFSET,status); - - if (ERROR_SOCKET_INACTIVE == status) - { - // The only synchronous event that can come from SL device in form of - // command complete is "Command Complete" on data sent, in case SL device - // was unable to transmit - STREAM_TO_UINT8(event_hdr, HCI_EVENT_STATUS_OFFSET, tSLInformation.slTransmitDataError); - update_socket_active_status(M_BSD_RESP_PARAMS_OFFSET(event_hdr)); - - return (1); - } - else - return (0); - } - - //handle a case where unsolicited event arrived, but was not handled by any of the cases above - if ((event_type != tSLInformation.usRxEventOpcode) && (event_type != HCI_EVNT_PATCHES_REQ)) - { - return(1); - } - - return(0); -} - -//***************************************************************************** -// -//! hci_unsolicited_event_handler -//! -//! @param None -//! -//! @return ESUCCESS if successful, EFAIL if an error occurred -//! -//! @brief Parse the incoming unsolicited event packets and issues -//! corresponding event handler. -// -//***************************************************************************** -INT32 hci_unsolicited_event_handler(void) -{ - UINT32 res = 0; - UINT8 *pucReceivedData; - - if (tSLInformation.usEventOrDataReceived != 0) - { - pucReceivedData = (tSLInformation.pucReceivedData); - - if (*pucReceivedData == HCI_TYPE_EVNT) - { - - // In case unsolicited event received - here the handling finished - if (hci_unsol_event_handler((CHAR *)pucReceivedData) == 1) - { - - // There was an unsolicited event received - we can release the buffer - // and clean the event received - tSLInformation.usEventOrDataReceived = 0; - - res = 1; - SpiResumeSpi(); - } - } - } - - return res; -} - -//***************************************************************************** -// -//! set_socket_active_status -//! -//! @param Sd -//! @param Status -//! @return none -//! -//! @brief Check if the socket ID and status are valid and set -//! accordingly the global socket status -// -//***************************************************************************** -void set_socket_active_status(INT32 Sd, INT32 Status) -{ - if(M_IS_VALID_SD(Sd) && M_IS_VALID_STATUS(Status)) - { - socket_active_status &= ~(1 << Sd); /* clean socket's mask */ - socket_active_status |= (Status << Sd); /* set new socket's mask */ - } -} - - -//***************************************************************************** -// -//! hci_event_unsol_flowcontrol_handler -//! -//! @param pEvent pointer to the string contains parameters for IPERF -//! @return ESUCCESS if successful, EFAIL if an error occurred -//! -//! @brief Called in case unsolicited event from type -//! HCI_EVNT_DATA_UNSOL_FREE_BUFF has received. -//! Keep track on the number of packets transmitted and update the -//! number of free buffer in the SL device. -// -//***************************************************************************** -INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent) -{ - - INT32 temp, value; - UINT16 i; - UINT16 pusNumberOfHandles=0; - CHAR *pReadPayload; - - STREAM_TO_UINT16((CHAR *)pEvent,HCI_EVENT_HEADER_SIZE,pusNumberOfHandles); - pReadPayload = ((CHAR *)pEvent + - HCI_EVENT_HEADER_SIZE + sizeof(pusNumberOfHandles)); - temp = 0; - - for(i = 0; i < pusNumberOfHandles ; i++) - { - STREAM_TO_UINT16(pReadPayload, FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET, value); - temp += value; - pReadPayload += FLOW_CONTROL_EVENT_SIZE; - } - - tSLInformation.usNumberOfFreeBuffers += temp; - tSLInformation.NumberOfReleasedPackets += temp; - - return(ESUCCESS); -} - -//***************************************************************************** -// -//! get_socket_active_status -//! -//! @param Sd Socket IS -//! @return Current status of the socket. -//! -//! @brief Retrieve socket status -// -//***************************************************************************** - -INT32 get_socket_active_status(INT32 Sd) -{ - if(M_IS_VALID_SD(Sd)) - { - return (socket_active_status & (1 << Sd)) ? SOCKET_STATUS_INACTIVE : SOCKET_STATUS_ACTIVE; - } - return SOCKET_STATUS_INACTIVE; -} - -//***************************************************************************** -// -//! update_socket_active_status -//! -//! @param resp_params Socket IS -//! @return Current status of the socket. -//! -//! @brief Retrieve socket status -// -//***************************************************************************** -void update_socket_active_status(CHAR *resp_params) -{ - INT32 status, sd; - - STREAM_TO_UINT32(resp_params, BSD_RSP_PARAMS_SOCKET_OFFSET,sd); - STREAM_TO_UINT32(resp_params, BSD_RSP_PARAMS_STATUS_OFFSET,status); - - if(ERROR_SOCKET_INACTIVE == status) - { - set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); - } -} - - -//***************************************************************************** -// -//! SimpleLinkWaitEvent -//! -//! @param usOpcode command operation code -//! @param pRetParams command return parameters -//! -//! @return none -//! -//! @brief Wait for event, pass it to the hci_event_handler and -//! update the event opcode in a global variable. -// -//***************************************************************************** - -void SimpleLinkWaitEvent(UINT16 usOpcode, void *pRetParams) -{ - // In the blocking implementation the control to caller will be returned only - // after the end of current transaction - tSLInformation.usRxEventOpcode = usOpcode; - hci_event_handler(pRetParams, 0, 0); -} - -//***************************************************************************** -// -//! SimpleLinkWaitData -//! -//! @param pBuf data buffer -//! @param from from information -//! @param fromlen from information length -//! -//! @return none -//! -//! @brief Wait for data, pass it to the hci_event_handler -//! and update in a global variable that there is -//! data to read. -// -//***************************************************************************** - -void SimpleLinkWaitData(UINT8 *pBuf, UINT8 *from, UINT8 *fromlen) -{ - // In the blocking implementation the control to caller will be returned only - // after the end of current transaction, i.e. only after data will be received - tSLInformation.usRxDataPending = 1; - hci_event_handler(pBuf, from, fromlen); -} - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** diff --git a/drivers/cc3000/src/hci.c b/drivers/cc3000/src/hci.c deleted file mode 100644 index 4391692b8b..0000000000 --- a/drivers/cc3000/src/hci.c +++ /dev/null @@ -1,225 +0,0 @@ -/***************************************************************************** -* -* hci.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -//***************************************************************************** -// -//! \addtogroup hci_app -//! @{ -// -//***************************************************************************** - -#include -#include "cc3000_common.h" -#include "hci.h" -#include "ccspi.h" -#include "evnt_handler.h" -#include "wlan.h" - -#define SL_PATCH_PORTION_SIZE (1000) - - -//***************************************************************************** -// -//! hci_command_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the command's arguments buffer -//! @param ucArgsLength length of the arguments -//! -//! @return none -//! -//! @brief Initiate an HCI command. -// -//***************************************************************************** -UINT16 hci_command_send(UINT16 usOpcode, UINT8 *pucBuff, UINT8 ucArgsLength) -{ - UINT8 *stream; - - stream = (pucBuff + SPI_HEADER_SIZE); - - UINT8_TO_STREAM(stream, HCI_TYPE_CMND); - stream = UINT16_TO_STREAM(stream, usOpcode); - UINT8_TO_STREAM(stream, ucArgsLength); - - //Update the opcode of the event we will be waiting for - SpiWrite(pucBuff, ucArgsLength + SIMPLE_LINK_HCI_CMND_HEADER_SIZE); - - return(0); -} - -//***************************************************************************** -// -//! hci_data_send -//! -//! @param usOpcode command operation code -//! @param ucArgs pointer to the command's arguments buffer -//! @param usArgsLength length of the arguments -//! @param ucTail pointer to the data buffer -//! @param usTailLength buffer length -//! -//! @return none -//! -//! @brief Initiate an HCI data write operation -// -//***************************************************************************** -INT32 hci_data_send(UINT8 ucOpcode, - UINT8 *ucArgs, - UINT16 usArgsLength, - UINT16 usDataLength, - const UINT8 *ucTail, - UINT16 usTailLength) -{ - UINT8 *stream; - - stream = ((ucArgs) + SPI_HEADER_SIZE); - - UINT8_TO_STREAM(stream, HCI_TYPE_DATA); - UINT8_TO_STREAM(stream, ucOpcode); - UINT8_TO_STREAM(stream, usArgsLength); - stream = UINT16_TO_STREAM(stream, usArgsLength + usDataLength + usTailLength); - - // Send the packet over the SPI - SpiWrite(ucArgs, SIMPLE_LINK_HCI_DATA_HEADER_SIZE + usArgsLength + usDataLength + usTailLength); - - return(ESUCCESS); -} - - -//***************************************************************************** -// -//! hci_data_command_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the data buffer -//! @param ucArgsLength arguments length -//! @param ucDataLength data length -//! -//! @return none -//! -//! @brief Prepeare HCI header and initiate an HCI data write operation -// -//***************************************************************************** -void hci_data_command_send(UINT16 usOpcode, UINT8 *pucBuff, UINT8 ucArgsLength,UINT16 ucDataLength) -{ - UINT8 *stream = (pucBuff + SPI_HEADER_SIZE); - - UINT8_TO_STREAM(stream, HCI_TYPE_DATA); - UINT8_TO_STREAM(stream, usOpcode); - UINT8_TO_STREAM(stream, ucArgsLength); - stream = UINT16_TO_STREAM(stream, ucArgsLength + ucDataLength); - - // Send the command over SPI on data channel - SpiWrite(pucBuff, ucArgsLength + ucDataLength + SIMPLE_LINK_HCI_DATA_CMND_HEADER_SIZE); - - return; -} - -//***************************************************************************** -// -//! hci_patch_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the command's arguments buffer -//! @param patch pointer to patch content buffer -//! @param usDataLength data length -//! -//! @return none -//! -//! @brief Prepeare HCI header and initiate an HCI patch write operation -// -//***************************************************************************** -void hci_patch_send(UINT8 ucOpcode, UINT8 *pucBuff, CHAR *patch, UINT16 usDataLength) -{ - UINT8 *data_ptr = (pucBuff + SPI_HEADER_SIZE); - UINT16 usTransLength; - UINT8 *stream = (pucBuff + SPI_HEADER_SIZE); - - UINT8_TO_STREAM(stream, HCI_TYPE_PATCH); - UINT8_TO_STREAM(stream, ucOpcode); - stream = UINT16_TO_STREAM(stream, usDataLength + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE); - - if (usDataLength <= SL_PATCH_PORTION_SIZE) - { - UINT16_TO_STREAM(stream, usDataLength); - stream = UINT16_TO_STREAM(stream, usDataLength); - memcpy((pucBuff + SPI_HEADER_SIZE) + HCI_PATCH_HEADER_SIZE, patch, usDataLength); - - // Update the opcode of the event we will be waiting for - SpiWrite(pucBuff, usDataLength + HCI_PATCH_HEADER_SIZE); - } - else - { - - usTransLength = (usDataLength/SL_PATCH_PORTION_SIZE); - UINT16_TO_STREAM(stream, usDataLength + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE + usTransLength*SIMPLE_LINK_HCI_PATCH_HEADER_SIZE); - stream = UINT16_TO_STREAM(stream, SL_PATCH_PORTION_SIZE); - memcpy(pucBuff + SPI_HEADER_SIZE + HCI_PATCH_HEADER_SIZE, patch, SL_PATCH_PORTION_SIZE); - usDataLength -= SL_PATCH_PORTION_SIZE; - patch += SL_PATCH_PORTION_SIZE; - - // Update the opcode of the event we will be waiting for - SpiWrite(pucBuff, SL_PATCH_PORTION_SIZE + HCI_PATCH_HEADER_SIZE); - - while (usDataLength) - { - if (usDataLength <= SL_PATCH_PORTION_SIZE) - { - usTransLength = usDataLength; - usDataLength = 0; - - } - else - { - usTransLength = SL_PATCH_PORTION_SIZE; - usDataLength -= usTransLength; - } - - *(UINT16 *)data_ptr = usTransLength; - memcpy(data_ptr + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE, patch, usTransLength); - patch += usTransLength; - - // Update the opcode of the event we will be waiting for - SpiWrite((UINT8 *)data_ptr, usTransLength + sizeof(usTransLength)); - } - } -} - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -// -//***************************************************************************** diff --git a/drivers/cc3000/src/inet_ntop.c b/drivers/cc3000/src/inet_ntop.c deleted file mode 100644 index 83242efa00..0000000000 --- a/drivers/cc3000/src/inet_ntop.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 1996-2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM - * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL - * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include "cc3000_common.h" -#include "socket.h" -#include "inet_ntop.h" - -// We can't include stdio.h because it defines _types_fd_set, but we -// need to use the CC3000 version of this type. So we must provide -// our own declaration of snprintf. Grrr. -int snprintf(char *str, size_t size, const char *fmt, ...); - -#define IN6ADDRSZ 16 -#define INADDRSZ 4 -#define INT16SZ 2 - -#define ENOSPC (28) -#define EAFNOSUPPORT (106) -#define SET_ERRNO(err) (CC3000_EXPORT(errno)=-err) - -/* - * Format an IPv4 address, more or less like inet_ntoa(). - * - * Returns `dst' (as a const) - * Note: - * - uses no statics - * - takes a unsigned char* not an in_addr as input - */ -static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size) -{ - size_t len; - char tmp[sizeof "255.255.255.255"]; - - tmp[0] = '\0'; - (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d", - ((int)((unsigned char)src[3])) & 0xff, - ((int)((unsigned char)src[2])) & 0xff, - ((int)((unsigned char)src[1])) & 0xff, - ((int)((unsigned char)src[0])) & 0xff); - - len = strlen(tmp); - if(len == 0 || len >= size) - { - SET_ERRNO(ENOSPC); - return (NULL); - } - strcpy(dst, tmp); - return dst; -} - -#ifdef ENABLE_IPV6 -/* - * Convert IPv6 binary address into presentation (printable) format. - */ -static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size) -{ - /* - * Note that int32_t and int16_t need only be "at least" large enough - * to contain a value of the specified size. On some systems, like - * Crays, there is no such thing as an integer variable with 16 bits. - * Keep this in mind if you think this function should have been coded - * to use pointer overlays. All the world's not a VAX. - */ - char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; - char *tp; - struct { - long base; - long len; - } best, cur; - unsigned long words[IN6ADDRSZ / INT16SZ]; - int i; - - /* Preprocess: - * Copy the input (bytewise) array into a wordwise array. - * Find the longest run of 0x00's in src[] for :: shorthanding. - */ - memset(words, '\0', sizeof(words)); - for (i = 0; i < IN6ADDRSZ; i++) - words[i/2] |= (src[i] << ((1 - (i % 2)) << 3)); - - best.base = -1; - cur.base = -1; - best.len = 0; - cur.len = 0; - - for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) - { - if(words[i] == 0) - { - if(cur.base == -1) - cur.base = i, cur.len = 1; - else - cur.len++; - } - else if(cur.base != -1) - { - if(best.base == -1 || cur.len > best.len) - best = cur; - cur.base = -1; - } - } - if((cur.base != -1) && (best.base == -1 || cur.len > best.len)) - best = cur; - if(best.base != -1 && best.len < 2) - best.base = -1; - - /* Format the result. - */ - tp = tmp; - for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) - { - /* Are we inside the best run of 0x00's? - */ - if(best.base != -1 && i >= best.base && i < (best.base + best.len)) - { - if(i == best.base) - *tp++ = ':'; - continue; - } - - /* Are we following an initial run of 0x00s or any real hex? - */ - if(i != 0) - *tp++ = ':'; - - /* Is this address an encapsulated IPv4? - */ - if(i == 6 && best.base == 0 && - (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) - { - if(!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp))) - { - SET_ERRNO(ENOSPC); - return (NULL); - } - tp += strlen(tp); - break; - } - tp += snprintf(tp, 5, "%lx", words[i]); - } - - /* Was it a trailing run of 0x00's? - */ - if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) - *tp++ = ':'; - *tp++ = '\0'; - - /* Check for overflow, copy, and we're done. - */ - if((size_t)(tp - tmp) > size) - { - SET_ERRNO(ENOSPC); - return (NULL); - } - strcpy(dst, tmp); - return dst; -} -#endif /* ENABLE_IPV6 */ - -/* - * Convert a network format address to presentation format. - * - * Returns pointer to presentation format address (`buf'). - * Returns NULL on error and errno set with the specific - * error, EAFNOSUPPORT or ENOSPC. - * - * On Windows we store the error in the thread errno, not - * in the winsock error code. This is to avoid loosing the - * actual last winsock error. So use macro ERRNO to fetch the - * errno this funtion sets when returning NULL, not SOCKERRNO. - */ -char *inet_ntop(int af, const void *src, char *buf, size_t size) -{ - switch (af) { - case AF_INET: - return inet_ntop4((const unsigned char*)src, buf, size); -#ifdef ENABLE_IPV6 - case AF_INET6: - return inet_ntop6((const unsigned char*)src, buf, size); -#endif - default: - SET_ERRNO(EAFNOSUPPORT); - return NULL; - } -} diff --git a/drivers/cc3000/src/inet_pton.c b/drivers/cc3000/src/inet_pton.c deleted file mode 100644 index 5f5ae5f9d7..0000000000 --- a/drivers/cc3000/src/inet_pton.c +++ /dev/null @@ -1,216 +0,0 @@ -/* This is from the BIND 4.9.4 release, modified to compile by itself */ - -/* Copyright (c) 1996 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include -#include "cc3000_common.h" -#include "socket.h" -#include "inet_pton.h" - -#define IN6ADDRSZ 16 -#define INADDRSZ 4 -#define INT16SZ 2 - -static int inet_pton4(const char *src, unsigned char *dst); -#ifdef ENABLE_IPV6 -static int inet_pton6(const char *src, unsigned char *dst); -#endif - -#define EAFNOSUPPORT (106) -#define SET_ERRNO(err) (CC3000_EXPORT(errno)=-err) - -/* int - * inet_pton(af, src, dst) - * convert from presentation format (which usually means ASCII printable) - * to network format (which is usually some kind of binary format). - * return: - * 1 if the address was valid for the specified address family - * 0 if the address wasn't valid (`dst' is untouched in this case) - * -1 if some other error occurred (`dst' is untouched in this case, too) - * notice: - * On Windows we store the error in the thread errno, not - * in the winsock error code. This is to avoid loosing the - * actual last winsock error. So use macro ERRNO to fetch the - * errno this funtion sets when returning (-1), not SOCKERRNO. - * author: - * Paul Vixie, 1996. - */ -int inet_pton(int af, const char *src, void *dst) -{ - switch (af) { - case AF_INET: - return (inet_pton4(src, (unsigned char *)dst)); -#ifdef ENABLE_IPV6 - case AF_INET6: - return (inet_pton6(src, (unsigned char *)dst)); -#endif - default: - SET_ERRNO(EAFNOSUPPORT); - return (-1); - } - /* NOTREACHED */ -} - -/* int - * inet_pton4(src, dst) - * like inet_aton() but without all the hexadecimal and shorthand. - * return: - * 1 if `src' is a valid dotted quad, else 0. - * notice: - * does not touch `dst' unless it's returning 1. - * author: - * Paul Vixie, 1996. - */ -static int inet_pton4(const char *src, unsigned char *dst) -{ - static const char digits[] = "0123456789"; - int saw_digit, octets, ch; - unsigned char tmp[INADDRSZ], *tp; - - saw_digit = 0; - octets = 0; - tp = tmp; - *tp = 0; - while((ch = *src++) != '\0') { - const char *pch; - - if((pch = strchr(digits, ch)) != NULL) { - unsigned int val = *tp * 10 + (unsigned int)(pch - digits); - - if(saw_digit && *tp == 0) - return (0); - if(val > 255) - return (0); - *tp = (unsigned char)val; - if(! saw_digit) { - if(++octets > 4) - return (0); - saw_digit = 1; - } - } - else if(ch == '.' && saw_digit) { - if(octets == 4) - return (0); - *++tp = 0; - saw_digit = 0; - } - else - return (0); - } - if(octets < 4) - return (0); - memcpy(dst, tmp, INADDRSZ); - return (1); -} - -#ifdef ENABLE_IPV6 -/* int - * inet_pton6(src, dst) - * convert presentation level address to network order binary form. - * return: - * 1 if `src' is a valid [RFC1884 2.2] address, else 0. - * notice: - * (1) does not touch `dst' unless it's returning 1. - * (2) :: in a full address is silently ignored. - * credit: - * inspired by Mark Andrews. - * author: - * Paul Vixie, 1996. - */ -static int inet_pton6(const char *src, unsigned char *dst) -{ - static const char xdigits_l[] = "0123456789abcdef", - xdigits_u[] = "0123456789ABCDEF"; - unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp; - const char *xdigits, *curtok; - int ch, saw_xdigit; - unsigned int val; - - memset((tp = tmp), 0, IN6ADDRSZ); - endp = tp + IN6ADDRSZ; - colonp = NULL; - /* Leading :: requires some special handling. */ - if(*src == ':') - if(*++src != ':') - return (0); - curtok = src; - saw_xdigit = 0; - val = 0; - while((ch = *src++) != '\0') { - const char *pch; - - if((pch = strchr((xdigits = xdigits_l), ch)) == NULL) - pch = strchr((xdigits = xdigits_u), ch); - if(pch != NULL) { - val <<= 4; - val |= (pch - xdigits); - if(++saw_xdigit > 4) - return (0); - continue; - } - if(ch == ':') { - curtok = src; - if(!saw_xdigit) { - if(colonp) - return (0); - colonp = tp; - continue; - } - if(tp + INT16SZ > endp) - return (0); - *tp++ = (unsigned char) (val >> 8) & 0xff; - *tp++ = (unsigned char) val & 0xff; - saw_xdigit = 0; - val = 0; - continue; - } - if(ch == '.' && ((tp + INADDRSZ) <= endp) && - inet_pton4(curtok, tp) > 0) { - tp += INADDRSZ; - saw_xdigit = 0; - break; /* '\0' was seen by inet_pton4(). */ - } - return (0); - } - if(saw_xdigit) { - if(tp + INT16SZ > endp) - return (0); - *tp++ = (unsigned char) (val >> 8) & 0xff; - *tp++ = (unsigned char) val & 0xff; - } - if(colonp != NULL) { - /* - * Since some memmove()'s erroneously fail to handle - * overlapping regions, we'll do the shift by hand. - */ - const long n = tp - colonp; - long i; - - if(tp == endp) - return (0); - for (i = 1; i <= n; i++) { - endp[- i] = colonp[n - i]; - colonp[n - i] = 0; - } - tp = endp; - } - if(tp != endp) - return (0); - memcpy(dst, tmp, IN6ADDRSZ); - return (1); -} -#endif /* ENABLE_IPV6 */ diff --git a/drivers/cc3000/src/netapp.c b/drivers/cc3000/src/netapp.c deleted file mode 100644 index a6f60feda0..0000000000 --- a/drivers/cc3000/src/netapp.c +++ /dev/null @@ -1,459 +0,0 @@ -/***************************************************************************** -* -* netapp.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -#include -#include "netapp.h" -#include "hci.h" -#include "socket.h" -#include "evnt_handler.h" -#include "nvmem.h" - -#define MIN_TIMER_VAL_SECONDS 10 -#define MIN_TIMER_SET(t) if ((0 != t) && (t < MIN_TIMER_VAL_SECONDS)) \ - { \ - t = MIN_TIMER_VAL_SECONDS; \ - } - - -#define NETAPP_DHCP_PARAMS_LEN (20) -#define NETAPP_SET_TIMER_PARAMS_LEN (20) -#define NETAPP_SET_DEBUG_LEVEL_PARAMS_LEN (4) -#define NETAPP_PING_SEND_PARAMS_LEN (16) - - -//***************************************************************************** -// -//! netapp_config_mac_adrress -//! -//! @param mac device mac address, 6 bytes. Saved: yes -//! -//! @return return on success 0, otherwise error. -//! -//! @brief Configure device MAC address and store it in NVMEM. -//! The value of the MAC address configured through the API will -//! be stored in CC3000 non volatile memory, thus preserved -//! over resets. -// -//***************************************************************************** -INT32 netapp_config_mac_adrress(UINT8 * mac) -{ - return nvmem_set_mac_address(mac); -} - -//***************************************************************************** -// -//! netapp_dhcp -//! -//! @param aucIP device mac address, 6 bytes. Saved: yes -//! @param aucSubnetMask device mac address, 6 bytes. Saved: yes -//! @param aucDefaultGateway device mac address, 6 bytes. Saved: yes -//! @param aucDNSServer device mac address, 6 bytes. Saved: yes -//! -//! @return return on success 0, otherwise error. -//! -//! @brief netapp_dhcp is used to configure the network interface, -//! static or dynamic (DHCP).\n In order to activate DHCP mode, -//! aucIP, aucSubnetMask, aucDefaultGateway must be 0. -//! The default mode of CC3000 is DHCP mode. -//! Note that the configuration is saved in non volatile memory -//! and thus preserved over resets. -//! -//! @note If the mode is altered a reset of CC3000 device is required -//! in order to apply changes.\nAlso note that asynchronous event -//! of DHCP_EVENT, which is generated when an IP address is -//! allocated either by the DHCP server or due to static -//! allocation is generated only upon a connection to the -//! AP was established. -//! -//***************************************************************************** -INT32 netapp_dhcp(UINT32 *aucIP, UINT32 *aucSubnetMask,UINT32 *aucDefaultGateway, UINT32 *aucDNSServer) -{ - INT8 scRet; - UINT8 *ptr; - UINT8 *args; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - ARRAY_TO_STREAM(args,aucIP,4); - ARRAY_TO_STREAM(args,aucSubnetMask,4); - ARRAY_TO_STREAM(args,aucDefaultGateway,4); - args = UINT32_TO_STREAM(args, 0); - ARRAY_TO_STREAM(args,aucDNSServer,4); - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_DHCP, ptr, NETAPP_DHCP_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_DHCP, &scRet); - - return(scRet); -} - - -//***************************************************************************** -// -//! netapp_timeout_values -//! -//! @param aucDHCP DHCP lease time request, also impact -//! the DHCP renew timeout. Range: [0-0xffffffff] seconds, -//! 0 or 0xffffffff == infinity lease timeout. -//! Resolution:10 seconds. Influence: only after -//! reconnecting to the AP. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds. -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 14400 seconds. -//! -//! @param aucARP ARP refresh timeout, if ARP entry is not updated by -//! incoming packet, the ARP entry will be deleted by -//! the end of the timeout. -//! Range: [0-0xffffffff] seconds, 0 == infinity ARP timeout -//! Resolution: 10 seconds. Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 3600 seconds. -//! -//! @param aucKeepalive Keepalive event sent by the end of keepalive timeout -//! Range: [0-0xffffffff] seconds, 0 == infinity timeout -//! Resolution: 10 seconds. -//! Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 10 seconds. -//! -//! @param aucInactivity Socket inactivity timeout, socket timeout is -//! refreshed by incoming or outgoing packet, by the -//! end of the socket timeout the socket will be closed -//! Range: [0-0xffffffff] sec, 0 == infinity timeout. -//! Resolution: 10 seconds. Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 60 seconds. -//! -//! @return return on success 0, otherwise error. -//! -//! @brief Set new timeout values. Function set new timeout values for: -//! DHCP lease timeout, ARP refresh timeout, keepalive event -//! timeout and socket inactivity timeout -//! -//! @note If a parameter set to non zero value which is less than 10s, -//! it will be set automatically to 10s. -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 netapp_timeout_values(UINT32 *aucDHCP, UINT32 *aucARP,UINT32 *aucKeepalive, UINT32 *aucInactivity) -{ - INT8 scRet; - UINT8 *ptr; - UINT8 *args; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Set minimal values of timers - MIN_TIMER_SET(*aucDHCP) - MIN_TIMER_SET(*aucARP) - MIN_TIMER_SET(*aucKeepalive) - MIN_TIMER_SET(*aucInactivity) - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, *aucDHCP); - args = UINT32_TO_STREAM(args, *aucARP); - args = UINT32_TO_STREAM(args, *aucKeepalive); - args = UINT32_TO_STREAM(args, *aucInactivity); - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_SET_TIMERS, ptr, NETAPP_SET_TIMER_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_SET_TIMERS, &scRet); - - return(scRet); -} -#endif - - -//***************************************************************************** -// -//! netapp_ping_send -//! -//! @param ip destination IP address -//! @param pingAttempts number of echo requests to send -//! @param pingSize send buffer size which may be up to 1400 bytes -//! @param pingTimeout Time to wait for a response,in milliseconds. -//! -//! @return return on success 0, otherwise error. -//! -//! @brief send ICMP ECHO_REQUEST to network hosts -//! -//! @note If an operation finished successfully asynchronous ping report -//! event will be generated. The report structure is as defined -//! by structure netapp_pingreport_args_t. -//! -//! @warning Calling this function while a previous Ping Requests are in -//! progress will stop the previous ping request. -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 - netapp_ping_send(UINT32 *ip, UINT32 ulPingAttempts, UINT32 ulPingSize, UINT32 ulPingTimeout) -{ - INT8 scRet; - UINT8 *ptr, *args; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, *ip); - args = UINT32_TO_STREAM(args, ulPingAttempts); - args = UINT32_TO_STREAM(args, ulPingSize); - args = UINT32_TO_STREAM(args, ulPingTimeout); - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_PING_SEND, ptr, NETAPP_PING_SEND_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_PING_SEND, &scRet); - - return(scRet); -} -#endif - -//***************************************************************************** -// -//! netapp_ping_report -//! -//! @param none -//! -//! @return none -//! -//! @brief Request for ping status. This API triggers the CC3000 to send -//! asynchronous events: HCI_EVNT_WLAN_ASYNC_PING_REPORT. -//! This event will carry the report structure: -//! netapp_pingreport_args_t. This structure is filled in with ping -//! results up till point of triggering API. -//! netapp_pingreport_args_t:\n packets_sent - echo sent, -//! packets_received - echo reply, min_round_time - minimum -//! round time, max_round_time - max round time, -//! avg_round_time - average round time -//! -//! @note When a ping operation is not active, the returned structure -//! fields are 0. -//! -//***************************************************************************** - - -#ifndef CC3000_TINY_DRIVER -void netapp_ping_report() -{ - UINT8 *ptr; - ptr = tSLInformation.pucTxCommandBuffer; - INT8 scRet; - - scRet = EFAIL; - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_PING_REPORT, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_PING_REPORT, &scRet); -} -#endif - -//***************************************************************************** -// -//! netapp_ping_stop -//! -//! @param none -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief Stop any ping request. -//! -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 netapp_ping_stop() -{ - INT8 scRet; - UINT8 *ptr; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_PING_STOP, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_PING_STOP, &scRet); - - return(scRet); -} -#endif - -//***************************************************************************** -// -//! netapp_ipconfig -//! -//! @param[out] ipconfig This argument is a pointer to a -//! tNetappIpconfigRetArgs structure. This structure is -//! filled in with the network interface configuration. -//! tNetappIpconfigRetArgs:\n aucIP - ip address, -//! aucSubnetMask - mask, aucDefaultGateway - default -//! gateway address, aucDHCPServer - dhcp server address -//! aucDNSServer - dns server address, uaMacAddr - mac -//! address, uaSSID - connected AP ssid -//! -//! @return none -//! -//! @brief Obtain the CC3000 Network interface information. -//! Note that the information is available only after the WLAN -//! connection was established. Calling this function before -//! associated, will cause non-defined values to be returned. -//! -//! @note The function is useful for figuring out the IP Configuration of -//! the device when DHCP is used and for figuring out the SSID of -//! the Wireless network the device is associated with. -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig ) -{ - UINT8 *ptr; - - ptr = tSLInformation.pucTxCommandBuffer; - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_IPCONFIG, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_IPCONFIG, ipconfig ); - -} -#else -void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig ) -{ - -} -#endif - -//***************************************************************************** -// -//! netapp_arp_flush -//! -//! @param none -//! -//! @return none -//! -//! @brief Flushes ARP table -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 netapp_arp_flush(void) -{ - INT8 scRet; - UINT8 *ptr; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_ARP_FLUSH, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_ARP_FLUSH, &scRet); - - return(scRet); -} -#endif - -//***************************************************************************** -// -//! netapp_set_debug_level -//! -//! @param[in] level debug level. Bitwise [0-8], -//! 0(disable)or 1(enable).\n Bitwise map: 0 - Critical -//! message, 1 information message, 2 - core messages, 3 - -//! HCI messages, 4 - Network stack messages, 5 - wlan -//! messages, 6 - wlan driver messages, 7 - epprom messages, -//! 8 - general messages. Default: 0x13f. Saved: no -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Debug messages sent via the UART debug channel, this function -//! enable/disable the debug level -//! -//***************************************************************************** - - -#ifndef CC3000_TINY_DRIVER -INT32 netapp_set_debug_level(UINT32 ulLevel) -{ - INT8 scRet; - UINT8 *ptr, *args; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // - // Fill in temporary command buffer - // - args = UINT32_TO_STREAM(args, ulLevel); - - - // - // Initiate a HCI command - // - hci_command_send(HCI_NETAPP_SET_DEBUG_LEVEL, ptr, NETAPP_SET_DEBUG_LEVEL_PARAMS_LEN); - - // - // Wait for command complete event - // - SimpleLinkWaitEvent(HCI_NETAPP_SET_DEBUG_LEVEL, &scRet); - - return(scRet); - -} -#endif diff --git a/drivers/cc3000/src/nvmem.c b/drivers/cc3000/src/nvmem.c deleted file mode 100644 index c6e170a746..0000000000 --- a/drivers/cc3000/src/nvmem.c +++ /dev/null @@ -1,334 +0,0 @@ -/***************************************************************************** -* -* nvmem.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -//***************************************************************************** -// -//! \addtogroup nvmem_api -//! @{ -// -//***************************************************************************** - -#include -#include "nvmem.h" -#include "hci.h" -#include "socket.h" -#include "evnt_handler.h" - -//***************************************************************************** -// -// Prototypes for the structures for APIs. -// -//***************************************************************************** - -#define NVMEM_READ_PARAMS_LEN (12) -#define NVMEM_CREATE_PARAMS_LEN (8) -#define NVMEM_WRITE_PARAMS_LEN (16) - -//***************************************************************************** -// -//! nvmem_read -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_NVS_FILEID, NVMEM_NVS_SHADOW_FILEID, -//! NVMEM_WLAN_CONFIG_FILEID, NVMEM_WLAN_CONFIG_SHADOW_FILEID, -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! NVMEM_MAC_FILEID, NVMEM_FRONTEND_VARS_FILEID, -//! NVMEM_IP_CONFIG_FILEID, NVMEM_IP_CONFIG_SHADOW_FILEID, -//! NVMEM_BOOTLOADER_SP_FILEID, NVMEM_RM_FILEID, -//! and user files 12-15. -//! @param ulLength number of bytes to read -//! @param ulOffset ulOffset in file from where to read -//! @param buff output buffer pointer -//! -//! @return on success 0, error otherwise. -//! -//! @brief Reads data from the file referred by the ulFileId parameter. -//! Reads data from file ulOffset till length. Err if the file can't -//! be used, is invalid, or if the read is out of bounds. -//! -//***************************************************************************** - -INT32 nvmem_read(UINT32 ulFileId, UINT32 ulLength, UINT32 ulOffset, UINT8 *buff) -{ - UINT8 ucStatus = 0xFF; - UINT8 *ptr; - UINT8 *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, ulFileId); - args = UINT32_TO_STREAM(args, ulLength); - args = UINT32_TO_STREAM(args, ulOffset); - - // Initiate a HCI command - hci_command_send(HCI_CMND_NVMEM_READ, ptr, NVMEM_READ_PARAMS_LEN); - SimpleLinkWaitEvent(HCI_CMND_NVMEM_READ, &ucStatus); - - // In case there is data - read it - even if an error code is returned - // Note: It is the user responsibility to ignore the data in case of an error code - - // Wait for the data in a synchronous way. Here we assume that the buffer is - // big enough to store also parameters of nvmem - - SimpleLinkWaitData(buff, 0, 0); - - return(ucStatus); -} - -//***************************************************************************** -// -//! nvmem_write -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! NVMEM_MAC_FILEID, NVMEM_BOOTLOADER_SP_FILEID, -//! and user files 12-15. -//! @param ulLength number of bytes to write -//! @param ulEntryOffset offset in file to start write operation from -//! @param buff data to write -//! -//! @return on success 0, error otherwise. -//! -//! @brief Write data to nvmem. -//! writes data to file referred by the ulFileId parameter. -//! Writes data to file ulOffset till ulLength.The file id will be -//! marked invalid till the write is done. The file entry doesn't -//! need to be valid - only allocated. -//! -//***************************************************************************** - -INT32 nvmem_write(UINT32 ulFileId, UINT32 ulLength, UINT32 ulEntryOffset, UINT8 *buff) -{ - INT32 iRes; - UINT8 *ptr; - UINT8 *args; - - iRes = EFAIL; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, ulFileId); - args = UINT32_TO_STREAM(args, 12); - args = UINT32_TO_STREAM(args, ulLength); - args = UINT32_TO_STREAM(args, ulEntryOffset); - - memcpy((ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE + - NVMEM_WRITE_PARAMS_LEN),buff,ulLength); - - // Initiate a HCI command but it will come on data channel - hci_data_command_send(HCI_CMND_NVMEM_WRITE, ptr, NVMEM_WRITE_PARAMS_LEN, - ulLength); - - SimpleLinkWaitEvent(HCI_EVNT_NVMEM_WRITE, &iRes); - - return(iRes); -} - - -//***************************************************************************** -// -//! nvmem_set_mac_address -//! -//! @param mac mac address to be set -//! -//! @return on success 0, error otherwise. -//! -//! @brief Write MAC address to EEPROM. -//! mac address as appears over the air (OUI first) -//! -//***************************************************************************** - -UINT8 nvmem_set_mac_address(UINT8 *mac) -{ - return nvmem_write(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac); -} - -//***************************************************************************** -// -//! nvmem_get_mac_address -//! -//! @param[out] mac mac address -//! -//! @return on success 0, error otherwise. -//! -//! @brief Read MAC address from EEPROM. -//! mac address as appears over the air (OUI first) -//! -//***************************************************************************** - -UINT8 nvmem_get_mac_address(UINT8 *mac) -{ - return nvmem_read(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac); -} - -//***************************************************************************** -// -//! nvmem_write_patch -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! @param spLength number of bytes to write -//! @param spData SP data to write -//! -//! @return on success 0, error otherwise. -//! -//! @brief program a patch to a specific file ID. -//! The SP data is assumed to be organized in 2-dimensional. -//! Each line is SP_PORTION_SIZE bytes long. Actual programming is -//! applied in SP_PORTION_SIZE bytes portions. -//! -//***************************************************************************** - -UINT8 nvmem_write_patch(UINT32 ulFileId, UINT32 spLength, const UINT8 *spData) -{ - UINT8 status = 0; - UINT16 offset = 0; - UINT8* spDataPtr = (UINT8*)spData; - - while ((status == 0) && (spLength >= SP_PORTION_SIZE)) - { - status = nvmem_write(ulFileId, SP_PORTION_SIZE, offset, spDataPtr); - offset += SP_PORTION_SIZE; - spLength -= SP_PORTION_SIZE; - spDataPtr += SP_PORTION_SIZE; - } - - if (status !=0) - { - // NVMEM error occurred - return status; - } - - if (spLength != 0) - { - // if reached here, a reminder is left - status = nvmem_write(ulFileId, spLength, offset, spDataPtr); - } - - return status; -} - -//***************************************************************************** -// -//! nvmem_read_sp_version -//! -//! @param[out] patchVer first number indicates package ID and the second -//! number indicates package build number -//! -//! @return on success 0, error otherwise. -//! -//! @brief Read patch version. read package version (WiFi FW patch, -//! driver-supplicant-NS patch, bootloader patch) -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -UINT8 nvmem_read_sp_version(UINT8* patchVer) -{ - UINT8 *ptr; - // 1st byte is the status and the rest is the SP version - UINT8 retBuf[5]; - - ptr = tSLInformation.pucTxCommandBuffer; - - // Initiate a HCI command, no args are required - hci_command_send(HCI_CMND_READ_SP_VERSION, ptr, 0); - SimpleLinkWaitEvent(HCI_CMND_READ_SP_VERSION, retBuf); - - // package ID - *patchVer = retBuf[3]; - // package build number - *(patchVer+1) = retBuf[4]; - - return(retBuf[0]); -} -#endif - -//***************************************************************************** -// -//! nvmem_create_entry -//! -//! @param ulFileId nvmem file Id:\n -//! * NVMEM_AES128_KEY_FILEID: 12 -//! * NVMEM_SHARED_MEM_FILEID: 13 -//! * and fileIDs 14 and 15 -//! @param ulNewLen entry ulLength -//! -//! @return on success 0, error otherwise. -//! -//! @brief Create new file entry and allocate space on the NVMEM. -//! Applies only to user files. -//! Modify the size of file. -//! If the entry is unallocated - allocate it to size -//! ulNewLen (marked invalid). -//! If it is allocated then deallocate it first. -//! To just mark the file as invalid without resizing - -//! set ulNewLen=0. -//! -//***************************************************************************** - -INT32 nvmem_create_entry(UINT32 ulFileId, UINT32 ulNewLen) -{ - UINT8 *ptr; - UINT8 *args; - UINT8 retval; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, ulFileId); - args = UINT32_TO_STREAM(args, ulNewLen); - - // Initiate a HCI command - hci_command_send(HCI_CMND_NVMEM_CREATE_ENTRY,ptr, NVMEM_CREATE_PARAMS_LEN); - - SimpleLinkWaitEvent(HCI_CMND_NVMEM_CREATE_ENTRY, &retval); - - return(retval); -} - - - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** diff --git a/drivers/cc3000/src/patch.c b/drivers/cc3000/src/patch.c deleted file mode 100644 index 227be3c9f2..0000000000 --- a/drivers/cc3000/src/patch.c +++ /dev/null @@ -1,117 +0,0 @@ -/***************************************************************************** - * - * {PatchProgrammer_DR_Patch.c} - * - * Burn Patches to EEPROM - * - * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ - * ALL RIGHTS RESERVED - * - *****************************************************************************/ -// -// Service Pack version P1.13.7.15.28 - Driver patches -// This file contains the CC3K driver and firmware patches -// From CC3000-FRAM-PATCH V:1.13.7 15-MAY-2014 - -unsigned short fw_length = 5700; -unsigned short drv_length = 8024; - -const unsigned char wlan_drv_patch[8024] = { 0x00, 0x01, 0x00, 0x00, 0x50, 0x1F, 0x00, 0x00, 0xF0, 0x03, 0x18, 0x00, 0xE4, 0x62, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7A, 0x63, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x64, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x20, 0x0C, 0x49, 0x08, 0x60, 0x0C, 0x48, 0x19, 0x30, 0xF7, 0x46, 0x30, 0xB5, 0x05, 0x1C, 0xAC, 0x69, 0x68, 0x68, 0x5F, 0x30, 0x09, 0xD1, 0x60, 0x6B, 0x0C, 0x38, 0x01, 0x21, 0x8E, 0x46, 0x06, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x00, 0x20, 0x60, 0x63, 0xAC, 0x69, 0x6C, 0x60, 0x04, 0x48, 0x5B, 0x30, 0x30, 0xBD, 0x40, 0x3B, 0x08, 0x00, 0x49, 0xD0, 0x01, 0x00, 0x09, 0xEA, 0x02, 0x00, 0x91, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA6, 0x64, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3C, 0x65, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xB5, 0x85, 0xB0, 0x05, 0x1C, 0xA8, 0x88, 0x00, 0x90, 0x28, 0x89, 0x01, 0x90, 0xE9, 0x68, 0x02, 0x91, 0x28, 0x7C, 0x03, 0x90, 0x2A, 0x6A, 0x00, 0x20, 0x17, 0x56, 0x68, 0x60, 0x00, 0x29, 0x4C, 0xD0, 0x00, 0x2F, 0x4A, 0xDC , -0xCA, 0x49, 0x0C, 0x1C, 0x08, 0x26, 0x04, 0x90, 0x21, 0x88, 0x00, 0x98, 0x81, 0x42, 0x0C, 0xD1, 0x62, 0x88, 0x01, 0x98, 0x82, 0x42, 0x08, 0xD1, 0x46, 0x20, 0x02, 0x5D, 0x03, 0x98, 0x82, 0x42, 0x03, 0xD1, 0x0E, 0x20, 0x00, 0x57, 0xB8, 0x42, 0x0A, 0xD0, 0x46, 0x20, 0x00, 0x5D, 0x11, 0x28, 0x22, 0xD1, 0x00, 0x98, 0x81, 0x42, 0x1F, 0xD1, 0x0E, 0x20, 0x00, 0x57, 0xFF, 0xFF, 0xD2, 0x65, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xB8, 0x42, 0x1B, 0xD1, 0x04, 0x20, 0x02, 0x1C, 0x02, 0x98, 0xB9, 0x49, 0x01, 0x23, 0x9E, 0x46, 0xEC, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x17, 0xD0, 0x20, 0x1D, 0x02, 0x99, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xE7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x0D, 0xD0, 0x46, 0x20, 0x00, 0x5D, 0x11, 0x28, 0x09, 0xD0, 0xA0, 0x6D, 0x00, 0x28, 0x06, 0xD0, 0xAC, 0x34, 0x04, 0x98, 0x01, 0x30, 0x04, 0x90, 0x01, 0x3E, 0xC1, 0xD1, 0x07, 0xE0, 0x04, 0x98, 0x00, 0x06, 0x00, 0x0E , -0xAC, 0x21, 0x41, 0x43, 0xA6, 0x48, 0x40, 0x18, 0x68, 0x60, 0xA6, 0x48, 0xAD, 0x30, 0x05, 0xB0, 0xF0, 0xBD, 0x00, 0xB5, 0xC2, 0x68, 0x90, 0x69, 0x02, 0x21, 0x01, 0x23, 0x9E, 0x46, 0xA2, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xA2, 0x48, 0x61, 0x30, 0x00, 0xBD, 0x01, 0x79, 0x0B, 0x29, 0x03, 0xD0, 0x89, 0x00, 0x9F, 0x4A, 0x51, 0x5A, 0x01, 0xE0, 0x01, 0x21, 0x49, 0x02, 0x41, 0x60, 0x9D, 0x48, 0x0D, 0x30, 0xF7, 0x46, 0x01, 0x1C, 0xFF, 0xFF, 0x68, 0x66, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x9C, 0x48, 0x02, 0x68, 0x9C, 0x48, 0x01, 0x2A, 0x01, 0xD1, 0x25, 0x30, 0xF7, 0x46, 0x9B, 0x4A, 0x12, 0x68, 0x4A, 0x60, 0x19, 0x30, 0xF7, 0x46, 0x00, 0x21, 0x41, 0x60, 0x99, 0x48, 0x98, 0x49, 0x08, 0x18, 0xF7, 0x46, 0x00, 0x21, 0x41, 0x60, 0x97, 0x48, 0xE7, 0x49, 0x08, 0x18, 0xF7, 0x46, 0xFF, 0xB5, 0x46, 0x69, 0x40, 0x68, 0x01, 0x90, 0x94, 0x49, 0x0A, 0x7C, 0x9A, 0x4F, 0x01, 0x2A, 0x63, 0xD0, 0x09, 0x7C, 0x03, 0x29 , -0x60, 0xD0, 0x91, 0x4A, 0x92, 0x4B, 0x00, 0x21, 0x02, 0x91, 0x59, 0x56, 0x24, 0x23, 0x59, 0x43, 0x53, 0x18, 0x03, 0x93, 0x01, 0x28, 0x17, 0xD1, 0x8A, 0x18, 0x04, 0x23, 0x6C, 0x46, 0x8C, 0x49, 0x15, 0x79, 0x08, 0x78, 0xC0, 0x43, 0x28, 0x43, 0x20, 0x70, 0x01, 0x32, 0x01, 0x31, 0x01, 0x34, 0x01, 0x3B, 0xF5, 0xD1, 0x31, 0x1D, 0x68, 0x46, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xA9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x40, 0xD0, 0x35, 0x1D, 0x82, 0x48, 0x00, 0x78, 0xFF, 0x28, 0xFF, 0xFF, 0xFE, 0x66, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x11, 0xD0, 0x00, 0x28, 0x0F, 0xD0, 0x03, 0x98, 0x01, 0x1D, 0x28, 0x1C, 0x01, 0x24, 0xA6, 0x46, 0x7E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x00, 0x28, 0x05, 0xD1, 0x7A, 0x48, 0xA6, 0x46, 0x7B, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x05, 0xE0, 0x28, 0x1C, 0x01, 0x21, 0x8E, 0x46, 0x78, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x99, 0x01, 0x29, 0x01, 0xD1, 0x00, 0x28, 0x1E, 0xD1 , -0x01, 0x99, 0x5F, 0x31, 0x01, 0xD0, 0x00, 0x28, 0x0F, 0xD1, 0xA8, 0x20, 0x81, 0x5D, 0x00, 0x29, 0x08, 0xD0, 0x49, 0x1E, 0x81, 0x55, 0x80, 0x5D, 0x00, 0x28, 0x09, 0xD1, 0x38, 0x1C, 0xFF, 0x30, 0x08, 0x30, 0x11, 0xE0, 0x03, 0x21, 0x02, 0x91, 0x00, 0xE0, 0xA8, 0x20, 0x02, 0x99, 0x81, 0x55, 0x38, 0x1C, 0xFF, 0x30, 0x16, 0x30, 0x07, 0xE0, 0x01, 0x98, 0x01, 0x28, 0x02, 0xD1, 0x38, 0x1C, 0xA3, 0x30, 0x01, 0xE0, 0x38, 0x1C, 0x9F, 0x30, 0x00, 0x90, 0xFF, 0xBD, 0x00, 0xB5, 0x02, 0x1C, 0x10, 0x6A, 0xD1, 0x69, 0x52, 0x69, 0xC3, 0x69, 0x5A, 0x60, 0xFF, 0xFF, 0x94, 0x67, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x01, 0x22, 0x96, 0x46, 0x5E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x5E, 0x48, 0xFF, 0x30, 0x6E, 0x30, 0x00, 0xBD, 0x10, 0xB5, 0x0A, 0x1C, 0x41, 0x69, 0x00, 0x6A, 0x93, 0x69, 0xDB, 0x69, 0x58, 0x60, 0x90, 0x69, 0x01, 0x24, 0xA6, 0x46, 0x56, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0xA6, 0x46, 0x56, 0x48, 0xFE, 0x44 , -0x00, 0x47, 0x55, 0x48, 0xFF, 0x30, 0xB6, 0x30, 0x10, 0xBD, 0x70, 0xB5, 0x05, 0x1C, 0x6E, 0x69, 0x53, 0x48, 0x02, 0x68, 0x5C, 0x21, 0x88, 0x5D, 0x04, 0x28, 0x15, 0xD1, 0x07, 0x20, 0x88, 0x55, 0x10, 0x0B, 0x11, 0xD2, 0x01, 0x24, 0xA6, 0x46, 0x4E, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x00, 0x28, 0x0A, 0xD0, 0x47, 0x21, 0x89, 0x57, 0xC1, 0x60, 0x11, 0x21, 0xC9, 0x02, 0x00, 0x22, 0x04, 0x23, 0xA6, 0x46, 0xE8, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x01, 0x20, 0x68, 0x60, 0x43, 0x48, 0xED, 0x49, 0x08, 0x18, 0x70, 0xBD, 0x70, 0xB5, 0x05, 0x1C, 0xAE, 0x69, 0x9C, 0x20, 0x80, 0x19, 0x4B, 0x21, 0x89, 0x00, 0x01, 0x24, 0xFF, 0xFF, 0x2A, 0x68, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA6, 0x46, 0xE8, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x5C, 0x21, 0x88, 0x5D, 0x07, 0x28, 0x01, 0xD1, 0x09, 0x20, 0x00, 0xE0, 0x05, 0x20, 0xAA, 0x69, 0x88, 0x54, 0x30, 0x1C, 0xA6, 0x46, 0xE9, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x68, 0x60, 0xE8, 0x48 , -0x4D, 0x30, 0x70, 0xBD, 0xF0, 0xB5, 0x41, 0x68, 0x82, 0x68, 0x88, 0x23, 0x5E, 0x18, 0x37, 0x88, 0x0B, 0x6F, 0x00, 0x2B, 0x01, 0xD1, 0x00, 0x2F, 0x10, 0xD1, 0x06, 0x2F, 0x02, 0xDD, 0x00, 0x21, 0xC9, 0x43, 0x07, 0xE0, 0x33, 0x88, 0x9B, 0x00, 0xC9, 0x18, 0x0A, 0x67, 0x31, 0x88, 0x01, 0x31, 0x31, 0x80, 0x01, 0x21, 0x81, 0x60, 0xE1, 0x48, 0x1D, 0x30, 0xF0, 0xBD, 0x0B, 0x1C, 0x01, 0x24, 0x5D, 0x6F, 0x1D, 0x67, 0x04, 0x33, 0x01, 0x34, 0x06, 0x2C, 0xE1, 0xDA, 0xF8, 0xE7, 0x00, 0xB5, 0x00, 0x21, 0xC1, 0x60, 0xE9, 0x48, 0x01, 0x68, 0x10, 0x31, 0xE6, 0x48, 0x20, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xE7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE5, 0x48, 0xFB, 0x30, 0x00, 0xBD, 0xFF, 0xFF, 0xC0, 0x68, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x14, 0x0D, 0x1B, 0x00, 0x54, 0x19, 0x1B, 0x00, 0x91, 0x1A, 0x01, 0x00, 0x4B, 0xAD, 0x03, 0x00, 0x61, 0x4E, 0x01, 0x00, 0x06, 0x32, 0x08, 0x00, 0x1F, 0x0B, 0x02, 0x00, 0x54, 0x3F , -0x08, 0x00, 0x45, 0xC1, 0x00, 0x00, 0x84, 0x3C, 0x08, 0x00, 0x1B, 0x02, 0x00, 0x00, 0xED, 0x17, 0x00, 0x00, 0xF3, 0xC1, 0x01, 0x00, 0x34, 0x19, 0x1B, 0x00, 0x08, 0x19, 0x1B, 0x00, 0xA6, 0x44, 0x08, 0x00, 0x1C, 0x17, 0x1B, 0x00, 0x18, 0x17, 0x1B, 0x00, 0xCB, 0x67, 0x03, 0x00, 0x0D, 0x47, 0x02, 0x00, 0x39, 0x42, 0x03, 0x00, 0xBD, 0xE7, 0x02, 0x00, 0xB1, 0x40, 0x03, 0x00, 0xB9, 0xEA, 0x01, 0x00, 0x45, 0xDA, 0x00, 0x00, 0x24, 0x41, 0x08, 0x00, 0x71, 0xC0, 0x02, 0x00, 0xF0, 0xB5, 0x88, 0xB0, 0x06, 0x91, 0x07, 0x90, 0x86, 0x69, 0xF0, 0x1C, 0xD9, 0xA1, 0x04, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x14, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x32, 0xD1, 0xF2, 0x79, 0xD7, 0x48, 0x02, 0x70, 0x35, 0x7A, 0x77, 0x7A, 0x78, 0x1B, 0xFF, 0xFF, 0x56, 0x69, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x43, 0x1C, 0x93, 0x42, 0x1D, 0xD0, 0x16, 0x2A, 0x0C, 0xDB, 0x00, 0x2D, 0x0A, 0xD1, 0xD6, 0x48, 0x04, 0x70, 0x0A, 0x20 , -0x81, 0x19, 0xD0, 0x48, 0x1A, 0x1C, 0xA6, 0x46, 0xB8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x74, 0xE0, 0xD2, 0x48, 0x04, 0x70, 0xCC, 0x48, 0x40, 0x19, 0x0A, 0x21, 0x89, 0x19, 0x7A, 0x1B, 0x52, 0x1C, 0xA6, 0x46, 0xB1, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x67, 0xE0, 0x8F, 0xC6, 0x03, 0x00, 0xC9, 0x48, 0x04, 0x70, 0xC9, 0x48, 0x04, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xC2, 0x48, 0xA6, 0x46, 0xAA, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x59, 0xE0, 0xF0, 0x1C, 0x03, 0x21, 0x0A, 0x1C, 0xBC, 0xA1, 0xA6, 0x46, 0xC6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x4F, 0xD1, 0xF1, 0x79, 0xBB, 0x48, 0x01, 0x70, 0xBB, 0x4D, 0xB2, 0x79, 0x2A, 0x70, 0x03, 0x20, 0x17, 0x49, 0xF4, 0x31, 0xA6, 0x46, 0xB8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x28, 0x78, 0x00, 0x28, 0x0B, 0xD1, 0xFF, 0xE7, 0xB8, 0x49, 0x0C, 0x70, 0xB8, 0x49, 0xFF, 0xFF, 0xEC, 0x69, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0C, 0x70, 0x03, 0x20, 0x0F, 0x49, 0xF5, 0x31, 0xA6, 0x46 , -0xB6, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x20, 0x1C, 0xF2, 0x79, 0x35, 0x7A, 0x77, 0x7A, 0x79, 0x1B, 0x4B, 0x1C, 0x93, 0x42, 0x20, 0xD0, 0xA9, 0x49, 0x09, 0x78, 0x16, 0x29, 0x0F, 0xDB, 0x00, 0x2D, 0x0D, 0xD1, 0xAB, 0x49, 0x08, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xE9, 0x48, 0x1A, 0x1C, 0xA6, 0x46, 0x8B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x1A, 0xE0, 0xC0, 0x46, 0xC7, 0x04, 0x00, 0x00, 0xA5, 0x49, 0x08, 0x70, 0xE3, 0x48, 0x40, 0x19, 0x0A, 0x21, 0x89, 0x19, 0x7A, 0x1B, 0x52, 0x1C, 0xA6, 0x46, 0x83, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x0A, 0xE0, 0x9E, 0x49, 0x08, 0x70, 0x9E, 0x49, 0x08, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xDB, 0x48, 0xA6, 0x46, 0x7D, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x96, 0x48, 0x00, 0x78, 0x00, 0x28, 0x0A, 0xD0, 0x95, 0x48, 0x00, 0x78, 0x00, 0x28, 0x06, 0xD0, 0x94, 0x48, 0x00, 0x78, 0x00, 0x28, 0x02, 0xD0, 0x93, 0x48, 0x00, 0x78, 0x00, 0x28, 0xFF, 0xFF, 0x82, 0x6A, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00 , -0x00, 0xD1, 0x8C, 0xE0, 0x03, 0x20, 0x17, 0x21, 0x89, 0x01, 0xA6, 0x46, 0x90, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x87, 0x48, 0x01, 0x78, 0x87, 0x48, 0x07, 0x78, 0x84, 0x4E, 0x83, 0x4D, 0xE0, 0x48, 0x00, 0x68, 0x00, 0x28, 0x2E, 0xD1, 0x07, 0x98, 0x41, 0x61, 0x06, 0x62, 0xC6, 0x48, 0x06, 0x9A, 0x10, 0x64, 0x02, 0x2F, 0x01, 0xD0, 0x03, 0x2F, 0x01, 0xD1, 0x03, 0x22, 0x00, 0xE0, 0x3A, 0x1C, 0x06, 0x9B, 0xDA, 0x63, 0x2A, 0x78, 0x9A, 0x63, 0x01, 0x2F, 0x03, 0xD1, 0x05, 0x29, 0x04, 0xD0, 0x0D, 0x29, 0x02, 0xD0, 0xEC, 0x48, 0xDB, 0x30, 0x64, 0xE0, 0x00, 0x25, 0x00, 0x95, 0x01, 0x91, 0x02, 0x96, 0x03, 0x95, 0x04, 0x90, 0x2B, 0x1C, 0x20, 0x1C, 0x01, 0x1C, 0x8E, 0x46, 0xE6, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0xE6, 0x48, 0x04, 0x60, 0x28, 0x1C, 0xA6, 0x46, 0xE5, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x4C, 0xE0, 0x0D, 0x27, 0x00, 0x20, 0x39, 0x1C, 0x05, 0xAA, 0xA6, 0x46, 0xE3, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x68, 0x46 , -0xFF, 0xFF, 0x18, 0x6B, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x80, 0x8A, 0x40, 0x08, 0x05, 0xD2, 0x38, 0x1C, 0x50, 0x21, 0xA6, 0x46, 0xDC, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x38, 0x1C, 0x21, 0x1C, 0x0B, 0x1C, 0x29, 0x1C, 0x00, 0x22, 0xA6, 0x46, 0xD9, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x2B, 0x78, 0x0D, 0x20, 0x31, 0x1C, 0x22, 0x1C, 0xA6, 0x46, 0xD5, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x28, 0x78, 0x01, 0x30, 0x02, 0x1C, 0x0D, 0x20, 0x57, 0x49, 0x23, 0x1C, 0xA6, 0x46, 0xD0, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x55, 0x4E, 0x28, 0x78, 0x02, 0x30, 0x02, 0x1C, 0x0D, 0x20, 0x31, 0x1C, 0x23, 0x1C, 0xA6, 0x46, 0xCA, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x30, 0x78, 0x00, 0x28, 0x0A, 0xD0, 0x28, 0x78, 0x03, 0x30, 0x02, 0x1C, 0x4C, 0x48, 0x03, 0x78, 0x0D, 0x20, 0x8F, 0x49, 0xA6, 0x46, 0xC3, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0xBF, 0x48, 0x04, 0x60, 0x00, 0x20, 0xA6, 0x46, 0xBE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xB9, 0x48, 0xEC, 0x49 , -0x08, 0x18, 0x08, 0xB0, 0xF0, 0xBD, 0xC0, 0x46, 0x7B, 0xC0, 0xFF, 0xFF, 0xAE, 0x6B, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x1C, 0xE9, 0x48, 0x02, 0x68, 0xE9, 0x48, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x22, 0x0A, 0x62, 0x8A, 0x61, 0x1D, 0x30, 0xF7, 0x46, 0xD7, 0x30, 0xF7, 0x46, 0xC0, 0x46, 0x9F, 0x03, 0x00, 0x00, 0x7D, 0xB8, 0x03, 0x00, 0x01, 0x1C, 0xE2, 0x48, 0x02, 0x68, 0xE2, 0x48, 0x00, 0x2A, 0x02, 0xD0, 0xFF, 0x30, 0xB4, 0x30, 0xF7, 0x46, 0x00, 0x22, 0xCA, 0x61, 0x8A, 0x61, 0x4F, 0x30, 0xF7, 0x46, 0xC9, 0x21, 0x01, 0x00, 0x91, 0xE1, 0x00, 0x00, 0xDB, 0x48, 0x01, 0x68, 0x8A, 0x69, 0x01, 0x20, 0xC0, 0x03, 0x10, 0x43, 0x88, 0x61, 0x00, 0x20, 0x08, 0x61, 0xD8, 0x48, 0x23, 0x30, 0xF7, 0x46, 0x89, 0x17, 0x02, 0x00, 0x70, 0xB5, 0x05, 0x1C, 0xD5, 0x4E, 0x29, 0x6A, 0xEA, 0x69, 0x30, 0x1C, 0x01, 0x24, 0xA6, 0x46, 0x0B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x68, 0x69, 0xA6, 0x46, 0xD1, 0x49 , -0xFE, 0x44, 0x08, 0x47, 0xA8, 0x69, 0x06, 0x30, 0xA8, 0x60, 0xCF, 0x48, 0x00, 0x68, 0x68, 0x60, 0xEE, 0x60, 0xCE, 0x48, 0xFF, 0xFF, 0x44, 0x6C, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x6D, 0x30, 0x70, 0xBD, 0x46, 0x17, 0x1B, 0x00, 0x30, 0x3F, 0x08, 0x00, 0x41, 0xEB, 0x00, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x30, 0xB5, 0xEE, 0x48, 0x01, 0x6D, 0x80, 0x6C, 0x08, 0x43, 0x18, 0xD0, 0xEC, 0x49, 0x08, 0x1C, 0x07, 0x22, 0xFF, 0x23, 0x09, 0x33, 0x1B, 0x58, 0x00, 0x2B, 0x04, 0xD0, 0xFF, 0x30, 0x1D, 0x30, 0x01, 0x3A, 0xF6, 0xD1, 0x0B, 0xE0, 0x02, 0x20, 0xF0, 0x4A, 0xF1, 0x4B, 0x01, 0x24, 0xA6, 0x46, 0xF0, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0xA6, 0x46, 0xEF, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xEF, 0x48, 0xFF, 0x30, 0x5C, 0x30, 0x30, 0xBD, 0xC0, 0x46, 0x53, 0x53, 0x49, 0x44, 0x00, 0xC0, 0x46, 0xC0, 0x4B, 0x45, 0x59, 0x00, 0xEE, 0x62, 0x08, 0x00, 0xF0, 0x62, 0x08, 0x00, 0xEC, 0x62, 0x08, 0x00, 0xED, 0x62, 0x08, 0x00 , -0xE7, 0x7E, 0x03, 0x00, 0xE8, 0x62, 0x08, 0x00, 0xE9, 0x62, 0x08, 0x00, 0xEA, 0x62, 0x08, 0x00, 0xEB, 0x62, 0x08, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0xF0, 0xB5, 0xFF, 0xFF, 0xDA, 0x6C, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x87, 0xB0, 0x00, 0x91, 0x01, 0x90, 0x6B, 0x48, 0x01, 0x68, 0xCC, 0x4A, 0x14, 0x1C, 0x02, 0x94, 0x07, 0x26, 0x00, 0x25, 0x03, 0x95, 0x04, 0x94, 0x05, 0x95, 0xDF, 0x48, 0x00, 0x68, 0x08, 0x43, 0x27, 0xD0, 0xE0, 0x68, 0x03, 0x99, 0x88, 0x42, 0x0A, 0xDD, 0x03, 0x90, 0x40, 0x1C, 0x00, 0x99, 0x88, 0x60, 0xC2, 0x49, 0xFF, 0x20, 0x1D, 0x30, 0x68, 0x43, 0x0C, 0x18, 0xE0, 0x68, 0x04, 0x91, 0x02, 0x99, 0xC9, 0x68, 0x88, 0x42, 0x10, 0xDB, 0x88, 0x42, 0x10, 0xD1, 0x02, 0x98, 0x01, 0x27, 0xBE, 0x46, 0xCE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x06, 0x90, 0x20, 0x1C, 0xBE, 0x46, 0xCB, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x06, 0x99, 0x88, 0x42, 0x01, 0xDA, 0x05, 0x95, 0x02, 0x94 , -0x51, 0x48, 0x01, 0x68, 0xFF, 0x27, 0x09, 0x37, 0x38, 0x59, 0x00, 0x28, 0x06, 0xD0, 0xC7, 0x48, 0x00, 0x68, 0x07, 0x2E, 0x00, 0xD1, 0x2E, 0x1C, 0x08, 0x43, 0x04, 0xD0, 0xFF, 0x34, 0x1D, 0x34, 0x01, 0x35, 0x07, 0x2D, 0xC2, 0xDB, 0x07, 0x2E, 0xFF, 0xFF, 0x70, 0x6D, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0A, 0xD1, 0xC0, 0x48, 0x00, 0x68, 0x08, 0x43, 0x06, 0xD0, 0x05, 0x9E, 0x30, 0x1C, 0x01, 0x21, 0x8E, 0x46, 0xBA, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x98, 0x47, 0x61, 0x00, 0x21, 0x81, 0x61, 0xFF, 0x22, 0x1D, 0x32, 0x72, 0x43, 0x04, 0x99, 0x89, 0x18, 0xC1, 0x61, 0x06, 0x62, 0xB4, 0x48, 0x39, 0x30, 0x07, 0xB0, 0xF0, 0xBD, 0x10, 0xB5, 0x04, 0x1C, 0x00, 0x20, 0x01, 0x21, 0x8E, 0x46, 0xB1, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x40, 0x1E, 0x00, 0xD5, 0x00, 0x20, 0x60, 0x60, 0xE0, 0x61, 0xAE, 0x48, 0x21, 0x30, 0x10, 0xBD, 0xC0, 0x46, 0x10, 0x63, 0x08, 0x00, 0x70, 0xB5, 0x04, 0x1C, 0xE5, 0x69, 0x66, 0x69 , -0x00, 0x20, 0x01, 0x21, 0x8E, 0x46, 0xA7, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x60, 0x60, 0xAB, 0x19, 0xA6, 0x4A, 0xA5, 0x49, 0x93, 0x42, 0x02, 0xD3, 0x9A, 0x1A, 0x82, 0x42, 0x02, 0xD9, 0x08, 0x1C, 0x99, 0x30, 0x70, 0xBD, 0x08, 0x1C, 0xAB, 0x30, 0x70, 0xBD, 0x08, 0x6B, 0x41, 0x7D, 0x02, 0x88, 0x92, 0x00, 0xFF, 0xFF, 0x06, 0x6E, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x51, 0x1A, 0x3C, 0x39, 0xFF, 0x22, 0x5F, 0x32, 0x91, 0x42, 0x03, 0xD9, 0x65, 0x21, 0x01, 0x80, 0x02, 0x21, 0x81, 0x73, 0x9B, 0x48, 0x99, 0x49, 0x08, 0x18, 0xF7, 0x46, 0xC0, 0x46, 0x30, 0x63, 0x08, 0x00, 0xF8, 0xB5, 0x40, 0x68, 0x24, 0x21, 0x41, 0x43, 0x97, 0x48, 0x45, 0x18, 0x28, 0x1D, 0x0C, 0x21, 0x49, 0x19, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x94, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x91, 0x4C, 0x00, 0x28, 0x1B, 0xD0, 0x2B, 0x1C, 0x04, 0x22, 0x6E, 0x46, 0x91, 0x49, 0x1F, 0x7B, 0x08, 0x78, 0xC0, 0x43, 0x38, 0x43, 0x30, 0x70, 0x01, 0x33 , -0x01, 0x31, 0x01, 0x36, 0x01, 0x3A, 0xF5, 0xD1, 0x0C, 0x20, 0x41, 0x19, 0x68, 0x46, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x87, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x02, 0xD0, 0x20, 0x1C, 0x4A, 0x30, 0xF8, 0xBD, 0x20, 0x1C, 0xF8, 0xBD, 0xB1, 0xBD, 0x00, 0x00, 0x15, 0x95, 0x00, 0x00, 0x58, 0x3F, 0x08, 0x00, 0xF3, 0xF8, 0x00, 0x00, 0xE9, 0x09, 0x02, 0x00, 0xFF, 0xFF, 0x9C, 0x6E, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x2B, 0x09, 0x02, 0x00, 0xDD, 0x0A, 0x02, 0x00, 0xF8, 0xB5, 0x05, 0x1C, 0xAA, 0x69, 0x7D, 0x49, 0x00, 0x20, 0x08, 0x56, 0x24, 0x21, 0x41, 0x43, 0x76, 0x48, 0x43, 0x18, 0x04, 0x24, 0x6E, 0x46, 0x76, 0x49, 0x1F, 0x79, 0x08, 0x78, 0xC0, 0x43, 0x38, 0x43, 0x30, 0x70, 0x01, 0x33, 0x01, 0x31, 0x01, 0x36, 0x01, 0x3C, 0xF5, 0xD1, 0x11, 0x1D, 0x68, 0x46, 0x04, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x6D, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x01, 0x1C, 0x6D, 0x48, 0x04, 0xD0, 0x6E, 0x49, 0x09, 0x78 , -0x69, 0x60, 0x45, 0x30, 0xF8, 0xBD, 0xEC, 0x61, 0xAF, 0x30, 0xF8, 0xBD, 0x70, 0xB5, 0xC5, 0x68, 0x81, 0x68, 0x0A, 0x89, 0x6D, 0x4E, 0x00, 0x2A, 0x22, 0xD0, 0x01, 0x24, 0xC2, 0x6D, 0xA2, 0x18, 0xC2, 0x65, 0x08, 0x89, 0x0D, 0x28, 0x1B, 0xD1, 0x68, 0x6B, 0x21, 0x1C, 0xA6, 0x46, 0x63, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x22, 0x1C, 0x28, 0x1C, 0x00, 0x21, 0xA6, 0x46, 0x60, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x2C, 0x60, 0xE9, 0x6B, 0xFF, 0xFF, 0x32, 0x6F, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x28, 0x1C, 0xA6, 0x46, 0x5E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x28, 0x1C, 0xA6, 0x46, 0x5C, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x30, 0x1C, 0x3D, 0x30, 0x70, 0xBD, 0x30, 0x1C, 0x23, 0x30, 0x70, 0xBD, 0xC0, 0x46, 0xB1, 0x02, 0x00, 0x00, 0x74, 0x3F, 0x08, 0x00, 0x19, 0xC6, 0x00, 0x00, 0x5C, 0x3F, 0x08, 0x00, 0x1D, 0xC2, 0x00, 0x00, 0x68, 0x44, 0x08, 0x00, 0x43, 0x12, 0x03, 0x00, 0x34, 0x63, 0x08, 0x00, 0x2F, 0x7A, 0x02, 0x00 , -0xB4, 0x36, 0x08, 0x00, 0x8F, 0xF4, 0x01, 0x00, 0xF0, 0xB5, 0x05, 0x1C, 0xAB, 0x69, 0xEC, 0x69, 0x60, 0x68, 0x00, 0x68, 0x2A, 0x30, 0x01, 0x78, 0x0A, 0x06, 0x41, 0x78, 0x09, 0x04, 0x8A, 0x18, 0x81, 0x78, 0x09, 0x02, 0x8A, 0x18, 0xC1, 0x78, 0x8A, 0x18, 0x8E, 0x26, 0xF1, 0x5A, 0x09, 0x0A, 0x01, 0x70, 0xF0, 0x5C, 0x61, 0x68, 0x09, 0x68, 0x2B, 0x26, 0x70, 0x54, 0x8C, 0x20, 0xC0, 0x18, 0x61, 0x68, 0x0E, 0x68, 0x01, 0x88, 0x09, 0x0A, 0x2C, 0x27, 0xB9, 0x55, 0x61, 0x68, 0x09, 0x68, 0xFF, 0xFF, 0xC8, 0x6F, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x2D, 0x26, 0x00, 0x78, 0x70, 0x54, 0x60, 0x68, 0x01, 0x68, 0x32, 0x31, 0x08, 0x78, 0x00, 0x02, 0x49, 0x78, 0x08, 0x18, 0x00, 0x04, 0x00, 0x0C, 0x8C, 0x21, 0xCB, 0x58, 0x35, 0x49, 0x41, 0x40, 0x08, 0x04, 0x00, 0x0C, 0xC0, 0x18, 0x80, 0x1A, 0x01, 0x21, 0x8E, 0x46, 0x32, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x61, 0x68, 0x0A, 0x68, 0x32, 0x23, 0x01, 0x0A, 0x99, 0x54 , -0x61, 0x68, 0x09, 0x68, 0x33, 0x22, 0x50, 0x54, 0x60, 0x68, 0x68, 0x60, 0x2C, 0x48, 0xF0, 0xBD, 0x00, 0x00, 0x1B, 0x00, 0x34, 0x04, 0x1B, 0x00, 0x02, 0x6A, 0x8B, 0x69, 0xDB, 0x69, 0x1B, 0x68, 0x83, 0x60, 0x88, 0x69, 0xC0, 0x69, 0x41, 0x68, 0x8A, 0x42, 0x00, 0xDA, 0x42, 0x60, 0x25, 0x48, 0x79, 0x30, 0xF7, 0x46, 0x24, 0x48, 0x57, 0x30, 0xF7, 0x46, 0x24, 0x48, 0x91, 0x30, 0xF7, 0x46, 0x32, 0x04, 0x00, 0x00, 0xC4, 0x07, 0x00, 0x00, 0x15, 0x09, 0x02, 0x00, 0xC5, 0x93, 0x00, 0x00, 0x0D, 0x91, 0x00, 0x00, 0x40, 0x1E, 0x80, 0x00, 0x1E, 0x4B, 0xFF, 0xFF, 0x5E, 0x70, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x19, 0x50, 0x1C, 0x49, 0x0A, 0x50, 0xF7, 0x46, 0xC0, 0x46, 0xBD, 0xB5, 0x00, 0x00, 0x95, 0x92, 0x00, 0x00, 0xFD, 0x93, 0x00, 0x00, 0x54, 0x3F, 0x08, 0x00, 0x29, 0x4F, 0x03, 0x00, 0xDF, 0xE8, 0x02, 0x00, 0x36, 0x89, 0x41, 0x00, 0x81, 0x06, 0x00, 0x00, 0xB1, 0x78, 0x00, 0x00, 0x94, 0xEC, 0x01, 0x00 , -0x08, 0x19, 0x1B, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0x1C, 0x17, 0x1B, 0x00, 0x67, 0x66, 0x03, 0x00, 0xA6, 0x44, 0x08, 0x00, 0x18, 0x17, 0x1B, 0x00, 0xA7, 0x2F, 0x02, 0x00, 0x91, 0x44, 0x03, 0x00, 0x91, 0x63, 0x03, 0x00, 0x5B, 0x44, 0x03, 0x00, 0xE7, 0x44, 0x03, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x61, 0xA2, 0x03, 0x00, 0x6A, 0x1E, 0x01, 0x00, 0x45, 0xDA, 0x00, 0x00, 0xD7, 0xE8, 0x01, 0x00, 0xE9, 0x78, 0x02, 0x00, 0x04, 0xF3, 0x1A, 0x00, 0x80, 0x7B, 0x08, 0x00, 0xFC, 0xB5, 0x04, 0x1C, 0xA5, 0x69, 0x60, 0x6A, 0x01, 0x90, 0x20, 0x69, 0x00, 0x28, 0x35, 0xD4, 0x08, 0x28, 0x33, 0xDA, 0xE1, 0x69, 0x09, 0x68, 0xFF, 0xFF, 0xF4, 0x70, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x10, 0x29, 0x2F, 0xD1, 0xAC, 0x21, 0x41, 0x43, 0x9E, 0x4A, 0x51, 0x5C, 0x49, 0x08, 0x27, 0xD3, 0x00, 0x06, 0x00, 0x16, 0xA2, 0x68, 0x69, 0x46, 0x01, 0x23, 0x9E, 0x46, 0x9A, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x06, 0x1C, 0x39, 0x30, 0x1F, 0xD0 , -0x00, 0x2E, 0x1D, 0xD0, 0x00, 0x98, 0x07, 0x68, 0x00, 0x99, 0x0C, 0x39, 0x01, 0x98, 0x01, 0x60, 0x28, 0x1D, 0x10, 0x21, 0x79, 0x1A, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x91, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x22, 0x2A, 0x80, 0xA8, 0x1C, 0x08, 0x21, 0x79, 0x1A, 0x01, 0x23, 0x9E, 0x46, 0x8C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x03, 0xE0, 0x38, 0x20, 0x00, 0xE0, 0x00, 0x20, 0xC6, 0x43, 0x26, 0x60, 0x89, 0x48, 0x7C, 0x30, 0x20, 0x62, 0xFC, 0xBD, 0x30, 0xB5, 0x05, 0x1C, 0x28, 0x69, 0xA9, 0x69, 0x90, 0x29, 0x1D, 0xD1, 0x69, 0x69, 0x09, 0x78, 0x04, 0x29, 0x19, 0xD0, 0x05, 0x29, 0x17, 0xD0, 0x0A, 0x29, 0x15, 0xD0, 0x06, 0x29, 0x13, 0xD0, 0x0C, 0x29, 0x01, 0xDB, 0xFF, 0xFF, 0x8A, 0x71, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x10, 0x29, 0x0F, 0xD1, 0x01, 0x24, 0xA6, 0x46, 0x7D, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x7C, 0x48, 0x7D, 0x49, 0x00, 0x22, 0xA6, 0x46, 0x7C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x7C, 0x48 , -0xFF, 0x30, 0x5F, 0x30, 0x28, 0x62, 0x30, 0xBD, 0xF0, 0xB5, 0x89, 0xB0, 0x05, 0x90, 0x41, 0x69, 0x02, 0x69, 0x75, 0x48, 0x79, 0x4E, 0x82, 0x42, 0x3A, 0xD0, 0x04, 0x30, 0x82, 0x42, 0x25, 0xD0, 0x74, 0x4D, 0xAA, 0x42, 0x00, 0xD0, 0xCC, 0xE0, 0x08, 0x68, 0x06, 0x1C, 0x0C, 0x22, 0x8F, 0x1A, 0x4A, 0x68, 0x89, 0x18, 0x09, 0x1D, 0x10, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x6E, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x01, 0x1C, 0x09, 0xD1, 0xAC, 0x22, 0x72, 0x43, 0xCB, 0x48, 0x80, 0x18, 0x46, 0x22, 0x12, 0x5C, 0x11, 0x2A, 0x01, 0xD1, 0x44, 0x22, 0x14, 0x54, 0x28, 0x1C, 0x3A, 0x1C, 0xA6, 0x46, 0x62, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x69, 0x48, 0xEC, 0x30, 0xAB, 0xE0, 0x08, 0x68, 0xC0, 0x00, 0x30, 0x18, 0x8A, 0x68, 0x02, 0x2A, 0x02, 0xD0, 0xFF, 0xFF, 0x20, 0x72, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xE7, 0x20, 0x80, 0x00, 0xA2, 0xE0, 0xCA, 0x68, 0x89, 0x18, 0x09, 0x7B, 0x41, 0x60, 0x80, 0x21, 0x01, 0x60, 0x3B, 0x20 , -0x00, 0x01, 0x99, 0xE0, 0x08, 0x68, 0x06, 0x90, 0xC0, 0x00, 0x34, 0x58, 0x10, 0x20, 0x04, 0x90, 0x01, 0x25, 0xAE, 0x46, 0x57, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x07, 0x90, 0x00, 0x28, 0x00, 0xD1, 0x89, 0xE0, 0x0C, 0x21, 0x07, 0x98, 0x0F, 0x18, 0xB0, 0x49, 0xAC, 0x20, 0x06, 0x9A, 0x50, 0x43, 0x08, 0x18, 0x48, 0x22, 0x13, 0x5C, 0x5B, 0x06, 0x5B, 0x0E, 0x13, 0x54, 0x06, 0x9A, 0xD2, 0x00, 0xB6, 0x18, 0x71, 0x68, 0x00, 0x29, 0x47, 0xD1, 0x00, 0x2C, 0x01, 0xDD, 0x08, 0x2C, 0x21, 0xDB, 0x00, 0x22, 0x69, 0x46, 0x0A, 0x70, 0x01, 0x92, 0x0A, 0x81, 0x8A, 0x72, 0xCD, 0x72, 0x0D, 0x73, 0x4D, 0x73, 0x01, 0x88, 0x44, 0x48, 0x06, 0x23, 0xAE, 0x46, 0x44, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x04, 0x1C, 0x02, 0xDC, 0x00, 0x20, 0xC0, 0x43, 0x36, 0xE0, 0x34, 0x60, 0xAC, 0x20, 0x60, 0x43, 0x9A, 0x49, 0xFF, 0xFF, 0xB6, 0x72, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x09, 0x18, 0x5C, 0x22, 0x28, 0x1C, 0x50, 0x54, 0x48, 0x20 , -0x42, 0x5C, 0x52, 0x06, 0x52, 0x0E, 0x42, 0x54, 0xAC, 0x20, 0x60, 0x43, 0x94, 0x49, 0x08, 0x18, 0x5C, 0x21, 0x09, 0x5C, 0x49, 0x1E, 0x02, 0x29, 0x16, 0xD9, 0x03, 0x39, 0x08, 0xD0, 0x00, 0x20, 0x30, 0x56, 0xAE, 0x46, 0xEA, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x80, 0x20, 0x30, 0x60, 0xDB, 0xE7, 0x08, 0x94, 0x80, 0x21, 0x31, 0x60, 0x48, 0x22, 0x13, 0x5C, 0x19, 0x43, 0x11, 0x54, 0xAE, 0x46, 0xE4, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x0A, 0xE0, 0x01, 0x20, 0xCE, 0xE7, 0x06, 0x98, 0x39, 0x1C, 0x04, 0xAA, 0xAE, 0x46, 0xE0, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x1C, 0x08, 0x90, 0x06, 0x98, 0x38, 0x60, 0x08, 0x98, 0x78, 0x60, 0x00, 0x28, 0x15, 0xD0, 0xAC, 0x20, 0x60, 0x43, 0x7C, 0x49, 0x09, 0x18, 0x48, 0x88, 0x02, 0x04, 0x02, 0x20, 0x10, 0x43, 0xB8, 0x60, 0x48, 0x68, 0x02, 0x0E, 0x01, 0x02, 0x09, 0x0E, 0x09, 0x02, 0x11, 0x43, 0x02, 0x04, 0x12, 0x0E, 0xFF, 0xFF, 0x4C, 0x73, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00 , -0x12, 0x04, 0x0A, 0x43, 0x00, 0x06, 0x10, 0x43, 0xF8, 0x60, 0x07, 0x98, 0x0D, 0x49, 0x00, 0x22, 0x10, 0x23, 0xAE, 0x46, 0xCE, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x13, 0x48, 0x00, 0xE0, 0x16, 0x20, 0xCC, 0x49, 0x09, 0x18, 0x05, 0x98, 0x01, 0x62, 0x09, 0xB0, 0xF0, 0xBD, 0x5D, 0x0D, 0x1B, 0x00, 0x81, 0xE7, 0x02, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x27, 0x1A, 0x02, 0x00, 0x2F, 0x7A, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x05, 0x10, 0x00, 0x00, 0xCF, 0xF6, 0x00, 0x00, 0xD5, 0xF4, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x91, 0x19, 0x02, 0x00, 0x50, 0x65, 0x08, 0x00, 0x71, 0xC0, 0x02, 0x00, 0x50, 0x19, 0x1B, 0x00, 0x29, 0x16, 0x01, 0x00, 0x2A, 0x03, 0x00, 0x00, 0xF0, 0xB5, 0x8B, 0xB0, 0x07, 0x90, 0x05, 0x69, 0x47, 0x69, 0x0C, 0x20, 0x38, 0x1A, 0x08, 0x90, 0xB6, 0x49, 0x8D, 0x42, 0x16, 0xD1, 0x78, 0x68, 0x0F, 0x30, 0x00, 0x11, 0x00, 0x01, 0x78, 0x60, 0x38, 0x68, 0x0B, 0x28, 0x0E, 0xD8, 0x00, 0x23, 0x68, 0x46 , -0xFF, 0xFF, 0xE2, 0x73, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x03, 0x70, 0x08, 0x98, 0x05, 0x22, 0x01, 0x24, 0xA6, 0x46, 0xAE, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0xAE, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0x08, 0x62, 0xAC, 0x48, 0x85, 0x42, 0x23, 0xD1, 0xAC, 0x48, 0x02, 0x78, 0x6C, 0x46, 0x22, 0x72, 0x43, 0x78, 0x63, 0x72, 0x81, 0x78, 0xA1, 0x72, 0xC0, 0x78, 0xE0, 0x72, 0x00, 0x91, 0x01, 0x90, 0x03, 0x20, 0xA6, 0x49, 0x01, 0x39, 0x01, 0x26, 0xB6, 0x46, 0xF3, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x04, 0x20, 0x20, 0x70, 0x08, 0x98, 0x9F, 0x49, 0x00, 0x22, 0x02, 0xAB, 0x01, 0x24, 0xA6, 0x46, 0x9B, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x9A, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0x08, 0x62, 0xEB, 0x49, 0x8D, 0x42, 0x14, 0xD1, 0x02, 0x22, 0x68, 0x46, 0x02, 0x70, 0x3A, 0x68, 0xAC, 0x20, 0x42, 0x43, 0x30, 0x48, 0x68, 0x30, 0x83, 0x18, 0x08, 0x98, 0x00, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x8F, 0x4C, 0xFE, 0x44 , -0x20, 0x47, 0x8E, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0xFF, 0xFF, 0x78, 0x74, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x08, 0x62, 0xEF, 0x48, 0x85, 0x42, 0x00, 0xD0, 0x04, 0xE1, 0x03, 0x20, 0x8C, 0x49, 0x01, 0x22, 0x96, 0x46, 0xEC, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x86, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x09, 0x90, 0x38, 0x68, 0xEA, 0x4D, 0x00, 0x28, 0x00, 0xD1, 0xE2, 0xE0, 0x01, 0x24, 0xA6, 0x46, 0xE6, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x00, 0x28, 0x00, 0xD1, 0xD6, 0xE0, 0xE4, 0x48, 0x02, 0x68, 0x03, 0x20, 0x7F, 0x49, 0x01, 0x31, 0xA6, 0x46, 0xE2, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xDF, 0x48, 0x00, 0x68, 0x00, 0x28, 0x5A, 0xD1, 0xDF, 0x4D, 0x2E, 0x20, 0x41, 0x19, 0xB8, 0x68, 0x03, 0x30, 0x08, 0x70, 0x38, 0x7A, 0x48, 0x70, 0x2E, 0x1C, 0x30, 0x36, 0xB8, 0x68, 0x28, 0x18, 0x30, 0x30, 0xDA, 0x49, 0x0A, 0x68, 0x30, 0x3A, 0x31, 0x1C, 0xA6, 0x46, 0xD8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x78, 0x68, 0x38, 0x18 , -0x01, 0x1D, 0xBA, 0x68, 0x30, 0x1C, 0xA6, 0x46, 0xD9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xB8, 0x68, 0x41, 0x19, 0x97, 0x22, 0xFF, 0xFF, 0x0E, 0x75, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x09, 0x30, 0x50, 0x54, 0xB8, 0x68, 0x46, 0x19, 0x9E, 0x36, 0x30, 0x70, 0x01, 0x36, 0xB8, 0x68, 0x01, 0xE0, 0x14, 0x0D, 0x1B, 0x00, 0x30, 0x18, 0xCA, 0x49, 0x0A, 0x68, 0x9E, 0x3A, 0x31, 0x1C, 0xA6, 0x46, 0xC8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x78, 0x68, 0x38, 0x18, 0x01, 0x1D, 0xBA, 0x68, 0x30, 0x1C, 0xA6, 0x46, 0xC9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xB8, 0x68, 0x40, 0x00, 0xC0, 0x49, 0x09, 0x68, 0x08, 0x18, 0x28, 0x18, 0xC0, 0x49, 0x0A, 0x79, 0x02, 0x70, 0x4A, 0x79, 0x42, 0x70, 0x8A, 0x79, 0x82, 0x70, 0xC9, 0x79, 0xC1, 0x70, 0x04, 0x30, 0x0F, 0x21, 0x41, 0x1A, 0x0A, 0x78, 0xBB, 0x68, 0x9A, 0x18, 0x0A, 0x70, 0x40, 0x1B, 0x00, 0x04, 0x00, 0x0C, 0xB5, 0x49, 0x08, 0x60, 0xB1, 0x48, 0x04, 0x60, 0x02, 0x20, 0x01, 0x1C , -0x11, 0x22, 0xA6, 0x46, 0xB4, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x06, 0x1C, 0x63, 0xD4, 0x03, 0x20, 0xA6, 0x46, 0xB1, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x0A, 0x90, 0x00, 0x25, 0x01, 0x1C, 0xFF, 0xFF, 0xA4, 0x75, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x8D, 0x42, 0x50, 0xD0, 0x29, 0x1C, 0x2B, 0x22, 0xA6, 0x46, 0xAD, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x0C, 0x20, 0x0A, 0x99, 0x40, 0x18, 0xAC, 0x22, 0x72, 0x43, 0xAB, 0x49, 0x8F, 0x18, 0x78, 0x63, 0x29, 0x1C, 0x18, 0x22, 0xA6, 0x46, 0xA6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x9F, 0x48, 0x02, 0x68, 0x79, 0x6B, 0x4A, 0x60, 0x0A, 0x98, 0xAC, 0x30, 0x08, 0x60, 0x08, 0x68, 0x9A, 0x49, 0xA6, 0x46, 0xA0, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x29, 0x1C, 0x03, 0xA8, 0x10, 0x22, 0xA6, 0x46, 0x9C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE0, 0x21, 0x68, 0x46, 0x01, 0x74, 0x45, 0x74, 0x85, 0x74, 0xFB, 0x21, 0xC1, 0x74, 0xEE, 0x49, 0xC1, 0x81, 0x02, 0x21, 0x81, 0x81, 0x79, 0x6B, 0xCA, 0x68 , -0x01, 0x20, 0xC0, 0x03, 0x10, 0x43, 0xC8, 0x60, 0x48, 0x68, 0x00, 0x90, 0x2A, 0x1C, 0x30, 0x1C, 0x0A, 0x9D, 0x29, 0x1C, 0x03, 0xAB, 0xA6, 0x46, 0xE6, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x07, 0x1C, 0x30, 0x06, 0x00, 0x16, 0xA6, 0x46, 0xEF, 0x49, 0xFF, 0xFF, 0x3A, 0x76, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xFE, 0x44, 0x08, 0x47, 0x28, 0x1C, 0xA6, 0x46, 0xEE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x11, 0xE0, 0x30, 0x06, 0x00, 0x16, 0xA6, 0x46, 0xE9, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x20, 0xC7, 0x43, 0x08, 0xE0, 0x07, 0x1C, 0x06, 0xE0, 0x00, 0x20, 0x00, 0x21, 0xCF, 0x43, 0x01, 0xE0, 0x00, 0x20, 0x07, 0x1C, 0x28, 0x60, 0x00, 0x23, 0x68, 0x46, 0x03, 0x70, 0x3A, 0x06, 0x12, 0x0E, 0x08, 0x98, 0x6F, 0x49, 0x01, 0x24, 0xA6, 0x46, 0x09, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x07, 0x98, 0x09, 0x99, 0x01, 0x62, 0x0B, 0xB0, 0xF0, 0xBD, 0xC1, 0x18, 0x01, 0x00, 0xF1, 0x1B, 0x01, 0x00, 0xF3, 0x1C, 0x02, 0x00, 0x7B, 0xC0 , -0x02, 0x00, 0x91, 0xF0, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0xA3, 0xC0, 0x02, 0x00, 0xA9, 0xE9, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 0xE4, 0x62, 0x08, 0x00, 0xAC, 0x05, 0x00, 0x00, 0xFE, 0xB5, 0x07, 0x1C, 0x7D, 0x69, 0xBE, 0x69, 0x0C, 0x20, 0x30, 0x1A, 0x01, 0x90, 0xDF, 0x4C, 0x0A, 0x2D, 0x13, 0xD1, 0xFF, 0xFF, 0xD0, 0x76, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x30, 0x68, 0xDB, 0x49, 0x08, 0x60, 0x01, 0x20, 0x86, 0x46, 0xDA, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x0A, 0x20, 0x00, 0x21, 0x01, 0x9A, 0x01, 0x23, 0x9E, 0x46, 0xE6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xF5, 0x20, 0x80, 0x00, 0x00, 0x19, 0x38, 0x62, 0x03, 0x2D, 0x79, 0xD1, 0xF5, 0x20, 0x80, 0x00, 0x00, 0x19, 0x02, 0x90, 0x70, 0x68, 0x00, 0x28, 0x0C, 0xD1, 0x00, 0x21, 0xCF, 0x48, 0x01, 0x60, 0xCF, 0x48, 0x00, 0x68, 0x00, 0x28, 0x61, 0xD0, 0x01, 0x21, 0x8E, 0x46, 0xCD, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x5B, 0xE0, 0xCC, 0x48, 0xB1, 0x68, 0x01, 0x60 , -0xF1, 0x68, 0x41, 0x60, 0x31, 0x69, 0x81, 0x60, 0x71, 0x69, 0xC1, 0x60, 0xB1, 0x69, 0xC1, 0x63, 0xF1, 0x69, 0x01, 0x64, 0x31, 0x6A, 0xC1, 0x64, 0x01, 0x24, 0xA6, 0x46, 0xC5, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xA6, 0x46, 0xC4, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x70, 0x68, 0x7D, 0x25, 0xED, 0x00, 0xA8, 0x42, 0x21, 0xD8, 0x01, 0x28, 0x18, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0xFF, 0xFF, 0x66, 0x77, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x28, 0x1C, 0xA6, 0x46, 0xBE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x1C, 0xE0, 0xB9, 0x48, 0x00, 0x23, 0x19, 0x1C, 0x59, 0x43, 0x3E, 0x22, 0x4A, 0x43, 0x82, 0x83, 0x02, 0x30, 0x01, 0x33, 0x10, 0x2B, 0xF6, 0xDB, 0xA6, 0x46, 0xB4, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xB5, 0x48, 0x0D, 0xE0, 0xB5, 0x4D, 0x28, 0x1C, 0xA6, 0x46, 0xB2, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x04, 0xE0, 0xA6, 0x46, 0xAF, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x75, 0x68, 0xAE, 0x48, 0x05, 0x60, 0x05, 0x1C, 0xA7, 0x4E, 0x30, 0x68 , -0x00, 0x28, 0x06, 0xD1, 0xAD, 0x48, 0x00, 0x68, 0xA6, 0x46, 0xAC, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x30, 0x60, 0x00, 0x94, 0x2B, 0x68, 0xAA, 0x49, 0xAB, 0x4A, 0xA6, 0x46, 0xAB, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0x9C, 0x48, 0x04, 0x60, 0x03, 0x20, 0x00, 0x21, 0x01, 0x9A, 0x01, 0x23, 0x9E, 0x46, 0xA7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x98, 0x38, 0x62, 0xFE, 0xBD, 0xC0, 0x46, 0x13, 0x7F, 0x03, 0x00, 0x12, 0x10, 0x00, 0x00, 0xFF, 0xFF, 0xFC, 0x77, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x30, 0xB5, 0x05, 0x1C, 0x00, 0x20, 0x01, 0x24, 0xA6, 0x46, 0xA0, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xA6, 0x46, 0x9F, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xA6, 0x46, 0x9E, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x7D, 0x21, 0xC9, 0x00, 0xA6, 0x46, 0x9E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x9B, 0x49, 0x08, 0x18, 0x99, 0x49, 0x08, 0x80, 0x9B, 0x48, 0x0A, 0x30, 0x28, 0x62, 0x30, 0xBD, 0x11, 0x10, 0x00, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0xB9, 0x90 , -0x00, 0x00, 0x6C, 0x64, 0x08, 0x00, 0xE7, 0x7E, 0x03, 0x00, 0x74, 0x64, 0x08, 0x00, 0x70, 0x64, 0x08, 0x00, 0x6D, 0xC6, 0x03, 0x00, 0x08, 0x19, 0x1B, 0x00, 0x11, 0x18, 0x02, 0x00, 0xD1, 0x78, 0x02, 0x00, 0xC9, 0xBA, 0x03, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x14, 0x0D, 0x1B, 0x00, 0xFE, 0xB5, 0x02, 0x90, 0x45, 0x69, 0x68, 0x46, 0x01, 0x21, 0x8E, 0x46, 0x89, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x89, 0x48, 0x04, 0x1C, 0x68, 0x68, 0x01, 0x69, 0x4A, 0x78, 0x00, 0x27, 0x3E, 0x1C, 0x20, 0x88, 0xFF, 0xFF, 0x92, 0x78, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x40, 0x08, 0x22, 0xD3, 0x20, 0x1D, 0x89, 0x1C, 0x01, 0x23, 0x9E, 0x46, 0x83, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x07, 0xD1, 0x68, 0x68, 0x00, 0x69, 0x40, 0x78, 0x21, 0x88, 0x09, 0x04, 0x89, 0x16, 0x81, 0x42, 0x3D, 0xD0, 0x02, 0x20, 0x00, 0x5F, 0x00, 0x99, 0x08, 0x1A, 0x00, 0x04, 0x00, 0x14, 0x3C, 0x28, 0x03, 0xDD, 0x20, 0x88, 0x40, 0x10, 0x40, 0x00 , -0x20, 0x80, 0x78, 0x1C, 0x07, 0x06, 0x3F, 0x0E, 0x68, 0x68, 0x01, 0x69, 0x4A, 0x78, 0x2A, 0x34, 0x01, 0x36, 0x14, 0x2E, 0xD5, 0xDB, 0x00, 0x2A, 0x02, 0xD1, 0xAB, 0x20, 0x40, 0x00, 0x50, 0xE0, 0x00, 0x9B, 0x6D, 0x48, 0x14, 0x21, 0x00, 0x22, 0x04, 0x88, 0x64, 0x08, 0x03, 0xD3, 0x2A, 0x30, 0x01, 0x32, 0x01, 0x39, 0xF8, 0xD1, 0x12, 0x06, 0x12, 0x0E, 0x14, 0x2F, 0x16, 0xD1, 0x66, 0x48, 0x00, 0x88, 0x00, 0x06, 0x44, 0x16, 0x64, 0x49, 0x00, 0x22, 0x01, 0x20, 0x4E, 0x8D, 0x36, 0x06, 0x76, 0x16, 0xA6, 0x42, 0x02, 0xDD, 0x34, 0x1C, 0x02, 0x06, 0xFF, 0xFF, 0x28, 0x79, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x12, 0x0E, 0x2A, 0x31, 0x01, 0x30, 0x14, 0x28, 0xF3, 0xDB, 0x02, 0xE0, 0x32, 0x06, 0x12, 0x0E, 0x00, 0x9B, 0x2A, 0x20, 0x42, 0x43, 0x5A, 0x48, 0x11, 0x18, 0x0C, 0x88, 0x01, 0x20, 0x20, 0x43, 0x00, 0x04, 0x00, 0x0C, 0x08, 0x80, 0xFE, 0x24, 0xA0, 0x43, 0x14, 0x24, 0x64, 0x57, 0x64, 0x06, 0x24, 0x0E , -0x04, 0x43, 0x52, 0x48, 0x14, 0x52, 0x14, 0x18, 0x63, 0x80, 0x08, 0x88, 0x80, 0x05, 0x82, 0x0D, 0x68, 0x68, 0x00, 0x69, 0x40, 0x78, 0x80, 0x02, 0x10, 0x43, 0x08, 0x80, 0x68, 0x68, 0x02, 0x69, 0x20, 0x1D, 0x91, 0x1C, 0x52, 0x78, 0x01, 0x23, 0x9E, 0x46, 0x4B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x98, 0x04, 0x61, 0xFE, 0x20, 0x47, 0x49, 0x09, 0x18, 0x02, 0x98, 0x01, 0x62, 0xFE, 0xBD, 0x82, 0x69, 0x41, 0x69, 0x03, 0x69, 0x02, 0x2B, 0x0A, 0xD1, 0x01, 0x2A, 0x01, 0xD1, 0x00, 0x29, 0x05, 0xD0, 0x02, 0x2A, 0x04, 0xD1, 0x00, 0x29, 0x02, 0xD1, 0x11, 0x21, 0x00, 0xE0, 0x06, 0x21, 0x41, 0x61, 0xF7, 0x46, 0xFF, 0xFF, 0xBE, 0x79, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xC0, 0x46, 0x14, 0xE9, 0x00, 0x00, 0xC9, 0x18, 0x02, 0x00, 0x30, 0xB5, 0x05, 0x1C, 0x3A, 0x48, 0x00, 0x78, 0x00, 0x28, 0x04, 0xD0, 0x01, 0x20, 0x86, 0x46, 0x38, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x01, 0x24, 0xA6, 0x46, 0x37, 0x48, 0xFE, 0x44 , -0x00, 0x47, 0xA6, 0x46, 0x36, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x35, 0x48, 0x0E, 0x30, 0x28, 0x62, 0x30, 0xBD, 0x49, 0x19, 0x01, 0x00, 0x2F, 0x7A, 0x02, 0x00, 0x18, 0xB5, 0x43, 0x69, 0x81, 0x69, 0x31, 0x48, 0x81, 0x29, 0x00, 0xD1, 0x0B, 0x38, 0x00, 0x21, 0x00, 0x91, 0x1A, 0x68, 0x9B, 0x68, 0x01, 0x24, 0xA6, 0x46, 0x2D, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x18, 0xBD, 0x18, 0xB5, 0x40, 0x69, 0x00, 0x21, 0x00, 0x91, 0x02, 0x68, 0x83, 0x68, 0x27, 0x48, 0x01, 0x30, 0x01, 0x24, 0xA6, 0x46, 0x26, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x18, 0xBD, 0xC0, 0x46, 0x30, 0x63, 0x08, 0x00, 0x19, 0x9E, 0x00, 0x00, 0xB9, 0xEC, 0x00, 0x00, 0x74, 0x3F, 0x08, 0x00, 0x80, 0x3F, 0x08, 0x00, 0xFF, 0xFF, 0x54, 0x7A, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xB7, 0x5D, 0x03, 0x00, 0x00, 0x00, 0x1B, 0x00, 0xD3, 0x8E, 0x00, 0x00, 0xF7, 0xC6, 0x00, 0x00, 0xE5, 0x90, 0x00, 0x00, 0x68, 0x64, 0x08, 0x00, 0xC0, 0x27, 0x09, 0x00, 0xA0, 0x3B , -0x08, 0x00, 0x3D, 0x5D, 0x03, 0x00, 0x19, 0xC6, 0x00, 0x00, 0xE8, 0x3A, 0x08, 0x00, 0x81, 0x5D, 0x03, 0x00, 0xCF, 0xF6, 0x00, 0x00, 0x4B, 0x4F, 0x03, 0x00, 0x6B, 0xC0, 0x03, 0x00, 0x95, 0x1E, 0x01, 0x00, 0xDA, 0x40, 0x08, 0x00, 0xDC, 0x05, 0x00, 0x00, 0x55, 0xAA, 0x03, 0x00, 0x0D, 0x91, 0x00, 0x00, 0xD7, 0x56, 0x03, 0x00, 0x08, 0x51, 0x08, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0x65, 0xB8, 0x00, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x84, 0x17, 0x1B, 0x00, 0xB5, 0x86, 0x01, 0x00, 0x3D, 0x47, 0x02, 0x00, 0x73, 0x49, 0x02, 0x00, 0x5F, 0x90, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x00, 0xF7, 0xF6, 0x00, 0x00, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x76, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x5A, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0xFF, 0xFF, 0xEA, 0x7A, 0x08, 0x00, 0x58, 0x00, 0x00, 0x00, 0x68, 0x46, 0xFF, 0xF7, 0x99, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x83, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5 , -0x68, 0x46, 0xFF, 0xF7, 0xB6, 0xFE, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x55, 0xFC, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x27, 0xFB, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0xDD, 0xFA, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x68, 0xFE, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x3D, 0xFB, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0xBE, 0xFD, 0xFF, 0xBD, 0x78, 0x7B, 0x08, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0xB5, 0xF8, 0xF0, 0x43, 0xFA, 0x00, 0xBD, 0x35, 0x66, 0x08, 0x00, 0x67, 0x66, 0x08, 0x00, 0x71, 0x65, 0x08, 0x00, 0x4D, 0x66, 0x08, 0x00, 0x25, 0x64, 0x08, 0x00, 0x81, 0x66, 0x08, 0x00, 0x8D, 0x66, 0x08, 0x00, 0x99, 0x66, 0x08, 0x00, 0x87, 0x67, 0x08, 0x00, 0xA7, 0x67, 0x08, 0x00, 0xD1, 0x67, 0x08, 0x00, 0x1B, 0x68, 0x08, 0x00, 0x57, 0x68, 0x08, 0x00, 0x2D, 0x69, 0x08, 0x00, 0xB1, 0x6B, 0x08, 0x00, 0xD5, 0x6B, 0x08, 0x00, 0xF9, 0x6B , -0x08, 0x00, 0x15, 0x6C, 0x08, 0x00, 0xA1, 0x68, 0x08, 0x00, 0x59, 0x6C, 0x08, 0x00, 0xA7, 0x6D, 0x08, 0x00, 0xFF, 0x6D, 0x08, 0x00, 0x29, 0x6E, 0x08, 0x00, 0xF9, 0x6E, 0x08, 0x00, 0xD9, 0x6C, 0x08, 0x00, 0xA5, 0x6E, 0x08, 0x00, 0xCD, 0x6D, 0x08, 0x00, 0x81, 0x6F, 0x08, 0x00, 0x1D, 0x70, 0x08, 0x00, 0x31, 0x64, 0x08, 0x00, 0x39, 0x70, 0x08, 0x00, 0x3F, 0x70, 0x08, 0x00, 0x04, 0xF3, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x00, 0xB2, 0x4E, 0x01, 0x00, 0x5A, 0xC1, 0x00, 0x00, 0x96, 0x1A, 0x01, 0x00, 0x22, 0x0B, 0x02, 0x00, 0x60, 0xD0, 0x01, 0x00, 0x06, 0x1A, 0x00, 0x00, 0xB8, 0xC6, 0x01, 0x00, 0xD8, 0x42, 0x03, 0x00, 0x16, 0x42, 0x03, 0x00, 0xEE, 0xDB, 0x00, 0x00, 0x62, 0xDC, 0x00, 0x00, 0xC8, 0xE1, 0x00, 0x00, 0x8A, 0x17, 0x02, 0x00, 0x38, 0xBE, 0x00, 0x00, 0x26, 0xC6, 0x00, 0x00, 0x56, 0xC2, 0x00, 0x00, 0x62, 0x12, 0x03, 0x00, 0xE4, 0xF4, 0x01, 0x00, 0x3A, 0xEC, 0x00, 0x00, 0x5E, 0x92, 0x00, 0x00 , -0xFE, 0xE8, 0x02, 0x00, 0x18, 0x7F, 0x00, 0x00, 0x64, 0xEC, 0x01, 0x00, 0xFE, 0x44, 0x03, 0x00, 0x1C, 0x94, 0x00, 0x00, 0xA8, 0x66, 0x03, 0x00, 0x74, 0xE9, 0x02, 0x00, 0x68, 0x1E, 0x01, 0x00, 0xBC, 0xDA, 0x00, 0x00, 0xEA, 0xE1, 0x00, 0x00, 0x24, 0xE9, 0x01, 0x00, 0x70, 0x79, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x1C, 0xF0, 0xB5, 0x88, 0xB0, 0xCA, 0x4C, 0x03, 0x20, 0x22, 0x78, 0x63, 0x78, 0xCA, 0x4E, 0x31, 0x1C, 0x01, 0x39, 0x01, 0x25, 0xAE, 0x46, 0xC7, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0xA2, 0x78, 0xE3, 0x78, 0x03, 0x20, 0x31, 0x1C, 0xAE, 0x46, 0xC3, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x03, 0x20, 0x31, 0x1C, 0x01, 0x31, 0xAE, 0x46, 0xC1, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0xC1, 0x48, 0x21, 0x78, 0x01, 0x70, 0x61, 0x78, 0x41, 0x70, 0xE1, 0x78, 0xC1, 0x70, 0xA1, 0x78, 0x81, 0x70, 0xBF, 0x48, 0x04, 0x1C, 0x33, 0x3C, 0x20, 0x1C, 0x00, 0x21, 0xDC, 0x22, 0xAE, 0x46 , -0xBA, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x84, 0x20, 0xA0, 0x70, 0x05, 0x27, 0xE7, 0x71, 0x0C, 0x26, 0x26, 0x73, 0x0D, 0x20, 0x00, 0x19, 0x98, 0xA1, 0x32, 0x1C, 0xAE, 0x46, 0xB4, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x20, 0x60, 0x76, 0x1A, 0x20, 0x00, 0x19, 0x97, 0xA1, 0x06, 0x91, 0x04, 0x22, 0xAE, 0x46, 0xAE, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xFF, 0xFF, 0x96, 0x00, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA7, 0x77, 0x1F, 0x34, 0x95, 0xA1, 0x07, 0x91, 0x20, 0x1C, 0x3A, 0x1C, 0xAE, 0x46, 0xA9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE6, 0x71, 0x28, 0x1C, 0x60, 0x72, 0x11, 0x20, 0x20, 0x73, 0x94, 0x20, 0x60, 0x73, 0xC0, 0x25, 0x65, 0x74, 0xA6, 0x74, 0x09, 0x22, 0xE2, 0x74, 0xA3, 0x4C, 0x20, 0x1C, 0x8C, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x9F, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x07, 0x22, 0x62, 0x72, 0x9E, 0x4C, 0x0A, 0x34, 0x20, 0x1C, 0x89, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x9A, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x20 , -0xE0, 0x71, 0x98, 0x4C, 0x12, 0x34, 0x20, 0x1C, 0x06, 0x99, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x94, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x27, 0x71, 0x93, 0x4C, 0x17, 0x34, 0x20, 0x1C, 0x07, 0x99, 0x3A, 0x1C, 0x01, 0x23, 0x9E, 0x46, 0x8E, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE6, 0x71, 0x01, 0x20, 0x60, 0x72, 0x11, 0x20, 0x20, 0x73, 0x94, 0x20, 0x60, 0x73, 0x02, 0x20, 0xE0, 0x73, 0x25, 0x74, 0x66, 0x74, 0xFF, 0xFF, 0x2C, 0x01, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA5, 0x74, 0x2F, 0x27, 0xE7, 0x74, 0x10, 0x20, 0x60, 0x75, 0x80, 0x26, 0xA6, 0x75, 0x01, 0x20, 0xE0, 0x75, 0x11, 0x20, 0xA0, 0x76, 0x94, 0x20, 0xE0, 0x76, 0x24, 0x20, 0x60, 0x77, 0x0A, 0x22, 0xA2, 0x77, 0x80, 0x4C, 0x36, 0x34, 0x20, 0x1C, 0x6D, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x7C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x18, 0x22, 0xA2, 0x72, 0x7A, 0x4C, 0x41, 0x34, 0x20, 0x1C, 0x6B, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x76, 0x4B, 0xFE, 0x44, 0x18, 0x47 , -0x25, 0x76, 0x67, 0x76, 0x21, 0x20, 0xE0, 0x76, 0x26, 0x77, 0x01, 0x20, 0x60, 0x77, 0x72, 0x48, 0x61, 0x30, 0x11, 0x21, 0x01, 0x70, 0x94, 0x21, 0x41, 0x70, 0x04, 0x21, 0x01, 0x72, 0xD2, 0x21, 0x41, 0x72, 0xC5, 0x72, 0x1E, 0x21, 0x01, 0x73, 0x45, 0x73, 0x9E, 0x21, 0x81, 0x73, 0x01, 0x21, 0x01, 0x74, 0x46, 0x74, 0x81, 0x74, 0x11, 0x21, 0x41, 0x75, 0x94, 0x21, 0x81, 0x75, 0x04, 0x21, 0x01, 0x76, 0xAD, 0x20, 0x66, 0x49, 0x08, 0x60, 0x00, 0x24, 0x0F, 0x25, 0xFF, 0xFF, 0xC2, 0x01, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x29, 0x06, 0x09, 0x0E, 0x00, 0x20, 0x6A, 0x46, 0x01, 0x23, 0x9E, 0x46, 0x62, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x6B, 0x46, 0x18, 0x88, 0x40, 0x08, 0x0E, 0xD3, 0xA0, 0x00, 0x0F, 0x21, 0xCA, 0x43, 0x69, 0x46, 0x0E, 0x88, 0x16, 0x40, 0x01, 0xAF, 0x3E, 0x52, 0x49, 0x88, 0x11, 0x40, 0x68, 0x44, 0xC1, 0x80, 0x60, 0x1C, 0x04, 0x04, 0x24, 0x0C, 0x01, 0x3D, 0x0B, 0x2D, 0xE0, 0xDA, 0x60, 0x1E , -0x00, 0x04, 0x00, 0x0C, 0x1D, 0xD0, 0x86, 0x46, 0x01, 0x1C, 0x01, 0xAD, 0x01, 0x22, 0xAE, 0x88, 0x90, 0x00, 0xC7, 0x5A, 0xB7, 0x42, 0x0A, 0xDA, 0xBC, 0x46, 0x07, 0x1C, 0x6F, 0x44, 0x7F, 0x88, 0x68, 0x44, 0x06, 0x80, 0xEE, 0x88, 0x46, 0x80, 0x60, 0x46, 0xA8, 0x80, 0xEF, 0x80, 0x04, 0x35, 0x50, 0x1C, 0x02, 0x04, 0x12, 0x0C, 0x01, 0x39, 0xE9, 0xD1, 0x70, 0x46, 0x01, 0x38, 0x86, 0x46, 0xE2, 0xD1, 0x99, 0x88, 0x68, 0x46, 0xC0, 0x88, 0x40, 0x18, 0x00, 0x04, 0x00, 0x0C, 0x42, 0x4B, 0x18, 0x80, 0x42, 0x49, 0x08, 0x1A, 0xFF, 0xFF, 0x58, 0x02, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x58, 0x80, 0x02, 0x2C, 0x1E, 0xDB, 0x65, 0x1E, 0x01, 0xAA, 0x01, 0x20, 0x01, 0x1C, 0x8C, 0x00, 0x6B, 0x46, 0xE6, 0x5A, 0x93, 0x88, 0xD4, 0x88, 0xE7, 0x18, 0xB7, 0x42, 0x0C, 0xDA, 0x06, 0x24, 0x44, 0x43, 0x38, 0x4B, 0x1B, 0x19, 0x1F, 0x80, 0x1C, 0x88, 0x34, 0x1B, 0x5C, 0x80, 0x01, 0x24, 0x1C, 0x71, 0x40, 0x1C, 0x00, 0x04 , -0x00, 0x0C, 0x04, 0x32, 0x49, 0x1C, 0x09, 0x06, 0x09, 0x0E, 0x01, 0x3D, 0xE4, 0xD1, 0x00, 0x24, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x01, 0x20, 0x86, 0x46, 0x30, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x2F, 0x49, 0x22, 0x1C, 0x08, 0x68, 0x00, 0x28, 0x02, 0xD0, 0x01, 0x20, 0x90, 0x40, 0x04, 0x43, 0x04, 0x31, 0x01, 0x32, 0x20, 0x2A, 0xF5, 0xD3, 0x2A, 0x48, 0x04, 0x60, 0x08, 0xB0, 0xF0, 0xBD, 0x5F, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2D, 0x69, 0x6E, 0x66, 0x6F, 0x00, 0xC0, 0x46, 0xC0, 0x5F, 0x75, 0x64, 0x70, 0x00, 0xC0, 0xFF, 0xFF, 0xEE, 0x02, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x46, 0xC0, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x00, 0xC0, 0x46, 0x5F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x00, 0xC0, 0x46, 0x5F, 0x64, 0x6E, 0x73, 0x2D, 0x73, 0x64, 0x00, 0x64, 0x65, 0x76, 0x3D, 0x43, 0x43, 0x33, 0x30, 0x30, 0x30, 0x00, 0xC0, 0x76, 0x65 , -0x6E, 0x64, 0x6F, 0x72, 0x3D, 0x54, 0x65, 0x78, 0x61, 0x73, 0x2D, 0x49, 0x6E, 0x73, 0x74, 0x72, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x73, 0x00, 0xC0, 0x46, 0xC0, 0x00, 0x00, 0x18, 0x00, 0xF3, 0x7E, 0x03, 0x00, 0xC6, 0x05, 0x00, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0xE4, 0x62, 0x08, 0x00, 0xC9, 0xBA, 0x03, 0x00, 0x09, 0xB4, 0x03, 0x00, 0xA7, 0x64, 0x08, 0x00, 0x70, 0x64, 0x08, 0x00, 0xDD, 0x0A, 0x02, 0x00, 0x48, 0x32, 0x08, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xE8, 0x62, 0x08, 0x00, 0xE9, 0x62, 0x08, 0x00, 0xEA, 0x62, 0x08, 0x00, 0xEB, 0x62, 0x08, 0x00, 0x81, 0x03, 0x18, 0x00, 0x80, 0x7B, 0x08, 0x00, 0x84, 0xF3, 0x1A, 0x00, 0x0D, 0x49, 0x0E, 0x48, 0xFF, 0xFF, 0x84, 0x03, 0x18, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x88, 0x67, 0x0E, 0x48, 0x88, 0x64, 0x0E, 0x48, 0x48, 0x64, 0x0E, 0x48, 0xC8, 0x64, 0x0E, 0x48, 0x08, 0x65, 0x11, 0x48, 0x02, 0x1C, 0x04, 0x32, 0x0C, 0x4B, 0x13, 0x60, 0x0C, 0x4B, 0x93, 0x62, 0x0C, 0x4A , -0x8A, 0x66, 0x0D, 0x49, 0x01, 0x60, 0x0D, 0x48, 0x0E, 0x49, 0x01, 0x60, 0x0E, 0x49, 0x41, 0x60, 0xF7, 0x46, 0x1C, 0x21, 0x08, 0x00, 0x1B, 0x7B, 0x08, 0x00, 0x11, 0x7B, 0x08, 0x00, 0x07, 0x7B, 0x08, 0x00, 0x39, 0x7B, 0x08, 0x00, 0x2F, 0x7B, 0x08, 0x00, 0x25, 0x7B, 0x08, 0x00, 0xFD, 0x7A, 0x08, 0x00, 0xDF, 0x7A, 0x08, 0x00, 0x50, 0x23, 0x08, 0x00, 0xD5, 0x7A, 0x08, 0x00, 0x58, 0x26, 0x08, 0x00, 0xF3, 0x7A, 0x08, 0x00, 0xE9, 0x7A, 0x08, 0x00 }; - - -const unsigned char cRMdefaultParams[128] = { 0x03, 0x00, 0x01, 0x01, 0x14, 0x14, 0x00, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x23, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x01, 0x77, 0x80, 0x1D, 0x1F, 0x22, 0x26, 0x28, 0x29, 0x1A, 0x1F, 0x22, 0x24, 0x26, 0x28, 0x16, 0x1D, 0x1E, 0x20, 0x24, 0x25, 0x1E, 0x2D, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x15, 0x15, 0x15, 0x11, 0x15, 0x15, 0x0E, 0x00}; - -// -//Service Pack version P1.13.7.15.15 - FW patches -// -const unsigned char fw_patch[5700] = { 0x00, 0x01, 0x00, 0x00, 0x3C, 0x16, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x14, 0x03, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x46, 0x25, 0xF0, 0x95, 0xFB, 0xE0, 0x6B, 0xD0, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x25, 0xF0, 0x38, 0xFB, 0x2C, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x25, 0xF0, 0x0A, 0xFB, 0x04, 0x15, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB8, 0xF1, 0x90, 0x0F, 0xA4, 0x16, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x66, 0xE0, 0x04, 0xA8, 0x35, 0x1D, 0x21, 0xF0, 0x99, 0xFC, 0x68, 0x46, 0x23, 0xF0, 0x28, 0xFB, 0x9A, 0xF8, 0x00, 0x00, 0x01, 0x28, 0x07, 0xD1, 0x28, 0x46, 0x05, 0xF0, 0xC3, 0xFE, 0x01, 0x46, 0x01, 0xAA, 0x00, 0x20, 0x21, 0xF0, 0x50, 0xF9, 0x28, 0x46, 0x05, 0xF0, 0xBB, 0xFE, 0x01, 0xA9, 0x21, 0xF0, 0x2A, 0xFA, 0xE9, 0x79, 0x4F, 0xEA, 0xE0, 0x00, 0x40, 0xB2, 0x11, 0xB1, 0x00, 0xF1, 0x06, 0x00, 0x40, 0xB2, 0xA8, 0x71, 0x1F, 0x38, 0x40, 0x00, 0xE8, 0x71, 0x30, 0x46 , -0x01, 0xF0, 0x0D, 0xFF, 0x10, 0xF1, 0x00, 0x09, 0x4F, 0xF0, 0x00, 0x01, 0x09, 0xD0, 0x28, 0x68, 0x40, 0x0C, 0x09, 0xD3, 0xE8, 0x68, 0xC0, 0x0B, 0x03, 0xD2, 0x48, 0x46, 0xFF, 0xF7, 0xDD, 0xFE, 0x01, 0x21, 0x28, 0x68, 0x40, 0x0C, 0x0A, 0xD2, 0x38, 0x68, 0x40, 0x1C, 0x38, 0x60, 0x20, 0x68, 0x6F, 0xF3, 0x0F, 0x00, 0x20, 0x60, 0x22, 0x68, 0x38, 0x68, 0x10, 0x43, 0x20, 0x60, 0xE8, 0x68, 0xC0, 0x0B, 0x0F, 0xD3, 0xD8, 0xF8, 0x00, 0x00, 0x00, 0xF1, 0x01, 0x00, 0xC8, 0xF8, 0x00, 0x00, 0x20, 0x68, 0x6F, 0xF3, 0x1F, 0x40, 0x20, 0x60, 0xD8, 0xF8, 0x00, 0x20, 0x20, 0x68, 0x40, 0xEA, 0x02, 0x40, 0x20, 0x60, 0x49, 0xB9, 0xB9, 0xF1, 0x00, 0x0F, 0x03, 0xD1, 0x30, 0x46, 0x07, 0xF0, 0xBE, 0xF9, 0x02, 0xE0, 0x48, 0x46, 0x07, 0xF0, 0x06, 0xFA, 0x6C, 0x17, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x68, 0x46, 0x0E, 0xF0, 0x85, 0xFB, 0x00, 0x9E, 0x00, 0x2E, 0x96, 0xD1, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xC0, 0x46 , -0x9C, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x23, 0xF0, 0x2A, 0xFE, 0x74, 0x47, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x21, 0x21, 0xF0, 0x41, 0xFA, 0x20, 0x68, 0x18, 0x4B, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x21, 0xF0, 0x1C, 0xF9, 0x0A, 0xE0, 0x20, 0x68, 0x00, 0x68, 0x0C, 0x21, 0x40, 0xF0, 0x20, 0x00, 0x21, 0xF0, 0x14, 0xF9, 0x10, 0x57, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0xA8, 0x20, 0xF0, 0x97, 0xF9, 0x01, 0x98, 0x5C, 0x57, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x20, 0xF0, 0x71, 0xF9, 0x03, 0x98, 0x00, 0x58, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x20, 0xF9, 0x1C, 0x58, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x12, 0xF9, 0x54, 0x58, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0xA8, 0x20, 0xF0, 0xF5, 0xF8, 0x04, 0xAB, 0x04, 0x62, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x79, 0x1F, 0xF0, 0x1B, 0xFD, 0x69, 0xE0, 0x60, 0x93, 0x00, 0x00, 0x40, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xA6, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1B, 0xF0, 0x39, 0xFB, 0x28, 0x46, 0x90, 0xA8, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1B, 0xF0, 0x69, 0xF9, 0x1E, 0x48, 0x34, 0xAD, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x68, 0xFF, 0x29, 0x98, 0xAD, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0xD4, 0x21, 0xD4, 0xB2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0xD0, 0x1A, 0xF0, 0x47, 0xFC, 0x20, 0x98, 0xAC, 0xC5, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x19, 0xF0 , -0xDB, 0xFA, 0x09, 0x49, 0x28, 0xC6, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x19, 0xF0, 0x9E, 0xFA, 0xDC, 0xD3, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xB5, 0x18, 0xF0, 0xAB, 0xFC, 0x00, 0xF0, 0x03, 0xF8, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xDF, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, 0xF0, 0xA8, 0xFD, 0xCC, 0xEB, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x38, 0x78, 0x17, 0xF0, 0x77, 0xF8, 0x38, 0x78, 0x16, 0xF0, 0xF0, 0xFF, 0xA8, 0xF7, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0E, 0x49, 0x09, 0x68, 0x23, 0x22, 0x41, 0x61, 0xC8, 0xF7, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x31, 0x2E, 0x31, 0x39, 0x2E, 0x33, 0x31, 0x34, 0x5F, 0x4E, 0x65, 0x77, 0x5F, 0x43, 0x43, 0x41, 0x5F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 0xC0, 0x74, 0x56, 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xF9, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x16, 0xF0, 0x79, 0xF8 , -0x12, 0xE0, 0x38, 0xFA, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0xA8, 0x16, 0xF0, 0x03, 0xF8, 0x32, 0x20, 0x94, 0xFB, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x0C, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x14, 0xF0, 0x05, 0xFF, 0x01, 0xF0, 0x10, 0x1B, 0x01, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x1E, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0xF0, 0x46, 0xBF, 0x18, 0x30, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x30, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0xF0, 0xD8, 0xFC, 0x9C, 0x31, 0x01, 0x00, 0x08, 0x00 , -0x00, 0x00, 0x68, 0x46, 0x12, 0xF0, 0x51, 0xFC, 0xFE, 0xF7, 0xF0, 0x35, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x46, 0x12, 0xF0, 0x27, 0xFA, 0xFE, 0xF7, 0xF0, 0x3D, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0xA9, 0x11, 0xF0, 0x27, 0xFE, 0x20, 0x6F, 0xD0, 0x62, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0xB8, 0xFB, 0x80, 0x7E, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0xDF, 0xF8, 0x58, 0x82, 0xE0, 0x7E, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0D, 0xF0, 0x6A, 0xFE, 0x0B, 0xF0, 0x9A, 0xF9, 0x03, 0x20, 0xA8, 0xF5, 0x88, 0x71, 0x08, 0x60, 0xF2, 0xF7, 0x16, 0xF9, 0x7A, 0x48, 0x6B, 0x49, 0x9C, 0x7F, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x70, 0x51, 0x4D, 0xC4, 0x7F, 0x01, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x40, 0x49, 0x00, 0xF1, 0x52, 0x00, 0x3A, 0x4A, 0xA8, 0x81, 0x28, 0x83, 0xE8, 0x83, 0xE8, 0x84, 0xA8, 0x85, 0x2A, 0x60, 0x39, 0x48, 0x41, 0xF2, 0x11, 0x12, 0x2A, 0x85, 0x18, 0x90, 0x19, 0x91 , -0x39, 0x49, 0x1A, 0x91, 0x39, 0x49, 0x1B, 0x91, 0x39, 0x49, 0x20, 0x46, 0xDF, 0xF8, 0xC4, 0x90, 0x1C, 0x91, 0x38, 0x49, 0xDF, 0xF8, 0xC0, 0xB0, 0x31, 0x4E, 0x1D, 0x91, 0x48, 0x80, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0D, 0xF0, 0x7C, 0xFA, 0xB4, 0x80, 0x01, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x12, 0x66, 0x09, 0x84, 0x6B, 0x00, 0x20, 0x94, 0x70, 0x00, 0x20, 0xB4, 0x70, 0x00, 0x20, 0xC4, 0x78, 0x00, 0x20, 0x50, 0x7A, 0x00, 0x20, 0xFE, 0xFF, 0x03, 0x00, 0xA4, 0x70, 0x00, 0x20, 0xB0, 0x70, 0x00, 0x20, 0xB8, 0x70, 0x00, 0x20, 0x60, 0x55, 0x30, 0x80, 0x3C, 0x5C, 0x00, 0x20, 0x04, 0x74, 0x00, 0x20, 0xB8, 0xE4, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x78, 0x07, 0xF0, 0x01, 0xFC, 0x20, 0x78, 0x07, 0xF0, 0x7A, 0xFB, 0x04, 0x4D, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xAD, 0xF1, 0x8C, 0x0D, 0x04, 0x68, 0x0F, 0x30, 0x03, 0x94, 0xFE, 0xF7, 0xDB, 0xFA, 0x04, 0xF1, 0x14, 0x00 , -0x04, 0x90, 0x21, 0x7D, 0x00, 0x20, 0x21, 0xF0, 0x73, 0x01, 0x88, 0x29, 0x08, 0xBF, 0x01, 0x20, 0x05, 0x90, 0x03, 0x98, 0x00, 0x1D, 0x06, 0x90, 0x5D, 0x48, 0x00, 0x68, 0x01, 0x28, 0x40, 0xF0, 0xFA, 0x83, 0x5B, 0x4D, 0x5C, 0x48, 0xDF, 0xF8, 0x70, 0x91, 0x29, 0x68, 0xDF, 0xF8, 0x70, 0x81, 0xDF, 0xF8, 0x74, 0xA1, 0x88, 0x42, 0x21, 0xD1, 0x10, 0x22, 0x00, 0x21, 0x48, 0x46, 0x4F, 0x46, 0xFB, 0xF7, 0xB7, 0xFE, 0x10, 0x22, 0x00, 0x21, 0x40, 0x46, 0xFB, 0xF7, 0xB2, 0xFE, 0x54, 0x49, 0x08, 0x68, 0x40, 0xF4, 0x80, 0x10, 0x08, 0x60, 0x01, 0x20, 0x51, 0x46, 0x08, 0x60, 0x00, 0x21, 0x29, 0x60, 0x39, 0x78, 0x46, 0x46, 0x00, 0x91, 0x31, 0x78, 0x41, 0xF2, 0x11, 0x13, 0x04, 0x22, 0x01, 0x91, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF3, 0xF7, 0x41, 0xFC, 0x51, 0x46, 0x07, 0x91, 0x08, 0x68, 0x56, 0x49, 0xDF, 0xF8, 0x5C, 0xB1, 0x01, 0x28, 0x08, 0x91, 0x56, 0x49, 0xDF, 0xF8, 0x48, 0xA1, 0x09, 0x91, 0x55, 0x49 , -0x0A, 0x91, 0x44, 0x49, 0x0B, 0x91, 0x44, 0x49, 0x0C, 0x91, 0x44, 0x49, 0x0D, 0x91, 0x44, 0x49, 0x0E, 0x91, 0x44, 0x49, 0x0F, 0x91, 0x44, 0x49, 0x10, 0x91, 0x44, 0x49, 0xCC, 0x4D, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x11, 0x91, 0x44, 0x49, 0x12, 0x91, 0x44, 0x49, 0x13, 0x91, 0x44, 0x49, 0x14, 0x91, 0x44, 0x49, 0x15, 0x91, 0x44, 0x49, 0x16, 0x91, 0x9F, 0x49, 0x17, 0x91, 0x9F, 0x49, 0x18, 0x91, 0x9F, 0x49, 0x19, 0x91, 0x9F, 0x49, 0x1A, 0x91, 0x9F, 0x49, 0x1B, 0x91, 0x9F, 0x49, 0x1C, 0x91, 0x9F, 0x49, 0x1D, 0x91, 0x9F, 0x49, 0x1E, 0x91, 0x9F, 0x49, 0x1F, 0x91, 0x40, 0xF0, 0x00, 0x81, 0x04, 0x98, 0x40, 0x78, 0x00, 0xF0, 0x03, 0x01, 0x01, 0x29, 0x40, 0xF0, 0xF9, 0x80, 0x04, 0x99, 0x09, 0x78, 0x01, 0xF0, 0x0C, 0x01, 0x08, 0x29, 0x40, 0xF0, 0xF2, 0x80, 0x06, 0x99, 0x09, 0x88, 0xA1, 0xF1, 0x3C, 0x01, 0x0E, 0xB2, 0x05, 0x99, 0x11, 0xB1, 0xA6, 0xF1, 0x02, 0x06, 0x36, 0xB2, 0xC0, 0x09, 0x4F, 0xF0 , -0x00, 0x07, 0x15, 0xD3, 0x08, 0x3E, 0x36, 0xB2, 0x03, 0x2E, 0x10, 0xD0, 0x17, 0x2E, 0x0E, 0xD0, 0x08, 0x3E, 0x36, 0xB2, 0x03, 0x2E, 0x08, 0xD0, 0x17, 0x2E, 0x06, 0xD0, 0x36, 0x1F, 0x36, 0xB2, 0x03, 0x2E, 0x14, 0xBF, 0x17, 0x2E, 0x02, 0x27, 0x02, 0xE0, 0x03, 0x27, 0x00, 0xE0, 0x01, 0x27, 0x03, 0x2E, 0x18, 0xBF, 0x17, 0x2E, 0x04, 0x9A, 0x40, 0xF0, 0xC8, 0x80, 0x0A, 0x32, 0x12, 0xF8, 0x01, 0x1B, 0x05, 0x24, 0x12, 0xF8, 0x01, 0x3B, 0x4B, 0x40, 0x64, 0x1E, 0xD9, 0xB2, 0xF9, 0xD1, 0x81, 0xEA, 0x21, 0x11, 0x03, 0x2E, 0x94, 0x4E, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x0F, 0x01, 0x48, 0x46, 0x35, 0xD0, 0x43, 0x46, 0xCA, 0x5C, 0x52, 0x1C, 0xCA, 0x54, 0x0C, 0x18, 0x33, 0xE0, 0x50, 0x57, 0x02, 0x00, 0x04, 0x74, 0x00, 0x20, 0x34, 0x12, 0x66, 0x09, 0x60, 0x57, 0x02, 0x00, 0x70, 0x57, 0x02, 0x00, 0xC8, 0x48, 0x30, 0x80, 0x4C, 0x57, 0x02, 0x00, 0x88, 0x57, 0x02, 0x00, 0x80, 0x57, 0x02, 0x00 , -0x18, 0x58, 0x02, 0x00, 0x20, 0x58, 0x02, 0x00, 0x28, 0x58, 0x02, 0x00, 0x30, 0x58, 0x02, 0x00, 0x38, 0x58, 0x02, 0x00, 0x40, 0x58, 0x02, 0x00, 0xE4, 0x58, 0x02, 0x00, 0xE2, 0x58, 0x02, 0x00, 0x14, 0x58, 0x02, 0x00, 0xEF, 0x58, 0x02, 0x00, 0xE0, 0x58, 0x02, 0x00, 0xEE, 0x58, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0xE6, 0x58, 0x02, 0x00, 0xE8, 0x58, 0x02, 0x00, 0x0C, 0x18, 0x20, 0x78, 0x40, 0x1C, 0x20, 0x70, 0x20, 0x78, 0x43, 0x46, 0x03, 0xEB, 0x01, 0x08, 0x0A, 0x28, 0x76, 0xDB, 0x98, 0xF8, 0x00, 0x00, 0x0A, 0x28, 0x72, 0xDB, 0x94, 0x48, 0x00, 0x25, 0x01, 0x60, 0x04, 0x98, 0x00, 0xF1, 0x0A, 0x09, 0x40, 0x78, 0x41, 0x08, 0x24, 0xBF, 0x04, 0x99, 0x09, 0x1D, 0x04, 0xD2, 0x80, 0x08, 0x2E, 0xBF, 0x49, 0x46, 0x04, 0x99, 0x10, 0x31, 0x0B, 0x98, 0x06, 0x22, 0xFA, 0xF7, 0xB9, 0xFC, 0x0C, 0x98, 0x06, 0x22, 0x49, 0x46, 0xFA, 0xF7, 0xB4, 0xFC, 0x9B, 0x48, 0x9A, 0x49, 0x5C, 0x4F, 0x02, 0x00, 0xC8, 0x00 , -0x00, 0x00, 0x00, 0x78, 0x08, 0x22, 0x08, 0x60, 0x58, 0x46, 0x07, 0x60, 0x0D, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xAF, 0xFD, 0x08, 0x22, 0x0E, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xAA, 0xFD, 0x08, 0x22, 0x0F, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xA5, 0xFD, 0x08, 0x22, 0x10, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xA0, 0xFD, 0x08, 0x22, 0x11, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0x9B, 0xFD, 0x08, 0x22, 0x12, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0x96, 0xFD, 0x07, 0x99, 0x02, 0x20, 0x08, 0x60, 0x13, 0x99, 0x28, 0x46, 0x08, 0x80, 0x08, 0x99, 0x08, 0x70, 0x14, 0x99, 0x08, 0x70, 0x15, 0x99, 0x08, 0x60, 0x16, 0x99, 0x08, 0x70, 0x17, 0x99, 0x08, 0x60, 0x18, 0x99, 0x08, 0x60, 0x19, 0x99, 0x08, 0x60, 0x09, 0x99, 0x08, 0x80, 0x0A, 0x99, 0x08, 0x80, 0x1A, 0x99, 0x08, 0x80, 0x7D, 0x49, 0x0D, 0x60, 0x1B, 0x99, 0x08, 0x70, 0x1C, 0x99, 0x08, 0x70, 0x1D, 0x99, 0x08, 0x70, 0x1E, 0x99, 0x08, 0x80, 0x1F, 0x99, 0x08, 0x80, 0x51, 0x46, 0x08, 0x80 , -0x20, 0x78, 0x00, 0x96, 0x04, 0x22, 0x01, 0x90, 0x98, 0xF8, 0x00, 0x00, 0x41, 0xF2, 0x14, 0x13, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF3, 0xF7, 0x07, 0xFB, 0x07, 0x98, 0xA2, 0x49, 0x00, 0x68, 0x20, 0x91, 0xA2, 0x49, 0x05, 0x28, 0x21, 0x91, 0x9E, 0x49, 0x22, 0x91, 0x40, 0xF0, 0x37, 0x82, 0x04, 0x98, 0x40, 0x78, 0x24, 0x50, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x41, 0x08, 0x24, 0xBF, 0x04, 0x99, 0x09, 0x1D, 0x05, 0xD2, 0x80, 0x08, 0x27, 0xBF, 0x04, 0x99, 0x0A, 0x31, 0x04, 0x99, 0x10, 0x31, 0x0B, 0x98, 0xF8, 0xF7, 0x2D, 0xFC, 0x01, 0x28, 0x04, 0x98, 0x40, 0xF0, 0x23, 0x82, 0x40, 0x78, 0x00, 0xF0, 0x03, 0x00, 0x03, 0x28, 0x18, 0xD0, 0x02, 0x28, 0x07, 0xBF, 0x04, 0x99, 0x10, 0x31, 0x04, 0x99, 0x0A, 0x31, 0x13, 0xE0, 0x48, 0x58, 0x02, 0x00, 0x4C, 0x58, 0x02, 0x00, 0x50, 0x58, 0x02, 0x00, 0xF0, 0x58, 0x02, 0x00, 0xF2, 0x58, 0x02, 0x00, 0xF3, 0x58, 0x02, 0x00, 0xF4, 0x58, 0x02, 0x00, 0xEA, 0x58 , -0x02, 0x00, 0xEC, 0x58, 0x02, 0x00, 0x04, 0x99, 0x18, 0x31, 0x0C, 0x98, 0xF8, 0xF7, 0x06, 0xFC, 0x04, 0x99, 0x01, 0x28, 0x40, 0xF0, 0xFC, 0x81, 0x49, 0x78, 0x01, 0xF0, 0x03, 0x01, 0x01, 0x29, 0x40, 0xF0, 0xF6, 0x81, 0x59, 0x46, 0x09, 0x68, 0x04, 0x9A, 0x8E, 0x46, 0x51, 0x46, 0xD2, 0x8A, 0x0B, 0x88, 0x12, 0x11, 0x93, 0x42, 0x00, 0xF0, 0x37, 0x82, 0x0A, 0x80, 0x06, 0x99, 0x09, 0x88, 0x3C, 0x39, 0x0B, 0xB2, 0x71, 0x46, 0x49, 0x1E, 0x09, 0xD0, 0x49, 0x1E, 0x04, 0xD0, 0x49, 0x1E, 0x08, 0xD1, 0xA3, 0xF1, 0x10, 0x03, 0x04, 0xE0, 0xA3, 0xF1, 0x14, 0x03, 0x01, 0xE0, 0xA3, 0xF1, 0x08, 0x03, 0x1B, 0xB2, 0x05, 0x98, 0x10, 0xB1, 0xA3, 0xF1, 0x02, 0x03, 0x1B, 0xB2, 0xEC, 0x50, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0xF1, 0xCE, 0x81, 0x16, 0x98, 0x40, 0xF2, 0x77, 0x51, 0x99, 0x42, 0x0B, 0x90, 0x14, 0x98, 0x05, 0x90, 0x00, 0xF0, 0xA3, 0x81, 0x08, 0x46, 0x00, 0xF1, 0x3C, 0x00, 0x98, 0x42 , -0x05, 0x9A, 0x00, 0xF0, 0x9A, 0x81, 0xDF, 0xF8, 0x48, 0x82, 0x14, 0x78, 0x0B, 0x9A, 0xBB, 0x2C, 0x12, 0x78, 0x0C, 0x92, 0x63, 0xD1, 0xDD, 0xF8, 0x68, 0xC0, 0xBC, 0xF9, 0x00, 0x20, 0x91, 0x42, 0x18, 0xBF, 0x90, 0x42, 0x5B, 0xD1, 0x1C, 0x2B, 0x4F, 0xF0, 0x00, 0x00, 0xC0, 0xF2, 0x82, 0x81, 0x3D, 0x2B, 0x13, 0x9D, 0x80, 0xF2, 0x7E, 0x81, 0xA3, 0xF1, 0x1C, 0x01, 0x09, 0xB2, 0x29, 0x80, 0x1E, 0x9A, 0xDD, 0xF8, 0x30, 0x90, 0xB2, 0xF9, 0x00, 0x60, 0xB9, 0xF1, 0x01, 0x0F, 0x15, 0xD1, 0xDD, 0xF8, 0x24, 0x90, 0x03, 0x2E, 0x0D, 0xDA, 0xB9, 0xF9, 0x00, 0x70, 0xB9, 0x42, 0x07, 0xD0, 0x01, 0x26, 0x16, 0x80, 0x4A, 0x46, 0x0E, 0x46, 0x03, 0xE0, 0xC0, 0x46, 0x90, 0x57, 0x02, 0x00, 0x76, 0x1C, 0x16, 0x80, 0x1B, 0x9A, 0x16, 0x78, 0x1D, 0x9A, 0x16, 0x70, 0x0C, 0x9A, 0x1F, 0x9E, 0x02, 0x2A, 0x28, 0xD1, 0xB6, 0xF9, 0x00, 0x20, 0xBE, 0xF1, 0x00, 0x0F, 0x1A, 0xD0, 0x03, 0x2A, 0x35, 0x46, 0x0B, 0xDA, 0x0A, 0x9E , -0xB6, 0xF9, 0x00, 0x70, 0xB9, 0x42, 0x04, 0xD0, 0x01, 0x22, 0x2A, 0x80, 0x0A, 0x46, 0x35, 0x46, 0x00, 0xE0, 0xB4, 0x51, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x52, 0x1C, 0x2A, 0x80, 0x1C, 0x99, 0x0A, 0x78, 0x1D, 0x99, 0x0A, 0x70, 0x0F, 0xE0, 0xC0, 0x46, 0x58, 0x57, 0x02, 0x00, 0xA6, 0x64, 0x00, 0x20, 0x54, 0x57, 0x02, 0x00, 0x28, 0x80, 0x05, 0x99, 0x08, 0x70, 0x08, 0x9A, 0x11, 0x78, 0x41, 0xF0, 0x04, 0x01, 0x11, 0x70, 0x04, 0x46, 0x45, 0x46, 0xAC, 0xF8, 0x00, 0x00, 0x28, 0x70, 0xCC, 0x2C, 0x09, 0x9A, 0x40, 0xF0, 0x00, 0x81, 0xDD, 0xF8, 0x7C, 0xC0, 0x0A, 0x99, 0x1E, 0x9F, 0x45, 0x46, 0xB1, 0xF9, 0x00, 0x60, 0xB2, 0xF9, 0x00, 0x90, 0x28, 0x78, 0xCD, 0xF8, 0x50, 0xC0, 0x16, 0x91, 0x0A, 0x97, 0x13, 0x92, 0x09, 0x95, 0x0C, 0x99, 0x01, 0x29, 0x05, 0xD1, 0x05, 0x9A, 0xB0, 0xEB, 0x49, 0x0F, 0x01, 0xD1, 0x00, 0x21, 0x11, 0x70, 0x0C, 0x99, 0x02, 0x29, 0x05, 0xD1, 0x05, 0x9A, 0xB0, 0xEB, 0x46, 0x0F , -0x01, 0xD1, 0x00, 0x21, 0x11, 0x70, 0xB3, 0xF5, 0x14, 0x7F, 0x40, 0xF3, 0xBA, 0x80, 0x40, 0xF2, 0x51, 0x31, 0x99, 0x42, 0x08, 0x99, 0x40, 0xF3, 0xB4, 0x80, 0x09, 0x78, 0x06, 0x29, 0x00, 0xF0, 0xB0, 0x80, 0xA3, 0xF2, 0x51, 0x21, 0x0B, 0xB2, 0x4F, 0xEA, 0xE3, 0x01, 0x03, 0xEB, 0x11, 0x71, 0x4F, 0xEA, 0x21, 0x11, 0xCA, 0xB2, 0x4F, 0xEA, 0xE3, 0x01, 0x03, 0xEB, 0x11, 0x71, 0x15, 0x9D, 0x21, 0xF0, 0x0F, 0x01, 0xA3, 0xEB, 0x01, 0x03, 0x1D, 0x99, 0x2E, 0x68, 0x7C, 0x52, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x91, 0xF8, 0x00, 0xE0, 0x5F, 0xFA, 0x83, 0xF8, 0x60, 0xB1, 0x31, 0x18, 0x11, 0xF8, 0x01, 0x1C, 0x51, 0x40, 0xCB, 0xB2, 0x07, 0xE0, 0xC0, 0x46, 0x58, 0x58, 0x02, 0x00, 0x54, 0x58, 0x02, 0x00, 0xDC, 0x58, 0x02, 0x00, 0x13, 0x46, 0x19, 0x99, 0xDD, 0xF8, 0x6C, 0xA0, 0xDD, 0xF8, 0x70, 0xB0, 0xD1, 0xF8, 0x00, 0xC0, 0x00, 0xF0, 0x0F, 0x01, 0x99, 0x42, 0x22, 0xD0, 0x0A, 0x9B, 0x86, 0x45, 0x9A, 0xF8 , -0x00, 0x10, 0xB3, 0xF9, 0x00, 0x30, 0x9B, 0xF8, 0x00, 0x50, 0x15, 0xDD, 0x37, 0x5C, 0x44, 0x1C, 0x82, 0xEA, 0x07, 0x0C, 0x04, 0xF0, 0x0F, 0x07, 0x67, 0x45, 0x0B, 0xD0, 0xA6, 0x45, 0x06, 0x44, 0x0A, 0xDD, 0x76, 0x78, 0x72, 0x40, 0x86, 0x1C, 0x06, 0xF0, 0x0F, 0x06, 0x96, 0x42, 0x03, 0xD1, 0xC0, 0x1C, 0x4D, 0xE0, 0x80, 0x1C, 0x4B, 0xE0, 0x05, 0x9E, 0x00, 0x22, 0x32, 0x70, 0x4A, 0xE0, 0x00, 0xF0, 0x1F, 0x01, 0x01, 0x22, 0x8A, 0x40, 0x17, 0x99, 0xC4, 0x10, 0x0B, 0x68, 0x24, 0xF0, 0x03, 0x01, 0x5C, 0xF8, 0x01, 0x70, 0x3A, 0x42, 0x32, 0xD1, 0x5F, 0x58, 0x3A, 0x42, 0x06, 0x44, 0x1F, 0xD0, 0x18, 0x9B, 0x37, 0x78, 0x1B, 0x68, 0xB8, 0x45, 0x04, 0xD1, 0x58, 0x58, 0x02, 0x42, 0x19, 0xD0, 0x63, 0x46, 0x15, 0xE0, 0xA1, 0x10, 0x8C, 0x00, 0x19, 0x59, 0x91, 0x43, 0x19, 0x51, 0x00, 0x90, 0x30, 0x78, 0x01, 0x90, 0x44, 0x53, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x03, 0x20, 0x06, 0x21, 0x02, 0x46, 0x4D, 0xF6 , -0x80, 0x53, 0xF3, 0xF7, 0x63, 0xF9, 0x09, 0x99, 0x28, 0x68, 0x0E, 0x78, 0x36, 0x18, 0x06, 0xE0, 0xE3, 0x58, 0x02, 0x00, 0xA0, 0x10, 0x81, 0x00, 0x58, 0x58, 0x02, 0x43, 0x5A, 0x50, 0x86, 0xF8, 0x00, 0x80, 0x0B, 0x98, 0x00, 0x78, 0x0C, 0x90, 0x13, 0x98, 0xB0, 0xF9, 0x00, 0x90, 0x09, 0x98, 0x00, 0x78, 0x0A, 0x9A, 0x40, 0x1C, 0x9B, 0xF8, 0x00, 0x50, 0x9A, 0xF8, 0x00, 0x10, 0xB2, 0xF9, 0x00, 0x30, 0x09, 0x9A, 0xC0, 0xB2, 0x10, 0x70, 0x0C, 0x9A, 0x01, 0x2A, 0x03, 0xD1, 0x88, 0x42, 0xC8, 0xBF, 0x8A, 0xF8, 0x00, 0x00, 0x0C, 0x99, 0x02, 0x29, 0x07, 0xD1, 0xA8, 0x42, 0xC8, 0xBF, 0x8B, 0xF8, 0x00, 0x00, 0x02, 0xE0, 0x0A, 0x98, 0xB0, 0xF9, 0x00, 0x30, 0xB9, 0xF1, 0x00, 0x0F, 0x06, 0xDD, 0x03, 0x2B, 0x04, 0xD1, 0x11, 0x98, 0x01, 0x22, 0x49, 0x46, 0x00, 0xF0, 0x72, 0xFB, 0x16, 0x98, 0xB0, 0xF9, 0x00, 0x10, 0x14, 0x98, 0x00, 0x29, 0xB0, 0xF9, 0x00, 0x00, 0x05, 0xDD, 0x03, 0x28, 0x03, 0xD1, 0x12, 0x98 , -0x02, 0x22, 0x00, 0xF0, 0x64, 0xFB, 0x05, 0x98, 0x04, 0x78, 0x0B, 0x98, 0x00, 0x78, 0x0C, 0x90, 0x08, 0x98, 0xBB, 0x2C, 0x01, 0x78, 0x02, 0xD0, 0xAA, 0x2C, 0x2F, 0xD0, 0x31, 0xE0, 0x0C, 0x98, 0x01, 0x28, 0x0B, 0xD1, 0x0D, 0x98, 0x17, 0x9A, 0x10, 0x60, 0x0C, 0x54, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x0F, 0x98, 0x18, 0x9A, 0x10, 0x60, 0x19, 0x9A, 0x11, 0x98, 0x10, 0x60, 0x47, 0x4A, 0x15, 0x98, 0x02, 0x60, 0x0C, 0x98, 0x02, 0x28, 0x0B, 0xD1, 0x0E, 0x98, 0x17, 0x9A, 0x10, 0x60, 0x10, 0x98, 0x18, 0x9A, 0x10, 0x60, 0x19, 0x9A, 0x12, 0x98, 0x10, 0x60, 0x41, 0x4A, 0x15, 0x98, 0x02, 0x60, 0xCC, 0x20, 0x0F, 0xE0, 0x08, 0x99, 0x09, 0x78, 0x0C, 0xE0, 0x02, 0x20, 0x00, 0xE0, 0x01, 0x20, 0x0B, 0x99, 0x08, 0x70, 0x1A, 0x99, 0x0B, 0x80, 0x13, 0x99, 0x00, 0x20, 0x08, 0x80, 0x08, 0x98, 0x01, 0x78, 0xBB, 0x20, 0x05, 0x9A, 0x10, 0x70, 0x06, 0x29, 0x07, 0x99, 0x11, 0xD1, 0x06, 0x20, 0x08, 0x60, 0x20, 0x98 , -0x00, 0x25, 0x05, 0x70, 0x21, 0x98, 0x29, 0x46, 0x04, 0x22, 0xFB, 0xF7, 0x27, 0xFB, 0x01, 0x20, 0x00, 0xF0, 0x3A, 0xFA, 0x02, 0x20, 0x00, 0xF0, 0x37, 0xFA, 0x22, 0x98, 0x05, 0x60, 0x07, 0x98, 0x04, 0x99, 0x00, 0x68, 0x07, 0x28, 0x44, 0xD1, 0x09, 0x78, 0x03, 0x9C, 0x80, 0x29, 0x40, 0xD1, 0x38, 0x34, 0x21, 0x78, 0x64, 0x1C, 0x22, 0x46, 0x00, 0x29, 0x3A, 0xD1, 0x20, 0x98, 0x90, 0xF8, 0x00, 0xA0, 0x22, 0x98, 0x05, 0x90, 0xD0, 0xF8, 0x00, 0x90, 0x51, 0x46, 0x48, 0x46, 0xFD, 0xF7, 0x79, 0xF9, 0x5F, 0xFA, 0x80, 0xF8, 0x21, 0x9F, 0x15, 0x78, 0x51, 0x46, 0x48, 0x46, 0x17, 0xF8, 0x08, 0x30, 0xFD, 0xF7, 0xD4, 0x54, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x6F, 0xF9, 0x1E, 0x46, 0x1B, 0x1D, 0xC0, 0xB2, 0x38, 0x5C, 0x00, 0x1D, 0xA8, 0x42, 0x28, 0x46, 0x07, 0xDD, 0x80, 0x18, 0x82, 0x1C, 0x10, 0x78, 0x2D, 0x18, 0xAD, 0x1C, 0xAD, 0xB2, 0xAB, 0x42, 0xF7, 0xDC, 0x04, 0xF8, 0x01, 0x6B, 0x11, 0x49, 0x32, 0x46 , -0x20, 0x46, 0x01, 0xEB, 0x48, 0x11, 0xFA, 0xF7, 0xDC, 0xF9, 0xAD, 0x1B, 0xFF, 0x20, 0x34, 0x19, 0xAD, 0x1E, 0x04, 0xF8, 0x01, 0x0B, 0x25, 0x70, 0x05, 0x98, 0x01, 0x68, 0x49, 0x1C, 0x01, 0x60, 0x07, 0x98, 0x00, 0x68, 0x07, 0x28, 0x04, 0xD0, 0x06, 0x99, 0x08, 0x68, 0x20, 0xF4, 0x80, 0x30, 0x08, 0x60, 0x23, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xC0, 0x46, 0x94, 0x57, 0x02, 0x00, 0xD4, 0x57, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x6E, 0x48, 0x2D, 0xE9, 0xF0, 0x47, 0x6E, 0x4D, 0x82, 0x89, 0x4A, 0xF6, 0x55, 0x21, 0xAD, 0xF5, 0xFE, 0x7D, 0x91, 0x42, 0x4F, 0xF0, 0x00, 0x01, 0xAD, 0xF1, 0x38, 0x0D, 0x12, 0xD1, 0x29, 0x60, 0x68, 0x4A, 0x11, 0x70, 0x41, 0xF2, 0x10, 0x41, 0x81, 0x81, 0x4F, 0xF6, 0xFF, 0x70, 0x66, 0x49, 0x08, 0x60, 0x28, 0x68, 0x00, 0x90, 0x02, 0x22, 0x05, 0x21, 0x03, 0x20, 0x41, 0xF2, 0x34, 0x23, 0xF3, 0xF7, 0x48, 0xF8, 0x29, 0x68, 0x61, 0x4C, 0x01, 0x29, 0x20, 0x68, 0x40, 0xF0, 0xAF, 0x80 , -0x5F, 0x4D, 0x02, 0x28, 0x29, 0x68, 0x23, 0xD1, 0x9C, 0x55, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x5E, 0x48, 0x00, 0x68, 0x5F, 0x4A, 0x12, 0x5C, 0x00, 0x92, 0x01, 0x91, 0x5E, 0x49, 0x09, 0x68, 0x02, 0x91, 0x5B, 0x49, 0x0B, 0x5C, 0x03, 0x20, 0x07, 0x21, 0x04, 0x22, 0xF3, 0xF7, 0x2E, 0xF8, 0x5B, 0x49, 0x4A, 0x79, 0x59, 0x48, 0x00, 0x92, 0x02, 0x79, 0x01, 0x92, 0x40, 0x79, 0x04, 0x22, 0x02, 0x90, 0x03, 0x20, 0x0B, 0x79, 0x07, 0x21, 0xF3, 0xF7, 0x20, 0xF8, 0x03, 0x20, 0x20, 0x60, 0xEC, 0xF7, 0x1A, 0xFF, 0x20, 0x68, 0x29, 0x68, 0x04, 0x28, 0x15, 0xD1, 0x0D, 0x20, 0x8D, 0xF8, 0x10, 0x00, 0x00, 0x25, 0x8D, 0xF8, 0x14, 0x50, 0x8D, 0xF8, 0x15, 0x10, 0x28, 0x46, 0x63, 0x21, 0x00, 0xF0, 0xAA, 0xFB, 0x63, 0x21, 0x28, 0x46, 0x00, 0xF0, 0xFA, 0xFA, 0x03, 0xA9, 0x04, 0xA8, 0xE0, 0xF7, 0xCA, 0xFC, 0x05, 0x20, 0x20, 0x60, 0x46, 0x4D, 0x05, 0x28, 0x29, 0x68, 0x01, 0xF1, 0x01, 0x01, 0x29, 0x60, 0x1D, 0xD1 , -0x44, 0x4A, 0x8A, 0x42, 0x1A, 0xD1, 0x43, 0x48, 0x01, 0x68, 0x00, 0x91, 0x40, 0x68, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0x06, 0x21, 0x41, 0x4E, 0x33, 0x46, 0x22, 0x3B, 0xF2, 0xF7, 0xEB, 0xFF, 0x3E, 0x48, 0x01, 0x68, 0x00, 0x91, 0x40, 0x68, 0x33, 0x46, 0x06, 0x21, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0xF2, 0xF7, 0xE0, 0xFF, 0x00, 0x20, 0x28, 0x60, 0x20, 0x68, 0x06, 0x28, 0x47, 0xD1, 0x4F, 0xF0, 0x64, 0x56, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x07, 0x0A, 0xC4, 0xF8, 0x00, 0xA0, 0x03, 0x20, 0x48, 0xF2, 0x70, 0x53, 0x01, 0x22, 0x04, 0x21, 0xF2, 0xF7, 0xD0, 0xFF, 0xDF, 0xF8, 0xCC, 0x80, 0x31, 0x4F, 0x48, 0xF2, 0x70, 0x59, 0x01, 0x25, 0x49, 0xEA, 0x05, 0x03, 0x01, 0x22, 0x04, 0x21, 0x03, 0x20, 0xF2, 0xF7, 0xC3, 0xFF, 0x00, 0x24, 0x17, 0xF8, 0x02, 0x0F, 0x20, 0xE0, 0x69, 0x01, 0x04, 0xEB, 0x08, 0x02, 0x88, 0x18, 0xC6, 0x1C, 0x43, 0x78, 0x00, 0x93, 0x80, 0x78, 0x01, 0x90, 0x30, 0x78, 0x02, 0x90 , -0x53, 0x5C, 0x51, 0x46, 0x04, 0x22, 0x03, 0x20, 0xF2, 0xF7, 0xAE, 0xFF, 0x38, 0x78, 0x01, 0x1B, 0xB1, 0xF1, 0xFF, 0x3F, 0x08, 0xD1, 0xF0, 0x78, 0x00, 0x90, 0xB3, 0x78, 0x03, 0x20, 0x02, 0x22, 0x05, 0x21, 0xF2, 0xF7, 0xA1, 0xFF, 0x38, 0x78, 0x24, 0x1D, 0xE4, 0xB2, 0xA0, 0x42, 0xDC, 0xDC, 0xAD, 0x1C, 0xED, 0xB2, 0x04, 0x2D, 0xCD, 0xDB, 0x63, 0x21, 0x4F, 0xF4, 0x05, 0x70, 0xF1, 0xF7, 0xA3, 0xFC, 0xE1, 0xF7, 0x85, 0xFD, 0x7F, 0xB0, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xC0, 0x46, 0x04, 0x74, 0x00, 0x20, 0x50, 0x57, 0x02, 0x00, 0x6C, 0x5D, 0x02, 0x00, 0x40, 0x00, 0x3D, 0x80, 0x4C, 0x57, 0x02, 0x00, 0x58, 0x57, 0x02, 0x00, 0x90, 0x57, 0x02, 0x00, 0x60, 0x57, 0x02, 0x00, 0x70, 0x57, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0x80, 0x57, 0x02, 0x00, 0x2C, 0x57, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x88, 0x57, 0x02, 0x00, 0x54, 0x57, 0x02, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x38, 0x58, 0x02, 0x00, 0x40, 0x58 , -0x02, 0x00, 0x66, 0x55, 0xDD, 0xEE, 0xDB, 0x58, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x57, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0x58, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0xE9, 0xFE, 0x4F, 0x4A, 0x4A, 0x49, 0x4D, 0x00, 0x90, 0xB2, 0xF9, 0x00, 0x20, 0x43, 0xA3, 0x29, 0x78, 0x01, 0x93, 0x43, 0xA3, 0x01, 0x28, 0x02, 0x93, 0x47, 0x4E, 0xDF, 0xF8, 0x1C, 0x81, 0xDF, 0xF8, 0x1C, 0x91, 0x1E, 0xD0, 0x43, 0x48, 0x04, 0x78, 0x48, 0x01, 0x87, 0x19, 0x30, 0x18, 0x01, 0x99, 0x06, 0x22, 0xF9, 0xF7, 0xC8, 0xFF, 0x40, 0x46, 0x01, 0x78, 0x00, 0x68, 0x07, 0xF1, 0x06, 0x07, 0x07, 0xF8, 0x01, 0x1B, 0x07, 0xF8, 0x01, 0x4B, 0x4F, 0xF0, 0x00, 0x01, 0x07, 0xF8, 0x01, 0x1B, 0x20, 0xB9, 0x39, 0x70, 0x28, 0x78, 0x4E, 0x46, 0x0A, 0x21, 0x58, 0xE0, 0xDF, 0xF8, 0xE4, 0xB0, 0x0F, 0xE0, 0xD4, 0xB2, 0x48, 0x01, 0x87, 0x19, 0x30, 0x18, 0x02, 0x99, 0x07, 0x22, 0xF9, 0xF7, 0xAA, 0xFF, 0xFF, 0x1D, 0x00, 0x20, 0xDF, 0xF8, 0xCC, 0xB0, 0x07, 0xF8, 0x01, 0x4B, 0x07, 0xF8, 0x01, 0x0B, 0x16, 0x2C, 0xB2, 0x46, 0xAE, 0xBF, 0x14, 0x20, 0x84, 0x59 , -0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x60, 0x1E, 0xC0, 0xB2, 0x38, 0x70, 0x4E, 0x46, 0x7F, 0x1C, 0x40, 0x1C, 0xC2, 0xB2, 0x28, 0x78, 0x5B, 0x46, 0x00, 0x21, 0x32, 0x54, 0x38, 0x46, 0x00, 0xF0, 0xBC, 0xF9, 0x28, 0x78, 0x16, 0x2C, 0x31, 0x5C, 0x01, 0xF1, 0x0A, 0x01, 0x31, 0x54, 0x00, 0xF1, 0x01, 0x00, 0xC0, 0xB2, 0x28, 0x70, 0x2B, 0xDB, 0x00, 0x99, 0x0A, 0xEB, 0x40, 0x10, 0x07, 0x46, 0x01, 0x29, 0xA4, 0xF1, 0x01, 0x09, 0x09, 0xD0, 0x01, 0x99, 0x06, 0x22, 0xF9, 0xF7, 0x79, 0xFF, 0x40, 0x46, 0x00, 0x78, 0xBF, 0x1D, 0x07, 0xF8, 0x01, 0x0B, 0x04, 0xE0, 0x02, 0x99, 0x07, 0x22, 0xF9, 0xF7, 0x6F, 0xFF, 0xFF, 0x1D, 0x07, 0xF8, 0x01, 0x4B, 0x15, 0x3C, 0x15, 0x21, 0x28, 0x78, 0xE2, 0xB2, 0x5B, 0x46, 0x07, 0xF8, 0x01, 0x1B, 0x32, 0x54, 0x07, 0xF8, 0x01, 0x9B, 0x38, 0x46, 0x00, 0xF0, 0x8B, 0xF9, 0x28, 0x78, 0x31, 0x5C, 0x0A, 0x31, 0x31, 0x54, 0x40, 0x1C, 0x28, 0x70, 0xBD, 0xE8, 0xFE, 0x8F, 0xC0, 0x46 , -0x54, 0x54, 0x54, 0x4B, 0x45, 0x59, 0x00, 0xC0, 0x54, 0x54, 0x54, 0x53, 0x53, 0x49, 0x44, 0x00, 0x54, 0x58, 0x02, 0x00, 0xE6, 0x58, 0x02, 0x00, 0xE8, 0x58, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0xDC, 0x58, 0x02, 0x00, 0xD4, 0x57, 0x02, 0x00, 0x94, 0x57, 0x02, 0x00, 0xFF, 0xB5, 0x0C, 0x46, 0x06, 0x46, 0xF7, 0xF7, 0x4C, 0x5A, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xE3, 0xFE, 0x15, 0x49, 0x15, 0x4A, 0x0D, 0x68, 0x01, 0xA9, 0x92, 0xE8, 0x8C, 0x00, 0x81, 0xE8, 0x8C, 0x00, 0xF7, 0xF7, 0xFD, 0xFE, 0x01, 0x98, 0x11, 0x49, 0x28, 0x1A, 0x03, 0x9D, 0x25, 0x60, 0x02, 0x9A, 0x80, 0x18, 0x82, 0x42, 0x30, 0x60, 0x0E, 0xD8, 0x08, 0x46, 0x00, 0x68, 0x22, 0x68, 0x82, 0x42, 0x0E, 0xD2, 0x68, 0x46, 0xE8, 0xF7, 0xB9, 0xFF, 0x9D, 0xF8, 0x00, 0x00, 0x05, 0xF1, 0x01, 0x05, 0x30, 0xB9, 0x03, 0x95, 0x03, 0xE0, 0x25, 0x68, 0x6D, 0x1C, 0x25, 0x60, 0x0C, 0x46, 0x25, 0x60, 0x00, 0x20, 0x00, 0x90 , -0xFF, 0xBD, 0x60, 0x55, 0x30, 0x80, 0x24, 0x5D, 0x00, 0x20, 0x6C, 0x5D, 0x02, 0x00, 0x70, 0xB5, 0x4D, 0x00, 0x20, 0x2D, 0x4F, 0xF0, 0x00, 0x01, 0x0C, 0x46, 0x4F, 0xEA, 0x55, 0x13, 0x09, 0xD3, 0x50, 0xF8, 0x21, 0x60, 0xB6, 0xF1, 0xFF, 0x3F, 0x04, 0xD1, 0x49, 0x1C, 0xC9, 0xB2, 0x20, 0x3D, 0x5B, 0x1E, 0xF5, 0xD1, 0x4D, 0xB1, 0x20, 0x2D, 0x09, 0xD2, 0x01, 0x23, 0xAB, 0x40, 0x5B, 0x1E, 0x50, 0xF8, 0x21, 0x00, 0x18, 0x40, 0x83, 0x42, 0x01, 0xD1, 0x4F, 0xF0, 0x01, 0x04, 0x07, 0x48, 0x03, 0x78, 0x2C, 0xB9, 0x01, 0x21, 0x91, 0x40, 0xC9, 0x43, 0xC9, 0xB2, 0x0B, 0x40, 0x03, 0xE0, 0x01, 0x21, 0x91, 0x40, 0xC9, 0xB2, 0x0B, 0x43, 0x03, 0x70, 0x70, 0xBD, 0xC0, 0x46, 0xEE, 0x58, 0x02, 0x00, 0x14, 0x5B, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x7E, 0xB5, 0x05, 0x46, 0x95, 0xF8, 0x36, 0x20, 0x0E, 0x46, 0x0F, 0x49, 0x07, 0x2A, 0x12, 0xBF, 0x08, 0x68, 0x01, 0x20, 0x08, 0x60, 0x0D, 0x4C, 0x00, 0x92, 0x21, 0x68 , -0x41, 0xF2, 0x12, 0x13, 0x04, 0x22, 0x01, 0x91, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF2, 0xF7, 0x6B, 0xFD, 0x31, 0x46, 0x28, 0x46, 0xE7, 0xF7, 0x21, 0xFC, 0x21, 0x68, 0x00, 0x22, 0x05, 0x29, 0x02, 0xD1, 0x04, 0x49, 0x08, 0x31, 0x0A, 0x60, 0x7E, 0xBD, 0xC0, 0x46, 0x50, 0x57, 0x02, 0x00, 0x4C, 0x57, 0x02, 0x00, 0x00, 0x7C, 0x00, 0x20, 0x0E, 0x49, 0x09, 0x68, 0x49, 0x08, 0x15, 0xD2, 0x0D, 0x49, 0x09, 0x78, 0x91, 0xB1, 0x44, 0xF2, 0xE9, 0x21, 0x68, 0xB9, 0x0B, 0x48, 0x01, 0x78, 0x07, 0x48, 0x01, 0x29, 0x03, 0xD1, 0x0A, 0x49, 0x09, 0x78, 0x0E, 0x29, 0x02, 0xD0, 0x44, 0xF2, 0xDE, 0x21, 0x41, 0x60, 0x01, 0x21, 0x00, 0xE0, 0x06, 0x48, 0x01, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x00, 0x97, 0x3C, 0x80, 0x10, 0x0C, 0x30, 0x80, 0xDD, 0x6A, 0x00, 0x20, 0xE0, 0x7C, 0x00, 0x20, 0xA6, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x00, 0xB5, 0xAD, 0xF1, 0x18, 0x0D, 0x4F, 0xF0, 0x09, 0x00, 0x00, 0x90, 0x4F, 0xF4 , -0x0C, 0x60, 0x03, 0x90, 0x4F, 0xF0, 0x00, 0x00, 0x01, 0x90, 0x02, 0x90, 0x08, 0x48, 0x08, 0x49, 0x05, 0x90, 0x08, 0x68, 0x20, 0xB9, 0xDC, 0x5B, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x68, 0x46, 0x03, 0x22, 0xED, 0xF7, 0x3A, 0xFA, 0x03, 0xE0, 0x68, 0x46, 0x03, 0x22, 0xED, 0xF7, 0xC1, 0xFC, 0x06, 0xB0, 0x00, 0xBD, 0xC0, 0x46, 0x81, 0x5C, 0x02, 0x00, 0xDC, 0x7C, 0x00, 0x20, 0x1C, 0xB5, 0x0F, 0x4C, 0x22, 0x68, 0x01, 0x2A, 0x15, 0xD1, 0x0C, 0x48, 0x00, 0x68, 0x07, 0x28, 0x14, 0xBF, 0x40, 0x20, 0x4F, 0xF4, 0x05, 0x70, 0x63, 0x21, 0xF1, 0xF7, 0x0F, 0xFA, 0x20, 0x68, 0x00, 0x90, 0x43, 0xF2, 0x33, 0x33, 0x06, 0x21, 0x40, 0x20, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0xF2, 0xF7, 0xF4, 0xFC, 0x1C, 0xBD, 0xF1, 0xF7, 0x01, 0xFA, 0x1C, 0xBD, 0x4C, 0x57, 0x02, 0x00, 0x50, 0x57, 0x02, 0x00, 0x1E, 0xB5, 0x04, 0x46, 0x0A, 0x49, 0x00, 0x20, 0x0A, 0x4A, 0x08, 0x60, 0x0A, 0x49, 0x00, 0x90, 0x01, 0x90, 0x11, 0x60 , -0x09, 0x4A, 0x45, 0xF2, 0x55, 0x53, 0x02, 0x91, 0x10, 0x60, 0x07, 0x21, 0x04, 0x22, 0x03, 0x20, 0xF2, 0xF7, 0xD8, 0xFC, 0x20, 0x46, 0xE7, 0xF7, 0x59, 0xFD, 0x1E, 0xBD, 0x50, 0x57, 0x02, 0x00, 0x04, 0x74, 0x00, 0x20, 0x34, 0x12, 0x66, 0x09, 0x4C, 0x57, 0x02, 0x00, 0x00, 0xB5, 0x0B, 0x49, 0x00, 0x20, 0x08, 0x60, 0xE0, 0x20, 0xF7, 0xF7, 0xAA, 0xFD, 0x09, 0x49, 0x09, 0x78, 0x49, 0xB1, 0x08, 0x49, 0x0A, 0x78, 0x08, 0x49, 0x00, 0x2A, 0x06, 0xBF, 0x01, 0x22, 0x09, 0x1F, 0x44, 0xF2, 0xA4, 0x5C, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xE9, 0x22, 0x0A, 0x60, 0xF7, 0xF7, 0xA1, 0xFD, 0x00, 0xBD, 0xC0, 0x46, 0xDC, 0x7C, 0x00, 0x20, 0xDD, 0x6A, 0x00, 0x20, 0xA7, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x50, 0xB9, 0x09, 0x48, 0x00, 0x78, 0x01, 0x28, 0x06, 0xD1, 0x08, 0x48, 0x00, 0x78, 0x0E, 0x28, 0x08, 0xBF, 0x44, 0xF2, 0xCB, 0x20, 0x01, 0xD0, 0x44, 0xF2, 0xDE, 0x20, 0x04, 0x49, 0x08, 0x60, 0x01, 0x20 , -0x41, 0xF8, 0x04, 0x0C, 0x70, 0x47, 0xE0, 0x7C, 0x00, 0x20, 0xA6, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x30, 0xB5, 0x0D, 0x46, 0x84, 0x69, 0xDC, 0xF7, 0x97, 0xFB, 0x24, 0x1D, 0x01, 0x28, 0x04, 0xEB, 0x45, 0x01, 0x06, 0xD1, 0x89, 0x8E, 0x04, 0xEB, 0x85, 0x04, 0x11, 0xB9, 0x21, 0x69, 0x01, 0xB9, 0x00, 0x20, 0x30, 0xBD, 0x30, 0xB5, 0x05, 0x46, 0x5A, 0xB1, 0x03, 0xEB, 0x41, 0x03, 0x1C, 0x78, 0x59, 0x78, 0x41, 0xEA, 0x04, 0x11, 0x52, 0x1E, 0x03, 0xF1, 0x02, 0x03, 0x05, 0xF8, 0x01, 0x1B, 0xF5, 0xD1, 0x30, 0xBD, 0x00, 0xB5, 0x00, 0x20, 0xE7, 0xF7, 0xD6, 0xFE, 0x03, 0x48, 0x01, 0x68, 0x03, 0x29, 0x04, 0xBF, 0x04, 0x21, 0x01, 0x60, 0x00, 0xBD, 0xC0, 0x46, 0x4C, 0x57, 0x02, 0x00, 0x03, 0x4A, 0x12, 0x68, 0x01, 0x2A, 0x04, 0xBF, 0x02, 0x48, 0x63, 0x21, 0xF1, 0xF7, 0x76, 0xB9, 0x50, 0x57, 0x02, 0x00, 0x02, 0x20, 0x01, 0x00, 0x6C, 0x5D, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; diff --git a/drivers/cc3000/src/patch_prog.c b/drivers/cc3000/src/patch_prog.c deleted file mode 100644 index fd128928fb..0000000000 --- a/drivers/cc3000/src/patch_prog.c +++ /dev/null @@ -1,414 +0,0 @@ -#include -#include -#include "cc3000_common.h" -#include "nvmem.h" -#include "ccspi.h" -#include "hci.h" -#include "wlan.h" -#include "patch_prog.h" -#define BIT0 0x1 -#define BIT1 0x2 -#define BIT2 0x4 -#define BIT3 0x8 -#define BIT4 0x10 -#define BIT5 0x20 -#define BIT6 0x40 -#define BIT7 0x80 - -static unsigned char ucStatus_Dr; -static unsigned char ucStatus_FW; -static unsigned char return_status = 0xFF; - -static signed char mac_status = -1; -static unsigned char counter = 0; - -// Array to store RM parameters from EEPROM. -static unsigned char cRMParamsFromEeprom[128]; -// Array to store MAC address from EEPROM. -static unsigned char cMacFromEeprom[MAC_ADDR_LEN]; -// Smart Config Prefix -static const char aucCC3000_prefix[] = {'T', 'T', 'T'}; - -static void systick_sleep(unsigned long ms) { - extern void HAL_Delay(volatile uint32_t Delay); - HAL_Delay(ms); -} - -// 2 dim array to store address and length of new FAT -static const unsigned short aFATEntries[2][NVMEM_RM_FILEID + 1] = -/* address */ {{0x50, 0x1f0, 0x390, 0x1390, 0x2390, 0x4390, 0x6390, 0x63a0, 0x63b0, 0x63f0, 0x6430, 0x6830}, -/* length */ {0x1a0, 0x1a0, 0x1000, 0x1000, 0x2000, 0x2000, 0x10, 0x10, 0x40, 0x40, 0x400, 0x200}}; -/* 0. NVS */ -/* 1. NVS Shadow */ -/* 2. Wireless Conf */ -/* 3. Wireless Conf Shadow */ -/* 4. BT (WLAN driver) Patches */ -/* 5. WiLink (Firmware) Patches */ -/* 6. MAC addr */ -/* 7. Frontend Vars */ -/* 8. IP config */ -/* 9. IP config Shadow */ -/* 10. Bootloader Patches */ -/* 11. Radio Module params */ -/* 12. AES128 for smart config */ -/* 13. user file */ -/* 14. user file */ -/* 15. user file */ - -//***************************************************************************** -// -//! sendDriverPatch -//! -//! \param pointer to the length -//! -//! \return none -//! -//! \brief The function returns a pointer to the driver patch: -//! since there is no patch yet - it returns 0 -// -//***************************************************************************** - -static char *sendDriverPatch(unsigned long *Length) -{ - *Length = 0; - return NULL; -} - - -//***************************************************************************** -// -//! sendBootLoaderPatch -//! -//! \param pointer to the length -//! -//! \return none -//! -//! \brief The function returns a pointer to the boot loader patch: -//! since there is no patch yet - it returns 0 -// -//***************************************************************************** - -static char *sendBootLoaderPatch(unsigned long *Length) -{ - *Length = 0; - return NULL; -} - -//***************************************************************************** -// -//! sendWLFWPatch -//! -//! \param pointer to the length -//! -//! \return none -//! -//! \brief The function returns a pointer to the FW patch: -//! since there is no patch yet - it returns 0 -// -//***************************************************************************** - -static char *sendWLFWPatch(unsigned long *Length) -{ - *Length = 0; - return NULL; -} - -//***************************************************************************** -// -//! CC3000_UsynchCallback -//! -//! \param Event type -//! -//! \return none -//! -//! \brief The function handles asynchronous events that come from CC3000 -//! device and operates a LED4 to have an on-board indication -// -//***************************************************************************** - -static void CC3000_UsynchCallback(long lEventType, char * data, unsigned char length) -{ - -} - -//***************************************************************************** -// -//! initDriver -//! -//! \param[in] cRequestPatch 0 to load with EEPROM patches -//! and 1 to load with no patches -//! -//! \return none -//! -//! \brief The function initializes a CC3000 device -//! and triggers it to start operation -// -//***************************************************************************** -static int initDriver(unsigned short cRequestPatch) -{ - // WLAN On API Implementation - wlan_init(CC3000_UsynchCallback, sendWLFWPatch, sendDriverPatch, sendBootLoaderPatch, - ReadWlanInterruptPin, SpiResumeSpi, SpiPauseSpi, WriteWlanPin); - - // Trigger a WLAN device - wlan_start(cRequestPatch); - wlan_smart_config_set_prefix((char*)aucCC3000_prefix); - wlan_ioctl_set_connection_policy(0, 0, 0); - wlan_ioctl_del_profile(255); - - // Mask out all non-required events from CC3000 - wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE| - HCI_EVNT_WLAN_UNSOL_INIT| - HCI_EVNT_WLAN_ASYNC_PING_REPORT); - - //unsolicicted_events_timer_init(); - systick_sleep(100); - return(0); -} - - -//***************************************************************************** -// -//! fat_read_content -//! -//! \param[out] is_allocated array of is_allocated in FAT table:\n -//! an allocated entry implies the address and length of the -//! file are valid. -//! 0: not allocated; 1: allocated. -//! \param[out] is_valid array of is_valid in FAT table:\n -//! a valid entry implies the content of the file is relevant. -//! 0: not valid; 1: valid. -//! \param[out] write_protected array of write_protected in FAT table:\n -//! a write protected entry implies it is not possible to write -//! into this entry. -//! 0: not protected; 1: protected. -//! \param[out] file_address array of file address in FAT table:\n -//! this is the absolute address of the file in the EEPROM. -//! \param[out] file_length array of file length in FAT table:\n -//! this is the upper limit of the file size in the EEPROM. -//! -//! \return on succes 0, error otherwise -//! -//! \brief parse the FAT table from eeprom -// -//***************************************************************************** -static unsigned char __attribute__ ((unused)) -fat_read_content(unsigned char *is_allocated, unsigned char *is_valid, - unsigned char *write_protected, unsigned short *file_address, unsigned short *file_length) -{ - unsigned short index; - unsigned char ucStatus; - unsigned char fatTable[48]; - unsigned char* fatTablePtr = fatTable; - - // - // Read in 6 parts to work with tiny driver - // - for (index = 0; index < 6; index++) - { - ucStatus = nvmem_read(16, 8, 4 + 8*index, fatTablePtr); - fatTablePtr += 8; - } - - fatTablePtr = fatTable; - - for (index = 0; index <= NVMEM_RM_FILEID; index++) - { - *is_allocated++ = (*fatTablePtr) & BIT0; - *is_valid++ = ((*fatTablePtr) & BIT1) >> 1; - *write_protected++ = ((*fatTablePtr) & BIT2) >> 2; - *file_address++ = ((*(fatTablePtr+1)<<8) | (*fatTablePtr)) & (BIT4|BIT5|BIT6|BIT7); - *file_length++ = ((*(fatTablePtr+3)<<8) | (*(fatTablePtr+2))) & (BIT4|BIT5|BIT6|BIT7); - - // - // Move to next file ID - // - fatTablePtr += 4; - } - - return ucStatus; -} - -//***************************************************************************** -// -//! fat_write_content -//! -//! \param[in] file_address array of file address in FAT table:\n -//! this is the absolute address of the file in the EEPROM. -//! \param[in] file_length array of file length in FAT table:\n -//! this is the upper limit of the file size in the EEPROM. -//! -//! \return on succes 0, error otherwise -//! -//! \brief parse the FAT table from eeprom -// -//***************************************************************************** -static unsigned char fat_write_content(unsigned short const *file_address, - unsigned short const *file_length) -{ - unsigned short index = 0; - unsigned char ucStatus; - unsigned char fatTable[48]; - unsigned char* fatTablePtr = fatTable; - - // - // First, write the magic number. - // - ucStatus = nvmem_write(16, 2, 0, (unsigned char*)"LS"); - - for (; index <= NVMEM_RM_FILEID; index++) - { - // - // Write address low char and mark as allocated. - // - *fatTablePtr++ = (unsigned char)(file_address[index] & 0xff) | BIT0; - - // - // Write address high char. - // - *fatTablePtr++ = (unsigned char)((file_address[index]>>8) & 0xff); - - // - // Write length low char. - // - *fatTablePtr++ = (unsigned char)(file_length[index] & 0xff); - - // - // Write length high char. - // - *fatTablePtr++ = (unsigned char)((file_length[index]>>8) & 0xff); - } - - // - // Second, write the FAT. - // Write in two parts to work with tiny driver. - // - ucStatus = nvmem_write(16, 24, 4, fatTable); - ucStatus = nvmem_write(16, 24, 24+4, &fatTable[24]); - - // - // Third, we want to erase any user files. - // - memset(fatTable, 0, sizeof(fatTable)); - ucStatus = nvmem_write(16, 16, 52, fatTable); - - return ucStatus; -} - -void patch_prog_start() -{ - unsigned short index; - unsigned char *pRMParams; - - printf("Initializing module...\n"); - - // Init module and request to load with no patches. - // This is in order to overwrite restrictions to - // write to specific places in EEPROM. - initDriver(1); - - // Read MAC address. - mac_status = nvmem_get_mac_address(cMacFromEeprom); - - return_status = 1; - - printf("Reading RM parameters...\n"); - while ((return_status) && (counter < 3)) { - // Read RM parameters. - // Read in 16 parts to work with tiny driver. - return_status = 0; - pRMParams = cRMParamsFromEeprom; - for (index = 0; index < 16; index++) { - return_status |= nvmem_read(NVMEM_RM_FILEID, 8, 8*index, pRMParams); - pRMParams += 8; - } - counter++; - } - - // If RM file is not valid, load the default one. - if (counter == 3) { - printf("RM is not valid, loading default one...\n"); - pRMParams = (unsigned char *)cRMdefaultParams; - } else { - printf("RM is valid.\n"); - pRMParams = cRMParamsFromEeprom; - } - - return_status = 1; - - printf("Writing new FAT\n"); - while (return_status) { - // Write new FAT. - return_status = fat_write_content(aFATEntries[0], aFATEntries[1]); - } - - return_status = 1; - - printf("Writing RM parameters...\n"); - while (return_status) { - // Write RM parameters. - // Write in 4 parts to work with tiny driver. - return_status = 0; - - for (index = 0; index < 4; index++) { - return_status |= nvmem_write(NVMEM_RM_FILEID, - 32, - 32*index, - (pRMParams + 32*index)); - } - } - - return_status = 1; - - // Write back the MAC address, only if exists. - if (mac_status == 0) { - // Zero out MCAST bit if set. - cMacFromEeprom[0] &= 0xfe; - printf("Writing back MAC address..\n"); - while (return_status) { - return_status = nvmem_set_mac_address(cMacFromEeprom); - } - } - - // Update driver - ucStatus_Dr = 1; - printf("Updating driver patch...\n"); - while (ucStatus_Dr) { - // Writing driver patch to EEPRROM - PROTABLE CODE - // Note that the array itself is changing between the - // different Service Packs. - ucStatus_Dr = nvmem_write_patch(NVMEM_WLAN_DRIVER_SP_FILEID, - drv_length, - wlan_drv_patch); - } - - // Update firmware - ucStatus_FW = 1; - printf("Updating firmware patch...\n"); - while (ucStatus_FW) { - // Writing FW patch to EEPRROM - PROTABLE CODE - // Note that the array itself is changing between the - // different Service Packs. - ucStatus_FW = nvmem_write_patch(NVMEM_WLAN_FW_SP_FILEID, - fw_length, - fw_patch); - } - - printf("Update complete, resetting module\n"\ - "If this doesn't work, reset manually...\n"); - - wlan_stop(); - systick_sleep(500); - - // Re-Init module and request to load with patches. - initDriver(0); - - // If MAC does not exist, it is recommended - // that the user will write a valid mac address. - if (mac_status != 0) { - printf("MAC address is not valid, please write a new one\n"); - } - - // Patch update done - printf("All done, call wlan.patch_version()\n"); -} diff --git a/drivers/cc3000/src/security.c b/drivers/cc3000/src/security.c deleted file mode 100644 index 62b4f88134..0000000000 --- a/drivers/cc3000/src/security.c +++ /dev/null @@ -1,530 +0,0 @@ -/***************************************************************************** -* -* security.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -//***************************************************************************** -// -//! \addtogroup security_api -//! @{ -// -//***************************************************************************** - -#include "security.h" - -#ifndef CC3000_UNENCRYPTED_SMART_CONFIG -// foreward sbox -const UINT8 sbox[256] = { -//0 1 2 3 4 5 6 7 8 9 A B C D E F -0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0 -0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1 -0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2 -0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3 -0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4 -0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5 -0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6 -0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7 -0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8 -0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9 -0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A -0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B -0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C -0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D -0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E -0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //F -// inverse sbox -const UINT8 rsbox[256] = -{ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb -, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb -, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e -, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 -, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 -, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 -, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 -, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b -, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 -, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e -, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b -, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 -, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f -, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef -, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 -, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; -// round constant -const UINT8 Rcon[11] = { - 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; - - -UINT8 expandedKey[176]; - -//***************************************************************************** -// -//! expandKey -//! -//! @param key AES128 key - 16 bytes -//! @param expandedKey expanded AES128 key -//! -//! @return none -//! -//! @brief expend a 16 bytes key for AES128 implementation -//! -//***************************************************************************** - -void expandKey(UINT8 *expandedKey, UINT8 *key) -{ - UINT16 ii, buf1; - for (ii=0;ii<16;ii++) - expandedKey[ii] = key[ii]; - for (ii=1;ii<11;ii++){ - buf1 = expandedKey[ii*16 - 4]; - expandedKey[ii*16 + 0] = sbox[expandedKey[ii*16 - 3]]^expandedKey[(ii-1)*16 + 0]^Rcon[ii]; - expandedKey[ii*16 + 1] = sbox[expandedKey[ii*16 - 2]]^expandedKey[(ii-1)*16 + 1]; - expandedKey[ii*16 + 2] = sbox[expandedKey[ii*16 - 1]]^expandedKey[(ii-1)*16 + 2]; - expandedKey[ii*16 + 3] = sbox[buf1 ]^expandedKey[(ii-1)*16 + 3]; - expandedKey[ii*16 + 4] = expandedKey[(ii-1)*16 + 4]^expandedKey[ii*16 + 0]; - expandedKey[ii*16 + 5] = expandedKey[(ii-1)*16 + 5]^expandedKey[ii*16 + 1]; - expandedKey[ii*16 + 6] = expandedKey[(ii-1)*16 + 6]^expandedKey[ii*16 + 2]; - expandedKey[ii*16 + 7] = expandedKey[(ii-1)*16 + 7]^expandedKey[ii*16 + 3]; - expandedKey[ii*16 + 8] = expandedKey[(ii-1)*16 + 8]^expandedKey[ii*16 + 4]; - expandedKey[ii*16 + 9] = expandedKey[(ii-1)*16 + 9]^expandedKey[ii*16 + 5]; - expandedKey[ii*16 +10] = expandedKey[(ii-1)*16 +10]^expandedKey[ii*16 + 6]; - expandedKey[ii*16 +11] = expandedKey[(ii-1)*16 +11]^expandedKey[ii*16 + 7]; - expandedKey[ii*16 +12] = expandedKey[(ii-1)*16 +12]^expandedKey[ii*16 + 8]; - expandedKey[ii*16 +13] = expandedKey[(ii-1)*16 +13]^expandedKey[ii*16 + 9]; - expandedKey[ii*16 +14] = expandedKey[(ii-1)*16 +14]^expandedKey[ii*16 +10]; - expandedKey[ii*16 +15] = expandedKey[(ii-1)*16 +15]^expandedKey[ii*16 +11]; - } - -} - -//***************************************************************************** -// -//! galois_mul2 -//! -//! @param value argument to multiply -//! -//! @return multiplied argument -//! -//! @brief multiply by 2 in the galois field -//! -//***************************************************************************** - -UINT8 galois_mul2(UINT8 value) -{ - if (value>>7) - { - value = value << 1; - return (value^0x1b); - } else - return value<<1; -} - -//***************************************************************************** -// -//! aes_encr -//! -//! @param[in] expandedKey expanded AES128 key -//! @param[in/out] state 16 bytes of plain text and cipher text -//! -//! @return none -//! -//! @brief internal implementation of AES128 encryption. -//! straight forward aes encryption implementation -//! first the group of operations -//! - addRoundKey -//! - subbytes -//! - shiftrows -//! - mixcolums -//! is executed 9 times, after this addroundkey to finish the 9th -//! round, after that the 10th round without mixcolums -//! no further subfunctions to save cycles for function calls -//! no structuring with "for (....)" to save cycles. -//! -//! -//***************************************************************************** - -void aes_encr(UINT8 *state, UINT8 *expandedKey) -{ - UINT8 buf1, buf2, buf3, round; - - for (round = 0; round < 9; round ++){ - // addroundkey, sbox and shiftrows - // row 0 - state[ 0] = sbox[(state[ 0] ^ expandedKey[(round*16) ])]; - state[ 4] = sbox[(state[ 4] ^ expandedKey[(round*16) + 4])]; - state[ 8] = sbox[(state[ 8] ^ expandedKey[(round*16) + 8])]; - state[12] = sbox[(state[12] ^ expandedKey[(round*16) + 12])]; - // row 1 - buf1 = state[1] ^ expandedKey[(round*16) + 1]; - state[ 1] = sbox[(state[ 5] ^ expandedKey[(round*16) + 5])]; - state[ 5] = sbox[(state[ 9] ^ expandedKey[(round*16) + 9])]; - state[ 9] = sbox[(state[13] ^ expandedKey[(round*16) + 13])]; - state[13] = sbox[buf1]; - // row 2 - buf1 = state[2] ^ expandedKey[(round*16) + 2]; - buf2 = state[6] ^ expandedKey[(round*16) + 6]; - state[ 2] = sbox[(state[10] ^ expandedKey[(round*16) + 10])]; - state[ 6] = sbox[(state[14] ^ expandedKey[(round*16) + 14])]; - state[10] = sbox[buf1]; - state[14] = sbox[buf2]; - // row 3 - buf1 = state[15] ^ expandedKey[(round*16) + 15]; - state[15] = sbox[(state[11] ^ expandedKey[(round*16) + 11])]; - state[11] = sbox[(state[ 7] ^ expandedKey[(round*16) + 7])]; - state[ 7] = sbox[(state[ 3] ^ expandedKey[(round*16) + 3])]; - state[ 3] = sbox[buf1]; - - // mixcolums ////////// - // col1 - buf1 = state[0] ^ state[1] ^ state[2] ^ state[3]; - buf2 = state[0]; - buf3 = state[0]^state[1]; buf3=galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1; - buf3 = state[1]^state[2]; buf3=galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1; - buf3 = state[2]^state[3]; buf3=galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1; - buf3 = state[3]^buf2; buf3=galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1; - // col2 - buf1 = state[4] ^ state[5] ^ state[6] ^ state[7]; - buf2 = state[4]; - buf3 = state[4]^state[5]; buf3=galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1; - buf3 = state[5]^state[6]; buf3=galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1; - buf3 = state[6]^state[7]; buf3=galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1; - buf3 = state[7]^buf2; buf3=galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1; - // col3 - buf1 = state[8] ^ state[9] ^ state[10] ^ state[11]; - buf2 = state[8]; - buf3 = state[8]^state[9]; buf3=galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1; - buf3 = state[9]^state[10]; buf3=galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1; - buf3 = state[10]^state[11]; buf3=galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1; - buf3 = state[11]^buf2; buf3=galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1; - // col4 - buf1 = state[12] ^ state[13] ^ state[14] ^ state[15]; - buf2 = state[12]; - buf3 = state[12]^state[13]; buf3=galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1; - buf3 = state[13]^state[14]; buf3=galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1; - buf3 = state[14]^state[15]; buf3=galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1; - buf3 = state[15]^buf2; buf3=galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1; - - } - // 10th round without mixcols - state[ 0] = sbox[(state[ 0] ^ expandedKey[(round*16) ])]; - state[ 4] = sbox[(state[ 4] ^ expandedKey[(round*16) + 4])]; - state[ 8] = sbox[(state[ 8] ^ expandedKey[(round*16) + 8])]; - state[12] = sbox[(state[12] ^ expandedKey[(round*16) + 12])]; - // row 1 - buf1 = state[1] ^ expandedKey[(round*16) + 1]; - state[ 1] = sbox[(state[ 5] ^ expandedKey[(round*16) + 5])]; - state[ 5] = sbox[(state[ 9] ^ expandedKey[(round*16) + 9])]; - state[ 9] = sbox[(state[13] ^ expandedKey[(round*16) + 13])]; - state[13] = sbox[buf1]; - // row 2 - buf1 = state[2] ^ expandedKey[(round*16) + 2]; - buf2 = state[6] ^ expandedKey[(round*16) + 6]; - state[ 2] = sbox[(state[10] ^ expandedKey[(round*16) + 10])]; - state[ 6] = sbox[(state[14] ^ expandedKey[(round*16) + 14])]; - state[10] = sbox[buf1]; - state[14] = sbox[buf2]; - // row 3 - buf1 = state[15] ^ expandedKey[(round*16) + 15]; - state[15] = sbox[(state[11] ^ expandedKey[(round*16) + 11])]; - state[11] = sbox[(state[ 7] ^ expandedKey[(round*16) + 7])]; - state[ 7] = sbox[(state[ 3] ^ expandedKey[(round*16) + 3])]; - state[ 3] = sbox[buf1]; - // last addroundkey - state[ 0]^=expandedKey[160]; - state[ 1]^=expandedKey[161]; - state[ 2]^=expandedKey[162]; - state[ 3]^=expandedKey[163]; - state[ 4]^=expandedKey[164]; - state[ 5]^=expandedKey[165]; - state[ 6]^=expandedKey[166]; - state[ 7]^=expandedKey[167]; - state[ 8]^=expandedKey[168]; - state[ 9]^=expandedKey[169]; - state[10]^=expandedKey[170]; - state[11]^=expandedKey[171]; - state[12]^=expandedKey[172]; - state[13]^=expandedKey[173]; - state[14]^=expandedKey[174]; - state[15]^=expandedKey[175]; -} - -//***************************************************************************** -// -//! aes_decr -//! -//! @param[in] expandedKey expanded AES128 key -//! @param[in\out] state 16 bytes of cipher text and plain text -//! -//! @return none -//! -//! @brief internal implementation of AES128 decryption. -//! straight forward aes decryption implementation -//! the order of substeps is the exact reverse of decryption -//! inverse functions: -//! - addRoundKey is its own inverse -//! - rsbox is inverse of sbox -//! - rightshift instead of leftshift -//! - invMixColumns = barreto + mixColumns -//! no further subfunctions to save cycles for function calls -//! no structuring with "for (....)" to save cycles -//! -//***************************************************************************** - -void aes_decr(UINT8 *state, UINT8 *expandedKey) -{ - UINT8 buf1, buf2, buf3; - INT8 round; - round = 9; - - // initial addroundkey - state[ 0]^=expandedKey[160]; - state[ 1]^=expandedKey[161]; - state[ 2]^=expandedKey[162]; - state[ 3]^=expandedKey[163]; - state[ 4]^=expandedKey[164]; - state[ 5]^=expandedKey[165]; - state[ 6]^=expandedKey[166]; - state[ 7]^=expandedKey[167]; - state[ 8]^=expandedKey[168]; - state[ 9]^=expandedKey[169]; - state[10]^=expandedKey[170]; - state[11]^=expandedKey[171]; - state[12]^=expandedKey[172]; - state[13]^=expandedKey[173]; - state[14]^=expandedKey[174]; - state[15]^=expandedKey[175]; - - // 10th round without mixcols - state[ 0] = rsbox[state[ 0]] ^ expandedKey[(round*16) ]; - state[ 4] = rsbox[state[ 4]] ^ expandedKey[(round*16) + 4]; - state[ 8] = rsbox[state[ 8]] ^ expandedKey[(round*16) + 8]; - state[12] = rsbox[state[12]] ^ expandedKey[(round*16) + 12]; - // row 1 - buf1 = rsbox[state[13]] ^ expandedKey[(round*16) + 1]; - state[13] = rsbox[state[ 9]] ^ expandedKey[(round*16) + 13]; - state[ 9] = rsbox[state[ 5]] ^ expandedKey[(round*16) + 9]; - state[ 5] = rsbox[state[ 1]] ^ expandedKey[(round*16) + 5]; - state[ 1] = buf1; - // row 2 - buf1 = rsbox[state[ 2]] ^ expandedKey[(round*16) + 10]; - buf2 = rsbox[state[ 6]] ^ expandedKey[(round*16) + 14]; - state[ 2] = rsbox[state[10]] ^ expandedKey[(round*16) + 2]; - state[ 6] = rsbox[state[14]] ^ expandedKey[(round*16) + 6]; - state[10] = buf1; - state[14] = buf2; - // row 3 - buf1 = rsbox[state[ 3]] ^ expandedKey[(round*16) + 15]; - state[ 3] = rsbox[state[ 7]] ^ expandedKey[(round*16) + 3]; - state[ 7] = rsbox[state[11]] ^ expandedKey[(round*16) + 7]; - state[11] = rsbox[state[15]] ^ expandedKey[(round*16) + 11]; - state[15] = buf1; - - for (round = 8; round >= 0; round--){ - // barreto - //col1 - buf1 = galois_mul2(galois_mul2(state[0]^state[2])); - buf2 = galois_mul2(galois_mul2(state[1]^state[3])); - state[0] ^= buf1; state[1] ^= buf2; state[2] ^= buf1; state[3] ^= buf2; - //col2 - buf1 = galois_mul2(galois_mul2(state[4]^state[6])); - buf2 = galois_mul2(galois_mul2(state[5]^state[7])); - state[4] ^= buf1; state[5] ^= buf2; state[6] ^= buf1; state[7] ^= buf2; - //col3 - buf1 = galois_mul2(galois_mul2(state[8]^state[10])); - buf2 = galois_mul2(galois_mul2(state[9]^state[11])); - state[8] ^= buf1; state[9] ^= buf2; state[10] ^= buf1; state[11] ^= buf2; - //col4 - buf1 = galois_mul2(galois_mul2(state[12]^state[14])); - buf2 = galois_mul2(galois_mul2(state[13]^state[15])); - state[12] ^= buf1; state[13] ^= buf2; state[14] ^= buf1; state[15] ^= buf2; - // mixcolums ////////// - // col1 - buf1 = state[0] ^ state[1] ^ state[2] ^ state[3]; - buf2 = state[0]; - buf3 = state[0]^state[1]; buf3=galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1; - buf3 = state[1]^state[2]; buf3=galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1; - buf3 = state[2]^state[3]; buf3=galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1; - buf3 = state[3]^buf2; buf3=galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1; - // col2 - buf1 = state[4] ^ state[5] ^ state[6] ^ state[7]; - buf2 = state[4]; - buf3 = state[4]^state[5]; buf3=galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1; - buf3 = state[5]^state[6]; buf3=galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1; - buf3 = state[6]^state[7]; buf3=galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1; - buf3 = state[7]^buf2; buf3=galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1; - // col3 - buf1 = state[8] ^ state[9] ^ state[10] ^ state[11]; - buf2 = state[8]; - buf3 = state[8]^state[9]; buf3=galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1; - buf3 = state[9]^state[10]; buf3=galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1; - buf3 = state[10]^state[11]; buf3=galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1; - buf3 = state[11]^buf2; buf3=galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1; - // col4 - buf1 = state[12] ^ state[13] ^ state[14] ^ state[15]; - buf2 = state[12]; - buf3 = state[12]^state[13]; buf3=galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1; - buf3 = state[13]^state[14]; buf3=galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1; - buf3 = state[14]^state[15]; buf3=galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1; - buf3 = state[15]^buf2; buf3=galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1; - - // addroundkey, rsbox and shiftrows - // row 0 - state[ 0] = rsbox[state[ 0]] ^ expandedKey[(round*16) ]; - state[ 4] = rsbox[state[ 4]] ^ expandedKey[(round*16) + 4]; - state[ 8] = rsbox[state[ 8]] ^ expandedKey[(round*16) + 8]; - state[12] = rsbox[state[12]] ^ expandedKey[(round*16) + 12]; - // row 1 - buf1 = rsbox[state[13]] ^ expandedKey[(round*16) + 1]; - state[13] = rsbox[state[ 9]] ^ expandedKey[(round*16) + 13]; - state[ 9] = rsbox[state[ 5]] ^ expandedKey[(round*16) + 9]; - state[ 5] = rsbox[state[ 1]] ^ expandedKey[(round*16) + 5]; - state[ 1] = buf1; - // row 2 - buf1 = rsbox[state[ 2]] ^ expandedKey[(round*16) + 10]; - buf2 = rsbox[state[ 6]] ^ expandedKey[(round*16) + 14]; - state[ 2] = rsbox[state[10]] ^ expandedKey[(round*16) + 2]; - state[ 6] = rsbox[state[14]] ^ expandedKey[(round*16) + 6]; - state[10] = buf1; - state[14] = buf2; - // row 3 - buf1 = rsbox[state[ 3]] ^ expandedKey[(round*16) + 15]; - state[ 3] = rsbox[state[ 7]] ^ expandedKey[(round*16) + 3]; - state[ 7] = rsbox[state[11]] ^ expandedKey[(round*16) + 7]; - state[11] = rsbox[state[15]] ^ expandedKey[(round*16) + 11]; - state[15] = buf1; - } - -} - -//***************************************************************************** -// -//! aes_encrypt -//! -//! @param[in] key AES128 key of size 16 bytes -//! @param[in\out] state 16 bytes of plain text and cipher text -//! -//! @return none -//! -//! @brief AES128 encryption: -//! Given AES128 key and 16 bytes plain text, cipher text of 16 bytes -//! is computed. The AES implementation is in mode ECB (Electronic -//! Code Book). -//! -//! -//***************************************************************************** - -void aes_encrypt(UINT8 *state, UINT8 *key) -{ - // expand the key into 176 bytes - expandKey(expandedKey, key); - aes_encr(state, expandedKey); -} - -//***************************************************************************** -// -//! aes_decrypt -//! -//! @param[in] key AES128 key of size 16 bytes -//! @param[in\out] state 16 bytes of cipher text and plain text -//! -//! @return none -//! -//! @brief AES128 decryption: -//! Given AES128 key and 16 bytes cipher text, plain text of 16 bytes -//! is computed The AES implementation is in mode ECB -//! (Electronic Code Book). -//! -//! -//***************************************************************************** - -void aes_decrypt(UINT8 *state, UINT8 *key) -{ - expandKey(expandedKey, key); // expand the key into 176 bytes - aes_decr(state, expandedKey); -} - -//***************************************************************************** -// -//! aes_read_key -//! -//! @param[out] key AES128 key of size 16 bytes -//! -//! @return on success 0, error otherwise. -//! -//! @brief Reads AES128 key from EEPROM -//! Reads the AES128 key from fileID #12 in EEPROM -//! returns an error if the key does not exist. -//! -//! -//***************************************************************************** - -INT32 aes_read_key(UINT8 *key) -{ - INT32 returnValue; - - returnValue = nvmem_read(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key); - - return returnValue; -} - -//***************************************************************************** -// -//! aes_write_key -//! -//! @param[out] key AES128 key of size 16 bytes -//! -//! @return on success 0, error otherwise. -//! -//! @brief writes AES128 key from EEPROM -//! Writes the AES128 key to fileID #12 in EEPROM -//! -//! -//***************************************************************************** - -INT32 aes_write_key(UINT8 *key) -{ - INT32 returnValue; - - returnValue = nvmem_write(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key); - - return returnValue; -} - -#endif //CC3000_UNENCRYPTED_SMART_CONFIG - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** diff --git a/drivers/cc3000/src/socket.c b/drivers/cc3000/src/socket.c deleted file mode 100644 index ddd7e56e80..0000000000 --- a/drivers/cc3000/src/socket.c +++ /dev/null @@ -1,1182 +0,0 @@ -/***************************************************************************** -* -* socket.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -//***************************************************************************** -// -//! \addtogroup socket_api -//! @{ -// -//***************************************************************************** - -#include -#include -#include "hci.h" -#include "socket.h" -#include "evnt_handler.h" -#include "netapp.h" - - - -//Enable this flag if and only if you must comply with BSD socket -//close() function -#ifdef _API_USE_BSD_CLOSE -#define close(sd) closesocket(sd) -#endif - -//Enable this flag if and only if you must comply with BSD socket read() and -//write() functions -#ifdef _API_USE_BSD_READ_WRITE -#define read(sd, buf, len, flags) recv(sd, buf, len, flags) -#define write(sd, buf, len, flags) send(sd, buf, len, flags) -#endif - -#define SOCKET_OPEN_PARAMS_LEN (12) -#define SOCKET_CLOSE_PARAMS_LEN (4) -#define SOCKET_ACCEPT_PARAMS_LEN (4) -#define SOCKET_BIND_PARAMS_LEN (20) -#define SOCKET_LISTEN_PARAMS_LEN (8) -#define SOCKET_GET_HOST_BY_NAME_PARAMS_LEN (9) -#define SOCKET_CONNECT_PARAMS_LEN (20) -#define SOCKET_SELECT_PARAMS_LEN (44) -#define SOCKET_SET_SOCK_OPT_PARAMS_LEN (20) -#define SOCKET_GET_SOCK_OPT_PARAMS_LEN (12) -#define SOCKET_RECV_FROM_PARAMS_LEN (12) -#define SOCKET_SENDTO_PARAMS_LEN (24) -#define SOCKET_MDNS_ADVERTISE_PARAMS_LEN (12) -#define SOCKET_GET_MSS_VALUE_PARAMS_LEN (4) - -// The legnth of arguments for the SEND command: sd + buff_offset + len + flags, -// while size of each parameter is 32 bit - so the total length is 16 bytes; - -#define HCI_CMND_SEND_ARG_LENGTH (16) - - -#define SELECT_TIMEOUT_MIN_MICRO_SECONDS 5000 - -#define HEADERS_SIZE_DATA (SPI_HEADER_SIZE + 5) - -#define SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE) - -#define MDNS_DEVICE_SERVICE_MAX_LENGTH (32) - - -//***************************************************************************** -// -//! HostFlowControlConsumeBuff -//! -//! @param sd socket descriptor -//! -//! @return 0 in case there are buffers available, -//! -1 in case of bad socket -//! -2 if there are no free buffers present (only when -//! SEND_NON_BLOCKING is enabled) -//! -//! @brief if SEND_NON_BLOCKING not define - block until have free buffer -//! becomes available, else return immediately with correct status -//! regarding the buffers available. -// -//***************************************************************************** -static INT16 HostFlowControlConsumeBuff(INT16 sd) -{ -#ifndef SEND_NON_BLOCKING - /* wait in busy loop */ - do - { - // In case last transmission failed then we will return the last failure - // reason here. - // Note that the buffer will not be allocated in this case - if (tSLInformation.slTransmitDataError != 0) - { - CC3000_EXPORT(errno) = tSLInformation.slTransmitDataError; - tSLInformation.slTransmitDataError = 0; - return CC3000_EXPORT(errno); - } - - if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd)) - return -1; - } while(0 == tSLInformation.usNumberOfFreeBuffers); - - tSLInformation.usNumberOfFreeBuffers--; - - return 0; -#else - - // In case last transmission failed then we will return the last failure - // reason here. - // Note that the buffer will not be allocated in this case - if (tSLInformation.slTransmitDataError != 0) - { - CC3000_EXPORT(errno) = tSLInformation.slTransmitDataError; - tSLInformation.slTransmitDataError = 0; - return CC3000_EXPORT(errno); - } - if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd)) - return -1; - - //If there are no available buffers, return -2. It is recommended to use - // select or receive to see if there is any buffer occupied with received data - // If so, call receive() to release the buffer. - if(0 == tSLInformation.usNumberOfFreeBuffers) - { - return -2; - } - else - { - tSLInformation.usNumberOfFreeBuffers--; - return 0; - } -#endif -} - -//***************************************************************************** -// -//! socket -//! -//! @param domain selects the protocol family which will be used for -//! communication. On this version only AF_INET is supported -//! @param type specifies the communication semantics. On this version -//! only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported -//! @param protocol specifies a particular protocol to be used with the -//! socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are -//! supported. -//! -//! @return On success, socket handle that is used for consequent socket -//! operations. On error, -1 is returned. -//! -//! @brief create an endpoint for communication -//! The socket function creates a socket that is bound to a specific -//! transport service provider. This function is called by the -//! application layer to obtain a socket handle. -// -//***************************************************************************** - -INT16 CC3000_EXPORT(socket)(INT32 domain, INT32 type, INT32 protocol) -{ - INT32 ret; - UINT8 *ptr, *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, domain); - args = UINT32_TO_STREAM(args, type); - args = UINT32_TO_STREAM(args, protocol); - - // Initiate a HCI command - hci_command_send(HCI_CMND_SOCKET, ptr, SOCKET_OPEN_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_SOCKET, &ret); - - // Process the event - CC3000_EXPORT(errno) = ret; - - set_socket_active_status(ret, SOCKET_STATUS_ACTIVE); - - return(ret); -} - -//***************************************************************************** -// -//! closesocket -//! -//! @param sd socket handle. -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief The socket function closes a created socket. -// -//***************************************************************************** - -INT32 CC3000_EXPORT(closesocket)(INT32 sd) -{ - INT32 ret; - UINT8 *ptr, *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, sd); - - // Initiate a HCI command - hci_command_send(HCI_CMND_CLOSE_SOCKET, - ptr, SOCKET_CLOSE_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_CLOSE_SOCKET, &ret); - CC3000_EXPORT(errno) = ret; - - // since 'close' call may result in either OK (and then it closed) or error - // mark this socket as invalid - set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); - - return(ret); -} - -//***************************************************************************** -// -//! accept -//! -//! @param[in] sd socket descriptor (handle) -//! @param[out] addr the argument addr is a pointer to a sockaddr structure -//! This structure is filled in with the address of the -//! peer socket, as known to the communications layer. -//! determined. The exact format of the address returned -//! addr is by the socket's address sockaddr. -//! On this version only AF_INET is supported. -//! This argument returns in network order. -//! @param[out] addrlen the addrlen argument is a value-result argument: -//! it should initially contain the size of the structure -//! pointed to by addr. -//! -//! @return For socket in blocking mode: -//! On success, socket handle. on failure negative -//! For socket in non-blocking mode: -//! - On connection establishment, socket handle -//! - On connection pending, SOC_IN_PROGRESS (-2) -//! - On failure, SOC_ERROR (-1) -//! -//! @brief accept a connection on a socket: -//! This function is used with connection-based socket types -//! (SOCK_STREAM). It extracts the first connection request on the -//! queue of pending connections, creates a new connected socket, and -//! returns a new file descriptor referring to that socket. -//! The newly created socket is not in the listening state. -//! The original socket sd is unaffected by this call. -//! The argument sd is a socket that has been created with socket(), -//! bound to a local address with bind(), and is listening for -//! connections after a listen(). The argument addr is a pointer -//! to a sockaddr structure. This structure is filled in with the -//! address of the peer socket, as known to the communications layer. -//! The exact format of the address returned addr is determined by the -//! socket's address family. The addrlen argument is a value-result -//! argument: it should initially contain the size of the structure -//! pointed to by addr, on return it will contain the actual -//! length (in bytes) of the address returned. -//! -//! @sa socket ; bind ; listen -// -//***************************************************************************** - -INT32 CC3000_EXPORT(accept)(INT32 sd, sockaddr *addr, socklen_t *addrlen) -{ - INT32 ret; - UINT8 *ptr, *args; - tBsdReturnParams tAcceptReturnArguments; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - - // Initiate a HCI command - hci_command_send(HCI_CMND_ACCEPT, - ptr, SOCKET_ACCEPT_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_ACCEPT, &tAcceptReturnArguments); - - - // need specify return parameters!!! - memcpy(addr, &tAcceptReturnArguments.tSocketAddress, ASIC_ADDR_LEN); - *addrlen = ASIC_ADDR_LEN; - CC3000_EXPORT(errno) = tAcceptReturnArguments.iStatus; - ret = CC3000_EXPORT(errno); - - // if succeeded, iStatus = new socket descriptor. otherwise - error number - if(M_IS_VALID_SD(ret)) - { - set_socket_active_status(ret, SOCKET_STATUS_ACTIVE); - } - else - { - set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); - } - - return(ret); -} - -//***************************************************************************** -// -//! bind -//! -//! @param[in] sd socket descriptor (handle) -//! @param[out] addr specifies the destination address. On this version -//! only AF_INET is supported. -//! @param[out] addrlen contains the size of the structure pointed to by addr. -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief assign a name to a socket -//! This function gives the socket the local address addr. -//! addr is addrlen bytes long. Traditionally, this is called when a -//! socket is created with socket, it exists in a name space (address -//! family) but has no name assigned. -//! It is necessary to assign a local address before a SOCK_STREAM -//! socket may receive connections. -//! -//! @sa socket ; accept ; listen -// -//***************************************************************************** - -INT32 CC3000_EXPORT(bind)(INT32 sd, const sockaddr *addr, INT32 addrlen) -{ - INT32 ret; - UINT8 *ptr, *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - addrlen = ASIC_ADDR_LEN; - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, 0x00000008); - args = UINT32_TO_STREAM(args, addrlen); - ARRAY_TO_STREAM(args, ((UINT8 *)addr), addrlen); - - // Initiate a HCI command - hci_command_send(HCI_CMND_BIND, - ptr, SOCKET_BIND_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_BIND, &ret); - - CC3000_EXPORT(errno) = ret; - - return(ret); -} - -//***************************************************************************** -// -//! listen -//! -//! @param[in] sd socket descriptor (handle) -//! @param[in] backlog specifies the listen queue depth. On this version -//! backlog is not supported. -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief listen for connections on a socket -//! The willingness to accept incoming connections and a queue -//! limit for incoming connections are specified with listen(), -//! and then the connections are accepted with accept. -//! The listen() call applies only to sockets of type SOCK_STREAM -//! The backlog parameter defines the maximum length the queue of -//! pending connections may grow to. -//! -//! @sa socket ; accept ; bind -//! -//! @note On this version, backlog is not supported -// -//***************************************************************************** - -INT32 CC3000_EXPORT(listen)(INT32 sd, INT32 backlog) -{ - INT32 ret; - UINT8 *ptr, *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, backlog); - - // Initiate a HCI command - hci_command_send(HCI_CMND_LISTEN, - ptr, SOCKET_LISTEN_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_LISTEN, &ret); - CC3000_EXPORT(errno) = ret; - - return(ret); -} - -//***************************************************************************** -// -//! gethostbyname -//! -//! @param[in] hostname host name -//! @param[in] usNameLen name length -//! @param[out] out_ip_addr This parameter is filled in with host IP address. -//! In case that host name is not resolved, -//! out_ip_addr is zero. -//! @return On success, positive is returned. On error, negative is returned -//! -//! @brief Get host IP by name. Obtain the IP Address of machine on network, -//! by its name. -//! -//! @note On this version, only blocking mode is supported. Also note that -//! the function requires DNS server to be configured prior to its usage. -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT16 CC3000_EXPORT(gethostbyname)(CHAR * hostname, UINT16 usNameLen, - UINT32* out_ip_addr) -{ - tBsdGethostbynameParams ret; - UINT8 *ptr, *args; - - CC3000_EXPORT(errno) = EFAIL; - - if (usNameLen > HOSTNAME_MAX_LENGTH) - { - return CC3000_EXPORT(errno); - } - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, 8); - args = UINT32_TO_STREAM(args, usNameLen); - ARRAY_TO_STREAM(args, hostname, usNameLen); - - // Initiate a HCI command - hci_command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN - + usNameLen - 1); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_EVNT_BSD_GETHOSTBYNAME, &ret); - - CC3000_EXPORT(errno) = ret.retVal; - - (*((INT32*)out_ip_addr)) = ret.outputAddress; - - return CC3000_EXPORT(errno); - -} -#endif - -//***************************************************************************** -// -//! connect -//! -//! @param[in] sd socket descriptor (handle) -//! @param[in] addr specifies the destination addr. On this version -//! only AF_INET is supported. -//! @param[out] addrlen contains the size of the structure pointed to by addr -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief initiate a connection on a socket -//! Function connects the socket referred to by the socket descriptor -//! sd, to the address specified by addr. The addrlen argument -//! specifies the size of addr. The format of the address in addr is -//! determined by the address space of the socket. If it is of type -//! SOCK_DGRAM, this call specifies the peer with which the socket is -//! to be associated; this address is that to which datagrams are to be -//! sent, and the only address from which datagrams are to be received. -//! If the socket is of type SOCK_STREAM, this call attempts to make a -//! connection to another socket. The other socket is specified by -//! address, which is an address in the communications space of the -//! socket. Note that the function implements only blocking behavior -//! thus the caller will be waiting either for the connection -//! establishment or for the connection establishment failure. -//! -//! @sa socket -// -//***************************************************************************** - -INT32 CC3000_EXPORT(connect)(INT32 sd, const sockaddr *addr, INT32 addrlen) -{ - INT32 ret; - UINT8 *ptr, *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); - addrlen = 8; - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, 0x00000008); - args = UINT32_TO_STREAM(args, addrlen); - ARRAY_TO_STREAM(args, ((UINT8 *)addr), addrlen); - - // Initiate a HCI command - hci_command_send(HCI_CMND_CONNECT, - ptr, SOCKET_CONNECT_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_CONNECT, &ret); - - CC3000_EXPORT(errno) = ret; - - return((INT32)ret); -} - - -//***************************************************************************** -// -//! select -//! -//! @param[in] nfds the highest-numbered file descriptor in any of the -//! three sets, plus 1. -//! @param[out] writesds socket descriptors list for write monitoring -//! @param[out] readsds socket descriptors list for read monitoring -//! @param[out] exceptsds socket descriptors list for exception monitoring -//! @param[in] timeout is an upper bound on the amount of time elapsed -//! before select() returns. Null means infinity -//! timeout. The minimum timeout is 5 milliseconds, -//! less than 5 milliseconds will be set -//! automatically to 5 milliseconds. -//! @return On success, select() returns the number of file descriptors -//! contained in the three returned descriptor sets (that is, the -//! total number of bits that are set in readfds, writefds, -//! exceptfds) which may be zero if the timeout expires before -//! anything interesting happens. -//! On error, -1 is returned. -//! *readsds - return the sockets on which Read request will -//! return without delay with valid data. -//! *writesds - return the sockets on which Write request -//! will return without delay. -//! *exceptsds - return the sockets which closed recently. -//! -//! @brief Monitor socket activity -//! Select allow a program to monitor multiple file descriptors, -//! waiting until one or more of the file descriptors become -//! "ready" for some class of I/O operation -//! -//! @Note If the timeout value set to less than 5ms it will automatically set -//! to 5ms to prevent overload of the system -//! -//! @sa socket -// -//***************************************************************************** - -INT16 CC3000_EXPORT(select)(INT32 nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds, -struct cc3000_timeval *timeout) -{ - UINT8 *ptr, *args; - tBsdSelectRecvParams tParams; - UINT32 is_blocking; - - if( timeout == NULL) - { - is_blocking = 1; /* blocking , infinity timeout */ - } - else - { - is_blocking = 0; /* no blocking, timeout */ - } - - // Fill in HCI packet structure - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, nfds); - args = UINT32_TO_STREAM(args, 0x00000014); - args = UINT32_TO_STREAM(args, 0x00000014); - args = UINT32_TO_STREAM(args, 0x00000014); - args = UINT32_TO_STREAM(args, 0x00000014); - args = UINT32_TO_STREAM(args, is_blocking); - args = UINT32_TO_STREAM(args, ((readsds) ? *(UINT32*)readsds : 0)); - args = UINT32_TO_STREAM(args, ((writesds) ? *(UINT32*)writesds : 0)); - args = UINT32_TO_STREAM(args, ((exceptsds) ? *(UINT32*)exceptsds : 0)); - - if (timeout) - { - if ( 0 == timeout->tv_sec && timeout->tv_usec < - SELECT_TIMEOUT_MIN_MICRO_SECONDS) - { - timeout->tv_usec = SELECT_TIMEOUT_MIN_MICRO_SECONDS; - } - args = UINT32_TO_STREAM(args, timeout->tv_sec); - args = UINT32_TO_STREAM(args, timeout->tv_usec); - } - - // Initiate a HCI command - hci_command_send(HCI_CMND_BSD_SELECT, ptr, SOCKET_SELECT_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_EVNT_SELECT, &tParams); - - // Update actually read FD - if (tParams.iStatus >= 0) - { - if (readsds) - { - memcpy(readsds, &tParams.uiRdfd, sizeof(tParams.uiRdfd)); - } - - if (writesds) - { - memcpy(writesds, &tParams.uiWrfd, sizeof(tParams.uiWrfd)); - } - - if (exceptsds) - { - memcpy(exceptsds, &tParams.uiExfd, sizeof(tParams.uiExfd)); - } - - return(tParams.iStatus); - - } - else - { - CC3000_EXPORT(errno) = tParams.iStatus; - return(-1); - } -} - -//***************************************************************************** -// -//! setsockopt -//! -//! @param[in] sd socket handle -//! @param[in] level defines the protocol level for this option -//! @param[in] optname defines the option name to Interrogate -//! @param[in] optval specifies a value for the option -//! @param[in] optlen specifies the length of the option value -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief set socket options -//! This function manipulate the options associated with a socket. -//! Options may exist at multiple protocol levels; they are always -//! present at the uppermost socket level. -//! When manipulating socket options the level at which the option -//! resides and the name of the option must be specified. -//! To manipulate options at the socket level, level is specified as -//! SOL_SOCKET. To manipulate options at any other level the protocol -//! number of the appropriate protocol controlling the option is -//! supplied. For example, to indicate that an option is to be -//! interpreted by the TCP protocol, level should be set to the -//! protocol number of TCP; -//! The parameters optval and optlen are used to access optval - -//! use for setsockopt(). For getsockopt() they identify a buffer -//! in which the value for the requested option(s) are to -//! be returned. For getsockopt(), optlen is a value-result -//! parameter, initially containing the size of the buffer -//! pointed to by option_value, and modified on return to -//! indicate the actual size of the value returned. If no option -//! value is to be supplied or returned, option_value may be NULL. -//! -//! @Note On this version the following two socket options are enabled: -//! The only protocol level supported in this version -//! is SOL_SOCKET (level). -//! 1. SOCKOPT_RECV_TIMEOUT (optname) -//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout -//! in milliseconds. -//! In that case optval should be pointer to UINT32. -//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on -//! or off. -//! In that case optval should be SOCK_ON or SOCK_OFF (optval). -//! -//! @sa getsockopt -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT16 CC3000_EXPORT(setsockopt)(INT32 sd, INT32 level, INT32 optname, const void *optval, - socklen_t optlen) -{ - INT32 ret; - UINT8 *ptr, *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, level); - args = UINT32_TO_STREAM(args, optname); - args = UINT32_TO_STREAM(args, 0x00000008); - args = UINT32_TO_STREAM(args, optlen); - ARRAY_TO_STREAM(args, ((UINT8 *)optval), optlen); - - // Initiate a HCI command - hci_command_send(HCI_CMND_SETSOCKOPT, - ptr, SOCKET_SET_SOCK_OPT_PARAMS_LEN + optlen); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_SETSOCKOPT, &ret); - - if (ret >= 0) - { - return (0); - } - else - { - CC3000_EXPORT(errno) = ret; - return ret; - } -} -#endif - -//***************************************************************************** -// -//! getsockopt -//! -//! @param[in] sd socket handle -//! @param[in] level defines the protocol level for this option -//! @param[in] optname defines the option name to Interrogate -//! @param[out] optval specifies a value for the option -//! @param[out] optlen specifies the length of the option value -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief set socket options -//! This function manipulate the options associated with a socket. -//! Options may exist at multiple protocol levels; they are always -//! present at the uppermost socket level. -//! When manipulating socket options the level at which the option -//! resides and the name of the option must be specified. -//! To manipulate options at the socket level, level is specified as -//! SOL_SOCKET. To manipulate options at any other level the protocol -//! number of the appropriate protocol controlling the option is -//! supplied. For example, to indicate that an option is to be -//! interpreted by the TCP protocol, level should be set to the -//! protocol number of TCP; -//! The parameters optval and optlen are used to access optval - -//! use for setsockopt(). For getsockopt() they identify a buffer -//! in which the value for the requested option(s) are to -//! be returned. For getsockopt(), optlen is a value-result -//! parameter, initially containing the size of the buffer -//! pointed to by option_value, and modified on return to -//! indicate the actual size of the value returned. If no option -//! value is to be supplied or returned, option_value may be NULL. -//! -//! @Note On this version the following two socket options are enabled: -//! The only protocol level supported in this version -//! is SOL_SOCKET (level). -//! 1. SOCKOPT_RECV_TIMEOUT (optname) -//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout -//! in milliseconds. -//! In that case optval should be pointer to UINT32. -//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on -//! or off. -//! In that case optval should be SOCK_ON or SOCK_OFF (optval). -//! -//! @sa setsockopt -// -//***************************************************************************** - -INT16 CC3000_EXPORT(getsockopt) (INT32 sd, INT32 level, INT32 optname, void *optval, socklen_t *optlen) -{ - UINT8 *ptr, *args; - tBsdGetSockOptReturnParams tRetParams; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, level); - args = UINT32_TO_STREAM(args, optname); - - // Initiate a HCI command - hci_command_send(HCI_CMND_GETSOCKOPT, - ptr, SOCKET_GET_SOCK_OPT_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_GETSOCKOPT, &tRetParams); - - if (((INT8)tRetParams.iStatus) >= 0) - { - *optlen = 4; - memcpy(optval, tRetParams.ucOptValue, 4); - return (0); - } - else - { - CC3000_EXPORT(errno) = tRetParams.iStatus; - return CC3000_EXPORT(errno); - } -} - -//***************************************************************************** -// -//! simple_link_recv -//! -//! @param sd socket handle -//! @param buf read buffer -//! @param len buffer length -//! @param flags indicates blocking or non-blocking operation -//! @param from pointer to an address structure indicating source address -//! @param fromlen source address structure size -//! -//! @return Return the number of bytes received, or -1 if an error -//! occurred -//! -//! @brief Read data from socket -//! Return the length of the message on successful completion. -//! If a message is too long to fit in the supplied buffer, -//! excess bytes may be discarded depending on the type of -//! socket the message is received from -// -//***************************************************************************** -static INT16 simple_link_recv(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from, - socklen_t *fromlen, INT32 opcode) -{ - UINT8 *ptr, *args; - tBsdReadReturnParams tSocketReadEvent; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, len); - args = UINT32_TO_STREAM(args, flags); - - // Generate the read command, and wait for the - hci_command_send(opcode, ptr, SOCKET_RECV_FROM_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(opcode, &tSocketReadEvent); - - // In case the number of bytes is more then zero - read data - if (tSocketReadEvent.iNumberOfBytes > 0) - { - // Wait for the data in a synchronous way. Here we assume that the bug is - // big enough to store also parameters of receive from too.... - SimpleLinkWaitData(buf, (UINT8 *)from, (UINT8 *)fromlen); - } - - CC3000_EXPORT(errno) = tSocketReadEvent.iNumberOfBytes; - - return(tSocketReadEvent.iNumberOfBytes); -} - -//***************************************************************************** -// -//! recv -//! -//! @param[in] sd socket handle -//! @param[out] buf Points to the buffer where the message should be stored -//! @param[in] len Specifies the length in bytes of the buffer pointed to -//! by the buffer argument. -//! @param[in] flags Specifies the type of message reception. -//! On this version, this parameter is not supported. -//! -//! @return Return the number of bytes received, or -1 if an error -//! occurred -//! -//! @brief function receives a message from a connection-mode socket -//! -//! @sa recvfrom -//! -//! @Note On this version, only blocking mode is supported. -// -//***************************************************************************** - -INT16 CC3000_EXPORT(recv)(INT32 sd, void *buf, INT32 len, INT32 flags) -{ - return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV)); -} - -//***************************************************************************** -// -//! recvfrom -//! -//! @param[in] sd socket handle -//! @param[out] buf Points to the buffer where the message should be stored -//! @param[in] len Specifies the length in bytes of the buffer pointed to -//! by the buffer argument. -//! @param[in] flags Specifies the type of message reception. -//! On this version, this parameter is not supported. -//! @param[in] from pointer to an address structure indicating the source -//! address: sockaddr. On this version only AF_INET is -//! supported. -//! @param[in] fromlen source address tructure size -//! -//! @return Return the number of bytes received, or -1 if an error -//! occurred -//! -//! @brief read data from socket -//! function receives a message from a connection-mode or -//! connectionless-mode socket. Note that raw sockets are not -//! supported. -//! -//! @sa recv -//! -//! @Note On this version, only blocking mode is supported. -// -//***************************************************************************** -INT16 CC3000_EXPORT(recvfrom)(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from, - socklen_t *fromlen) -{ - return(simple_link_recv(sd, buf, len, flags, from, fromlen, - HCI_CMND_RECVFROM)); -} - -//***************************************************************************** -// -//! simple_link_send -//! -//! @param sd socket handle -//! @param buf write buffer -//! @param len buffer length -//! @param flags On this version, this parameter is not supported -//! @param to pointer to an address structure indicating destination -//! address -//! @param tolen destination address structure size -//! -//! @return Return the number of bytes transmitted, or -1 if an error -//! occurred, or -2 in case there are no free buffers available -//! (only when SEND_NON_BLOCKING is enabled) -//! -//! @brief This function is used to transmit a message to another -//! socket -// -//***************************************************************************** -static INT16 simple_link_send(INT32 sd, const void *buf, INT32 len, INT32 flags, - const sockaddr *to, INT32 tolen, INT32 opcode) -{ - UINT8 uArgSize=0, addrlen; - UINT8 *ptr, *pDataPtr=0, *args; - UINT32 addr_offset=0; - INT16 res; - tBsdReadReturnParams tSocketSendEvent; - - // Check the bsd_arguments - if (0 != (res = HostFlowControlConsumeBuff(sd))) - { - return res; - } - - //Update the number of sent packets - tSLInformation.NumberOfSentPackets++; - - // Allocate a buffer and construct a packet and send it over spi - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_DATA); - - // Update the offset of data and parameters according to the command - switch(opcode) - { - case HCI_CMND_SENDTO: - { - addr_offset = len + sizeof(len) + sizeof(len); - addrlen = 8; - uArgSize = SOCKET_SENDTO_PARAMS_LEN; - pDataPtr = ptr + HEADERS_SIZE_DATA + SOCKET_SENDTO_PARAMS_LEN; - break; - } - - case HCI_CMND_SEND: - { - tolen = 0; - to = NULL; - uArgSize = HCI_CMND_SEND_ARG_LENGTH; - pDataPtr = ptr + HEADERS_SIZE_DATA + HCI_CMND_SEND_ARG_LENGTH; - break; - } - - default: - { - break; - } - } - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, uArgSize - sizeof(sd)); - args = UINT32_TO_STREAM(args, len); - args = UINT32_TO_STREAM(args, flags); - - if (opcode == HCI_CMND_SENDTO) - { - args = UINT32_TO_STREAM(args, addr_offset); - args = UINT32_TO_STREAM(args, addrlen); - } - - // Copy the data received from user into the TX Buffer - ARRAY_TO_STREAM(pDataPtr, ((UINT8 *)buf), len); - - // In case we are using SendTo, copy the to parameters - if (opcode == HCI_CMND_SENDTO) - { - ARRAY_TO_STREAM(pDataPtr, ((UINT8 *)to), tolen); - } - - // Initiate a HCI command - hci_data_send(opcode, ptr, uArgSize, len,(UINT8*)to, tolen); - - if (opcode == HCI_CMND_SENDTO) - SimpleLinkWaitEvent(HCI_EVNT_SENDTO, &tSocketSendEvent); - else - SimpleLinkWaitEvent(HCI_EVNT_SEND, &tSocketSendEvent); - - return (len); -} - - -//***************************************************************************** -// -//! send -//! -//! @param sd socket handle -//! @param buf Points to a buffer containing the message to be sent -//! @param len message size in bytes -//! @param flags On this version, this parameter is not supported -//! -//! @return Return the number of bytes transmitted, or -1 if an -//! error occurred -//! -//! @brief Write data to TCP socket -//! This function is used to transmit a message to another -//! socket. -//! -//! @Note On this version, only blocking mode is supported. -//! -//! @sa sendto -// -//***************************************************************************** - -INT16 CC3000_EXPORT(send)(INT32 sd, const void *buf, INT32 len, INT32 flags) -{ - return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND)); -} - -//***************************************************************************** -// -//! sendto -//! -//! @param sd socket handle -//! @param buf Points to a buffer containing the message to be sent -//! @param len message size in bytes -//! @param flags On this version, this parameter is not supported -//! @param to pointer to an address structure indicating the destination -//! address: sockaddr. On this version only AF_INET is -//! supported. -//! @param tolen destination address structure size -//! -//! @return Return the number of bytes transmitted, or -1 if an -//! error occurred -//! -//! @brief Write data to TCP socket -//! This function is used to transmit a message to another -//! socket. -//! -//! @Note On this version, only blocking mode is supported. -//! -//! @sa send -// -//***************************************************************************** - -INT16 CC3000_EXPORT(sendto)(INT32 sd, const void *buf, INT32 len, INT32 flags, const sockaddr *to, - socklen_t tolen) -{ - return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO)); -} - -//***************************************************************************** -// -//! mdnsAdvertiser -//! -//! @param[in] mdnsEnabled flag to enable/disable the mDNS feature -//! @param[in] deviceServiceName Service name as part of the published -//! canonical domain name -//! @param[in] deviceServiceNameLength Length of the service name - up to 32 chars -//! -//! -//! @return On success, zero is returned, return SOC_ERROR if socket was not -//! opened successfully, or if an error occurred. -//! -//! @brief Set CC3000 in mDNS advertiser mode in order to advertise itself. -// -//***************************************************************************** - -INT16 CC3000_EXPORT(mdnsAdvertiser)(UINT16 mdnsEnabled, CHAR * deviceServiceName, UINT16 deviceServiceNameLength) -{ - INT8 ret; - UINT8 *pTxBuffer, *pArgs; - - if (deviceServiceNameLength > MDNS_DEVICE_SERVICE_MAX_LENGTH) - { - return EFAIL; - } - - pTxBuffer = tSLInformation.pucTxCommandBuffer; - pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); - - // Fill in HCI packet structure - pArgs = UINT32_TO_STREAM(pArgs, mdnsEnabled); - pArgs = UINT32_TO_STREAM(pArgs, 8); - pArgs = UINT32_TO_STREAM(pArgs, deviceServiceNameLength); - ARRAY_TO_STREAM(pArgs, deviceServiceName, deviceServiceNameLength); - - // Initiate a HCI command - hci_command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + deviceServiceNameLength); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_EVNT_MDNS_ADVERTISE, &ret); - - return ret; - -} - - -//***************************************************************************** -// -//! getmssvalue -//! -//! @param[in] sd socket descriptor -//! -//! @return On success, returns the MSS value of a TCP connection -//! -//! @brief Returns the MSS value of a TCP connection according to the socket descriptor -// -//***************************************************************************** -UINT16 CC3000_EXPORT(getmssvalue) (INT32 sd) -{ - UINT8 *ptr, *args; - UINT16 ret; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - - // Initiate a HCI command - hci_command_send(HCI_CMND_GETMSSVALUE, ptr, SOCKET_GET_MSS_VALUE_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_EVNT_GETMSSVALUE, &ret); - - return ret; -} diff --git a/drivers/cc3000/src/wlan.c b/drivers/cc3000/src/wlan.c deleted file mode 100644 index 6385937778..0000000000 --- a/drivers/cc3000/src/wlan.c +++ /dev/null @@ -1,1252 +0,0 @@ -/***************************************************************************** -* -* wlan.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -//***************************************************************************** -// -//! \addtogroup wlan_api -//! @{ -// -//***************************************************************************** - -#include -#include "wlan.h" -#include "hci.h" -#include "ccspi.h" -#include "socket.h" -#include "nvmem.h" -#include "security.h" -#include "evnt_handler.h" - - -volatile sSimplLinkInformation tSLInformation; - -#define SMART_CONFIG_PROFILE_SIZE 67 // 67 = 32 (max ssid) + 32 (max key) + 1 (SSID length) + 1 (security type) + 1 (key length) - -#ifndef CC3000_UNENCRYPTED_SMART_CONFIG -UINT8 key[AES128_KEY_SIZE]; -UINT8 profileArray[SMART_CONFIG_PROFILE_SIZE]; -#endif //CC3000_UNENCRYPTED_SMART_CONFIG - -/* patches type */ -#define PATCHES_HOST_TYPE_WLAN_DRIVER 0x01 -#define PATCHES_HOST_TYPE_WLAN_FW 0x02 -#define PATCHES_HOST_TYPE_BOOTLOADER 0x03 - -#define SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE (16) -#define SL_SIMPLE_CONFIG_PREFIX_LENGTH (3) -#define ETH_ALEN (6) -#define MAXIMAL_SSID_LENGTH (32) - -#define SL_PATCHES_REQUEST_DEFAULT (0) -#define SL_PATCHES_REQUEST_FORCE_HOST (1) -#define SL_PATCHES_REQUEST_FORCE_NONE (2) - - -#define WLAN_SEC_UNSEC (0) -#define WLAN_SEC_WEP (1) -#define WLAN_SEC_WPA (2) -#define WLAN_SEC_WPA2 (3) - - -#define WLAN_SL_INIT_START_PARAMS_LEN (1) -#define WLAN_PATCH_PARAMS_LENGTH (8) -#define WLAN_SET_CONNECTION_POLICY_PARAMS_LEN (12) -#define WLAN_DEL_PROFILE_PARAMS_LEN (4) -#define WLAN_SET_MASK_PARAMS_LEN (4) -#define WLAN_SET_SCAN_PARAMS_LEN (100) -#define WLAN_GET_SCAN_RESULTS_PARAMS_LEN (4) -#define WLAN_ADD_PROFILE_NOSEC_PARAM_LEN (24) -#define WLAN_ADD_PROFILE_WEP_PARAM_LEN (36) -#define WLAN_ADD_PROFILE_WPA_PARAM_LEN (44) -#define WLAN_CONNECT_PARAM_LEN (29) -#define WLAN_SMART_CONFIG_START_PARAMS_LEN (4) - - - - -//***************************************************************************** -// -//! SimpleLink_Init_Start -//! -//! @param usPatchesAvailableAtHost flag to indicate if patches available -//! from host or from EEPROM. Due to the -//! fact the patches are burn to the EEPROM -//! using the patch programmer utility, the -//! patches will be available from the EEPROM -//! and not from the host. -//! -//! @return none -//! -//! @brief Send HCI_CMND_SIMPLE_LINK_START to CC3000 -// -//***************************************************************************** -static void SimpleLink_Init_Start(UINT16 usPatchesAvailableAtHost) -{ - UINT8 *ptr; - UINT8 *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); - - UINT8_TO_STREAM(args, ((usPatchesAvailableAtHost) ? SL_PATCHES_REQUEST_FORCE_NONE : SL_PATCHES_REQUEST_DEFAULT)); - - // IRQ Line asserted - send HCI_CMND_SIMPLE_LINK_START to CC3000 - hci_command_send(HCI_CMND_SIMPLE_LINK_START, ptr, WLAN_SL_INIT_START_PARAMS_LEN); - - SimpleLinkWaitEvent(HCI_CMND_SIMPLE_LINK_START, 0); -} - - - -//***************************************************************************** -// -//! wlan_init -//! -//! @param sWlanCB Asynchronous events callback. -//! 0 no event call back. -//! -call back parameters: -//! 1) event_type: HCI_EVNT_WLAN_UNSOL_CONNECT connect event, -//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event, -//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE config done, -//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp report, -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report OR -//! HCI_EVNT_WLAN_KEEPALIVE keepalive. -//! 2) data: pointer to extra data that received by the event -//! (NULL no data). -//! 3) length: data length. -//! -Events with extra data: -//! HCI_EVNT_WLAN_UNSOL_DHCP: 4 bytes IP, 4 bytes Mask, -//! 4 bytes default gateway, 4 bytes DHCP server and 4 bytes -//! for DNS server. -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT: 4 bytes Packets sent, -//! 4 bytes Packets received, 4 bytes Min round time, -//! 4 bytes Max round time and 4 bytes for Avg round time. -//! -//! @param sFWPatches 0 no patch or pointer to FW patches -//! @param sDriverPatches 0 no patch or pointer to driver patches -//! @param sBootLoaderPatches 0 no patch or pointer to bootloader patches -//! @param sReadWlanInterruptPin init callback. the callback read wlan -//! interrupt status. -//! @param sWlanInterruptEnable init callback. the callback enable wlan -//! interrupt. -//! @param sWlanInterruptDisable init callback. the callback disable wlan -//! interrupt. -//! @param sWriteWlanPin init callback. the callback write value -//! to device pin. -//! -//! @return none -//! -//! @sa wlan_set_event_mask , wlan_start , wlan_stop -//! -//! @brief Initialize wlan driver -//! -//! @warning This function must be called before ANY other wlan driver function -// -//***************************************************************************** - -void wlan_init( tWlanCB sWlanCB, - tFWPatches sFWPatches, - tDriverPatches sDriverPatches, - tBootLoaderPatches sBootLoaderPatches, - tWlanReadInteruptPin sReadWlanInterruptPin, - tWlanInterruptEnable sWlanInterruptEnable, - tWlanInterruptDisable sWlanInterruptDisable, - tWriteWlanPin sWriteWlanPin) -{ - - tSLInformation.sFWPatches = sFWPatches; - tSLInformation.sDriverPatches = sDriverPatches; - tSLInformation.sBootLoaderPatches = sBootLoaderPatches; - - // init io callback - tSLInformation.ReadWlanInterruptPin = sReadWlanInterruptPin; - tSLInformation.WlanInterruptEnable = sWlanInterruptEnable; - tSLInformation.WlanInterruptDisable = sWlanInterruptDisable; - tSLInformation.WriteWlanPin = sWriteWlanPin; - - //init asynchronous events callback - tSLInformation.sWlanCB= sWlanCB; - - // By default TX Complete events are routed to host too - tSLInformation.InformHostOnTxComplete = 1; -} - -//***************************************************************************** -// -//! SpiReceiveHandler -//! -//! @param pvBuffer - pointer to the received data buffer -//! The function triggers Received event/data processing -//! -//! @param Pointer to the received data -//! @return none -//! -//! @brief The function triggers Received event/data processing. It is -//! called from the SPI library to receive the data -// -//***************************************************************************** -void SpiReceiveHandler(void *pvBuffer) -{ - tSLInformation.usEventOrDataReceived = 1; - tSLInformation.pucReceivedData = (UINT8 *)pvBuffer; - - hci_unsolicited_event_handler(); -} - - -//***************************************************************************** -// -//! wlan_start -//! -//! @param usPatchesAvailableAtHost - flag to indicate if patches available -//! from host or from EEPROM. Due to the -//! fact the patches are burn to the EEPROM -//! using the patch programmer utility, the -//! patches will be available from the EEPROM -//! and not from the host. -//! -//! @return none -//! -//! @brief Start WLAN device. This function asserts the enable pin of -//! the device (WLAN_EN), starting the HW initialization process. -//! The function blocked until device Initialization is completed. -//! Function also configure patches (FW, driver or bootloader) -//! and calls appropriate device callbacks. -//! -//! @Note Prior calling the function wlan_init shall be called. -//! @Warning This function must be called after wlan_init and before any -//! other wlan API -//! @sa wlan_init , wlan_stop -//! -// -//***************************************************************************** -#define TIMEOUT (500000) - -int wlan_start(UINT16 usPatchesAvailableAtHost) -{ - - UINT32 ulSpiIRQState; - UINT32 wlan_timeout; - - tSLInformation.NumberOfSentPackets = 0; - tSLInformation.NumberOfReleasedPackets = 0; - tSLInformation.usRxEventOpcode = 0; - tSLInformation.usNumberOfFreeBuffers = 0; - tSLInformation.usSlBufferLength = 0; - tSLInformation.usBufferSize = 0; - tSLInformation.usRxDataPending = 0; - tSLInformation.slTransmitDataError = 0; - tSLInformation.usEventOrDataReceived = 0; - tSLInformation.pucReceivedData = 0; - - // Allocate the memory for the RX/TX data transactions - tSLInformation.pucTxCommandBuffer = (UINT8 *)wlan_tx_buffer; - - // init spi - SpiOpen(SpiReceiveHandler); - - // Check the IRQ line - ulSpiIRQState = tSLInformation.ReadWlanInterruptPin(); - - // Chip enable: toggle WLAN EN line - tSLInformation.WriteWlanPin( WLAN_ENABLE ); - - wlan_timeout = TIMEOUT; - if (ulSpiIRQState) { - // wait till the IRQ line goes low - while(tSLInformation.ReadWlanInterruptPin() != 0 && --wlan_timeout) - { - } - } - else - { - // wait till the IRQ line goes high and than low - while(tSLInformation.ReadWlanInterruptPin() == 0 && --wlan_timeout) - { - } - - if (wlan_timeout == 0) { - return -1; - } - - wlan_timeout = TIMEOUT; - while(tSLInformation.ReadWlanInterruptPin() != 0 && --wlan_timeout) - { - } - } - - if (wlan_timeout ==0) { - return -1; - } - - SimpleLink_Init_Start(usPatchesAvailableAtHost); - - // Read Buffer's size and finish - hci_command_send(HCI_CMND_READ_BUFFER_SIZE, tSLInformation.pucTxCommandBuffer, 0); - SimpleLinkWaitEvent(HCI_CMND_READ_BUFFER_SIZE, 0); - - return 0; -} - - -//***************************************************************************** -// -//! wlan_stop -//! -//! @param none -//! -//! @return none -//! -//! @brief Stop WLAN device by putting it into reset state. -//! -//! @sa wlan_start -// -//***************************************************************************** - -void wlan_stop(void) -{ - // Chip disable - tSLInformation.WriteWlanPin( WLAN_DISABLE ); - - // Wait till IRQ line goes high... - while(tSLInformation.ReadWlanInterruptPin() == 0) - { - } - - // Free the used by WLAN Driver memory - if (tSLInformation.pucTxCommandBuffer) - { - tSLInformation.pucTxCommandBuffer = 0; - } - - SpiClose(); -} - - -//***************************************************************************** -// -//! wlan_connect -//! -//! @param sec_type security options: -//! WLAN_SEC_UNSEC, -//! WLAN_SEC_WEP (ASCII support only), -//! WLAN_SEC_WPA or WLAN_SEC_WPA2 -//! @param ssid up to 32 bytes and is ASCII SSID of the AP -//! @param ssid_len length of the SSID -//! @param bssid 6 bytes specified the AP bssid -//! @param key up to 32 bytes specified the AP security key -//! @param key_len key length -//! -//! @return On success, zero is returned. On error, negative is returned. -//! Note that even though a zero is returned on success to trigger -//! connection operation, it does not mean that CCC3000 is already -//! connected. An asynchronous "Connected" event is generated when -//! actual association process finishes and CC3000 is connected to -//! the AP. If DHCP is set, An asynchronous "DHCP" event is -//! generated when DHCP process is finish. -//! -//! -//! @brief Connect to AP -//! @warning Please Note that when connection to AP configured with security -//! type WEP, please confirm that the key is set as ASCII and not -//! as HEX. -//! @sa wlan_disconnect -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 wlan_connect(UINT32 ulSecType, CHAR *ssid, INT32 ssid_len, - UINT8 *bssid, UINT8 *key, INT32 key_len) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0}; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in command buffer - args = UINT32_TO_STREAM(args, 0x0000001c); - args = UINT32_TO_STREAM(args, ssid_len); - args = UINT32_TO_STREAM(args, ulSecType); - args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len); - args = UINT32_TO_STREAM(args, key_len); - args = UINT16_TO_STREAM(args, 0); - - // padding shall be zeroed - if(bssid) - { - ARRAY_TO_STREAM(args, bssid, ETH_ALEN); - } - else - { - ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); - } - - ARRAY_TO_STREAM(args, ssid, ssid_len); - - if(key_len && key) - { - ARRAY_TO_STREAM(args, key, key_len); - } - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN + - ssid_len + key_len - 1); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret); - CC3000_EXPORT(errno) = ret; - - return(ret); -} -#else -INT32 wlan_connect(CHAR *ssid, INT32 ssid_len) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0}; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in command buffer - args = UINT32_TO_STREAM(args, 0x0000001c); - args = UINT32_TO_STREAM(args, ssid_len); - args = UINT32_TO_STREAM(args, 0); - args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len); - args = UINT32_TO_STREAM(args, 0); - args = UINT16_TO_STREAM(args, 0); - - // padding shall be zeroed - ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); - ARRAY_TO_STREAM(args, ssid, ssid_len); - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN + - ssid_len - 1); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret); - CC3000_EXPORT(errno) = ret; - - return(ret); -} -#endif - -//***************************************************************************** -// -//! wlan_disconnect -//! -//! @return 0 disconnected done, other CC3000 already disconnected -//! -//! @brief Disconnect connection from AP. -//! -//! @sa wlan_connect -// -//***************************************************************************** - -INT32 wlan_disconnect() -{ - INT32 ret; - UINT8 *ptr; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - - hci_command_send(HCI_CMND_WLAN_DISCONNECT, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_DISCONNECT, &ret); - CC3000_EXPORT(errno) = ret; - - return(ret); -} - -//***************************************************************************** -// -//! wlan_ioctl_set_connection_policy -//! -//! @param should_connect_to_open_ap enable(1), disable(0) connect to any -//! available AP. This parameter corresponds to the configuration of -//! item # 3 in the brief description. -//! @param should_use_fast_connect enable(1), disable(0). if enabled, tries -//! to connect to the last connected AP. This parameter corresponds -//! to the configuration of item # 1 in the brief description. -//! @param auto_start enable(1), disable(0) auto connect -//! after reset and periodically reconnect if needed. This -//! configuration configures option 2 in the above description. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief When auto is enabled, the device tries to connect according -//! the following policy: -//! 1) If fast connect is enabled and last connection is valid, -//! the device will try to connect to it without the scanning -//! procedure (fast). The last connection will be marked as -//! invalid, due to adding/removing profile. -//! 2) If profile exists, the device will try to connect it -//! (Up to seven profiles). -//! 3) If fast and profiles are not found, and open mode is -//! enabled, the device will try to connect to any AP. -//! * Note that the policy settings are stored in the CC3000 NVMEM. -//! -//! @sa wlan_add_profile , wlan_ioctl_del_profile -// -//***************************************************************************** - -INT32 wlan_ioctl_set_connection_policy(UINT32 should_connect_to_open_ap, - UINT32 ulShouldUseFastConnect, - UINT32 ulUseProfiles) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, should_connect_to_open_ap); - args = UINT32_TO_STREAM(args, ulShouldUseFastConnect); - args = UINT32_TO_STREAM(args, ulUseProfiles); - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, - ptr, WLAN_SET_CONNECTION_POLICY_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_add_profile -//! -//! @param ulSecType WLAN_SEC_UNSEC,WLAN_SEC_WEP,WLAN_SEC_WPA,WLAN_SEC_WPA2 -//! @param ucSsid ssid SSID up to 32 bytes -//! @param ulSsidLen ssid length -//! @param ucBssid bssid 6 bytes -//! @param ulPriority ulPriority profile priority. Lowest priority:0. -//! Important Note: Smartconfig process (in unencrypted mode) -//! stores the profile internally with priority 1, so changing -//! priorities when adding new profiles should be done with extra care -//! @param ulPairwiseCipher_Or_TxKeyLen key length for WEP security -//! @param ulGroupCipher_TxKeyIndex key index -//! @param ulKeyMgmt KEY management -//! @param ucPf_OrKey security key -//! @param ulPassPhraseLen security key length for WPA\WPA2 -//! -//! @return On success, index (1-7) of the stored profile is returned. -//! On error, -1 is returned. -//! -//! @brief When auto start is enabled, the device connects to -//! station from the profiles table. Up to 7 profiles are supported. -//! If several profiles configured the device choose the highest -//! priority profile, within each priority group, device will choose -//! profile based on security policy, signal strength, etc -//! parameters. All the profiles are stored in CC3000 NVMEM. -//! -//! @sa wlan_ioctl_del_profile -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 wlan_add_profile(UINT32 ulSecType, - UINT8* ucSsid, - UINT32 ulSsidLen, - UINT8 *ucBssid, - UINT32 ulPriority, - UINT32 ulPairwiseCipher_Or_TxKeyLen, - UINT32 ulGroupCipher_TxKeyIndex, - UINT32 ulKeyMgmt, - UINT8* ucPf_OrKey, - UINT32 ulPassPhraseLen) -{ - UINT16 arg_len=0; - INT32 ret; - UINT8 *ptr; - INT32 i = 0; - UINT8 *args; - UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0}; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - args = UINT32_TO_STREAM(args, ulSecType); - - // Setup arguments in accordance with the security type - switch (ulSecType) - { - //OPEN - case WLAN_SEC_UNSEC: - { - args = UINT32_TO_STREAM(args, 0x00000014); - args = UINT32_TO_STREAM(args, ulSsidLen); - args = UINT16_TO_STREAM(args, 0); - if(ucBssid) - { - ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); - } - else - { - ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); - } - args = UINT32_TO_STREAM(args, ulPriority); - ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); - - arg_len = WLAN_ADD_PROFILE_NOSEC_PARAM_LEN + ulSsidLen; - } - break; - - //WEP - case WLAN_SEC_WEP: - { - args = UINT32_TO_STREAM(args, 0x00000020); - args = UINT32_TO_STREAM(args, ulSsidLen); - args = UINT16_TO_STREAM(args, 0); - if(ucBssid) - { - ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); - } - else - { - ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); - } - args = UINT32_TO_STREAM(args, ulPriority); - args = UINT32_TO_STREAM(args, 0x0000000C + ulSsidLen); - args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen); - args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex); - ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); - - for(i = 0; i < 4; i++) - { - UINT8 *p = &ucPf_OrKey[i * ulPairwiseCipher_Or_TxKeyLen]; - - ARRAY_TO_STREAM(args, p, ulPairwiseCipher_Or_TxKeyLen); - } - - arg_len = WLAN_ADD_PROFILE_WEP_PARAM_LEN + ulSsidLen + - ulPairwiseCipher_Or_TxKeyLen * 4; - - } - break; - - //WPA - //WPA2 - case WLAN_SEC_WPA: - case WLAN_SEC_WPA2: - { - args = UINT32_TO_STREAM(args, 0x00000028); - args = UINT32_TO_STREAM(args, ulSsidLen); - args = UINT16_TO_STREAM(args, 0); - if(ucBssid) - { - ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); - } - else - { - ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); - } - args = UINT32_TO_STREAM(args, ulPriority); - args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen); - args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex); - args = UINT32_TO_STREAM(args, ulKeyMgmt); - args = UINT32_TO_STREAM(args, 0x00000008 + ulSsidLen); - args = UINT32_TO_STREAM(args, ulPassPhraseLen); - ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); - ARRAY_TO_STREAM(args, ucPf_OrKey, ulPassPhraseLen); - - arg_len = WLAN_ADD_PROFILE_WPA_PARAM_LEN + ulSsidLen + ulPassPhraseLen; - } - - break; - } - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, - ptr, arg_len); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, &ret); - - return(ret); -} -#else -INT32 wlan_add_profile(UINT32 ulSecType, - UINT8* ucSsid, - UINT32 ulSsidLen, - UINT8 *ucBssid, - UINT32 ulPriority, - UINT32 ulPairwiseCipher_Or_TxKeyLen, - UINT32 ulGroupCipher_TxKeyIndex, - UINT32 ulKeyMgmt, - UINT8* ucPf_OrKey, - UINT32 ulPassPhraseLen) -{ - return -1; -} -#endif - -//***************************************************************************** -// -//! wlan_ioctl_del_profile -//! -//! @param index number of profile to delete -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Delete WLAN profile -//! -//! @Note In order to delete all stored profile, set index to 255. -//! -//! @sa wlan_add_profile -// -//***************************************************************************** - -INT32 wlan_ioctl_del_profile(UINT32 ulIndex) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, ulIndex); - ret = EFAIL; - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, - ptr, WLAN_DEL_PROFILE_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_ioctl_get_scan_results -//! -//! @param[in] scan_timeout parameter not supported -//! @param[out] ucResults scan results (_wlan_full_scan_results_args_t) -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Gets entry from scan result table. -//! The scan results are returned one by one, and each entry -//! represents a single AP found in the area. The following is a -//! format of the scan result: -//! - 4 Bytes: number of networks found -//! - 4 Bytes: The status of the scan: 0 - aged results, -//! 1 - results valid, 2 - no results -//! - 42 bytes: Result entry, where the bytes are arranged as follows: -//! -//! - 1 bit isValid - is result valid or not -//! - 7 bits rssi - RSSI value; -//! - 2 bits: securityMode - security mode of the AP: -//! 0 - Open, 1 - WEP, 2 WPA, 3 WPA2 -//! - 6 bits: SSID name length -//! - 2 bytes: the time at which the entry has entered into -//! scans result table -//! - 32 bytes: SSID name -//! - 6 bytes: BSSID -//! -//! @Note scan_timeout, is not supported on this version. -//! -//! @sa wlan_ioctl_set_scan_params -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 wlan_ioctl_get_scan_results(UINT32 ulScanTimeout, - UINT8 *ucResults) -{ - UINT8 *ptr; - UINT8 *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, ulScanTimeout); - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, - ptr, WLAN_GET_SCAN_RESULTS_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, ucResults); - - return(0); -} -#endif - -//***************************************************************************** -// -//! wlan_ioctl_set_scan_params -//! -//! @param uiEnable - start/stop application scan: -//! 1 = start scan with default interval value of 10 min. -//! in order to set a different scan interval value apply the value -//! in milliseconds. minimum 1 second. 0=stop). Wlan reset -//! (wlan_stop() wlan_start()) is needed when changing scan interval -//! value. Saved: No -//! @param uiMinDwellTime minimum dwell time value to be used for each -//! channel, in milliseconds. Saved: yes -//! Recommended Value: 100 (Default: 20) -//! @param uiMaxDwellTime maximum dwell time value to be used for each -//! channel, in milliseconds. Saved: yes -//! Recommended Value: 100 (Default: 30) -//! @param uiNumOfProbeRequests max probe request between dwell time. -//! Saved: yes. Recommended Value: 5 (Default:2) -//! @param uiChannelMask bitwise, up to 13 channels (0x1fff). -//! Saved: yes. Default: 0x7ff -//! @param uiRSSIThreshold RSSI threshold. Saved: yes (Default: -80) -//! @param uiSNRThreshold NSR threshold. Saved: yes (Default: 0) -//! @param uiDefaultTxPower probe Tx power. Saved: yes (Default: 205) -//! @param aiIntervalList pointer to array with 16 entries (16 channels) -//! each entry (UINT32) holds timeout between periodic scan -//! (connection scan) - in millisecond. Saved: yes. Default 2000ms. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief start and stop scan procedure. Set scan parameters. -//! -//! @Note uiDefaultTxPower, is not supported on this version. -//! -//! @sa wlan_ioctl_get_scan_results -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 wlan_ioctl_set_scan_params(UINT32 uiEnable, UINT32 uiMinDwellTime, - UINT32 uiMaxDwellTime, - UINT32 uiNumOfProbeRequests, - UINT32 uiChannelMask,INT32 iRSSIThreshold, - UINT32 uiSNRThreshold, - UINT32 uiDefaultTxPower, - UINT32 *aiIntervalList) -{ - UINT32 uiRes; - UINT8 *ptr; - UINT8 *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, 36); - args = UINT32_TO_STREAM(args, uiEnable); - args = UINT32_TO_STREAM(args, uiMinDwellTime); - args = UINT32_TO_STREAM(args, uiMaxDwellTime); - args = UINT32_TO_STREAM(args, uiNumOfProbeRequests); - args = UINT32_TO_STREAM(args, uiChannelMask); - args = UINT32_TO_STREAM(args, iRSSIThreshold); - args = UINT32_TO_STREAM(args, uiSNRThreshold); - args = UINT32_TO_STREAM(args, uiDefaultTxPower); - ARRAY_TO_STREAM(args, aiIntervalList, sizeof(UINT32) * - SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE); - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, - ptr, WLAN_SET_SCAN_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, &uiRes); - - return(uiRes); -} -#endif - -//***************************************************************************** -// -//! wlan_set_event_mask -//! -//! @param mask mask option: -//! HCI_EVNT_WLAN_UNSOL_CONNECT connect event -//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event -//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE smart config done -//! HCI_EVNT_WLAN_UNSOL_INIT init done -//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp event report -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report -//! HCI_EVNT_WLAN_KEEPALIVE keepalive -//! HCI_EVNT_WLAN_TX_COMPLETE - disable information on end of transmission -//! Saved: no. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Mask event according to bit mask. In case that event is -//! masked (1), the device will not send the masked event to host. -// -//***************************************************************************** - -INT32 wlan_set_event_mask(UINT32 ulMask) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - - - if ((ulMask & HCI_EVNT_WLAN_TX_COMPLETE) == HCI_EVNT_WLAN_TX_COMPLETE) - { - tSLInformation.InformHostOnTxComplete = 0; - - // Since an event is a virtual event - i.e. it is not coming from CC3000 - // there is no need to send anything to the device if it was an only event - if (ulMask == HCI_EVNT_WLAN_TX_COMPLETE) - { - return 0; - } - - ulMask &= ~HCI_EVNT_WLAN_TX_COMPLETE; - ulMask |= HCI_EVNT_WLAN_UNSOL_BASE; - } - else - { - tSLInformation.InformHostOnTxComplete = 1; - } - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, ulMask); - - // Initiate a HCI command - hci_command_send(HCI_CMND_EVENT_MASK, - ptr, WLAN_SET_MASK_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_EVENT_MASK, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_ioctl_statusget -//! -//! @param none -//! -//! @return WLAN_STATUS_DISCONNECTED, WLAN_STATUS_SCANING, -//! STATUS_CONNECTING or WLAN_STATUS_CONNECTED -//! -//! @brief get wlan status: disconnected, scanning, connecting or connected -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 wlan_ioctl_statusget(void) -{ - INT32 ret; - UINT8 *ptr; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - - hci_command_send(HCI_CMND_WLAN_IOCTL_STATUSGET, - ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_STATUSGET, &ret); - - return(ret); -} -#endif - -//***************************************************************************** -// -//! wlan_smart_config_start -//! -//! @param algoEncryptedFlag indicates whether the information is encrypted -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Start to acquire device profile. The device acquire its own -//! profile, if profile message is found. The acquired AP information -//! is stored in CC3000 EEPROM only in case AES128 encryption is used. -//! In case AES128 encryption is not used, a profile is created by -//! CC3000 internally. -//! -//! @Note An asynchronous event - Smart Config Done will be generated as soon -//! as the process finishes successfully. -//! -//! @sa wlan_smart_config_set_prefix , wlan_smart_config_stop -// -//***************************************************************************** - -INT32 wlan_smart_config_start(UINT32 algoEncryptedFlag) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, algoEncryptedFlag); - ret = EFAIL; - - hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, ptr, - WLAN_SMART_CONFIG_START_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_smart_config_stop -//! -//! @param algoEncryptedFlag indicates whether the information is encrypted -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Stop the acquire profile procedure -//! -//! @sa wlan_smart_config_start , wlan_smart_config_set_prefix -// -//***************************************************************************** - -INT32 wlan_smart_config_stop(void) -{ - INT32 ret; - UINT8 *ptr; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - - hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_smart_config_set_prefix -//! -//! @param newPrefix 3 bytes identify the SSID prefix for the Smart Config. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Configure station ssid prefix. The prefix is used internally -//! in CC3000. It should always be TTT. -//! -//! @Note The prefix is stored in CC3000 NVMEM -//! -//! @sa wlan_smart_config_start , wlan_smart_config_stop -// -//***************************************************************************** - -INT32 wlan_smart_config_set_prefix(CHAR* cNewPrefix) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - if (cNewPrefix == NULL) - return ret; - else // with the new Smart Config, prefix must be TTT - { - *cNewPrefix = 'T'; - *(cNewPrefix + 1) = 'T'; - *(cNewPrefix + 2) = 'T'; - } - - ARRAY_TO_STREAM(args, cNewPrefix, SL_SIMPLE_CONFIG_PREFIX_LENGTH); - - hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, ptr, - SL_SIMPLE_CONFIG_PREFIX_LENGTH); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_smart_config_process -//! -//! @param none -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief process the acquired data and store it as a profile. The acquired -//! AP information is stored in CC3000 EEPROM encrypted. -//! The encrypted data is decrypted and stored as a profile. -//! behavior is as defined by connection policy. -// -//***************************************************************************** - - -#ifndef CC3000_UNENCRYPTED_SMART_CONFIG -INT32 wlan_smart_config_process() -{ - INT32 returnValue; - UINT32 ssidLen, keyLen; - UINT8 *decKeyPtr; - UINT8 *ssidPtr; - - // read the key from EEPROM - fileID 12 - returnValue = aes_read_key(key); - - if (returnValue != 0) - return returnValue; - - // read the received data from fileID #13 and parse it according to the followings: - // 1) SSID LEN - not encrypted - // 2) SSID - not encrypted - // 3) KEY LEN - not encrypted. always 32 bytes long - // 4) Security type - not encrypted - // 5) KEY - encrypted together with true key length as the first byte in KEY - // to elaborate, there are two corner cases: - // 1) the KEY is 32 bytes long. In this case, the first byte does not represent KEY length - // 2) the KEY is 31 bytes long. In this case, the first byte represent KEY length and equals 31 - returnValue = nvmem_read(NVMEM_SHARED_MEM_FILEID, SMART_CONFIG_PROFILE_SIZE, 0, profileArray); - - if (returnValue != 0) - return returnValue; - - ssidPtr = &profileArray[1]; - - ssidLen = profileArray[0]; - - decKeyPtr = &profileArray[profileArray[0] + 3]; - - aes_decrypt(decKeyPtr, key); - if (profileArray[profileArray[0] + 1] > 16) - aes_decrypt((UINT8 *)(decKeyPtr + 16), key); - - if (*(UINT8 *)(decKeyPtr +31) != 0) - { - if (*decKeyPtr == 31) - { - keyLen = 31; - decKeyPtr++; - } - else - { - keyLen = 32; - } - } - else - { - keyLen = *decKeyPtr; - decKeyPtr++; - } - - // add a profile - switch (profileArray[profileArray[0] + 2]) - { - case WLAN_SEC_UNSEC://None - { - returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], // security type - ssidPtr, // SSID - ssidLen, // SSID length - NULL, // BSSID - 1, // Priority - 0, 0, 0, 0, 0); - - break; - } - - case WLAN_SEC_WEP://WEP - { - returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], // security type - ssidPtr, // SSID - ssidLen, // SSID length - NULL, // BSSID - 1, // Priority - keyLen, // KEY length - 0, // KEY index - 0, - decKeyPtr, // KEY - 0); - - break; - } - - case WLAN_SEC_WPA://WPA - case WLAN_SEC_WPA2://WPA2 - { - returnValue = wlan_add_profile(WLAN_SEC_WPA2, // security type - ssidPtr, - ssidLen, - NULL, // BSSID - 1, // Priority - 0x18, // PairwiseCipher - 0x1e, // GroupCipher - 2, // KEY management - decKeyPtr, // KEY - keyLen); // KEY length - - break; - } - } - - return returnValue; -} -#endif //CC3000_UNENCRYPTED_SMART_CONFIG - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** From 858707181d907b96fe55e786defa8947e404ab91 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 23 Aug 2022 17:05:30 +1000 Subject: [PATCH 0323/1041] tools/mpremote: Print a nicer error when a filesystem command fails. Signed-off-by: Damien George --- tools/mpremote/mpremote/main.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/mpremote/mpremote/main.py b/tools/mpremote/mpremote/main.py index e614156dbf..fa4785b3bf 100644 --- a/tools/mpremote/mpremote/main.py +++ b/tools/mpremote/mpremote/main.py @@ -354,9 +354,13 @@ def do_filesystem(pyb, args): verbose=verbose, ) else: - pyboard.filesystem_command( - pyb, fs_args, progress_callback=show_progress_bar, verbose=verbose - ) + try: + pyboard.filesystem_command( + pyb, fs_args, progress_callback=show_progress_bar, verbose=verbose + ) + except OSError as er: + print(f"{_PROG}: {er}") + sys.exit(1) def do_edit(pyb, args): From 24f1161fe21df146b64a657acadf67e723040636 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 23 Aug 2022 17:25:54 +1000 Subject: [PATCH 0324/1041] tools/pyboard.py: Remove implicit fs_put if source starts with ./. Signed-off-by: Damien George --- tools/pyboard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pyboard.py b/tools/pyboard.py index 7525049875..8c4696c439 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -583,7 +583,7 @@ def filesystem_command(pyb, args, progress_callback=None, verbose=False): if cmd == "cp": srcs = args[:-1] dest = args[-1] - if srcs[0].startswith("./") or dest.startswith(":"): + if dest.startswith(":"): op = pyb.fs_put fmt = "cp %s :%s" dest = fname_remote(dest) From f5fedf4676274dd26d70142b08753873dc1b99bc Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 24 Aug 2022 10:26:35 +1000 Subject: [PATCH 0325/1041] tools/pyboard.py: Add fs_cp function for direct device-to-device copy. Signed-off-by: Damien George --- tools/pyboard.py | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/tools/pyboard.py b/tools/pyboard.py index 8c4696c439..436bc5ab1b 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -491,6 +491,20 @@ class Pyboard: ) self.exec_(cmd, data_consumer=stdout_write_bytes) + def fs_cp(self, src, dest, chunk_size=256, progress_callback=None): + if progress_callback: + src_size = int(self.exec_("import os\nprint(os.stat('%s')[6])" % src)) + written = 0 + self.exec_("fr=open('%s','rb')\nr=fr.read\nfw=open('%s','wb')\nw=fw.write" % (src, dest)) + while True: + data_len = int(self.exec_("d=r(%u)\nw(d)\nprint(len(d))" % chunk_size)) + if not data_len: + break + if progress_callback: + written += data_len + progress_callback(written, src_size) + self.exec_("fr.close()\nfw.close()") + def fs_get(self, src, dest, chunk_size=256, progress_callback=None): if progress_callback: src_size = int(self.exec_("import os\nprint(os.stat('%s')[6])" % src)) @@ -584,18 +598,21 @@ def filesystem_command(pyb, args, progress_callback=None, verbose=False): srcs = args[:-1] dest = args[-1] if dest.startswith(":"): - op = pyb.fs_put - fmt = "cp %s :%s" - dest = fname_remote(dest) + op_remote_src = pyb.fs_cp + op_local_src = pyb.fs_put else: - op = pyb.fs_get - fmt = "cp :%s %s" + op_remote_src = pyb.fs_get + op_local_src = lambda src, dest, **_: __import__("shutil").copy(src, dest) for src in srcs: - src = fname_remote(src) - dest2 = fname_cp_dest(src, dest) if verbose: - print(fmt % (src, dest2)) - op(src, dest2, progress_callback=progress_callback) + print("cp %s %s" % (src, dest)) + if src.startswith(":"): + op = op_remote_src + else: + op = op_local_src + src2 = fname_remote(src) + dest2 = fname_cp_dest(src2, fname_remote(dest)) + op(src2, dest2, progress_callback=progress_callback) else: op = { "cat": pyb.fs_cat, From 2e386bcf76c38a81a9de93452f9a253c571d2b72 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 24 Aug 2022 10:33:11 +1000 Subject: [PATCH 0326/1041] tools/mpremote: Print nicer errors for unsupported 'cp -r' arguments. Also document support for 'cp :a :b'. Signed-off-by: Damien George --- docs/reference/mpremote.rst | 2 ++ tools/mpremote/mpremote/main.py | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/reference/mpremote.rst b/docs/reference/mpremote.rst index eb0233bdda..a48df9953f 100644 --- a/docs/reference/mpremote.rst +++ b/docs/reference/mpremote.rst @@ -262,6 +262,8 @@ Examples mpremote cp main.py : + mpremote cp :a.py :b.py + mpremote cp -r dir/ : mpremote cp a.py b.py : + repl diff --git a/tools/mpremote/mpremote/main.py b/tools/mpremote/mpremote/main.py index fa4785b3bf..bd98da8824 100644 --- a/tools/mpremote/mpremote/main.py +++ b/tools/mpremote/mpremote/main.py @@ -333,10 +333,15 @@ def do_filesystem(pyb, args): if fs_args[0] == "cp" and fs_args[1] == "-r": fs_args.pop(0) fs_args.pop(0) - assert fs_args[-1] == ":" + if fs_args[-1] != ":": + print(f"{_PROG}: 'cp -r' destination must be ':'") + sys.exit(1) fs_args.pop() src_files = [] for path in fs_args: + if path.startswith(":"): + print(f"{_PROG}: 'cp -r' source files must be local") + sys.exit(1) _list_recursive(src_files, path) known_dirs = {""} pyb.exec_("import uos") From 6b16ce8d38461e9a8f11642a4a9c6e4621c00872 Mon Sep 17 00:00:00 2001 From: Matt Trentini Date: Fri, 19 Aug 2022 01:15:50 +1000 Subject: [PATCH 0327/1041] docs: Update CPython differences and improve the look of table layouts. Updated some of the CPython feature differences: - Updated status of some features. - Added CSS to fix table widths to 100% and word wrap. - Specified explicit table column ratios to improve layout appearance. - Added missing references to anchors. - Better consistency with use of formatting and case. --- docs/conf.py | 4 + docs/differences/python_35.rst | 330 +++++++++++++++++---------------- docs/differences/python_36.rst | 103 +++++----- docs/differences/python_37.rst | 127 +++++++------ docs/differences/python_38.rst | 33 ++-- docs/differences/python_39.rst | 43 +++-- docs/static/custom.css | 5 + 7 files changed, 353 insertions(+), 292 deletions(-) create mode 100644 docs/static/custom.css diff --git a/docs/conf.py b/docs/conf.py index a7a4ab08c5..5533bf0191 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -166,6 +166,10 @@ html_favicon = 'static/favicon.ico' # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['static'] +# Add a custom CSS file for HTML generation +html_css_files = [ + 'custom.css', +] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. diff --git a/docs/differences/python_35.rst b/docs/differences/python_35.rst index 94b10b5837..0fdc6121a1 100644 --- a/docs/differences/python_35.rst +++ b/docs/differences/python_35.rst @@ -5,55 +5,60 @@ Python 3.5 Below is a list of finalised/accepted PEPs for Python 3.5 grouped into their impact to MicroPython. - +----------------------------------------------------------------------------------------------------------+---------------+ - | **Extensions to the syntax:** | **Status** | - +--------------------------------------------------------+-------------------------------------------------+---------------+ - | `PEP 448 `_ | additional unpacking generalizations | Partial | - +--------------------------------------------------------+-------------------------------------------------+---------------+ - | `PEP 465 `_ | a new matrix multiplication operator | Completed | - +--------------------------------------------------------+-------------------------------------------------+---------------+ - | `PEP 492 `_ | coroutines with async and await syntax | Completed | - +--------------------------------------------------------+-------------------------------------------------+---------------+ - | **Extensions and changes to runtime:** | - +--------------------------------------------------------+-------------------------------------------------+---------------+ - | `PEP 461 `_ | % formatting for binary strings | Completed | - +--------------------------------------------------------+-------------------------------------------------+---------------+ - | `PEP 475 `_ | retrying system calls that fail with EINTR | Completed | - +--------------------------------------------------------+-------------------------------------------------+---------------+ - | `PEP 479 `_ | change StopIteration handling inside generators | Completed | - +--------------------------------------------------------+-------------------------------------------------+---------------+ - | **Standard library changes:** | - +--------------------------------------------------------+-------------------------------------------------+---------------+ - | `PEP 471 `_ | os.scandir() | | - +--------------------------------------------------------+-------------------------------------------------+---------------+ - | `PEP 485 `_ | math.isclose(), a function for testing | Completed | - | | approximate equality | | - +--------------------------------------------------------+-------------------------------------------------+---------------+ - | **Miscellaneous changes:** | - +--------------------------------------------------------+-------------------------------------------------+---------------+ - | `PEP 441 `_ | improved Python zip application support | | - +--------------------------------------------------------+-------------------------------------------------+---------------+ - | `PEP 486 `_ | make the Python Launcher aware of virtual | Not relevant | - | | environments | | - +--------------------------------------------------------+-------------------------------------------------+---------------+ - | `PEP 484 `_ | type hints (advisory only) | In Progress | - +--------------------------------------------------------+-------------------------------------------------+---------------+ - | `PEP 488 `_ | elimination of PYO files | Not relevant | - +--------------------------------------------------------+-------------------------------------------------+---------------+ - | `PEP 489 `_ | redesigning extension module loading | | - +--------------------------------------------------------+-------------------------------------------------+---------------+ +.. table:: + :widths: 30 50 20 + +--------------------------------------------------------------------------------------------------------------+--------------------+ + | **Extensions to the syntax** | **Status** | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 448 `_ | Additional unpacking generalizations | Partial | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 465 `_ | A new matrix multiplication operator | Complete | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 492 `_ | Coroutines with ``async`` and ``await`` syntax | Complete | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | **Extensions and changes to runtime** | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 461 `_ | % formatting for binary strings | Complete | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 475 `_ | Retrying system calls that fail with ``EINTR`` | Complete | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 479 `_ | Change ``StopIteration`` handling inside generators | Complete | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | **Standard library changes** | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 471 `_ | ``os.scandir()`` | | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 485 `_ | ``math.isclose()``, a function for testing | Complete | + | | approximate equality | | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | **Miscellaneous changes** | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 441 `_ | Improved Python zip application support | | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 486 `_ | Make the Python Launcher aware of virtual | Not relevant | + | | environments | | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 484 `_ | Type hints (advisory only) | Complete [#fth]_ | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 488 `_ | Elimination of PYO files | Not relevant | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 489 `_ | Redesigning extension module loading | | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ Other Language Changes: - +-----------------------------------------------------------------------------------------------------------+---------------+ - | Added the *namereplace* error handlers. The *backslashreplace* error handlers now work with decoding and | | - | translating. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | Property docstrings are now writable. This is especially useful for collections.namedtuple() docstrings | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | Circular imports involving relative imports are now supported. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ +.. table:: + :widths: 90 10 + + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Added the *namereplace* error handlers. The *backslashreplace* error handlers now work with decoding and | | + | translating. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Property docstrings are now writable. This is especially useful for collections.namedtuple() docstrings | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Circular imports involving relative imports are now supported. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ New Modules: @@ -65,117 +70,124 @@ New Modules: Changes to built-in modules: - +-----------------------------------------------------------------------------------------------------------+---------------+ - | `collections `_ | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | The *OrderedDict* class is now implemented in C, which makes it 4 to 100 times faster. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | *OrderedDict.items()* , *OrderedDict.keys()* , *OrderedDict.values()* views now support reversed() | | - | iteration. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | The deque class now defines *index()*, *insert()*, and *copy()*, and supports the + and * operators. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | Docstrings produced by namedtuple() can now be updated. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | The UserString class now implements the *__getnewargs__()*, *__rmod__()*, *casefold()*, *format_map()*, | | - | *isprintable()*, and *maketrans()* methods to match the corresponding methods of str. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | `heapq `_ | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | Element comparison in *merge()* can now be customized by passing a key function in a new optional key | | - | keyword argument, and a new optional *reverse* keyword argument can be used to reverse element comparison | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | `io `_ | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | A new *BufferedIOBase.readinto1()* method, that uses at most one call to the underlying raw stream's | | - | *RawIOBase.read()* or *RawIOBase.readinto()* methods | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | `json `_ | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | JSON decoder now raises JSONDecodeError instead of ValueError to provide better context information about | | - | the error. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | `math `_ | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | Two new constants have been added to the math module: *inf* and *nan*. | Completed | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | A new function *isclose()* provides a way to test for approximate equality. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | A new *gcd()* function has been added. The *fractions.gcd()* function is now deprecated. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | `os `_ | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | The new *scandir()* function returning an iterator of DirEntry objects has been added. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | The *urandom()* function now uses the *getrandom()* syscall on Linux 3.17 or newer, and *getentropy()* on | | - | OpenBSD 5.6 and newer, removing the need to use /dev/urandom and avoiding failures due to potential file | | - | descriptor exhaustion. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | New *get_blocking()* and *set_blocking()* functions allow getting and setting a file descriptor's blocking| | - | mode (O_NONBLOCK.) | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | There is a new *os.path.commonpath()* function returning the longest common sub-path of each passed | | - | pathname | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | `re `_ | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | References and conditional references to groups with fixed length are now allowed in lookbehind assertions| | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | The number of capturing groups in regular expressions is no longer limited to 100. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | The *sub()* and *subn()* functions now replace unmatched groups with empty strings instead of raising an | | - | exception. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | The *re.error* exceptions have new attributes, msg, pattern, pos, lineno, and colno, that provide better | | - | context information about the error | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | `socket `_ | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | Functions with timeouts now use a monotonic clock, instead of a system clock. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | A new *socket.sendfile()* method allows sending a file over a socket by using the high-performance | | - | *os.sendfile()* function on UNIX, resulting in uploads being from 2 to 3 times faster than when using | | - | plain *socket.send()* | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | The *socket.sendall()* method no longer resets the socket timeout every time bytes are received or sent. | | - | The socket timeout is now the maximum total duration to send all data. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | The backlog argument of the *socket.listen()* method is now optional. By default it is set to SOMAXCONN or| Completed | - | to 128, whichever is less. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | `ssl `_ | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | Memory BIO Support | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | Application-Layer Protocol Negotiation Support | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | There is a new *SSLSocket.version()* method to query the actual protocol version in use. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | The SSLSocket class now implements a *SSLSocket.sendfile()* method. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | The *SSLSocket.send()* method now raises either the *ssl.SSLWantReadError* or *ssl.SSLWantWriteError* | | - | exception on a non-blocking socket if the operation would block. Previously, it would return 0. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | The *cert_time_to_seconds()* function now interprets the input time as UTC and not as local time, per RFC | | - | 5280. Additionally, the return value is always an int. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | New *SSLObject.shared_ciphers()* and *SSLSocket.shared_ciphers()* methods return the list of ciphers sent | | - | by the client during the handshake. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | The *SSLSocket.do_handshake()*, *SSLSocket.read()*, *SSLSocket.shutdown()*, and *SSLSocket.write()* | | - | methods of the SSLSocket class no longer reset the socket timeout every time bytes are received or sent. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | The *match_hostname()* function now supports matching of IP addresses. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | `sys `_ | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | A new *set_coroutine_wrapper()* function allows setting a global hook that will be called whenever a | | - | coroutine object is created by an async def function. A corresponding *get_coroutine_wrapper()* can be | | - | used to obtain a currently set wrapper. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | A new *is_finalizing()* function can be used to check if the Python interpreter is shutting down. | | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | `time `_ | - +-----------------------------------------------------------------------------------------------------------+---------------+ - | The *monotonic()* function is now always available | | - +-----------------------------------------------------------------------------------------------------------+---------------+ +.. table:: + :widths: 90 10 + + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `collections `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *OrderedDict* class is now implemented in C, which makes it 4 to 100 times faster. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | *OrderedDict.items()* , *OrderedDict.keys()* , *OrderedDict.values()* views now support reversed() | | + | iteration. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The deque class now defines *index()*, *insert()*, and *copy()*, and supports the + and * operators. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Docstrings produced by namedtuple() can now be updated. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The UserString class now implements the *__getnewargs__()*, *__rmod__()*, *casefold()*, *format_map()*, | | + | *isprintable()*, and *maketrans()* methods to match the corresponding methods of str. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `heapq `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Element comparison in *merge()* can now be customized by passing a key function in a new optional key | | + | keyword argument, and a new optional *reverse* keyword argument can be used to reverse element comparison | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `io `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | A new *BufferedIOBase.readinto1()* method, that uses at most one call to the underlying raw stream's | | + | *RawIOBase.read()* or *RawIOBase.readinto()* methods | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `json `_ | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | JSON decoder now raises JSONDecodeError instead of ValueError to provide better context information about | | + | the error. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `math `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Two new constants have been added to the math module: *inf* and *nan*. | Complete | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | A new function *isclose()* provides a way to test for approximate equality. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | A new *gcd()* function has been added. The *fractions.gcd()* function is now deprecated. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `os `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The new *scandir()* function returning an iterator of DirEntry objects has been added. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *urandom()* function now uses the *getrandom()* syscall on Linux 3.17 or newer, and *getentropy()* on | | + | OpenBSD 5.6 and newer, removing the need to use /dev/urandom and avoiding failures due to potential file | | + | descriptor exhaustion. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | New *get_blocking()* and *set_blocking()* functions allow getting and setting a file descriptor's blocking| | + | mode (O_NONBLOCK.) | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | There is a new *os.path.commonpath()* function returning the longest common sub-path of each passed | | + | pathname | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `re `_ | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | References and conditional references to groups with fixed length are now allowed in lookbehind assertions| | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The number of capturing groups in regular expressions is no longer limited to 100. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *sub()* and *subn()* functions now replace unmatched groups with empty strings instead of raising an | | + | exception. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *re.error* exceptions have new attributes, msg, pattern, pos, lineno, and colno, that provide better | | + | context information about the error | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `socket `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Functions with timeouts now use a monotonic clock, instead of a system clock. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | A new *socket.sendfile()* method allows sending a file over a socket by using the high-performance | | + | *os.sendfile()* function on UNIX, resulting in uploads being from 2 to 3 times faster than when using | | + | plain *socket.send()* | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *socket.sendall()* method no longer resets the socket timeout every time bytes are received or sent. | | + | The socket timeout is now the maximum total duration to send all data. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The backlog argument of the *socket.listen()* method is now optional. By default it is set to SOMAXCONN or| Complete | + | to 128, whichever is less. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `ssl `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Memory BIO Support | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Application-Layer Protocol Negotiation Support | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | There is a new *SSLSocket.version()* method to query the actual protocol version in use. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The SSLSocket class now implements a *SSLSocket.sendfile()* method. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *SSLSocket.send()* method now raises either the *ssl.SSLWantReadError* or *ssl.SSLWantWriteError* | | + | exception on a non-blocking socket if the operation would block. Previously, it would return 0. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *cert_time_to_seconds()* function now interprets the input time as UTC and not as local time, per RFC | | + | 5280. Additionally, the return value is always an int. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | New *SSLObject.shared_ciphers()* and *SSLSocket.shared_ciphers()* methods return the list of ciphers sent | | + | by the client during the handshake. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *SSLSocket.do_handshake()*, *SSLSocket.read()*, *SSLSocket.shutdown()*, and *SSLSocket.write()* | | + | methods of the SSLSocket class no longer reset the socket timeout every time bytes are received or sent. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *match_hostname()* function now supports matching of IP addresses. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `sys `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | A new *set_coroutine_wrapper()* function allows setting a global hook that will be called whenever a | | + | coroutine object is created by an async def function. A corresponding *get_coroutine_wrapper()* can be | | + | used to obtain a currently set wrapper. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | A new *is_finalizing()* function can be used to check if the Python interpreter is shutting down. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `time `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *monotonic()* function is now always available | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + +.. rubric:: Notes + +.. [#fth] The MicroPython parser correct ignores all type hints. However, the ``typing`` module is not built-in. diff --git a/docs/differences/python_36.rst b/docs/differences/python_36.rst index edf6bef023..3315b0594d 100644 --- a/docs/differences/python_36.rst +++ b/docs/differences/python_36.rst @@ -5,53 +5,59 @@ Python 3.6 Python 3.6 beta 1 was released on 12 Sep 2016, and a summary of the new features can be found here: - +-----------------------------------------------------------------------------------------------------------+--------------+ - | **New Syntax Features:** | **Status** | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | `PEP 498 `_ | Literal String Formatting | | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | `PEP 515 `_ | Underscores in Numeric Literals | | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | `PEP 525 `_ | Asynchronous Generators | | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | `PEP 526 `_ | Syntax for Variable Annotations (provisional) | | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | `PEP 530 `_ | Asynchronous Comprehensions | | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | **New Built-in Features:** | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | `PEP 468 `_ | Preserving the order of *kwargs* in a function | | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | `PEP 487 `_ | Simpler customization of class creation | | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | `PEP 520 `_ | Preserving Class Attribute Definition Order | | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | **Standard Library Changes:** | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | `PEP 495 `_ | Local Time Disambiguation | | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | `PEP 506 `_ | Adding A Secrets Module To The Standard Library | | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | `PEP 519 `_ | Adding a file system path protocol | | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | **CPython internals:** | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | `PEP 509 `_ | Add a private version to dict | | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | `PEP 523 `_ | Adding a frame evaluation API to CPython | | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | **Linux/Window Changes** | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | `PEP 524 `_ | Make os.urandom() blocking on Linux | | - | | (during system startup) | | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | `PEP 528 `_ | Change Windows console encoding to UTF-8 | | - +--------------------------------------------------------+--------------------------------------------------+--------------+ - | `PEP 529 `_ | Change Windows filesystem encoding to UTF-8 | | - +--------------------------------------------------------+--------------------------------------------------+--------------+ +.. table:: + :widths: 30 50 20 + + +-----------------------------------------------------------------------------------------------------------+-----------------+ + | **New Syntax Features** | **Status** | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 498 `_ | Literal String Formatting | Complete | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 515 `_ | Underscores in Numeric Literals | Complete | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 525 `_ | Asynchronous Generators | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 526 `_ | Syntax for Variable Annotations (provisional) | Complete | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 530 `_ | Asynchronous Comprehensions | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | **New Built-in Features** | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 468 `_ | Preserving the order of *kwargs* in a function | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 487 `_ | Simpler customization of class creation | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 520 `_ | Preserving Class Attribute Definition Order | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | **Standard Library Changes** | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 495 `_ | Local Time Disambiguation | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 506 `_ | Adding A Secrets Module To The Standard Library | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 519 `_ | Adding a file system path protocol | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | **CPython Internals** | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 509 `_ | Add a private version to dict | Won't do | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 523 `_ | Adding a frame evaluation API to CPython | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | **Linux/Window Changes** | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 524 `_ | Make ``os.urandom()`` blocking on Linux | | + | | (during system startup) | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 528 `_ | Change Windows console encoding to UTF-8 | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 529 `_ | Change Windows filesystem encoding to UTF-8 | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ Other Language Changes: +.. table:: + :widths: 90 10 + +-------------------------------------------------------------------------------------------------------------+---------------+ | A *global* or *nonlocal* statement must now textually appear before the first use of the affected name in | | | the same scope. Previously this was a SyntaxWarning. | | @@ -71,6 +77,9 @@ Other Language Changes: Changes to built-in modules: +.. table:: + :widths: 90 10 + +--------------------------------------------------------------------------------------------------------------+----------------+ | `array `_ | | +--------------------------------------------------------------------------------------------------------------+----------------+ @@ -78,7 +87,7 @@ Changes to built-in modules: +--------------------------------------------------------------------------------------------------------------+----------------+ | `binascii `_ | | +--------------------------------------------------------------------------------------------------------------+----------------+ - | The b2a_base64() function now accepts an optional newline keyword argument to control whether the newline | Completed | + | The b2a_base64() function now accepts an optional newline keyword argument to control whether the newline | Complete | | character is appended to the return value | | +--------------------------------------------------------------------------------------------------------------+----------------+ | `cmath `_ | | @@ -121,7 +130,7 @@ Changes to built-in modules: +--------------------------------------------------------------------------------------------------------------+----------------+ | `math `_ | +--------------------------------------------------------------------------------------------------------------+----------------+ - | The new math.tau (τ) constant has been added | Completed | + | The new math.tau (τ) constant has been added | Complete | +--------------------------------------------------------------------------------------------------------------+----------------+ | `os `_ | +--------------------------------------------------------------------------------------------------------------+----------------+ @@ -136,7 +145,7 @@ Changes to built-in modules: | `re `_ | +--------------------------------------------------------------------------------------------------------------+----------------+ | Added support of modifier spans in regular expressions. Examples: *'(?i:p)ython'* matches 'python' and | | - | 'Python', but not 'PYTHON'; *'(?i)g(?-i:v)r'* matches *'GvR'* and *'gvr'*, but not *'GVR'* . | | + | 'Python', but not 'PYTHON'; *'(?i)g(?-i:v)r'* matches *'GvR'* and *'gvr'*, but not *'GVR'*. | | +--------------------------------------------------------------------------------------------------------------+----------------+ | Match object groups can be accessed by *__getitem__*, which is equivalent to *group()*. So *mo['name']* is | | | now equivalent to *mo.group('name')*. | | diff --git a/docs/differences/python_37.rst b/docs/differences/python_37.rst index c46678e931..86d1b6e81f 100644 --- a/docs/differences/python_37.rst +++ b/docs/differences/python_37.rst @@ -5,72 +5,81 @@ Python 3.7 New Features: - +--------------------------------------------------------+--------------------------------------------------+----------------+ - | **Features:** | **Status** | - +--------------------------------------------------------+--------------------------------------------------+----------------+ - | `PEP 538 `_ | Coercing the legacy C locale to a UTF-8 based | | - | | locale | | - +--------------------------------------------------------+--------------------------------------------------+----------------+ - | `PEP 539 `_ | A New C-API for Thread-Local Storage in CPython | | - +--------------------------------------------------------+--------------------------------------------------+----------------+ - | `PEP 540 `_ | UTF-8 mode | | - +--------------------------------------------------------+--------------------------------------------------+----------------+ - | `PEP 552 `_ | Deterministic pyc | | - +--------------------------------------------------------+--------------------------------------------------+----------------+ - | `PEP 553 `_ | Built-in breakpoint() | | - +--------------------------------------------------------+--------------------------------------------------+----------------+ - | `PEP 557 `_ | Data Classes | | - +--------------------------------------------------------+--------------------------------------------------+----------------+ - | `PEP 560 `_ | Core support for typing module and generic types | | - +--------------------------------------------------------+--------------------------------------------------+----------------+ - | `PEP 562 `_ | Module __getattr__ and __dir__ | Partially done | - +--------------------------------------------------------+--------------------------------------------------+----------------+ - | `PEP 563 `_ | Postponed Evaluation of Annotations | | - +--------------------------------------------------------+--------------------------------------------------+----------------+ - | `PEP 564 `_ | Time functions with nanosecond resolution | | - +--------------------------------------------------------+--------------------------------------------------+----------------+ - | `PEP 565 `_ | Show DeprecationWarning in __main__ | | - +--------------------------------------------------------+--------------------------------------------------+----------------+ - | `PEP 567 `_ | Context Variables | | - +--------------------------------------------------------+--------------------------------------------------+----------------+ +.. table:: + :widths: 20 60 20 + + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | **Feature** | **Status** | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 538 `_ | Coercing the legacy C locale to a UTF-8 based | | + | | locale | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 539 `_ | A New C-API for Thread-Local Storage in CPython | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 540 `_ | UTF-8 mode | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 552 `_ | Deterministic pyc | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 553 `_ | Built-in ``breakpoint()`` | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 557 `_ | Data Classes | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 560 `_ | Core support for typing module and generic types | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 562 `_ | Module ``__getattr__`` and ``__dir__`` | Partial | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 563 `_ | Postponed Evaluation of Annotations | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 564 `_ | Time functions with nanosecond resolution | Partial [#ftimenanosec]_ | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 565 `_ | Show DeprecationWarning in ``__main__`` | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 567 `_ | Context Variables | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ Other Language Changes: - +----------------------------------------------------------------------------------------------------------+----------------+ - | async and await are now reserved keywords | Completed | - +----------------------------------------------------------------------------------------------------------+----------------+ - | dict objects must preserve insertion-order | | - +----------------------------------------------------------------------------------------------------------+----------------+ - | More than 255 arguments can now be passed to a function; a function can now have more than 255 parameters| | - +----------------------------------------------------------------------------------------------------------+----------------+ - | bytes.fromhex() and bytearray.fromhex() now ignore all ASCII whitespace, not only spaces | | - +----------------------------------------------------------------------------------------------------------+----------------+ - | str, bytes, and bytearray gained support for the new isascii() method, which can be used to test if a | | - | string or bytes contain only the ASCII characters | | - +----------------------------------------------------------------------------------------------------------+----------------+ - | ImportError now displays module name and module __file__ path whenfrom ... import ... fails | | - +----------------------------------------------------------------------------------------------------------+----------------+ - | Circular imports involving absolute imports with binding a submodule to a name are now supported | | - +----------------------------------------------------------------------------------------------------------+----------------+ - | object.__format__(x, '') is now equivalent to str(x) rather than format(str(self), '') | | - +----------------------------------------------------------------------------------------------------------+----------------+ - | In order to better support dynamic creation of stack traces, types.TracebackType can now be instantiated | | - | from Python code, and the tb_next attribute on tracebacks is now writable | | - +----------------------------------------------------------------------------------------------------------+----------------+ - | When using the -m switch, sys.path[0] is now eagerly expanded to the full starting directory path, rather| | - | than being left as the empty directory (which allows imports from the current working directory at the | | - | time when an import occurs) | | - +----------------------------------------------------------------------------------------------------------+----------------+ - | The new -X importtime option or the PYTHONPROFILEIMPORTTIME environment variable can be used to show the | | - | timing of each module import | | - +----------------------------------------------------------------------------------------------------------+----------------+ +.. table:: + :widths: 90 10 + + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | ``async`` and ``await`` are now reserved keywords | Complete | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | ``dict`` objects must preserve insertion-order | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | More than 255 arguments can now be passed to a function; a function can now have more than 255 parameters | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | ``bytes.fromhex()`` and ``bytearray.fromhex()`` now ignore all ASCII whitespace, not only spaces | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | ``str``, ``bytes``, and ``bytearray`` gained support for the new ``isascii()`` method, which can be used to | | + | test if a string or bytes contain only the ASCII characters | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | ``ImportError`` now displays module name and module ``__file__`` path when ``from ... import ...`` fails | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | Circular imports involving absolute imports with binding a submodule to a name are now supported | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | ``object.__format__(x, '')`` is now equivalent to ``str(x)`` rather than ``format(str(self), '')`` | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | In order to better support dynamic creation of stack traces, ``types.TracebackType`` can now be | | + | instantiated from Python code, and the ``tb_next`` attribute on tracebacks is now writable | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | When using the ``-m`` switch, ``sys.path[0]`` is now eagerly expanded to the full starting directory path, | | + | rather than being left as the empty directory (which allows imports from the current working directory | | + | at the time when an import occurs) | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | The new ``-X importtime`` option or the ``PYTHONPROFILEIMPORTTIME`` environment variable can be used to | | + | show the timing of each module import | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ Changes to built-in modules: +.. table:: + :widths: 90 10 + +------------------------------------------------------------------------------------------------------------+----------------+ | `asyncio `_ | | +------------------------------------------------------------------------------------------------------------+----------------+ - | asyncio (many, may need a separate ticket) | | + | Too many to list | | +------------------------------------------------------------------------------------------------------------+----------------+ | `gc `_ | | +------------------------------------------------------------------------------------------------------------+----------------+ @@ -93,3 +102,7 @@ Changes to built-in modules: +------------------------------------------------------------------------------------------------------------+----------------+ | Mostly updates to support nanosecond resolution in PEP564, see above | | +------------------------------------------------------------------------------------------------------------+----------------+ + +.. rubric:: Notes + +.. [#ftimenanosec] Only :func:`time.time_ns` is implemented. diff --git a/docs/differences/python_38.rst b/docs/differences/python_38.rst index 47840a8b40..32fd68d2ca 100644 --- a/docs/differences/python_38.rst +++ b/docs/differences/python_38.rst @@ -5,15 +5,18 @@ Python 3.8 Python 3.8.0 (final) was released on the 14 October 2019. The Features for 3.8 are defined in `PEP 569 `_ and -a detailed description of the changes can be found in What's New in `Python +a detailed description of the changes can be found in `What's New in Python 3.8. `_ +.. table:: + :widths: 20 60 20 + +--------------------------------------------------------+---------------------------------------------------+---------------+ - | **Features:** | Status | + | **Features** | **Status** | +--------------------------------------------------------+---------------------------------------------------+---------------+ | `PEP 570 `_ | Positional-only arguments | | +--------------------------------------------------------+---------------------------------------------------+---------------+ - | `PEP 572 `_ | Assignment Expressions | | + | `PEP 572 `_ | Assignment Expressions | Complete | +--------------------------------------------------------+---------------------------------------------------+---------------+ | `PEP 574 `_ | Pickle protocol 5 with out-of-band data | | +--------------------------------------------------------+---------------------------------------------------+---------------+ @@ -25,13 +28,16 @@ a detailed description of the changes can be found in What's New in `Python +--------------------------------------------------------+---------------------------------------------------+---------------+ | **Miscellaneous** | +------------------------------------------------------------------------------------------------------------+---------------+ - | f-strings support = for self-documenting expressions and debugging | Completed | + | f-strings support = for self-documenting expressions and debugging | Complete | +------------------------------------------------------------------------------------------------------------+---------------+ Other Language Changes: +.. table:: + :widths: 90 10 + +------------------------------------------------------------------------------------------------------------+-------------+ - | A *continue* statement was illegal in the *finally* clause due to a problem with the implementation. In | Completed | + | A *continue* statement was illegal in the *finally* clause due to a problem with the implementation. In | Complete | | Python 3.8 this restriction was lifted | | +------------------------------------------------------------------------------------------------------------+-------------+ | The *bool*, *int* , and *fractions.Fraction* types now have an *as_integer_ratio()* method like that found | | @@ -72,14 +78,17 @@ Other Language Changes: Changes to built-in modules: +.. table:: + :widths: 90 10 + +------------------------------------------------------------------------------------------------------------+-------------+ - | `asyncio` | + | `asyncio `_ | +------------------------------------------------------------------------------------------------------------+-------------+ - | *asyncio.run()* has graduated from the provisional to stable API | Completed | + | *asyncio.run()* has graduated from the provisional to stable API | Complete | +------------------------------------------------------------------------------------------------------------+-------------+ | Running *python -m asyncio* launches a natively async REPL | | +------------------------------------------------------------------------------------------------------------+-------------+ - | The exception *asyncio.CancelledError* now inherits from *BaseException* rather than *Exception* and no | Completed | + | The exception *asyncio.CancelledError* now inherits from *BaseException* rather than *Exception* and no | Complete | | longer inherits from *concurrent.futures.CancelledError* | | +------------------------------------------------------------------------------------------------------------+-------------+ | Added *asyncio.Task.get_coro()* for getting the wrapped coroutine within an *asyncio.Task* | | @@ -90,12 +99,12 @@ Changes to built-in modules: | Added support for Happy Eyeballs to *asyncio.loop.create_connection()*. To specify the behavior, two new | | | parameters have been added: *happy_eyeballs_delay* and interleave. | | +------------------------------------------------------------------------------------------------------------+-------------+ - | `gc` | + | `gc `_ | +------------------------------------------------------------------------------------------------------------+-------------+ | *get_objects()* can now receive an optional generation parameter indicating a generation to get objects | | | from. (Note, though, that while *gc* is a built-in, *get_objects()* is not implemented for MicroPython) | | +------------------------------------------------------------------------------------------------------------+-------------+ - | `math` | + | `math `_ | +------------------------------------------------------------------------------------------------------------+-------------+ | Added new function *math.dist()* for computing Euclidean distance between two points | | +------------------------------------------------------------------------------------------------------------+-------------+ @@ -109,9 +118,9 @@ Changes to built-in modules: | Added a new function *math.isqrt()* for computing accurate integer square roots without conversion to | | | floating point | | +------------------------------------------------------------------------------------------------------------+-------------+ - | The function *math.factorial()* no longer accepts arguments that are not int-like | Completed | + | The function *math.factorial()* no longer accepts arguments that are not int-like | Complete | +------------------------------------------------------------------------------------------------------------+-------------+ - | `sys` | + | `sys `_ | +------------------------------------------------------------------------------------------------------------+-------------+ | Add new *sys.unraisablehook()* function which can be overridden to control how "unraisable exceptions" | | | are handled | | diff --git a/docs/differences/python_39.rst b/docs/differences/python_39.rst index 6852dd635e..023c6d7c1e 100644 --- a/docs/differences/python_39.rst +++ b/docs/differences/python_39.rst @@ -8,35 +8,41 @@ defined in `PEP 596 and a detailed description of the changes can be found in `What's New in Python 3.9 `_ +.. table:: + :widths: 20 60 20 + +--------------------------------------------------------+----------------------------------------------------+--------------+ - | **Features:** | | **Status** | + | **Features** | | **Status** | +--------------------------------------------------------+----------------------------------------------------+--------------+ - | `PEP 573 `_ | fast access to module state from methods of C | | + | `PEP 573 `_ | Fast access to module state from methods of C | | | | extension types | | +--------------------------------------------------------+----------------------------------------------------+--------------+ - | `PEP 584 `_ | union operators added to dict | | + | `PEP 584 `_ | Union operators added to dict | | +--------------------------------------------------------+----------------------------------------------------+--------------+ - | `PEP 585 `_ | type hinting generics in standard collections | | + | `PEP 585 `_ | Type hinting generics in standard collections | | +--------------------------------------------------------+----------------------------------------------------+--------------+ - | `PEP 593 `_ | flexible function and variable annotations | | + | `PEP 593 `_ | Flexible function and variable annotations | | +--------------------------------------------------------+----------------------------------------------------+--------------+ | `PEP 602 `_ | CPython adopts an annual release cycle. Instead of | | | | annual, aiming for two month release cycle | | +--------------------------------------------------------+----------------------------------------------------+--------------+ - | `PEP 614 `_ | relaxed grammar restrictions on decorators | | + | `PEP 614 `_ | Relaxed grammar restrictions on decorators | | +--------------------------------------------------------+----------------------------------------------------+--------------+ - | `PEP 615 `_ | the IANA Time Zone Database is now present in the | | + | `PEP 615 `_ | The IANA Time Zone Database is now present in the | | | | standard library in the zoneinfo module | | +--------------------------------------------------------+----------------------------------------------------+--------------+ - | `PEP 616 `_ | string methods to remove prefixes and suffixes | | + | `PEP 616 `_ | String methods to remove prefixes and suffixes | | +--------------------------------------------------------+----------------------------------------------------+--------------+ | `PEP 617 `_ | CPython now uses a new parser based on PEG | | +--------------------------------------------------------+----------------------------------------------------+--------------+ Other Language Changes: +.. table:: + :widths: 90 10 + +-------------------------------------------------------------------------------------------------------------+---------------+ - | *__import__()* now raises *ImportError* instead of *ValueError* | Completed | + | *__import__()* now raises *ImportError* instead of *ValueError* | Complete | +-------------------------------------------------------------------------------------------------------------+---------------+ | Python now gets the absolute path of the script filename specified on the command line (ex: *python3* | | | *script.py*): the *__file__* attribute of the *__main__* module became an absolute path, rather than a | | @@ -62,8 +68,11 @@ Other Language Changes: Changes to built-in modules: +.. table:: + :widths: 90 10 + +---------------------------------------------------------------------------------------------------------------+---------------+ - | `asyncio` | + | `asyncio `_ | +---------------------------------------------------------------------------------------------------------------+---------------+ | Due to significant security concerns, the reuse_address parameter of *asyncio.loop.create_datagram_endpoint()*| | | is no longer supported | | @@ -82,13 +91,13 @@ Changes to built-in modules: +---------------------------------------------------------------------------------------------------------------+---------------+ | *asyncio* now raises *TyperError* when calling incompatible methods with an *ssl.SSLSocket* socket | | +---------------------------------------------------------------------------------------------------------------+---------------+ - | `gc` | + | `gc `_ | +---------------------------------------------------------------------------------------------------------------+---------------+ | Garbage collection does not block on resurrected objects | | +---------------------------------------------------------------------------------------------------------------+---------------+ | Added a new function *gc.is_finalized()* to check if an object has been finalized by the garbage collector | | +---------------------------------------------------------------------------------------------------------------+---------------+ - | `math` | + | `math `_ | +---------------------------------------------------------------------------------------------------------------+---------------+ | Expanded the *math.gcd()* function to handle multiple arguments. Formerly, it only supported two arguments | | +---------------------------------------------------------------------------------------------------------------+---------------+ @@ -98,21 +107,21 @@ Changes to built-in modules: +---------------------------------------------------------------------------------------------------------------+---------------+ | Added *math.ulp()*: return the value of the least significant bit of a float | | +---------------------------------------------------------------------------------------------------------------+---------------+ - | `os` | + | `os `_ | +---------------------------------------------------------------------------------------------------------------+---------------+ | Exposed the Linux-specific *os.pidfd_open()* and *os.P_PIDFD* | | +---------------------------------------------------------------------------------------------------------------+---------------+ - | The *os.unsetenv()* function is now also available on Windows | Completed | + | The *os.unsetenv()* function is now also available on Windows | Complete | +---------------------------------------------------------------------------------------------------------------+---------------+ - | The *os.putenv()* and *os.unsetenv()* functions are now always available | Completed | + | The *os.putenv()* and *os.unsetenv()* functions are now always available | Complete | +---------------------------------------------------------------------------------------------------------------+---------------+ | Added *os.waitstatus_to_exitcode()* function: convert a wait status to an exit code | | +---------------------------------------------------------------------------------------------------------------+---------------+ - | `random` | + | `random `_ | +---------------------------------------------------------------------------------------------------------------+---------------+ | Added a new *random.Random.randbytes* method: generate random bytes | | +---------------------------------------------------------------------------------------------------------------+---------------+ - | `sys` | + | `sys `_ | +---------------------------------------------------------------------------------------------------------------+---------------+ | Added a new *sys.platlibdir* attribute: name of the platform-specific library directory | | +---------------------------------------------------------------------------------------------------------------+---------------+ diff --git a/docs/static/custom.css b/docs/static/custom.css new file mode 100644 index 0000000000..b0a7f746fc --- /dev/null +++ b/docs/static/custom.css @@ -0,0 +1,5 @@ +/* Workaround to force Sphinx to render tables to 100% and wordwrap */ +/* See https://stackoverflow.com/questions/69359978/grid-table-does-not-word-wrap for more details */ +.wy-table-responsive table td, .wy-table-responsive table th { + white-space: inherit; +} From 769262ef03b4e7198759bcc72c87c7ca5fc7de29 Mon Sep 17 00:00:00 2001 From: Tomasz 'CeDeROM' CEDRO Date: Thu, 18 Aug 2022 05:20:02 +0200 Subject: [PATCH 0328/1041] docs/esp32: Update UART quickref on input-only pins. Signed-off-by: Tomasz 'CeDeROM' CEDRO --- docs/esp32/quickref.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 1529c0ef49..03ca97c7a7 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -216,9 +216,10 @@ They each have default GPIO assigned to them, however depending on your ESP32 variant and board, these pins may conflict with embedded flash, onboard PSRAM or peripherals. -Any GPIO can be used for hardware UARTs using the GPIO matrix, so to avoid -conflicts simply provide ``tx`` and ``rx`` pins when constructing. The default -pins listed below. +Any GPIO can be used for hardware UARTs using the GPIO matrix, except for +input-only pins 34-39 that can be used as ``rx``. To avoid conflicts simply +provide ``tx`` and ``rx`` pins when constructing. The default pins listed +below. ===== ===== ===== ===== \ UART0 UART1 UART2 From 602f9db2f35924a687f8ded2170b2a0b0e13979a Mon Sep 17 00:00:00 2001 From: Tomasz 'CeDeROM' CEDRO Date: Thu, 18 Aug 2022 06:02:53 +0200 Subject: [PATCH 0329/1041] docs/library/machine.UART: Add notes about UART init and deinit. * `init()` can be called multiple times to reconfigure UART. * After `deinit()` it is impossible to call `init()` again. Signed-off-by: Tomasz 'CeDeROM' CEDRO --- docs/library/machine.UART.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/library/machine.UART.rst b/docs/library/machine.UART.rst index e239525736..1d54174c99 100644 --- a/docs/library/machine.UART.rst +++ b/docs/library/machine.UART.rst @@ -87,10 +87,22 @@ Methods When no pins are given, then the default set of TX and RX pins is taken, and hardware flow control will be disabled. If *pins* is ``None``, no pin assignment will be made. + .. note:: + It is possible to call ``init()`` multiple times on the same object in + order to reconfigure UART on the fly. That allows using single UART + peripheral to serve different devices attached to different GPIO pins. + Only one device can be served at a time in that case. + Also do not call ``deinit()`` as it will prevent calling ``init()`` + again. + .. method:: UART.deinit() Turn off the UART bus. + .. note:: + You will not be able to call ``init()`` on the object after ``deinit()``. + A new instance needs to be created in that case. + .. method:: UART.any() Returns an integer counting the number of characters that can be read without From da217e83d9a710a03fd8e324fe18d3684628cd69 Mon Sep 17 00:00:00 2001 From: Laurens Valk Date: Tue, 23 Aug 2022 21:35:49 +0200 Subject: [PATCH 0330/1041] docs/library: Fix nested rst styles not rendering. These can't be nested, so apply styling separately. Signed-off-by: Laurens Valk --- docs/library/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/library/index.rst b/docs/library/index.rst index ffd373a4df..59ed1127a7 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -195,4 +195,4 @@ but also the MicroPython libraries too (e.g. ``machine``, ``bluetooth``, etc). The main exception is the port-specific libraries (``pyb``, ``esp``, etc). *Other than when you specifically want to force the use of the built-in module, -we recommend always using ``import module`` rather than ``import umodule``.* +we recommend always using* ``import module`` *rather than* ``import umodule``. From 6dcfb25ae7cadc298a5aaa09c68205a828939cd9 Mon Sep 17 00:00:00 2001 From: Laurens Valk Date: Tue, 23 Aug 2022 21:37:24 +0200 Subject: [PATCH 0331/1041] docs/library/micropython: Fix spelling of compiler. Signed-off-by: Laurens Valk --- docs/library/micropython.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/library/micropython.rst b/docs/library/micropython.rst index 7106a1a2ff..b17dfa9a75 100644 --- a/docs/library/micropython.rst +++ b/docs/library/micropython.rst @@ -9,7 +9,7 @@ Functions .. function:: const(expr) - Used to declare that the expression is a constant so that the compile can + Used to declare that the expression is a constant so that the compiler can optimise it. The use of this function should be as follows:: from micropython import const From 09879f99ca3a6c0e48353eb2aaa1c71ed237f126 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 22 Aug 2022 11:16:16 +1000 Subject: [PATCH 0332/1041] esp8266/README: Update build instructions to match ci.sh. The existing non-Docker instructions are basically impossible to follow because the esp-open-sdk does not compile. Update these instructions to use the exact toolchain that our CI uses. Also split the Docker from non-Docker instructions, to avoid confusion about which commands need to be prefixed. Signed-off-by: Jim Mussared --- ports/esp8266/README.md | 112 ++++++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 28 deletions(-) diff --git a/ports/esp8266/README.md b/ports/esp8266/README.md index 15ca7f891c..dd50fc1af9 100644 --- a/ports/esp8266/README.md +++ b/ports/esp8266/README.md @@ -27,52 +27,106 @@ Documentation is available at http://docs.micropython.org/en/latest/esp8266/quic Build instructions ------------------ -You need the esp-open-sdk toolchain (which provides both the compiler and libraries), which -you can obtain using one of the following two options: +You need the esp-open-sdk toolchain, which provides both the compiler and libraries. - - Use a Docker image with a pre-built toolchain (**recommended**). - To use this, install Docker, then prepend - `docker run --rm -v $HOME:$HOME -u $UID -w $PWD larsks/esp-open-sdk ` to the start - of the mpy-cross and firmware `make` commands below. This will run the commands using the - toolchain inside the container but using the files on your local filesystem. +There are two ways to do this: + - By running the toolchain in [Docker](https://www.docker.com/) (**recommended**). + - By installing a pre-built toolchain and adding it to your `$PATH`. - - or, install the esp-open-sdk directly on your PC, which can be found at - . Clone this repository and - run `make` in its directory to build and install the SDK locally. Make sure - to add toolchain bin directory to your PATH. Read esp-open-sdk's README for - additional important information on toolchain setup. - If you use this approach, then the command below will work exactly. +Regardless of which toolchain you use, the first step is to make sure required +submodules are available: -Add the external dependencies to the MicroPython repository checkout: ```bash $ make -C ports/esp8266 submodules ``` + See the README in the repository root for more information about external dependencies. -The MicroPython cross-compiler must be built to pre-compile some of the -built-in scripts to bytecode. This can be done using: +__Building with Docker__ + +Once you have installed Docker, you can run all of the following build +commands inside the Docker container by prefixing them with `docker +run --rm -v $HOME:$HOME -u $UID -w $PWD larsks/esp-open-sdk ...command...`. +This will automatically download the Docker image provided by @larsks which +contains the full toolchain and SDK. + +Then you need to compile the MicroPython cross-compiler (`mpy-cross`). From +the root of this repository, run: + +```bash +$ docker run --rm -v $HOME:$HOME -u $UID -w $PWD larsks/esp-open-sdk make -C mpy-cross +``` + +**Note:** The `mpy-cross` binary will likely only work inside the Docker +container. This will not be a problem if you're only building ESP8266 +firmware, but if you're also working on other ports then you will need to +recompile for your host when switching between ports. To avoid this, use +the local toolchain instead. + +Then to compile the ESP8266 firmware: + +``` +$ cd ports/esp8266 +$ docker run --rm -v $HOME:$HOME -u $UID -w $PWD larsks/esp-open-sdk make -j BOARD=GENERIC +``` + +This will produce binary images in the `build-GENERIC/` subdirectory. +Substitute the board for whichever board you're using. + +__Building with a local toolchain__ + +First download the pre-built toolchain (thanks to @jepler from Adafruit). You +will need to find somewhere to put it in your filesystem, e.g. `~/espressif`. +Create that directory first if necessary. + +``` +$ cd ~/espressif # Change as necessary +$ wget https://github.com/jepler/esp-open-sdk/releases/download/2018-06-10/xtensa-lx106-elf-standalone.tar.gz +$ tar zxvf xtensa-lx106-elf-standalone.tar.gz +$ rm xtensa-lx106-elf/bin/esptool.py # Use system version of esptool.py instead. +``` + +Then append this to your `$PATH` variable so the compiler binaries can be +found: + +``` +$ export "PATH=$HOME/espressif/xtensa-lx106-elf/bin/:$PATH" +``` + +(You will need to do this each time you start a new terminal) + +Then you need to compile the MicroPython cross-compiler (`mpy-cross`). From +the root of this repository, run: + ```bash $ make -C mpy-cross ``` -(Prepend the Docker command if using Docker, see above) -Then, to build MicroPython for the ESP8266, just run: -```bash -$ cd ports/esp8266 -$ make +Then to compile the ESP8266 firmware: + +``` +$ cd ports/esp8266 +$ make -j BOARD=GENERIC ``` -(Prepend the Docker command if using Docker, see above) -This will produce binary images in the `build-GENERIC/` subdirectory. If you -install MicroPython to your module for the first time, or after installing any -other firmware, you should erase flash completely: +This will produce binary images in the `build-GENERIC/` subdirectory. +Substitute the board for whichever board you're using. + + +Installing MicroPython +---------------------- + +To communicate with the board you will need to install `esptool.py`. This can +be obtained from your system package manager or from PyPi via `pip`. + +If you install MicroPython to your module for the first time, or after +installing any other firmware, you should erase flash completely: + ```bash $ esptool.py --port /dev/ttyXXX erase_flash ``` -You can install esptool.py either from your system package manager or from PyPi. - Erasing the flash is also useful as a troubleshooting measure, if a module doesn't behave as expected. @@ -80,7 +134,9 @@ To flash MicroPython image to your ESP8266, use: ```bash $ make deploy ``` -(This should not be run inside Docker as it will need access to the serial port.) + +(If using the Docker instructions above, do not run this command via Docker as +it will need access to the serial port. Run it directly instead.) This will use the `esptool.py` script to download the images. You must have your ESP module in the bootloader mode, and connected to a serial port on your PC. From 8a0ee5a5c04e83f04d1c62029ac5ba7c74856507 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 22 Aug 2022 17:08:05 +1000 Subject: [PATCH 0333/1041] py/objstr: Split mp_obj_str_from_vstr into bytes/str versions. Previously the desired output type was specified. Now make the type part of the function name. Because this function is used in a few places this saves code size due to smaller call-site. This makes `mp_obj_new_str_type_from_vstr` a private function of objstr.c (which is almost the only place where the output type isn't a compile-time constant). This saves ~140 bytes on PYBV11. Signed-off-by: Jim Mussared --- extmod/machine_i2c.c | 4 ++-- extmod/machine_spi.c | 2 +- extmod/modlwip.c | 4 ++-- extmod/modubinascii.c | 4 ++-- extmod/moducryptolib.c | 2 +- extmod/moduhashlib.c | 12 +++++----- extmod/modujson.c | 4 ++-- extmod/modure.c | 6 ++++- extmod/modusocket.c | 4 ++-- extmod/vfs.c | 2 +- ports/cc3200/mods/moduos.c | 2 +- ports/cc3200/mods/modusocket.c | 4 ++-- ports/cc3200/mods/pybi2c.c | 4 ++-- ports/cc3200/mods/pybspi.c | 2 +- ports/esp32/modsocket.c | 2 +- ports/esp32/moduos.c | 2 +- ports/esp8266/moduos.c | 2 +- ports/mimxrt/moduos.c | 2 +- ports/nrf/modules/machine/spi.c | 2 +- ports/nrf/modules/uos/moduos.c | 2 +- ports/rp2/moduos.c | 2 +- ports/stm32/moduos.c | 2 +- ports/stm32/pyb_i2c.c | 4 ++-- ports/stm32/pyb_spi.c | 4 ++-- ports/stm32/usb.c | 4 ++-- ports/unix/main.c | 4 ++-- ports/unix/moduos.c | 2 +- ports/unix/modusocket.c | 2 +- ports/zephyr/modusocket.c | 2 +- py/modbuiltins.c | 4 ++-- py/modstruct.c | 2 +- py/obj.h | 3 ++- py/objint.c | 2 +- py/objstr.c | 40 ++++++++++++++++++++------------- py/parsenum.c | 2 +- py/persistentcode.c | 6 ++++- py/stream.c | 22 +++++++++++++----- 37 files changed, 102 insertions(+), 73 deletions(-) diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c index 452f07a2eb..2aa217914b 100644 --- a/extmod/machine_i2c.c +++ b/extmod/machine_i2c.c @@ -417,7 +417,7 @@ STATIC mp_obj_t machine_i2c_readfrom(size_t n_args, const mp_obj_t *args) { if (ret < 0) { mp_raise_OSError(-ret); } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_obj, 3, 4, machine_i2c_readfrom); @@ -581,7 +581,7 @@ STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args mp_raise_OSError(-ret); } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem); diff --git a/extmod/machine_spi.c b/extmod/machine_spi.c index f160f97d04..ba533b2a65 100644 --- a/extmod/machine_spi.c +++ b/extmod/machine_spi.c @@ -70,7 +70,7 @@ STATIC mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args) { vstr_init_len(&vstr, mp_obj_get_int(args[1])); memset(vstr.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, vstr.len); mp_machine_spi_transfer(args[0], vstr.len, vstr.buf, vstr.buf); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj, 2, 3, mp_machine_spi_read); diff --git a/extmod/modlwip.c b/extmod/modlwip.c index c6ee02132f..f9451a0ce4 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -1198,7 +1198,7 @@ STATIC mp_obj_t lwip_socket_recv(mp_obj_t self_in, mp_obj_t len_in) { return mp_const_empty_bytes; } vstr.len = ret; - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_recv_obj, lwip_socket_recv); @@ -1271,7 +1271,7 @@ STATIC mp_obj_t lwip_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { tuple[0] = mp_const_empty_bytes; } else { vstr.len = ret; - tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + tuple[0] = mp_obj_new_bytes_from_vstr(&vstr); } tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); return mp_obj_new_tuple(2, tuple); diff --git a/extmod/modubinascii.c b/extmod/modubinascii.c index 49c8d1fb97..45a39c58d4 100644 --- a/extmod/modubinascii.c +++ b/extmod/modubinascii.c @@ -104,7 +104,7 @@ STATIC mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) { mp_raise_ValueError(MP_ERROR_TEXT("incorrect padding")); } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj, mod_binascii_a2b_base64); @@ -166,7 +166,7 @@ STATIC mp_obj_t mod_binascii_b2a_base64(size_t n_args, const mp_obj_t *pos_args, if (newline) { *out = '\n'; } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_binascii_b2a_base64_obj, 1, mod_binascii_b2a_base64); diff --git a/extmod/moducryptolib.c b/extmod/moducryptolib.c index c58abaada6..dc0ecb9b20 100644 --- a/extmod/moducryptolib.c +++ b/extmod/moducryptolib.c @@ -329,7 +329,7 @@ STATIC mp_obj_t aes_process(size_t n_args, const mp_obj_t *args, bool encrypt) { if (out_buf != MP_OBJ_NULL) { return out_buf; } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC mp_obj_t ucryptolib_aes_encrypt(size_t n_args, const mp_obj_t *args) { diff --git a/extmod/moduhashlib.c b/extmod/moduhashlib.c index 39488788f2..7eae06b77d 100644 --- a/extmod/moduhashlib.c +++ b/extmod/moduhashlib.c @@ -109,7 +109,7 @@ STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) { vstr_t vstr; vstr_init_len(&vstr, 32); mbedtls_sha256_finish_ret((mbedtls_sha256_context *)&self->state, (unsigned char *)vstr.buf); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } #else @@ -143,7 +143,7 @@ STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) { vstr_t vstr; vstr_init_len(&vstr, SHA256_BLOCK_SIZE); sha256_final((CRYAL_SHA256_CTX *)self->state, (byte *)vstr.buf); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } #endif @@ -196,7 +196,7 @@ STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) { vstr_t vstr; vstr_init_len(&vstr, SHA1_SIZE); SHA1_Final((byte *)vstr.buf, (SHA1_CTX *)self->state); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } #endif @@ -237,7 +237,7 @@ STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) { vstr_init_len(&vstr, 20); mbedtls_sha1_finish_ret((mbedtls_sha1_context *)self->state, (byte *)vstr.buf); mbedtls_sha1_free((mbedtls_sha1_context *)self->state); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } #endif @@ -289,7 +289,7 @@ STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) { vstr_t vstr; vstr_init_len(&vstr, MD5_SIZE); MD5_Final((byte *)vstr.buf, (MD5_CTX *)self->state); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } #endif // MICROPY_SSL_AXTLS @@ -330,7 +330,7 @@ STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) { vstr_init_len(&vstr, 16); mbedtls_md5_finish_ret((mbedtls_md5_context *)self->state, (byte *)vstr.buf); mbedtls_md5_free((mbedtls_md5_context *)self->state); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } #endif // MICROPY_SSL_MBEDTLS diff --git a/extmod/modujson.c b/extmod/modujson.c index 9a73e4501e..57c50deec0 100644 --- a/extmod/modujson.c +++ b/extmod/modujson.c @@ -67,7 +67,7 @@ STATIC mp_obj_t mod_ujson_dump_helper(size_t n_args, const mp_obj_t *pos_args, m vstr_t vstr; vstr_init_print(&vstr, 8, &print_ext.base); mp_obj_print_helper(&print_ext.base, pos_args[0], PRINT_JSON); - return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + return mp_obj_new_str_from_vstr(&vstr); } else { // dump(obj, stream) print_ext.base.data = MP_OBJ_TO_PTR(pos_args[1]); @@ -103,7 +103,7 @@ STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) { mp_print_t print; vstr_init_print(&vstr, 8, &print); mp_obj_print_helper(&print, obj, PRINT_JSON); - return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + return mp_obj_new_str_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps); diff --git a/extmod/modure.c b/extmod/modure.c index 6bd8989843..59fbfddbf2 100644 --- a/extmod/modure.c +++ b/extmod/modure.c @@ -372,7 +372,11 @@ STATIC mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) { // Add post-match string vstr_add_strn(&vstr_return, subj.begin, subj.end - subj.begin); - return mp_obj_new_str_from_vstr(mp_obj_get_type(where), &vstr_return); + if (mp_obj_get_type(where) == &mp_type_str) { + return mp_obj_new_str_from_vstr(&vstr_return); + } else { + return mp_obj_new_bytes_from_vstr(&vstr_return); + } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_sub_obj, 3, 5, re_sub_helper); diff --git a/extmod/modusocket.c b/extmod/modusocket.c index 638ab0cf28..4d72531160 100644 --- a/extmod/modusocket.c +++ b/extmod/modusocket.c @@ -296,7 +296,7 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { return mp_const_empty_bytes; } vstr.len = ret; - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv); @@ -347,7 +347,7 @@ STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { tuple[0] = mp_const_empty_bytes; } else { vstr.len = ret; - tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + tuple[0] = mp_obj_new_bytes_from_vstr(&vstr); } tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); return mp_obj_new_tuple(2, tuple); diff --git a/extmod/vfs.c b/extmod/vfs.c index be1a82d404..0ef20e9281 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -360,7 +360,7 @@ mp_obj_t mp_vfs_getcwd(void) { if (!(cwd[0] == '/' && cwd[1] == 0)) { vstr_add_str(&vstr, cwd); } - return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + return mp_obj_new_str_from_vstr(&vstr); } MP_DEFINE_CONST_FUN_OBJ_0(mp_vfs_getcwd_obj, mp_vfs_getcwd); diff --git a/ports/cc3200/mods/moduos.c b/ports/cc3200/mods/moduos.c index cd01b59b35..e284e9eb1f 100644 --- a/ports/cc3200/mods/moduos.c +++ b/ports/cc3200/mods/moduos.c @@ -116,7 +116,7 @@ STATIC mp_obj_t os_urandom(mp_obj_t num) { for (int i = 0; i < n; i++) { vstr.buf[i] = rng_get(); } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); diff --git a/ports/cc3200/mods/modusocket.c b/ports/cc3200/mods/modusocket.c index 32849c51d4..23982eb966 100644 --- a/ports/cc3200/mods/modusocket.c +++ b/ports/cc3200/mods/modusocket.c @@ -581,7 +581,7 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { } vstr.len = ret; vstr.buf[vstr.len] = '\0'; - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv); @@ -625,7 +625,7 @@ STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { } else { vstr.len = ret; vstr.buf[vstr.len] = '\0'; - tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + tuple[0] = mp_obj_new_bytes_from_vstr(&vstr); } tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_LITTLE); return mp_obj_new_tuple(2, tuple); diff --git a/ports/cc3200/mods/pybi2c.c b/ports/cc3200/mods/pybi2c.c index 5310176091..40b3e2a207 100644 --- a/ports/cc3200/mods/pybi2c.c +++ b/ports/cc3200/mods/pybi2c.c @@ -392,7 +392,7 @@ STATIC mp_obj_t pyb_i2c_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map pyb_i2c_read_into(args, &vstr); // return the received data - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_obj, 3, pyb_i2c_readfrom); @@ -456,7 +456,7 @@ STATIC mp_obj_t pyb_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp vstr_t vstr; pyb_i2c_readmem_into (args, &vstr); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_mem_obj, 1, pyb_i2c_readfrom_mem); diff --git a/ports/cc3200/mods/pybspi.c b/ports/cc3200/mods/pybspi.c index 61b1a6bd11..ed03b09060 100644 --- a/ports/cc3200/mods/pybspi.c +++ b/ports/cc3200/mods/pybspi.c @@ -305,7 +305,7 @@ STATIC mp_obj_t pyb_spi_read(size_t n_args, const mp_obj_t *pos_args, mp_map_t * pybspi_transfer(self, NULL, vstr.buf, vstr.len, &write); // return the received data - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_read_obj, 1, pyb_spi_read); diff --git a/ports/esp32/modsocket.c b/ports/esp32/modsocket.c index 819ea26e98..a281558241 100644 --- a/ports/esp32/modsocket.c +++ b/ports/esp32/modsocket.c @@ -552,7 +552,7 @@ mp_obj_t _socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in, } vstr.len = ret; - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { diff --git a/ports/esp32/moduos.c b/ports/esp32/moduos.c index f307a9ffe0..bdfd19c5d2 100644 --- a/ports/esp32/moduos.c +++ b/ports/esp32/moduos.c @@ -45,7 +45,7 @@ STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) { vstr.buf[i] = r; r >>= 8; } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom); diff --git a/ports/esp8266/moduos.c b/ports/esp8266/moduos.c index 9a235e61b9..a023796fd3 100644 --- a/ports/esp8266/moduos.c +++ b/ports/esp8266/moduos.c @@ -48,7 +48,7 @@ STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) { for (int i = 0; i < n; i++) { vstr.buf[i] = *WDEV_HWRNG; } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom); diff --git a/ports/mimxrt/moduos.c b/ports/mimxrt/moduos.c index 34bd2b4248..ddb4826db9 100644 --- a/ports/mimxrt/moduos.c +++ b/ports/mimxrt/moduos.c @@ -63,7 +63,7 @@ STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) { trng_start(); TRNG_GetRandomData(TRNG, vstr.buf, n); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom); #endif diff --git a/ports/nrf/modules/machine/spi.c b/ports/nrf/modules/machine/spi.c index 880d946a29..81bc151beb 100644 --- a/ports/nrf/modules/machine/spi.c +++ b/ports/nrf/modules/machine/spi.c @@ -388,7 +388,7 @@ STATIC mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args) { vstr_init_len(&vstr, mp_obj_get_int(args[1])); memset(vstr.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, vstr.len); spi_transfer(args[0], vstr.len, vstr.buf, vstr.buf); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj, 2, 3, mp_machine_spi_read); diff --git a/ports/nrf/modules/uos/moduos.c b/ports/nrf/modules/uos/moduos.c index 184f833ef5..3fdd8eb19e 100644 --- a/ports/nrf/modules/uos/moduos.c +++ b/ports/nrf/modules/uos/moduos.c @@ -108,7 +108,7 @@ STATIC mp_obj_t os_urandom(mp_obj_t num) { for (int i = 0; i < n; i++) { vstr.buf[i] = (uint8_t)(rng_generate_random_word() & 0xFF); } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); #endif diff --git a/ports/rp2/moduos.c b/ports/rp2/moduos.c index 6288ff5696..398ec28d92 100644 --- a/ports/rp2/moduos.c +++ b/ports/rp2/moduos.c @@ -35,6 +35,6 @@ STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) { for (int i = 0; i < n; i++) { vstr.buf[i] = rosc_random_u8(8); } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom); diff --git a/ports/stm32/moduos.c b/ports/stm32/moduos.c index 1862564b61..85d0edeca8 100644 --- a/ports/stm32/moduos.c +++ b/ports/stm32/moduos.c @@ -58,7 +58,7 @@ STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) { for (int i = 0; i < n; i++) { vstr.buf[i] = rng_get(); } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom); #endif diff --git a/ports/stm32/pyb_i2c.c b/ports/stm32/pyb_i2c.c index 2ca0793c18..436b1c9bc2 100644 --- a/ports/stm32/pyb_i2c.c +++ b/ports/stm32/pyb_i2c.c @@ -926,7 +926,7 @@ STATIC mp_obj_t pyb_i2c_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t * if (o_ret != MP_OBJ_NULL) { return o_ret; } else { - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_recv_obj, 1, pyb_i2c_recv); @@ -1002,7 +1002,7 @@ STATIC mp_obj_t pyb_i2c_mem_read(size_t n_args, const mp_obj_t *pos_args, mp_map if (o_ret != MP_OBJ_NULL) { return o_ret; } else { - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_mem_read_obj, 1, pyb_i2c_mem_read); diff --git a/ports/stm32/pyb_spi.c b/ports/stm32/pyb_spi.c index abb7ba41db..f2cdcebf2a 100644 --- a/ports/stm32/pyb_spi.c +++ b/ports/stm32/pyb_spi.c @@ -229,7 +229,7 @@ STATIC mp_obj_t pyb_spi_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t * if (o_ret != MP_OBJ_NULL) { return o_ret; } else { - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_recv_obj, 1, pyb_spi_recv); @@ -298,7 +298,7 @@ STATIC mp_obj_t pyb_spi_send_recv(size_t n_args, const mp_obj_t *pos_args, mp_ma if (o_ret != MP_OBJ_NULL) { return o_ret; } else { - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr_recv); + return mp_obj_new_bytes_from_vstr(&vstr_recv); } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_send_recv_obj, 1, pyb_spi_send_recv); diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 2a669b2a28..c5fdd88acf 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -813,7 +813,7 @@ STATIC mp_obj_t pyb_usb_vcp_recv(size_t n_args, const mp_obj_t *args, mp_map_t * return mp_obj_new_int(ret); // number of bytes read into given buffer } else { vstr.len = ret; // set actual number of bytes read - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); // create a new buffer + return mp_obj_new_bytes_from_vstr(&vstr); // create a new buffer } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_usb_vcp_recv_obj, 1, pyb_usb_vcp_recv); @@ -1007,7 +1007,7 @@ STATIC mp_obj_t pyb_usb_hid_recv(size_t n_args, const mp_obj_t *args, mp_map_t * return mp_obj_new_int(ret); // number of bytes read into given buffer } else { vstr.len = ret; // set actual number of bytes read - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); // create a new buffer + return mp_obj_new_bytes_from_vstr(&vstr); // create a new buffer } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_usb_hid_recv_obj, 1, pyb_usb_hid_recv); diff --git a/ports/unix/main.c b/ports/unix/main.c index 0b27a1f5f5..c388106a64 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -554,7 +554,7 @@ MP_NOINLINE int main_(int argc, char **argv) { vstr_init(&vstr, home_l + (p1 - p - 1) + 1); vstr_add_strn(&vstr, home, home_l); vstr_add_strn(&vstr, p + 1, p1 - p - 1); - path_items[i] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + path_items[i] = mp_obj_new_str_from_vstr(&vstr); } else { path_items[i] = mp_obj_new_str_via_qstr(p, p1 - p); } @@ -650,7 +650,7 @@ MP_NOINLINE int main_(int argc, char **argv) { vstr_init(&vstr, len + sizeof(".__main__")); vstr_add_strn(&vstr, argv[a + 1], len); vstr_add_strn(&vstr, ".__main__", sizeof(".__main__") - 1); - import_args[0] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + import_args[0] = mp_obj_new_str_from_vstr(&vstr); goto reimport; } diff --git a/ports/unix/moduos.c b/ports/unix/moduos.c index b577dbd297..854ff335fa 100644 --- a/ports/unix/moduos.c +++ b/ports/unix/moduos.c @@ -94,7 +94,7 @@ STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) { vstr_t vstr; vstr_init_len(&vstr, n); mp_hal_get_random(n, vstr.buf); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom); diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c index 69ae2a78eb..88e7675a92 100644 --- a/ports/unix/modusocket.c +++ b/ports/unix/modusocket.c @@ -559,7 +559,7 @@ STATIC mp_obj_t mod_socket_inet_ntop(mp_obj_t family_in, mp_obj_t binaddr_in) { mp_raise_OSError(errno); } vstr.len = strlen(vstr.buf); - return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + return mp_obj_new_str_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_socket_inet_ntop_obj, mod_socket_inet_ntop); diff --git a/ports/zephyr/modusocket.c b/ports/zephyr/modusocket.c index 2b6adf4773..17cf9babd3 100644 --- a/ports/zephyr/modusocket.c +++ b/ports/zephyr/modusocket.c @@ -289,7 +289,7 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { } vstr.len = len; - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv); diff --git a/py/modbuiltins.c b/py/modbuiltins.c index f3caccbc83..2459edda13 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -250,7 +250,7 @@ STATIC mp_obj_t mp_builtin_input(size_t n_args, const mp_obj_t *args) { if (line.len == 0 && ret == CHAR_CTRL_D) { mp_raise_type(&mp_type_EOFError); } - return mp_obj_new_str_from_vstr(&mp_type_str, &line); + return mp_obj_new_str_from_vstr(&line); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_input_obj, 0, 1, mp_builtin_input); @@ -467,7 +467,7 @@ STATIC mp_obj_t mp_builtin_repr(mp_obj_t o_in) { mp_print_t print; vstr_init_print(&vstr, 16, &print); mp_obj_print_helper(&print, o_in, PRINT_REPR); - return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + return mp_obj_new_str_from_vstr(&vstr); } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr); diff --git a/py/modstruct.c b/py/modstruct.c index 69c7279e37..ec86d4b9c2 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -220,7 +220,7 @@ STATIC mp_obj_t struct_pack(size_t n_args, const mp_obj_t *args) { byte *p = (byte *)vstr.buf; memset(p, 0, size); struct_pack_into_internal(args[0], p, n_args - 1, &args[1]); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_obj, 1, MP_OBJ_FUN_ARGS_MAX, struct_pack); diff --git a/py/obj.h b/py/obj.h index 645fae79f5..d171e0fe62 100644 --- a/py/obj.h +++ b/py/obj.h @@ -791,7 +791,8 @@ mp_obj_t mp_obj_new_int_from_ll(long long val); // this must return a multi-prec mp_obj_t mp_obj_new_int_from_ull(unsigned long long val); // this must return a multi-precision integer object (or raise an overflow exception) mp_obj_t mp_obj_new_str(const char *data, size_t len); mp_obj_t mp_obj_new_str_via_qstr(const char *data, size_t len); -mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr); +mp_obj_t mp_obj_new_str_from_vstr(vstr_t *vstr); +mp_obj_t mp_obj_new_bytes_from_vstr(vstr_t *vstr); mp_obj_t mp_obj_new_bytes(const byte *data, size_t len); mp_obj_t mp_obj_new_bytearray(size_t n, const void *items); mp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items); diff --git a/py/objint.c b/py/objint.c index 740e7ea948..645b269966 100644 --- a/py/objint.c +++ b/py/objint.c @@ -446,7 +446,7 @@ STATIC mp_obj_t int_to_bytes(size_t n_args, const mp_obj_t *args) { mp_binary_set_int(l, big_endian, data + (big_endian ? (len - l) : 0), val); } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_to_bytes_obj, 3, 4, int_to_bytes); diff --git a/py/objstr.c b/py/objstr.c index 45dbb9b3eb..69745a2f58 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -41,6 +41,8 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_ STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in); +STATIC mp_obj_t mp_obj_new_str_type_from_vstr(const mp_obj_type_t *type, vstr_t *vstr); + STATIC void str_check_arg_type(const mp_obj_type_t *self_type, const mp_obj_t arg) { // String operations generally need the args type to match the object they're called on, // e.g. str.find(str), byte.startswith(byte) @@ -170,7 +172,7 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ mp_print_t print; vstr_init_print(&vstr, 16, &print); mp_obj_print_helper(&print, args[0], PRINT_STR); - return mp_obj_new_str_from_vstr(type, &vstr); + return mp_obj_new_str_type_from_vstr(type, &vstr); } default: // 2 or 3 args @@ -256,7 +258,7 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size vstr_t vstr; vstr_init_len(&vstr, len); memset(vstr.buf, 0, len); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); } // check if argument has the buffer protocol @@ -288,7 +290,7 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size vstr_add_byte(&vstr, val); } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + return mp_obj_new_bytes_from_vstr(&vstr); wrong_args: mp_raise_TypeError(MP_ERROR_TEXT("wrong number of arguments")); @@ -363,7 +365,7 @@ mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i vstr_t vstr; vstr_init_len(&vstr, lhs_len * n); mp_seq_multiply(lhs_data, sizeof(*lhs_data), lhs_len, n, vstr.buf); - return mp_obj_new_str_from_vstr(lhs_type, &vstr); + return mp_obj_new_str_type_from_vstr(lhs_type, &vstr); } // From now on all operations allow: @@ -414,7 +416,7 @@ mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i vstr_init_len(&vstr, lhs_len + rhs_len); memcpy(vstr.buf, lhs_data, lhs_len); memcpy(vstr.buf + lhs_len, rhs_data, rhs_len); - return mp_obj_new_str_from_vstr(lhs_type, &vstr); + return mp_obj_new_str_type_from_vstr(lhs_type, &vstr); } case MP_BINARY_OP_CONTAINS: @@ -528,7 +530,7 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { } // return joined string - return mp_obj_new_str_from_vstr(ret_type, &vstr); + return mp_obj_new_str_type_from_vstr(ret_type, &vstr); } MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join); @@ -918,7 +920,7 @@ STATIC mp_obj_t str_center(mp_obj_t str_in, mp_obj_t width_in) { memset(vstr.buf, ' ', width); int left = (width - str_len) / 2; memcpy(vstr.buf + left, str, str_len); - return mp_obj_new_str_from_vstr(mp_obj_get_type(str_in), &vstr); + return mp_obj_new_str_type_from_vstr(mp_obj_get_type(str_in), &vstr); } MP_DEFINE_CONST_FUN_OBJ_2(str_center_obj, str_center); #endif @@ -1144,7 +1146,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar mp_print_t arg_print; vstr_init_print(&arg_vstr, 16, &arg_print); mp_obj_print_helper(&arg_print, arg, print_kind); - arg = mp_obj_new_str_from_vstr(&mp_type_str, &arg_vstr); + arg = mp_obj_new_str_type_from_vstr(&mp_type_str, &arg_vstr); } char fill = '\0'; @@ -1429,7 +1431,7 @@ mp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs GET_STR_DATA_LEN(args[0], str, len); int arg_i = 0; vstr_t vstr = mp_obj_str_format_helper((const char *)str, (const char *)str + len, &arg_i, n_args, args, kwargs); - return mp_obj_new_str_from_vstr(mp_obj_get_type(args[0]), &vstr); + return mp_obj_new_str_type_from_vstr(mp_obj_get_type(args[0]), &vstr); } MP_DEFINE_CONST_FUN_OBJ_KW(str_format_obj, 1, mp_obj_str_format); @@ -1634,7 +1636,7 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_ mp_raise_TypeError(MP_ERROR_TEXT("format string didn't convert all arguments")); } - return mp_obj_new_str_from_vstr(is_bytes ? &mp_type_bytes : &mp_type_str, &vstr); + return mp_obj_new_str_type_from_vstr(is_bytes ? &mp_type_bytes : &mp_type_str, &vstr); } #endif @@ -1737,7 +1739,7 @@ STATIC mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) { } } - return mp_obj_new_str_from_vstr(self_type, &vstr); + return mp_obj_new_str_type_from_vstr(self_type, &vstr); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj, 3, 4, str_replace); @@ -1849,7 +1851,7 @@ STATIC mp_obj_t str_caseconv(unichar (*op)(unichar), mp_obj_t self_in) { for (size_t i = 0; i < self_len; i++) { *data++ = op(*self_data++); } - return mp_obj_new_str_from_vstr(mp_obj_get_type(self_in), &vstr); + return mp_obj_new_str_type_from_vstr(mp_obj_get_type(self_in), &vstr); } STATIC mp_obj_t str_lower(mp_obj_t self_in) { @@ -1988,7 +1990,7 @@ mp_obj_t mp_obj_bytes_hex(size_t n_args, const mp_obj_t *args, const mp_obj_type *out++ = *sep; } } - return mp_obj_new_str_from_vstr(type, &vstr); + return mp_obj_new_str_type_from_vstr(type, &vstr); } mp_obj_t mp_obj_bytes_fromhex(mp_obj_t type_in, mp_obj_t data) { @@ -2016,7 +2018,7 @@ mp_obj_t mp_obj_bytes_fromhex(mp_obj_t type_in, mp_obj_t data) { hex_byte = 0; } } - return mp_obj_new_str_from_vstr(MP_OBJ_TO_PTR(type_in), &vstr); + return mp_obj_new_str_type_from_vstr(MP_OBJ_TO_PTR(type_in), &vstr); } STATIC mp_obj_t bytes_hex_as_str(size_t n_args, const mp_obj_t *args) { @@ -2213,7 +2215,7 @@ mp_obj_t mp_obj_new_str_via_qstr(const char *data, size_t len) { // Create a str/bytes object from the given vstr. The vstr buffer is resized to // the exact length required and then reused for the str/bytes object. The vstr // is cleared and can safely be passed to vstr_free if it was heap allocated. -mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) { +STATIC mp_obj_t mp_obj_new_str_type_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) { // if not a bytes object, look if a qstr with this data already exists if (type == &mp_type_str) { qstr q = qstr_find_strn(vstr->buf, vstr->len); @@ -2245,6 +2247,14 @@ mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) { return MP_OBJ_FROM_PTR(o); } +mp_obj_t mp_obj_new_str_from_vstr(vstr_t *vstr) { + return mp_obj_new_str_type_from_vstr(&mp_type_str, vstr); +} + +mp_obj_t mp_obj_new_bytes_from_vstr(vstr_t *vstr) { + return mp_obj_new_str_type_from_vstr(&mp_type_bytes, vstr); +} + mp_obj_t mp_obj_new_str(const char *data, size_t len) { qstr q = qstr_find_strn(data, len); if (q != MP_QSTRnull) { diff --git a/py/parsenum.c b/py/parsenum.c index 19cc719201..79765f84f6 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -160,7 +160,7 @@ value_error: mp_printf(&print, "invalid syntax for integer with base %d: ", base); mp_str_print_quoted(&print, str_val_start, top - str_val_start, true); mp_obj_t exc = mp_obj_new_exception_arg1(&mp_type_ValueError, - mp_obj_new_str_from_vstr(&mp_type_str, &vstr)); + mp_obj_new_str_from_vstr(&vstr)); raise_exc(exc, lex); #endif } diff --git a/py/persistentcode.c b/py/persistentcode.c index a8e7429550..995dedb456 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -202,7 +202,11 @@ STATIC mp_obj_t load_obj(mp_reader_t *reader) { read_bytes(reader, (byte *)vstr.buf, len); if (obj_type == MP_PERSISTENT_OBJ_STR || obj_type == MP_PERSISTENT_OBJ_BYTES) { read_byte(reader); // skip null terminator - return mp_obj_new_str_from_vstr(obj_type == MP_PERSISTENT_OBJ_STR ? &mp_type_str : &mp_type_bytes, &vstr); + if (obj_type == MP_PERSISTENT_OBJ_STR) { + return mp_obj_new_str_from_vstr(&vstr); + } else { + return mp_obj_new_bytes_from_vstr(&vstr); + } } else if (obj_type == MP_PERSISTENT_OBJ_INT) { return mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL); } else { diff --git a/py/stream.c b/py/stream.c index dce64a44db..87bed38f67 100644 --- a/py/stream.c +++ b/py/stream.c @@ -40,8 +40,6 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in); -#define STREAM_CONTENT_TYPE(stream) (((stream)->is_text) ? &mp_type_str : &mp_type_bytes) - // Returns error condition in *errcode, if non-zero, return value is number of bytes written // before error condition occurred. If *errcode == 0, returns total bytes written (which will // be equal to input size). @@ -190,7 +188,7 @@ STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte fl } } - return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + return mp_obj_new_str_from_vstr(&vstr); } #endif @@ -211,7 +209,11 @@ STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte fl mp_raise_OSError(error); } else { vstr.len = out_sz; - return mp_obj_new_str_from_vstr(STREAM_CONTENT_TYPE(stream_p), &vstr); + if (stream_p->is_text) { + return mp_obj_new_str_from_vstr(&vstr); + } else { + return mp_obj_new_bytes_from_vstr(&vstr); + } } } @@ -337,7 +339,11 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) { } vstr.len = total_size; - return mp_obj_new_str_from_vstr(STREAM_CONTENT_TYPE(stream_p), &vstr); + if (stream_p->is_text) { + return mp_obj_new_str_from_vstr(&vstr); + } else { + return mp_obj_new_bytes_from_vstr(&vstr); + } } // Unbuffered, inefficient implementation of readline() for raw I/O files. @@ -390,7 +396,11 @@ STATIC mp_obj_t stream_unbuffered_readline(size_t n_args, const mp_obj_t *args) } } - return mp_obj_new_str_from_vstr(STREAM_CONTENT_TYPE(stream_p), &vstr); + if (stream_p->is_text) { + return mp_obj_new_str_from_vstr(&vstr); + } else { + return mp_obj_new_bytes_from_vstr(&vstr); + } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_unbuffered_readline_obj, 1, 2, stream_unbuffered_readline); From 88864587f5af292d7f86aceb6bf40e8331e9a8d6 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 26 Aug 2022 12:54:53 +1000 Subject: [PATCH 0334/1041] py/objstr: Always ensure mp_obj_str_from_vstr is unicode-safe. Now that we have `mp_obj_new_str_type_from_vstr` (private helper used by objstr.c) split from the public API (`mp_obj_new_str_from_vstr`), we can enforce a unicode check at the public API without incurring a performance cost on the various objstr.c methods (which are already working on known unicode-safe strings). Signed-off-by: Jim Mussared --- py/objstr.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/py/objstr.c b/py/objstr.c index 69745a2f58..ab1229ad66 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -2248,6 +2248,11 @@ STATIC mp_obj_t mp_obj_new_str_type_from_vstr(const mp_obj_type_t *type, vstr_t } mp_obj_t mp_obj_new_str_from_vstr(vstr_t *vstr) { + #if MICROPY_PY_BUILTINS_STR_UNICODE && MICROPY_PY_BUILTINS_STR_UNICODE_CHECK + if (!utf8_check((byte *)vstr->buf, vstr->len)) { + mp_raise_msg(&mp_type_UnicodeError, NULL); + } + #endif // MICROPY_PY_BUILTINS_STR_UNICODE && MICROPY_PY_BUILTINS_STR_UNICODE_CHECK return mp_obj_new_str_type_from_vstr(&mp_type_str, vstr); } From 3a910b15650636efc58bce48cc1bfa0debfd375c Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 23 Aug 2022 18:35:37 +1000 Subject: [PATCH 0335/1041] py/objstr: Optimise mp_obj_new_str_from_vstr for known-safe strings. The new `mp_obj_new_str_from_utf8_vstr` can be used when you know you already have a unicode-safe string. Signed-off-by: Jim Mussared --- extmod/modujson.c | 4 ++-- extmod/modure.c | 2 +- ports/unix/modusocket.c | 2 +- py/modbuiltins.c | 2 +- py/obj.h | 5 +++++ py/objstr.c | 7 +++++++ py/parsenum.c | 2 +- py/persistentcode.c | 2 +- 8 files changed, 19 insertions(+), 7 deletions(-) diff --git a/extmod/modujson.c b/extmod/modujson.c index 57c50deec0..4e992e2245 100644 --- a/extmod/modujson.c +++ b/extmod/modujson.c @@ -67,7 +67,7 @@ STATIC mp_obj_t mod_ujson_dump_helper(size_t n_args, const mp_obj_t *pos_args, m vstr_t vstr; vstr_init_print(&vstr, 8, &print_ext.base); mp_obj_print_helper(&print_ext.base, pos_args[0], PRINT_JSON); - return mp_obj_new_str_from_vstr(&vstr); + return mp_obj_new_str_from_utf8_vstr(&vstr); } else { // dump(obj, stream) print_ext.base.data = MP_OBJ_TO_PTR(pos_args[1]); @@ -103,7 +103,7 @@ STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) { mp_print_t print; vstr_init_print(&vstr, 8, &print); mp_obj_print_helper(&print, obj, PRINT_JSON); - return mp_obj_new_str_from_vstr(&vstr); + return mp_obj_new_str_from_utf8_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps); diff --git a/extmod/modure.c b/extmod/modure.c index 59fbfddbf2..799fef13b1 100644 --- a/extmod/modure.c +++ b/extmod/modure.c @@ -373,7 +373,7 @@ STATIC mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) { vstr_add_strn(&vstr_return, subj.begin, subj.end - subj.begin); if (mp_obj_get_type(where) == &mp_type_str) { - return mp_obj_new_str_from_vstr(&vstr_return); + return mp_obj_new_str_from_utf8_vstr(&vstr_return); } else { return mp_obj_new_bytes_from_vstr(&vstr_return); } diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c index 88e7675a92..72c70d1750 100644 --- a/ports/unix/modusocket.c +++ b/ports/unix/modusocket.c @@ -559,7 +559,7 @@ STATIC mp_obj_t mod_socket_inet_ntop(mp_obj_t family_in, mp_obj_t binaddr_in) { mp_raise_OSError(errno); } vstr.len = strlen(vstr.buf); - return mp_obj_new_str_from_vstr(&vstr); + return mp_obj_new_str_from_utf8_vstr(&vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_socket_inet_ntop_obj, mod_socket_inet_ntop); diff --git a/py/modbuiltins.c b/py/modbuiltins.c index 2459edda13..f74db95cf5 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -467,7 +467,7 @@ STATIC mp_obj_t mp_builtin_repr(mp_obj_t o_in) { mp_print_t print; vstr_init_print(&vstr, 16, &print); mp_obj_print_helper(&print, o_in, PRINT_REPR); - return mp_obj_new_str_from_vstr(&vstr); + return mp_obj_new_str_from_utf8_vstr(&vstr); } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr); diff --git a/py/obj.h b/py/obj.h index d171e0fe62..0b0a9692ed 100644 --- a/py/obj.h +++ b/py/obj.h @@ -792,6 +792,11 @@ mp_obj_t mp_obj_new_int_from_ull(unsigned long long val); // this must return a mp_obj_t mp_obj_new_str(const char *data, size_t len); mp_obj_t mp_obj_new_str_via_qstr(const char *data, size_t len); mp_obj_t mp_obj_new_str_from_vstr(vstr_t *vstr); +#if MICROPY_PY_BUILTINS_STR_UNICODE && MICROPY_PY_BUILTINS_STR_UNICODE_CHECK +mp_obj_t mp_obj_new_str_from_utf8_vstr(vstr_t *vstr); // only use when vstr is already known to be utf-8 encoded +#else +#define mp_obj_new_str_from_utf8_vstr mp_obj_new_str_from_vstr +#endif mp_obj_t mp_obj_new_bytes_from_vstr(vstr_t *vstr); mp_obj_t mp_obj_new_bytes(const byte *data, size_t len); mp_obj_t mp_obj_new_bytearray(size_t n, const void *items); diff --git a/py/objstr.c b/py/objstr.c index ab1229ad66..5a62237516 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -2256,6 +2256,13 @@ mp_obj_t mp_obj_new_str_from_vstr(vstr_t *vstr) { return mp_obj_new_str_type_from_vstr(&mp_type_str, vstr); } +#if MICROPY_PY_BUILTINS_STR_UNICODE && MICROPY_PY_BUILTINS_STR_UNICODE_CHECK +mp_obj_t mp_obj_new_str_from_utf8_vstr(vstr_t *vstr) { + // bypasses utf8_check. + return mp_obj_new_str_type_from_vstr(&mp_type_str, vstr); +} +#endif // MICROPY_PY_BUILTINS_STR_UNICODE && MICROPY_PY_BUILTINS_STR_UNICODE_CHECK + mp_obj_t mp_obj_new_bytes_from_vstr(vstr_t *vstr) { return mp_obj_new_str_type_from_vstr(&mp_type_bytes, vstr); } diff --git a/py/parsenum.c b/py/parsenum.c index 79765f84f6..d59715fdc9 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -160,7 +160,7 @@ value_error: mp_printf(&print, "invalid syntax for integer with base %d: ", base); mp_str_print_quoted(&print, str_val_start, top - str_val_start, true); mp_obj_t exc = mp_obj_new_exception_arg1(&mp_type_ValueError, - mp_obj_new_str_from_vstr(&vstr)); + mp_obj_new_str_from_utf8_vstr(&vstr)); raise_exc(exc, lex); #endif } diff --git a/py/persistentcode.c b/py/persistentcode.c index 995dedb456..82ef0c4995 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -203,7 +203,7 @@ STATIC mp_obj_t load_obj(mp_reader_t *reader) { if (obj_type == MP_PERSISTENT_OBJ_STR || obj_type == MP_PERSISTENT_OBJ_BYTES) { read_byte(reader); // skip null terminator if (obj_type == MP_PERSISTENT_OBJ_STR) { - return mp_obj_new_str_from_vstr(&vstr); + return mp_obj_new_str_from_utf8_vstr(&vstr); } else { return mp_obj_new_bytes_from_vstr(&vstr); } From 6c3d8d38bfbe24c3d810f89f546ac947cf0cb66d Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 24 Aug 2022 12:22:57 +1000 Subject: [PATCH 0336/1041] py/objstr: Always validate utf-8 for mp_obj_new_str. All uses of this are either tiny strings or not-known-to-be-safe. Update comments for mp_obj_new_str_copy and mp_obj_new_str_of_type. Signed-off-by: Jim Mussared --- py/obj.h | 8 ++++---- py/objstr.c | 11 ++++++----- py/objstr.h | 4 ++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/py/obj.h b/py/obj.h index 0b0a9692ed..e048cf0c28 100644 --- a/py/obj.h +++ b/py/obj.h @@ -789,11 +789,11 @@ mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value); mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base); mp_obj_t mp_obj_new_int_from_ll(long long val); // this must return a multi-precision integer object (or raise an overflow exception) mp_obj_t mp_obj_new_int_from_ull(unsigned long long val); // this must return a multi-precision integer object (or raise an overflow exception) -mp_obj_t mp_obj_new_str(const char *data, size_t len); -mp_obj_t mp_obj_new_str_via_qstr(const char *data, size_t len); -mp_obj_t mp_obj_new_str_from_vstr(vstr_t *vstr); +mp_obj_t mp_obj_new_str(const char *data, size_t len); // will check utf-8 (raises UnicodeError) +mp_obj_t mp_obj_new_str_via_qstr(const char *data, size_t len); // input data must be valid utf-8 +mp_obj_t mp_obj_new_str_from_vstr(vstr_t *vstr); // will check utf-8 (raises UnicodeError) #if MICROPY_PY_BUILTINS_STR_UNICODE && MICROPY_PY_BUILTINS_STR_UNICODE_CHECK -mp_obj_t mp_obj_new_str_from_utf8_vstr(vstr_t *vstr); // only use when vstr is already known to be utf-8 encoded +mp_obj_t mp_obj_new_str_from_utf8_vstr(vstr_t *vstr); // input data must be valid utf-8 #else #define mp_obj_new_str_from_utf8_vstr mp_obj_new_str_from_vstr #endif diff --git a/py/objstr.c b/py/objstr.c index 5a62237516..683d035e44 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -202,11 +202,7 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ } else { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); - #if MICROPY_PY_BUILTINS_STR_UNICODE_CHECK - if (!utf8_check(bufinfo.buf, bufinfo.len)) { - mp_raise_msg(&mp_type_UnicodeError, NULL); - } - #endif + // This will utf-8 check the input. return mp_obj_new_str(bufinfo.buf, bufinfo.len); } } @@ -2268,6 +2264,11 @@ mp_obj_t mp_obj_new_bytes_from_vstr(vstr_t *vstr) { } mp_obj_t mp_obj_new_str(const char *data, size_t len) { + #if MICROPY_PY_BUILTINS_STR_UNICODE && MICROPY_PY_BUILTINS_STR_UNICODE_CHECK + if (!utf8_check((byte *)data, len)) { + mp_raise_msg(&mp_type_UnicodeError, NULL); + } + #endif qstr q = qstr_find_strn(data, len); if (q != MP_QSTRnull) { // qstr with this data already exists diff --git a/py/objstr.h b/py/objstr.h index 78441fedaf..6c6735bf5e 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -88,8 +88,8 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t void mp_str_print_json(const mp_print_t *print, const byte *str_data, size_t str_len); mp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs); mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args); -mp_obj_t mp_obj_new_str_copy(const mp_obj_type_t *type, const byte *data, size_t len); -mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte *data, size_t len); +mp_obj_t mp_obj_new_str_copy(const mp_obj_type_t *type, const byte *data, size_t len); // for type=str, input data must be valid utf-8 +mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte *data, size_t len); // for type=str, will check utf-8 (raises UnicodeError) mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags); From bd4e45fd68e20af3f965b403e643fa5f71aa1b08 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 24 Aug 2022 12:42:45 +1000 Subject: [PATCH 0337/1041] tests/unicode: Add test for invalid utf-8 file contents. Signed-off-by: Jim Mussared --- tests/unicode/data/utf-8_invalid.txt | 1 + tests/unicode/file_invalid.py | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 tests/unicode/data/utf-8_invalid.txt create mode 100644 tests/unicode/file_invalid.py diff --git a/tests/unicode/data/utf-8_invalid.txt b/tests/unicode/data/utf-8_invalid.txt new file mode 100644 index 0000000000..50020482bf --- /dev/null +++ b/tests/unicode/data/utf-8_invalid.txt @@ -0,0 +1 @@ +aabb diff --git a/tests/unicode/file_invalid.py b/tests/unicode/file_invalid.py new file mode 100644 index 0000000000..3f7f184062 --- /dev/null +++ b/tests/unicode/file_invalid.py @@ -0,0 +1,5 @@ +try: + f = open("unicode/data/utf-8_invalid.txt", encoding="utf-8") + f.read() +except UnicodeError: + print("UnicodeError") From d521899e18c305a4cf3870449e3dd12308f7a806 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 17 Aug 2022 08:43:17 +1000 Subject: [PATCH 0338/1041] py/persistentcode: Clarify ValueError when native emitter disabled. --- py/persistentcode.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/py/persistentcode.c b/py/persistentcode.c index 82ef0c4995..1b1741f261 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -402,7 +402,13 @@ mp_compiled_module_t mp_raw_code_load(mp_reader_t *reader, mp_module_context_t * if (MPY_FEATURE_DECODE_ARCH(header[2]) != MP_NATIVE_ARCH_NONE) { byte arch = MPY_FEATURE_DECODE_ARCH(header[2]); if (!MPY_FEATURE_ARCH_TEST(arch)) { - mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy arch")); + if (MPY_FEATURE_ARCH_TEST(MP_NATIVE_ARCH_NONE)) { + // On supported ports this can be resolved by enabling feature, eg + // mpconfigboard.h: MICROPY_EMIT_THUMB (1) + mp_raise_ValueError(MP_ERROR_TEXT("native code in .mpy unsupported")); + } else { + mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy arch")); + } } } From 9a826e0f24add1b7e719e915e0d4dde1c14b416e Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 26 Jul 2022 18:48:06 +1000 Subject: [PATCH 0339/1041] lib/lwip: Update lwIP to v2.1.3, tag STABLE-2_1_3_RELEASE. There don't seem to be many changes going from v2.1.2 to v2.1.3 of lwIP. Mostly they are: - IPv6 fixes and improvements - changes to apps and other code that MicroPython doesn't use - comments and tests - minor bug fixes In particular there doesn't look to be any change to the API of any function used by MicroPython. Network multi tests pass on PYBD_SF2 and PYBD_SF6. PYBD_SF2, PYBD_SF6 and PICO_W have unchanged iperf3 performance. Similar results for networking on the mimxrt port. Signed-off-by: Damien George --- lib/lwip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lwip b/lib/lwip index 159e31b689..6ca936f6b5 160000 --- a/lib/lwip +++ b/lib/lwip @@ -1 +1 @@ -Subproject commit 159e31b689577dbf69cf0683bbaffbd71fa5ee10 +Subproject commit 6ca936f6b588cee702c638eee75c2436e6cf75de From 730e97509117ea9c8b527857c25f8a2bf04ecd86 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 30 Aug 2022 11:14:32 +1000 Subject: [PATCH 0340/1041] esp32/boards: Merge manifest_release modules into standard manifest. Having two separate manifests is confusing. It's simpler to have the daily builds use the same configuration as the stable, release builds. Signed-off-by: Damien George --- ports/esp32/boards/manifest.py | 6 ++++++ ports/esp32/boards/manifest_release.py | 7 ------- tools/autobuild/build-boards.sh | 7 +------ 3 files changed, 7 insertions(+), 13 deletions(-) delete mode 100644 ports/esp32/boards/manifest_release.py diff --git a/ports/esp32/boards/manifest.py b/ports/esp32/boards/manifest.py index f0ed38b515..23252442ea 100644 --- a/ports/esp32/boards/manifest.py +++ b/ports/esp32/boards/manifest.py @@ -6,3 +6,9 @@ freeze("$(MPY_DIR)/drivers/onewire") include("$(MPY_DIR)/extmod/uasyncio/manifest.py") include("$(MPY_DIR)/extmod/webrepl/manifest.py") include("$(MPY_DIR)/drivers/neopixel/manifest.py") + +# Freeze some micropython-lib modules. +freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py") +freeze("$(MPY_LIB_DIR)/micropython/upysh", "upysh.py") +freeze("$(MPY_LIB_DIR)/micropython/umqtt.simple", "umqtt/simple.py") +freeze("$(MPY_LIB_DIR)/micropython/umqtt.robust", "umqtt/robust.py") diff --git a/ports/esp32/boards/manifest_release.py b/ports/esp32/boards/manifest_release.py deleted file mode 100644 index 8b9bcde6ff..0000000000 --- a/ports/esp32/boards/manifest_release.py +++ /dev/null @@ -1,7 +0,0 @@ -include("manifest.py") - -freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py") - -freeze("$(MPY_LIB_DIR)/micropython/upysh", "upysh.py") -freeze("$(MPY_LIB_DIR)/micropython/umqtt.simple", "umqtt/simple.py") -freeze("$(MPY_LIB_DIR)/micropython/umqtt.robust", "umqtt/robust.py") diff --git a/tools/autobuild/build-boards.sh b/tools/autobuild/build-boards.sh index b3d2f8c4c5..48c7b81841 100755 --- a/tools/autobuild/build-boards.sh +++ b/tools/autobuild/build-boards.sh @@ -83,12 +83,7 @@ function build_esp32_boards { if idf.py --version | grep -q v4.2; then if [ $mcu = esp32 ]; then # build standard esp32-based boards with IDF v4.2 - if echo $board_json | grep -q GENERIC; then - # traditionally, GENERIC and GENERIC_SPIRAM boards used manifest_release.py - MICROPY_AUTOBUILD_MAKE="$MICROPY_AUTOBUILD_MAKE FROZEN_MANIFEST=$(pwd)/boards/manifest_release.py" build_board $board_json $fw_tag $dest_dir bin elf map - else - build_board $board_json $fw_tag $dest_dir bin elf map - fi + build_board $board_json $fw_tag $dest_dir bin elf map fi else if [ $mcu != esp32 ]; then From d108fc9c4793e1846b2ddfad925fb17bbc44cd51 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 30 Aug 2022 11:18:08 +1000 Subject: [PATCH 0341/1041] esp32/machine_sdcard: Free SPI bus when deiniting SD card. So that everything is reset and the SD card can be created again after calling SDCard.deinit() (and after a soft reset). Fixes issue #8949. Signed-off-by: Damien George --- ports/esp32/machine_sdcard.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/esp32/machine_sdcard.c b/ports/esp32/machine_sdcard.c index 82c2e6cd4e..3f94356adb 100644 --- a/ports/esp32/machine_sdcard.c +++ b/ports/esp32/machine_sdcard.c @@ -283,6 +283,10 @@ STATIC mp_obj_t sd_deinit(mp_obj_t self_in) { { self->host.deinit(); } + if (self->host.flags & SDMMC_HOST_FLAG_SPI) { + // SD card used a (dedicated) SPI bus, so free that SPI bus. + spi_bus_free(self->host.slot); + } self->flags &= ~SDCARD_CARD_FLAGS_HOST_INIT_DONE; } From 64c62f8cf162e56cf4c6049f4a65c3d5e18556ae Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 24 Aug 2022 23:47:58 +1000 Subject: [PATCH 0342/1041] README: Simplify and update, and move unix section to separate file. Changes are: - Remove unix- and stm32-specific sections (move unix to its own README.md), stm32 was duplicated. - Add links to GitHub Discussions and Discord. - Update information about the project. - Add a getting started section. - Explain `make submodules`. Signed-off-by: Jim Mussared Signed-off-by: Damien George --- README.md | 268 ++++++++++++++++++------------------------- ports/unix/README.md | 70 +++++++++++ 2 files changed, 184 insertions(+), 154 deletions(-) create mode 100644 ports/unix/README.md diff --git a/README.md b/README.md index 6941102f0a..6482899b25 100644 --- a/README.md +++ b/README.md @@ -15,167 +15,43 @@ code-base, including project-wide name changes and API changes. MicroPython implements the entire Python 3.4 syntax (including exceptions, `with`, `yield from`, etc., and additionally `async`/`await` keywords from -Python 3.5). The following core datatypes are provided: `str` (including -basic Unicode support), `bytes`, `bytearray`, `tuple`, `list`, `dict`, `set`, -`frozenset`, `array.array`, `collections.namedtuple`, classes and instances. -Builtin modules include `sys`, `time`, and `struct`, etc. Select ports have -support for `_thread` module (multithreading). Note that only a subset of -Python 3 functionality is implemented for the data types and modules. +Python 3.5 and some select features from later versions). The following core +datatypes are provided: `str`(including basic Unicode support), `bytes`, +`bytearray`, `tuple`, `list`, `dict`, `set`, `frozenset`, `array.array`, +`collections.namedtuple`, classes and instances. Builtin modules include +`os`, `sys`, `time`, `re`, and `struct`, etc. Select ports have support for +`_thread` module (multithreading), `socket` and `ssl` for networking, and +`asyncio`. Note that only a subset of Python 3 functionality is implemented +for the data types and modules. -MicroPython can execute scripts in textual source form or from precompiled -bytecode, in both cases either from an on-device filesystem or "frozen" into -the MicroPython executable. +MicroPython can execute scripts in textual source form (.py files) or from +precompiled bytecode (.mpy files), in both cases either from an on-device +filesystem or "frozen" into the MicroPython executable. -See the repository http://github.com/micropython/pyboard for the MicroPython -board (PyBoard), the officially supported reference electronic circuit board. +MicroPython also provides a set of MicroPython-specific modules to access +hardware-specific functionality and peripherals such as GPIO, Timers, ADC, +DAC, PWM, SPI, I2C, CAN, Bluetooth, and USB. -Major components in this repository: -- py/ -- the core Python implementation, including compiler, runtime, and - core library. -- mpy-cross/ -- the MicroPython cross-compiler which is used to turn scripts - into precompiled bytecode. -- ports/unix/ -- a version of MicroPython that runs on Unix. -- ports/stm32/ -- a version of MicroPython that runs on the PyBoard and similar - STM32 boards (using ST's Cube HAL drivers). -- ports/minimal/ -- a minimal MicroPython port. Start with this if you want - to port MicroPython to another microcontroller. -- tests/ -- test framework and test scripts. -- docs/ -- user documentation in Sphinx reStructuredText format. Rendered - HTML documentation is available at http://docs.micropython.org. +Getting started +--------------- -Additional components: -- ports/bare-arm/ -- a bare minimum version of MicroPython for ARM MCUs. Used - mostly to control code size. -- ports/teensy/ -- a version of MicroPython that runs on the Teensy 3.1 - (preliminary but functional). -- ports/pic16bit/ -- a version of MicroPython for 16-bit PIC microcontrollers. -- ports/cc3200/ -- a version of MicroPython that runs on the CC3200 from TI. -- ports/esp8266/ -- a version of MicroPython that runs on Espressif's ESP8266 SoC. -- ports/esp32/ -- a version of MicroPython that runs on Espressif's ESP32 SoC. -- ports/nrf/ -- a version of MicroPython that runs on Nordic's nRF51 and nRF52 MCUs. -- extmod/ -- additional (non-core) modules implemented in C. -- tools/ -- various tools, including the pyboard.py module. -- examples/ -- a few example Python scripts. +See the [online documentation](https://docs.micropython.org/) for API +references and information about using MicroPython and information about how +it is implemented. -The subdirectories above may include READMEs with additional info. +We use [GitHub Discussions](https://github.com/micropython/micropython/discussions) +as our forum, and [Discord](https://discord.gg/RB8HZSAExQ) for chat. These +are great places to ask questions and advice from the community or to discuss your +MicroPython-based projects. -"make" is used to build the components, or "gmake" on BSD-based systems. -You will also need bash, gcc, and Python 3.3+ available as the command `python3` -(if your system only has Python 2.7 then invoke make with the additional option -`PYTHON=python2`). +For bugs and feature requests, please [raise an issue](https://github.com/micropython/micropython/issues/new/choose) +and follow the templates there. -The MicroPython cross-compiler, mpy-cross ------------------------------------------ - -Most ports require the MicroPython cross-compiler to be built first. This -program, called mpy-cross, is used to pre-compile Python scripts to .mpy -files which can then be included (frozen) into the firmware/executable for -a port. To build mpy-cross use: - - $ cd mpy-cross - $ make - -The Unix version ----------------- - -The "unix" port requires a standard Unix environment with gcc and GNU make. -x86 and x64 architectures are supported (i.e. x86 32- and 64-bit), as well -as ARM and MIPS. Making full-featured port to another architecture requires -writing some assembly code for the exception handling and garbage collection. -Alternatively, fallback implementation based on setjmp/longjmp can be used. - -To build (see section below for required dependencies): - - $ cd ports/unix - $ make submodules - $ make - -Then to give it a try: - - $ ./micropython - >>> list(5 * x + y for x in range(10) for y in [4, 2, 1]) - -Use `CTRL-D` (i.e. EOF) to exit the shell. -Learn about command-line options (in particular, how to increase heap size -which may be needed for larger applications): - - $ ./micropython -h - -Run complete testsuite: - - $ make test - -Unix version comes with a builtin package manager called upip, e.g.: - - $ ./micropython -m upip install micropython-pystone - $ ./micropython -m pystone - -Browse available modules on -[PyPI](https://pypi.python.org/pypi?%3Aaction=search&term=micropython). -Standard library modules come from -[micropython-lib](https://github.com/micropython/micropython-lib) project. - -External dependencies ---------------------- - -Building MicroPython ports may require some dependencies installed. - -For Unix port, `libffi` library and `pkg-config` tool are required. On -Debian/Ubuntu/Mint derivative Linux distros, install `build-essential` -(includes toolchain and make), `libffi-dev`, and `pkg-config` packages. - -Other dependencies can be built together with MicroPython. This may -be required to enable extra features or capabilities, and in recent -versions of MicroPython, these may be enabled by default. To build -these additional dependencies, in the port directory you're -interested in (e.g. `ports/unix/`) first execute: - - $ make submodules - -This will fetch all the relevant git submodules (sub repositories) that -the port needs. Use the same command to get the latest versions of -submodules as they are updated from time to time. After that execute: - - $ make deplibs - -This will build all available dependencies (regardless whether they -are used or not). If you intend to build MicroPython with additional -options (like cross-compiling), the same set of options should be passed -to `make deplibs`. To actually enable/disable use of dependencies, edit -`ports/unix/mpconfigport.mk` file, which has inline descriptions of the options. -For example, to build SSL module (required for `upip` tool described above, -and so enabled by default), `MICROPY_PY_USSL` should be set to 1. - -For some ports, building required dependences is transparent, and happens -automatically. But they still need to be fetched with the `make submodules` -command. - -The STM32 version ------------------ - -The "stm32" port requires an ARM compiler, arm-none-eabi-gcc, and associated -bin-utils. For those using Arch Linux, you need arm-none-eabi-binutils, -arm-none-eabi-gcc and arm-none-eabi-newlib packages. Otherwise, try here: -https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads - -To build: - - $ cd ports/stm32 - $ make submodules - $ make - -You then need to get your board into DFU mode. On the pyboard, connect the -3V3 pin to the P1/DFU pin with a wire (on PYBv1.0 they are next to each other -on the bottom left of the board, second row from the bottom). - -Then to flash the code via USB DFU to your device: - - $ make deploy - -This will use the included `tools/pydfu.py` script. If flashing the firmware -does not work it may be because you don't have the correct permissions, and -need to use `sudo make deploy`. -See the README.md file in the ports/stm32/ directory for further details. +For information about the [MicroPython pyboard](https://store.micropython.org/pyb-features), +the officially supported board from the +[original Kickstarter campaign](https://www.kickstarter.com/projects/214379695/micro-python-python-for-microcontrollers), +see the [schematics and pinouts](http://github.com/micropython/pyboard) and +[documentation](https://docs.micropython.org/en/latest/pyboard/quickref.html). Contributing ------------ @@ -186,3 +62,87 @@ productive, please be sure to follow the and the [Code Conventions](https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md). Note that MicroPython is licenced under the MIT license, and all contributions should follow this license. + +About this repository +--------------------- + +This repository contains the following components: +- [py/](py/) -- the core Python implementation, including compiler, runtime, and + core library. +- [mpy-cross/](mpy-cross/) -- the MicroPython cross-compiler which is used to turn scripts + into precompiled bytecode. +- [ports/](ports/) -- platform-specific code for the various ports and architectures that MicroPython runs on. +- [lib/](lib/) -- submodules for external dependencies. +- [tests/](tests/) -- test framework and test scripts. +- [docs/](docs/) -- user documentation in Sphinx reStructuredText format. This is used to generate the [online documentation](http://docs.micropython.org). +- [extmod/](extmod/) -- additional (non-core) modules implemented in C. +- [tools/](tools/) -- various tools, including the pyboard.py module. +- [examples/](examples/) -- a few example Python scripts. + +"make" is used to build the components, or "gmake" on BSD-based systems. +You will also need bash, gcc, and Python 3.3+ available as the command `python3` +(if your system only has Python 2.7 then invoke make with the additional option +`PYTHON=python2`). Some ports (rp2 and esp32) additionally use CMake. + +Supported platforms & architectures +----------------------------------- + +MicroPython runs on a wide range of microcontrollers, as well as on Unix-like +(including Linux, BSD, macOS, WSL) and Windows systems. + +Microcontroller targets can be as small as 256kiB flash + 16kiB RAM, although +devices with at least 512kiB flash + 128kiB RAM allow a much more +full-featured experience. + +The [Unix](ports/unix) and [Windows](ports/windows) ports allow both +development and testing of MicroPython itself, as well as providing +lightweight alternative to CPython on these platforms (in particular on +embedded Linux systems). + +The ["minimal"](ports/minimal) port provides an example of a very basic +MicroPython port and can be compiled as both a standalone Linux binary as +well as for ARM Cortex M4. Start with this if you want to port MicroPython to +another microcontroller. Additionally the ["bare-arm"](ports/bare-arm) port +is an example of the absolute minimum configuration, and is used to keep +track of the code size of the core runtime and VM. + +In addition, the following ports are provided in this repository: + - [cc3200](ports/cc3200) -- Texas Instruments CC3200 (including PyCom WiPy). + - [esp32](ports/esp32) -- Espressif ESP32 SoC (including ESP32S2, ESP32S3, ESP32C3). + - [esp8266](ports/esp8266) -- Espressif ESP8266 SoC. + - [mimxrt](ports/mimxrt) -- NXP m.iMX RT (including Teensy 4.x). + - [nrf](ports/nrf) -- Nordic Semiconductor nRF51 and nRF52. + - [pic16bit](ports/pic16bit) -- Microchip PIC 16-bit. + - [powerpc](ports/powerpc) -- IBM PowerPC (including Microwatt) + - [qemu-arm](ports/qemu-arm) -- QEMU-based emulated target, for testing) + - [renesas-ra](ports/renesas-ra) -- Renesas RA family. + - [rp2](ports/rp2) -- Raspberry Pi RP2040 (including Pico and Pico W). + - [samd](ports/samd) -- Microchip (formerly Atmel) SAMD21 and SAMD51. + - [stm32](ports/stm32) -- STMicroelectronics STM32 family (including F0, F4, F7, G0, G4, H7, L0, L4, WB) + - [teensy](ports/teensy) -- Teensy 3.x. + - [webassembly](ports/webassembly) -- Emscripten port targeting browsers and NodeJS. + - [zephyr](ports/zephyr) -- Zephyr RTOS. + +The MicroPython cross-compiler, mpy-cross +----------------------------------------- + +Most ports require the [MicroPython cross-compiler](mpy-cross) to be built +first. This program, called mpy-cross, is used to pre-compile Python scripts +to .mpy files which can then be included (frozen) into the +firmware/executable for a port. To build mpy-cross use: + + $ cd mpy-cross + $ make + +External dependencies +--------------------- + +The core MicroPython VM and runtime has no external dependencies, but a given +port might depend on third-party drivers or vendor HALs. This repository +includes [several submodules](lib/) linking to these external dependencies. +Before compiling a given port, use + + $ cd ports/name + $ make submodules + +to ensure that all required submodules are initialised. diff --git a/ports/unix/README.md b/ports/unix/README.md new file mode 100644 index 0000000000..efc68b2455 --- /dev/null +++ b/ports/unix/README.md @@ -0,0 +1,70 @@ +The Unix version +---------------- + +The "unix" port requires a standard Unix-like environment with gcc and GNU +make. This includes Linux, BSD, macOS, and Windows Subsystem for Linux. The +x86 and x64 architectures are supported (i.e. x86 32- and 64-bit), as well as +ARM and MIPS. Making a full-featured port to another architecture requires +writing some assembly code for the exception handling and garbage collection. +Alternatively, a fallback implementation based on setjmp/longjmp can be used. + +To build (see section below for required dependencies): + + $ cd ports/unix + $ make submodules + $ make + +Then to give it a try: + + $ ./build-standard/micropython + >>> list(5 * x + y for x in range(10) for y in [4, 2, 1]) + +Use `CTRL-D` (i.e. EOF) to exit the shell. + +Learn about command-line options (in particular, how to increase heap size +which may be needed for larger applications): + + $ ./micropython -h + +To run the complete testsuite, use: + + $ make test + +The Unix port comes with a builtin package manager called upip, e.g.: + + $ ./micropython -m upip install micropython-pystone + $ ./micropython -m pystone + +Browse available modules on +[PyPI](https://pypi.python.org/pypi?%3Aaction=search&term=micropython). +Standard library modules come from the +[micropython-lib](https://github.com/micropython/micropython-lib) project. + +External dependencies +--------------------- + +The `libffi` library and `pkg-config` tool are required. On Debian/Ubuntu/Mint +derivative Linux distros, install `build-essential`(includes toolchain and +make), `libffi-dev`, and `pkg-config` packages. + +Other dependencies can be built together with MicroPython. This may +be required to enable extra features or capabilities, and in recent +versions of MicroPython, these may be enabled by default. To build +these additional dependencies, in the unix port directory first execute: + + $ make submodules + +This will fetch all the relevant git submodules (sub repositories) that +the port needs. Use the same command to get the latest versions of +submodules as they are updated from time to time. After that execute: + + $ make deplibs + +This will build all available dependencies (regardless whether they are used +or not). If you intend to build MicroPython with additional options +(like cross-compiling), the same set of options should be passed to `make +deplibs`. To actually enable/disable use of dependencies, edit the +`ports/unix/mpconfigport.mk` file, which has inline descriptions of the +options. For example, to build SSL module (required for the `upip` tool +described above, and so enabled by default), `MICROPY_PY_USSL` should be set +to 1. From 316008046a689b59e7a521c811d6e381bd03fb5a Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 25 Aug 2022 15:03:38 +1000 Subject: [PATCH 0343/1041] github/ISSUE_TEMPLATE: Replace forum with Discussions. Signed-off-by: Jim Mussared Signed-off-by: Damien George --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/ISSUE_TEMPLATE/config.yml | 4 ++-- .github/ISSUE_TEMPLATE/documentation.md | 2 +- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index ac9d97041a..7bad956296 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -7,7 +7,7 @@ assignees: '' --- -* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please see the MicroPython Forum (https://forum.micropython.org/) or raise a documentation request instead. +* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please use the Discussions tab or raise a documentation request instead. * In your issue, please include a clear and concise description of what the bug is, the expected output, and how to replicate it. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 318d9416ee..f3662464da 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,7 +1,7 @@ blank_issues_enabled: false contact_links: - - name: MicroPython Forum - url: https://forum.micropython.org/ + - name: MicroPython GitHub Discussions + url: https://github.com/orgs/micropython/discussions about: Community discussion about all things MicroPython. This is the best place to start if you have questions about using MicroPython or getting started with MicroPython development. - name: MicroPython Documentation url: https://docs.micropython.org/ diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md index c86c1ec2b8..e36fa62ac2 100644 --- a/.github/ISSUE_TEMPLATE/documentation.md +++ b/.github/ISSUE_TEMPLATE/documentation.md @@ -7,7 +7,7 @@ assignees: '' --- -* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please see the MicroPython Forum -- https://forum.micropython.org/ +* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please use the Discussions tab instead. * Describe what was missing from the documentation and/or what was incorrect/incomplete. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 3976699b28..81b55d98e0 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -7,7 +7,7 @@ assignees: '' --- -* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please see the MicroPython Forum (https://forum.micropython.org/) or raise a documentation request instead. +* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please use the Discussions tab or raise a documentation request instead. * Describe the feature you'd like to see added to MicroPython. In particular, what does this feature enable and why is it useful. MicroPython aims to strike a balance between functionality and code size, so please consider whether this feature can be optionally enabled and whether it can be provided in other ways (e.g. pure-Python library). From 31d7ab327b0da4fe7747aba5590a542b88caa123 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 25 Aug 2022 15:03:56 +1000 Subject: [PATCH 0344/1041] docs/templates/topindex.html: Update forum link. Signed-off-by: Jim Mussared --- docs/templates/topindex.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/templates/topindex.html b/docs/templates/topindex.html index 41bcc740dd..cfe3ad1516 100644 --- a/docs/templates/topindex.html +++ b/docs/templates/topindex.html @@ -119,7 +119,7 @@ the official MicroPython site

From 53ebbf10e56dd4cc33aec6cc6d0590c66fd1948e Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 27 Aug 2022 10:42:15 +0200 Subject: [PATCH 0345/1041] docs/library/machine.I2C: Add a note about I2C pull-up resistors. Quite regularly users complain about unexpected behavior of I2C, calling it a bug, when in fact the trouble is caused by missing pull-up resistors. So this commit adds a note to the documentation, in the slim hope that people will find and read it. --- docs/library/machine.I2C.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/library/machine.I2C.rst b/docs/library/machine.I2C.rst index 82a88390c3..2a33b1da47 100644 --- a/docs/library/machine.I2C.rst +++ b/docs/library/machine.I2C.rst @@ -20,6 +20,17 @@ Software I2C is implemented by bit-banging and can be used on any pin but is not as efficient. These classes have the same methods available and differ primarily in the way they are constructed. +.. Note:: + + The I2C bus requires pull-up circuitry on both SDA and SCL for it's operation. + Usually these are resistors in the range of 1 - 10 kOhm, connected from each SDA/SCL + to Vcc. Without these, the behaviour is undefined and may range from blocking, + unexpected watchdog reset to just wrong values. Often, this pull-up circuitry + is built-in already to the MCU board or sensor breakout boards, but there is + no rule for that. So please check in case of trouble. See also this excellent + `learning guide `_ + by Adafruit about I2C wiring. + Example usage:: from machine import I2C From 2488311dc2f5ef259a03b871620fd6d3f45a1086 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 26 Aug 2022 12:47:34 +0200 Subject: [PATCH 0346/1041] rp2/machine_uart: Implement uart.flush() and uart.txdone(). uart.flush() flush() will wait until all characters have been sent. It may return while the last character is sent. if needed, the calling code has to add one character wait time. To avoid a permanent lock, a timeout applies depending on the size of txbuf and the baud rate. ret = uart.txdone() ret is True if no transfer is in progress. It may return True if the last byte of a transfer is sent. ret is False otherwise. --- ports/rp2/machine_uart.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/ports/rp2/machine_uart.c b/ports/rp2/machine_uart.c index 77ccdb5f50..f7e44b6b25 100644 --- a/ports/rp2/machine_uart.c +++ b/ports/rp2/machine_uart.c @@ -435,17 +435,31 @@ STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { } 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) }, @@ -538,6 +552,19 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint if ((flags & MP_STREAM_POLL_WR) && ringbuf_free(&self->write_buffer) > 0) { ret |= MP_STREAM_POLL_WR; } + } else if (request == MP_STREAM_FLUSH) { + // The timeout is estimated using the buffer size and the baudrate. + // Take the worst case assumptions at 13 bit symbol size times 2. + 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) { + return 0; + } + MICROPY_EVENT_POLL_HOOK + } while (time_us_64() < timeout); + *errcode = MP_ETIMEDOUT; + ret = MP_STREAM_ERROR; } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; From 5466f1b0ea562548cd11cdbe31b5f71c97cf36f9 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 26 Aug 2022 15:21:48 +0200 Subject: [PATCH 0347/1041] esp32/machine_uart: Implement uart.flush() and uart.txdone(). uart.flush() flush() will wait until all characters have been sent.To avoid a permanent lock, a timeout applies depending on the size of txbuf and the baud rate. ret = uart.txdone() ret is True if no transfer is in progress. ret is False otherwise. --- ports/esp32/machine_uart.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/ports/esp32/machine_uart.c b/ports/esp32/machine_uart.c index 28110e39f3..7244591289 100644 --- a/ports/esp32/machine_uart.c +++ b/ports/esp32/machine_uart.c @@ -417,15 +417,28 @@ STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { } 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) }, @@ -491,6 +504,18 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr if ((flags & MP_STREAM_POLL_WR) && 1) { // FIXME: uart_tx_any_room(self->uart_num) ret |= MP_STREAM_POLL_WR; } + } else if (request == MP_STREAM_FLUSH) { + // The timeout is estimated using the buffer size and the baudrate. + // Take the worst case assumptions at 13 bit symbol size times 2. + uint32_t baudrate; + uart_get_baudrate(self->uart_num, &baudrate); + uint32_t timeout = (3 + self->txbuf) * 13000 * 2 / baudrate; + if (uart_wait_tx_done(self->uart_num, timeout) == ESP_OK) { + ret = 0; + } else { + *errcode = MP_ETIMEDOUT; + ret = MP_STREAM_ERROR; + } } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; From 49e17c8bb0c55d8efb3f768ba1dfd5b27c466b26 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 26 Aug 2022 15:49:59 +0200 Subject: [PATCH 0348/1041] mimxrt/machine_uart: Implement uart.flush() and uart.txdone(). uart.flush() flush() will wait until all characters have been sent.To avoid a permanent lock, a timeout applies depending on the size of txbuf and the baud rate. ret = uart.txdone() ret is True if no transfer is in progress. ret is False otherwise. --- ports/mimxrt/machine_uart.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/ports/mimxrt/machine_uart.c b/ports/mimxrt/machine_uart.c index 115d9226bf..302244f722 100644 --- a/ports/mimxrt/machine_uart.c +++ b/ports/mimxrt/machine_uart.c @@ -308,17 +308,30 @@ STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { } 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); + 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_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) }, @@ -433,6 +446,21 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint if ((flags & MP_STREAM_POLL_WR)) { ret |= MP_STREAM_POLL_WR; } + } else if (request == MP_STREAM_FLUSH) { + // The timeout is estimated using the buffer size and the baudrate. + // Take the worst case assumptions at 13 bit symbol size times 2. + uint64_t timeout = (uint64_t)(3 + self->txbuf_len) * 13000000ll * 2 / + self->config.baudRate_Bps + ticks_us64(); + + do { + if (machine_uart_txdone((mp_obj_t)self) == mp_const_true) { + return 0; + } + MICROPY_EVENT_POLL_HOOK + } while (ticks_us64() < timeout); + + *errcode = MP_ETIMEDOUT; + ret = MP_STREAM_ERROR; } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; From 8804993d0f5326fd71f137433a1b52199d65f119 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 26 Aug 2022 16:42:10 +0200 Subject: [PATCH 0349/1041] esp8266/machine_uart: Implement uart.flush() and uart.txdone(). uart.flush() flush() will wait until all characters but the last one have been sent. It returns while the last character is sent. If needed, the calling code has to add one character wait time. To avoid a permanent lock, a timeout applies depending on the size of the FIFO and the baud rate. ret = uart.txdone() ret is True if no transfer is in progress. It returns already True when the last byte of a transfer is sent. ret is False otherwise. --- ports/esp8266/machine_uart.c | 24 ++++++++++++++++++++++++ ports/esp8266/uart.c | 9 +++++++++ ports/esp8266/uart.h | 1 + 3 files changed, 34 insertions(+) diff --git a/ports/esp8266/machine_uart.c b/ports/esp8266/machine_uart.c index 4e88eee162..2fe6516dc7 100644 --- a/ports/esp8266/machine_uart.c +++ b/ports/esp8266/machine_uart.c @@ -231,10 +231,20 @@ STATIC mp_obj_t pyb_uart_any(mp_obj_t self_in) { } 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 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) }, @@ -305,6 +315,20 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t a if ((flags & MP_STREAM_POLL_WR) && uart_tx_any_room(self->uart_id)) { ret |= MP_STREAM_POLL_WR; } + } else if (request == MP_STREAM_FLUSH) { + // The timeout is estimated using the buffer size and the baudrate. + // Take the worst case assumptions at 13 bit symbol size times 2. + 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) { + return 0; + } + MICROPY_EVENT_POLL_HOOK + } while (system_get_time() < timeout); + + *errcode = MP_ETIMEDOUT; + ret = MP_STREAM_ERROR; } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; diff --git a/ports/esp8266/uart.c b/ports/esp8266/uart.c index 978a7efc38..117cd1bf6c 100644 --- a/ports/esp8266/uart.c +++ b/ports/esp8266/uart.c @@ -111,6 +111,15 @@ void uart_tx_one_char(uint8 uart, uint8 TxChar) { WRITE_PERI_REG(UART_FIFO(uart), TxChar); } +int uart_txdone(uint8 uart) { + uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S); + if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) == 0) { + return true; + } else { + return false; + } +} + void uart_flush(uint8 uart) { while (true) { uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S); diff --git a/ports/esp8266/uart.h b/ports/esp8266/uart.h index de0919bde0..3c5592ff0a 100644 --- a/ports/esp8266/uart.h +++ b/ports/esp8266/uart.h @@ -101,6 +101,7 @@ bool uart_rx_wait(uint32_t timeout_us); int uart_rx_char(void); void uart_tx_one_char(uint8 uart, uint8 TxChar); void uart_flush(uint8 uart); +int uart_txdone(uint8 uart); void uart_os_config(int uart); void uart_setup(uint8 uart); int uart0_get_rxbuf_len(void); From 8ea6fefc6d52ae46199a337064c05431f6dd30cb Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 26 Aug 2022 17:04:23 +0200 Subject: [PATCH 0350/1041] stm32/machine_uart: Implement uart.flush() and uart.txdone(). Since uart.write() of the STM32 port waits until all bytes have been sent, uart.flush() and uart.txdone() are implemented as empty functions to provide API consistency. uart.flush() flush() will always return immediately. ret = uart.txdone() uart.txdone() will always return True. --- ports/stm32/machine_uart.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index bf7bcfb9cd..1bb1d2a1a7 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -523,6 +523,12 @@ STATIC mp_obj_t pyb_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t * } 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 @@ -538,11 +544,13 @@ STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = { { 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) }, @@ -635,6 +643,9 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t a if ((flags & MP_STREAM_POLL_WR) && uart_tx_avail(self)) { ret |= MP_STREAM_POLL_WR; } + } else if (request == MP_STREAM_FLUSH) { + // Since uart.write() waits up to the last byte, uart.flush() always succeds. + ret = 0; } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; From cc0249c936091889c9f2bda0ecafc522e06364a3 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 26 Aug 2022 17:24:30 +0200 Subject: [PATCH 0351/1041] nrf/modules/machine/uart: Implement uart.flush() and uart.txdone(). Since uart.write() of the nrf port waits until all bytes but the last one have been sent, uart.flush() and uart.txdone() are implemented as empty functions to provide API consistency. uart.flush() flush() will always return immediately, even if the last byte may still be sent. ret = uart.txdone() uart.txdone() will always return True, even if the last byte may still be sent. --- ports/nrf/modules/machine/uart.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ports/nrf/modules/machine/uart.c b/ports/nrf/modules/machine/uart.c index e8c82e57dd..1fd2ccc06c 100644 --- a/ports/nrf/modules/machine/uart.c +++ b/ports/nrf/modules/machine/uart.c @@ -292,6 +292,12 @@ STATIC mp_obj_t machine_hard_uart_sendbreak(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hard_uart_sendbreak_obj, machine_hard_uart_sendbreak); +// 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 machine_hard_uart_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, @@ -302,6 +308,8 @@ STATIC const mp_rom_map_elem_t machine_hard_uart_locals_dict_table[] = { { 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 /* @@ -347,6 +355,11 @@ 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; (void)self; + + if (request == MP_STREAM_FLUSH) { + // Since uart.write() waits up to the last byte, uart.flush() always succeds. + return 0; + } return MP_STREAM_ERROR; } From a39b88f0fbffe802dc8a80980e6fd675c9ef5a65 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 26 Aug 2022 18:08:29 +0200 Subject: [PATCH 0352/1041] cc3200/mods/pybuart: Implement uart.flush() and uart.txdone(). uart.flush() flush() will wait until all characters have been sent. To avoid a permanent lock, a timeout applies depending on the size of FIFO and the baud rate. ret = uart.txdone() ret is True if no transfer is in progress. ret is False otherwise. --- ports/cc3200/mods/pybuart.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/ports/cc3200/mods/pybuart.c b/ports/cc3200/mods/pybuart.c index 6e774b70d9..a81954abb8 100644 --- a/ports/cc3200/mods/pybuart.c +++ b/ports/cc3200/mods/pybuart.c @@ -66,6 +66,7 @@ #define PYBUART_TX_MAX_TIMEOUT_MS (5) #define PYBUART_RX_BUFFER_LEN (256) +#define PYBUART_TX_BUFFER_LEN (17) // interrupt triggers #define UART_TRIGGER_RX_ANY (0x01) @@ -558,6 +559,17 @@ invalid_args: } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_irq_obj, 1, pyb_uart_irq); +STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) { + pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (MAP_UARTBusy(self->reg) == false) { + 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 pyb_uart_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) }, @@ -565,6 +577,7 @@ STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_uart_any_obj) }, { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&pyb_uart_sendbreak_obj) }, { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&pyb_uart_irq_obj) }, + { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) }, /// \method read([nbytes]) { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, @@ -574,6 +587,7 @@ STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = { { 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) }, // class constants { MP_ROM_QSTR(MP_QSTR_RX_ANY), MP_ROM_INT(UART_TRIGGER_RX_ANY) }, @@ -635,6 +649,21 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t a if ((flags & MP_STREAM_POLL_WR) && MAP_UARTSpaceAvail(self->reg)) { ret |= MP_STREAM_POLL_WR; } + } else if (request == MP_STREAM_FLUSH) { + // The timeout is estimated using the buffer size and the baudrate. + // Take the worst case assumptions at 13 bit symbol size times 2. + uint64_t timeout = mp_hal_ticks_ms() + + (PYBUART_TX_BUFFER_LEN) * 13000 * 2 / self->baudrate; + + do { + if (machine_uart_txdone((mp_obj_t)self) == mp_const_true) { + return 0; + } + MICROPY_EVENT_POLL_HOOK + } while (mp_hal_ticks_ms() < timeout); + + *errcode = MP_ETIMEDOUT; + ret = MP_STREAM_ERROR;; } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; From b74eeee5e0e2a6c1437072c7343ccf9a5e7b5aad Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 26 Aug 2022 20:37:43 +0200 Subject: [PATCH 0353/1041] docs/library/machine.UART: Add docs for uart.flush() and uart.txdone(). --- docs/library/machine.UART.rst | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/library/machine.UART.rst b/docs/library/machine.UART.rst index 1d54174c99..c3eca8f55a 100644 --- a/docs/library/machine.UART.rst +++ b/docs/library/machine.UART.rst @@ -177,6 +177,32 @@ Methods Availability: WiPy. +.. method:: UART.flush() + + Waits until all data has been sent. In case of a timeout, an exception is raised. The timeout + duration depends on the tx buffer size and the baud rate. Unless flow control is enabled, a timeout + should not occur. + + .. note:: + + For the rp2, esp8266 and nrf ports the call returns while the last byte is sent. + If required, a one character wait time has to be added in the calling script. + + Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports + +.. method:: UART.txdone() + + Tells whether all data has been sent or no data transfer is happening. In this case, + it returns ``True``. If a data transmission is ongoing it returns ``False``. + + .. note:: + + For the rp2, esp8266 and nrf ports the call may return ``True`` even if the last byte + of a transfer is still being sent. If required, a one character wait time has to be + added in the calling script. + + Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports + Constants --------- From 85a25895ffc17b6034f4348e26c6248c34be8324 Mon Sep 17 00:00:00 2001 From: hoihu Date: Mon, 29 Aug 2022 08:00:37 +0200 Subject: [PATCH 0354/1041] rp2/mbedtls: Fix missing time.h include. --- ports/rp2/mbedtls/mbedtls_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/rp2/mbedtls/mbedtls_config.h b/ports/rp2/mbedtls/mbedtls_config.h index 743d0a6a84..c80aa5bc18 100644 --- a/ports/rp2/mbedtls/mbedtls_config.h +++ b/ports/rp2/mbedtls/mbedtls_config.h @@ -106,6 +106,7 @@ void m_tracked_free(void *ptr); #define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf // Time hook +#include time_t rp2_rtctime_seconds(time_t *timer); #define MBEDTLS_PLATFORM_TIME_MACRO rp2_rtctime_seconds From 621bff8557c7a7e35cdc9f6c6de0e6c912d94202 Mon Sep 17 00:00:00 2001 From: Takeo Takahashi Date: Thu, 23 Jun 2022 22:27:47 +0900 Subject: [PATCH 0355/1041] renesas-ra/machine_pin: Support drive keyword and fix GPIO setting. Changes are: - Support drive= keyword argument. - Fix trigger keyword check. - Fix GPIO pin setting. Signed-off-by: Takeo Takahashi --- .../boards/RA4M1_CLICKER/mpconfigboard.h | 4 +- .../boards/RA4M1_EK/mpconfigboard.h | 4 +- .../boards/RA4W1_EK/mpconfigboard.h | 4 +- .../boards/RA6M1_EK/mpconfigboard.h | 4 +- .../boards/RA6M2_EK/mpconfigboard.h | 4 +- ports/renesas-ra/extint.c | 30 ++-- ports/renesas-ra/machine_pin.c | 132 +++++++++++------- ports/renesas-ra/mphalport.h | 12 +- ports/renesas-ra/ra/ra_gpio.c | 59 ++++---- ports/renesas-ra/ra/ra_gpio.h | 57 ++++---- ports/renesas-ra/ra/ra_i2c.c | 4 +- ports/renesas-ra/ra/ra_sci.c | 8 +- ports/renesas-ra/ra/ra_spi.c | 4 +- ports/renesas-ra/usrsw.c | 2 +- 14 files changed, 177 insertions(+), 151 deletions(-) diff --git a/ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h b/ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h index ec67d68b65..f39cf8f80e 100644 --- a/ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h +++ b/ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h @@ -47,8 +47,8 @@ // Switch #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_USRSW_PIN (pin_P304) -#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) -#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) +#define MICROPY_HW_USRSW_PULL (MP_HAL_PIN_PULL_NONE) +#define MICROPY_HW_USRSW_EXTI_MODE (MP_HAL_PIN_TRIGGER_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // LEDs diff --git a/ports/renesas-ra/boards/RA4M1_EK/mpconfigboard.h b/ports/renesas-ra/boards/RA4M1_EK/mpconfigboard.h index 500fe78b9e..2874142890 100644 --- a/ports/renesas-ra/boards/RA4M1_EK/mpconfigboard.h +++ b/ports/renesas-ra/boards/RA4M1_EK/mpconfigboard.h @@ -59,8 +59,8 @@ // Switch #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_USRSW_PIN (pin_P105) -#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) -#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) +#define MICROPY_HW_USRSW_PULL (MP_HAL_PIN_PULL_NONE) +#define MICROPY_HW_USRSW_EXTI_MODE (MP_HAL_PIN_TRIGGER_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // LEDs diff --git a/ports/renesas-ra/boards/RA4W1_EK/mpconfigboard.h b/ports/renesas-ra/boards/RA4W1_EK/mpconfigboard.h index 0e0dff1475..0bf907a48c 100644 --- a/ports/renesas-ra/boards/RA4W1_EK/mpconfigboard.h +++ b/ports/renesas-ra/boards/RA4W1_EK/mpconfigboard.h @@ -58,8 +58,8 @@ // Switch #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_USRSW_PIN (pin_P402) -#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) -#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) +#define MICROPY_HW_USRSW_PULL (MP_HAL_PIN_PULL_NONE) +#define MICROPY_HW_USRSW_EXTI_MODE (MP_HAL_PIN_TRIGGER_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // LEDs diff --git a/ports/renesas-ra/boards/RA6M1_EK/mpconfigboard.h b/ports/renesas-ra/boards/RA6M1_EK/mpconfigboard.h index 0693e404fd..59db4bc218 100644 --- a/ports/renesas-ra/boards/RA6M1_EK/mpconfigboard.h +++ b/ports/renesas-ra/boards/RA6M1_EK/mpconfigboard.h @@ -64,8 +64,8 @@ // Switch #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_USRSW_PIN (pin_P415) -#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) -#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) +#define MICROPY_HW_USRSW_PULL (MP_HAL_PIN_PULL_NONE) +#define MICROPY_HW_USRSW_EXTI_MODE (MP_HAL_PIN_TRIGGER_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // LEDs diff --git a/ports/renesas-ra/boards/RA6M2_EK/mpconfigboard.h b/ports/renesas-ra/boards/RA6M2_EK/mpconfigboard.h index 2d2dc326d3..9988e0ed25 100644 --- a/ports/renesas-ra/boards/RA6M2_EK/mpconfigboard.h +++ b/ports/renesas-ra/boards/RA6M2_EK/mpconfigboard.h @@ -77,8 +77,8 @@ // Switch #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_USRSW_PIN (pin_P105) -#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) -#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) +#define MICROPY_HW_USRSW_PULL (MP_HAL_PIN_PULL_NONE) +#define MICROPY_HW_USRSW_EXTI_MODE (MP_HAL_PIN_TRIGGER_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // LEDs diff --git a/ports/renesas-ra/extint.c b/ports/renesas-ra/extint.c index 19caa7a3b3..59f9ecfa37 100644 --- a/ports/renesas-ra/extint.c +++ b/ports/renesas-ra/extint.c @@ -138,8 +138,8 @@ uint extint_register(mp_obj_t pin_obj, uint32_t mode, uint32_t pull, mp_obj_t ca mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("The Pin object(%d) doesn't have EXTINT feature"), pin_idx); } } - if (pull != GPIO_NOPULL && - pull != GPIO_PULLUP) { + if ((pull != MP_HAL_PIN_PULL_NONE) && + (pull != MP_HAL_PIN_PULL_UP)) { mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid ExtInt Pull: %d"), pull); } mp_obj_t *cb = &MP_STATE_PORT(pyb_extint_callback)[v_line]; @@ -153,7 +153,6 @@ uint extint_register(mp_obj_t pin_obj, uint32_t mode, uint32_t pull, mp_obj_t ca extint_disable(v_line); *cb = callback_obj; - // ToDo: mode should be handled pyb_extint_mode[v_line] = mode; pyb_extint_callback_arg[v_line] = MP_OBJ_NEW_SMALL_INT(v_line); if (*cb != mp_const_none) { @@ -200,7 +199,6 @@ void extint_register_pin(const machine_pin_obj_t *pin, uint32_t mode, bool hard_ extint_disable(line); *cb = callback_obj; - // ToDo: mode should be handled pyb_extint_mode[line] = mode; if (*cb != mp_const_none) { @@ -255,16 +253,16 @@ void extint_trigger_mode(uint line, uint32_t mode) { // cond: 0: falling, 1: rising, 2: both edge, 3 low level // Enable or disable the rising detector uint32_t cond = 0; - if ((mode == GPIO_MODE_IT_RISING) || (mode == GPIO_MODE_EVT_RISING)) { - cond = 1; - } else if ((mode == GPIO_MODE_IT_FALLING) || (mode == GPIO_MODE_EVT_FALLING)) { - cond = 0; - } else if ((mode == GPIO_MODE_IT_RISING_FALLING) || (mode == GPIO_MODE_EVT_RISING_FALLING)) { - cond = 2; - } else if (mode == GPIO_IRQ_LOWLEVEL) { + if (mode & MP_HAL_PIN_TRIGGER_LOWLEVEL) { cond = 3; + } else if (mode & MP_HAL_PIN_TRIGGER_FALLING) { + if (mode & MP_HAL_PIN_TRIGGER_RISING) { + cond = 2; + } else { + cond = 0; + } } else { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("The device doesn't have (%d) feature"), (uint32_t)mode); + cond = 1; } ra_icu_trigger_irq_no((uint8_t)line, cond); enable_irq(irq_state); @@ -372,14 +370,6 @@ STATIC const mp_rom_map_elem_t extint_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&extint_obj_disable_obj) }, { MP_ROM_QSTR(MP_QSTR_swint), MP_ROM_PTR(&extint_obj_swint_obj) }, { MP_ROM_QSTR(MP_QSTR_regs), MP_ROM_PTR(&extint_regs_obj) }, - - // class constants - /// \constant IRQ_RISING - interrupt on a rising edge - /// \constant IRQ_FALLING - interrupt on a falling edge - /// \constant IRQ_RISING_FALLING - interrupt on a rising or falling edge - { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_MODE_IT_RISING) }, - { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_MODE_IT_FALLING) }, - { MP_ROM_QSTR(MP_QSTR_IRQ_RISING_FALLING), MP_ROM_INT(GPIO_MODE_IT_RISING_FALLING) }, }; STATIC MP_DEFINE_CONST_DICT(extint_locals_dict, extint_locals_dict_table); diff --git a/ports/renesas-ra/machine_pin.c b/ports/renesas-ra/machine_pin.c index 6e852e9cbf..f940b55547 100644 --- a/ports/renesas-ra/machine_pin.c +++ b/ports/renesas-ra/machine_pin.c @@ -78,7 +78,7 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin uint32_t mode = pin_get_mode(self); - if (mode == GPIO_MODE_ANALOG) { + if (mode == MP_HAL_PIN_MODE_ANALOG) { // analog mp_print_str(print, "ANALOG)"); @@ -86,15 +86,15 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin // IO mode bool af = false; qstr mode_qst; - if (mode == GPIO_MODE_INPUT) { + if (mode == MP_HAL_PIN_MODE_INPUT) { mode_qst = MP_QSTR_IN; - } else if (mode == GPIO_MODE_OUTPUT_PP) { + } else if (mode == MP_HAL_PIN_MODE_OUTPUT) { mode_qst = MP_QSTR_OUT; - } else if (mode == GPIO_MODE_OUTPUT_OD) { + } else if (mode == MP_HAL_PIN_MODE_OPEN_DRAIN) { mode_qst = MP_QSTR_OPEN_DRAIN; } else { af = true; - if (mode == GPIO_MODE_AF_PP) { + if (mode == MP_HAL_PIN_MODE_ALT) { mode_qst = MP_QSTR_ALT; } else { mode_qst = MP_QSTR_ALT_OPEN_DRAIN; @@ -105,9 +105,9 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin // pull mode qstr pull_qst = MP_QSTRnull; uint32_t pull = pin_get_pull(self); - if (pull == GPIO_PULLUP) { + if (pull == MP_HAL_PIN_PULL_UP) { pull_qst = MP_QSTR_PULL_UP; - } else if (pull == GPIO_NOPULL) { + } else if (pull == MP_HAL_PIN_PULL_NONE) { pull_qst = MP_QSTR_PULL_NONE; } if (pull_qst != MP_QSTRnull) { @@ -117,12 +117,14 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin // drive qstr drive_qst = MP_QSTRnull; uint32_t drive = pin_get_drive(self); - if (drive == GPIO_HIGH_POWER) { - drive_qst = MP_QSTR_HIGH_POWER; - } else if (drive == GPIO_MED_POWER) { - drive_qst = MP_QSTR_MED_POWER; - } else if (drive == GPIO_LOW_POWER) { - drive_qst = MP_QSTR_LOW_POWER; + if (drive == MP_HAL_PIN_DRIVE_3) { + drive_qst = MP_QSTR_DRIVE_3; + } else if (drive == MP_HAL_PIN_DRIVE_2) { + drive_qst = MP_QSTR_DRIVE_2; + } else if (drive == MP_HAL_PIN_DRIVE_1) { + drive_qst = MP_QSTR_DRIVE_1; + } else if (drive == MP_HAL_PIN_DRIVE_0) { + drive_qst = MP_QSTR_DRIVE_0; } if (drive_qst != MP_QSTRnull) { mp_printf(print, ", drive=Pin.%q", drive_qst); @@ -143,14 +145,14 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin } } -// pin.init(mode, pull=None, *, value=None, driver=None, alt=FUNC_SIO) +// pin.init(mode=-1, pull=-1, *, value=None, drive=0, alt=-1) STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_mode, ARG_pull, ARG_value, ARG_drive, ARG_alt }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, { MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, - { MP_QSTR_af, MP_ARG_INT, {.u_int = -1}}, // legacy - { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, - { MP_QSTR_drive, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = GPIO_LOW_POWER}}, + { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, + { MP_QSTR_drive, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, { MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}}, }; @@ -159,29 +161,50 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get io mode - uint mode = args[0].u_int; - if (!IS_GPIO_MODE(mode)) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid pin mode: %d"), mode); + uint32_t mode; + if (args[ARG_mode].u_obj != mp_const_none) { + mode = mp_obj_get_int(args[ARG_mode].u_obj); + if (!IS_GPIO_MODE(mode)) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid pin mode: %d"), mode); + } + } else { + mode = ra_gpio_get_mode(self->pin); } // get pull mode - uint pull = 0; - if (args[1].u_obj != mp_const_none) { - pull = mp_obj_get_int(args[1].u_obj); + uint32_t pull; + if (args[ARG_pull].u_obj != mp_const_none) { + pull = mp_obj_get_int(args[ARG_pull].u_obj); + if (!IS_GPIO_PULL(pull)) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid pull mode: %d"), pull); + } + if (pull == MP_HAL_PIN_PULL_DOWN) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%q is not supported"), MP_QSTR_PULL_DOWN); + } + } else { + pull = ra_gpio_get_pull(self->pin); } // get drive - uint drive = args[4].u_int; - if (!IS_GPIO_DRIVE(drive)) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid pin drive: %d"), drive); + uint32_t drive; + if (args[ARG_drive].u_obj != mp_const_none) { + drive = mp_obj_get_int(args[ARG_drive].u_obj); + if (!IS_GPIO_DRIVE(drive)) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid pin drive: %d"), drive); + } + } else { + drive = ra_gpio_get_drive(self->pin); } - mp_hal_pin_config(self, mode, pull, drive, -1); + // get alt + if (args[ARG_alt].u_int != (-1)) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("alt is not supported")); + } + mp_hal_pin_config(self, mode, pull, drive, 0); // if given, set the pin value before initialising to prevent glitches - if (args[3].u_obj != MP_OBJ_NULL) { - mp_hal_pin_write(self, mp_obj_is_true(args[3].u_obj)); + if (args[ARG_value].u_obj != mp_const_none) { + mp_hal_pin_write(self, mp_obj_is_true(args[ARG_value].u_obj)); } - return mp_const_none; } @@ -249,13 +272,17 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_ enum { ARG_handler, ARG_trigger, ARG_hard }; static const mp_arg_t allowed_args[] = { { MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, - { MP_QSTR_trigger, MP_ARG_INT, {.u_int = GPIO_MODE_IT_RISING | GPIO_MODE_IT_FALLING} }, + { MP_QSTR_trigger, MP_ARG_INT, {.u_int = MP_HAL_PIN_TRIGGER_RISING | MP_HAL_PIN_TRIGGER_FALLING} }, { MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} }, }; machine_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + if (args[ARG_trigger].u_int & MP_HAL_PIN_TRIGGER_HIGHLEVEL) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%q is not supported"), MP_QSTR_IRQ_HIGH_LEVEL); + } + if (n_args > 1 || kw_args->used != 0) { // configure irq extint_register_pin(self, args[ARG_trigger].u_int, @@ -282,27 +309,23 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_cpu), MP_ROM_PTR(&pin_cpu_pins_obj_type) }, // class constants - { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_INPUT) }, - { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_OUTPUT_PP) }, - { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_OUTPUT_OD) }, - { MP_ROM_QSTR(MP_QSTR_ALT), MP_ROM_INT(GPIO_MODE_AF_PP) }, - { MP_ROM_QSTR(MP_QSTR_ALT_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_AF_OD) }, - { MP_ROM_QSTR(MP_QSTR_ANALOG), MP_ROM_INT(GPIO_MODE_ANALOG) }, - { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULLUP) }, - { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULLDOWN) }, - { MP_ROM_QSTR(MP_QSTR_PULL_HOLD), MP_ROM_INT(GPIO_PULLHOLD) }, - { MP_ROM_QSTR(MP_QSTR_PULL_NONE), MP_ROM_INT(GPIO_NOPULL) }, - { MP_ROM_QSTR(MP_QSTR_LOW_POWER), MP_ROM_INT(GPIO_LOW_POWER) }, - { MP_ROM_QSTR(MP_QSTR_MED_POWER), MP_ROM_INT(GPIO_MED_POWER) }, - { MP_ROM_QSTR(MP_QSTR_HIGH_POWER), MP_ROM_INT(GPIO_HIGH_POWER) }, - { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_MODE_IT_RISING) }, - { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_MODE_IT_FALLING) }, - { MP_ROM_QSTR(MP_QSTR_IRQ_RISING_FALLING), MP_ROM_INT(GPIO_MODE_IT_RISING_FALLING) }, - { MP_ROM_QSTR(MP_QSTR_EVT_RISING), MP_ROM_INT(GPIO_MODE_EVT_RISING) }, - { MP_ROM_QSTR(MP_QSTR_EVT_FALLING), MP_ROM_INT(GPIO_MODE_EVT_FALLING) }, - { MP_ROM_QSTR(MP_QSTR_EVT_RISING_FALLING), MP_ROM_INT(GPIO_MODE_EVT_RISING_FALLING) }, - { MP_ROM_QSTR(MP_QSTR_IRQ_LOWLEVEL), MP_ROM_INT(GPIO_IRQ_LOWLEVEL) }, - { MP_ROM_QSTR(MP_QSTR_IRQ_HIGHLEVEL), MP_ROM_INT(GPIO_IRQ_HIGHLEVEL) }, + { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(MP_HAL_PIN_MODE_INPUT) }, + { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(MP_HAL_PIN_MODE_OUTPUT) }, + { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(MP_HAL_PIN_MODE_OPEN_DRAIN) }, + { MP_ROM_QSTR(MP_QSTR_ALT), MP_ROM_INT(MP_HAL_PIN_MODE_ALT) }, + { MP_ROM_QSTR(MP_QSTR_ALT_OPEN_DRAIN), MP_ROM_INT(MP_HAL_PIN_MODE_ALT_OPEN_DRAIN) }, + { MP_ROM_QSTR(MP_QSTR_ANALOG), MP_ROM_INT(MP_HAL_PIN_MODE_ANALOG) }, + { MP_ROM_QSTR(MP_QSTR_PULL_NONE), MP_ROM_INT(MP_HAL_PIN_PULL_NONE) }, + { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(MP_HAL_PIN_PULL_UP) }, + { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(MP_HAL_PIN_PULL_DOWN) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_0), MP_ROM_INT(MP_HAL_PIN_DRIVE_0) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_1), MP_ROM_INT(MP_HAL_PIN_DRIVE_1) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_2), MP_ROM_INT(MP_HAL_PIN_DRIVE_2) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_3), MP_ROM_INT(MP_HAL_PIN_DRIVE_3) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(MP_HAL_PIN_TRIGGER_FALLING) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(MP_HAL_PIN_TRIGGER_RISING) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_LOW_LEVEL), MP_ROM_INT(MP_HAL_PIN_TRIGGER_LOWLEVEL) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_HIGH_LEVEL), MP_ROM_INT(MP_HAL_PIN_TRIGGER_HIGHLEVEL) }, }; STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table); @@ -352,7 +375,8 @@ uint32_t pin_get_pull(const machine_pin_obj_t *pin) { } // Returns the pin drive. The value returned by this macro should -// be one of GPIO_HIGH_POWER, GPIO_MED_POWER, or GPIO_LOW_POWER. +// be one of GPIO_HIGH_POWER, GPIO_MID_FAST_POWER, GPIO_MID_POWER, +// or GPIO_LOW_POWER. uint32_t pin_get_drive(const machine_pin_obj_t *pin) { return (uint32_t)ra_gpio_get_drive(pin->pin); diff --git a/ports/renesas-ra/mphalport.h b/ports/renesas-ra/mphalport.h index c489d1b966..2648e22f99 100644 --- a/ports/renesas-ra/mphalport.h +++ b/ports/renesas-ra/mphalport.h @@ -4,7 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2018 Damien P. George - * Copyright (c) 2021 Renesas Electronics Corporation + * Copyright (c) 2021-2022 Renesas Electronics Corporation * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -69,13 +69,21 @@ static inline mp_uint_t mp_hal_ticks_cpu(void) { #define MP_HAL_PIN_PULL_NONE (GPIO_NOPULL) #define MP_HAL_PIN_PULL_UP (GPIO_PULLUP) #define MP_HAL_PIN_PULL_DOWN (GPIO_PULLDOWN) +#define MP_HAL_PIN_TRIGGER_FALLING (GPIO_IRQ_FALLING) +#define MP_HAL_PIN_TRIGGER_RISING (GPIO_IRQ_RISING) +#define MP_HAL_PIN_TRIGGER_LOWLEVEL (GPIO_IRQ_LOWLEVEL) +#define MP_HAL_PIN_TRIGGER_HIGHLEVEL (GPIO_IRQ_HIGHLEVEL) +#define MP_HAL_PIN_DRIVE_0 (GPIO_LOW_POWER) +#define MP_HAL_PIN_DRIVE_1 (GPIO_MID_POWER) +#define MP_HAL_PIN_DRIVE_2 (GPIO_MID_FAST_POWER) +#define MP_HAL_PIN_DRIVE_3 (GPIO_HIGH_POWER) #define mp_hal_pin_obj_t const machine_pin_obj_t * #define mp_hal_get_pin_obj(o) machine_pin_find(o) #define mp_hal_pin_name(p) ((p)->name) #define mp_hal_pin_input(p) ra_gpio_mode_input((p)->pin) #define mp_hal_pin_output(p) ra_gpio_mode_output((p)->pin) -#define mp_hal_pin_open_drain(p) ra_gpio_config((p)->pin, GPIO_MODE_OUTPUT_OD, 0, 0, 0) +#define mp_hal_pin_open_drain(p) ra_gpio_config((p)->pin, MP_HAL_PIN_MODE_OPEN_DRAIN, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_DRIVE_0, 0) #define mp_hal_pin_high(p) ra_gpio_write((p)->pin, 1) #define mp_hal_pin_low(p) ra_gpio_write((p)->pin, 0) #define mp_hal_pin_toggle(p) ra_gpio_toggle((p)->pin) diff --git a/ports/renesas-ra/ra/ra_gpio.c b/ports/renesas-ra/ra/ra_gpio.c index 598546cb93..a01131953c 100644 --- a/ports/renesas-ra/ra/ra_gpio.c +++ b/ports/renesas-ra/ra/ra_gpio.c @@ -31,23 +31,17 @@ void ra_gpio_config(uint32_t pin, uint32_t mode, uint32_t pull, uint32_t drive, uint32_t port = GPIO_PORT(pin); uint32_t bit = GPIO_BIT(pin); pwpr_unprotect(); + _PXXPFS(port, bit) &= ~(PMR_MASK | ASEL_MASK | NCODR_MASK | PCR_MASK | PDR_MASK | DSCR1_MASK | DSCR_MASK); switch (mode) { case GPIO_MODE_INPUT: - _PXXPFS(port, bit) &= ~(PMR_MASK | ASEL_MASK); // GPIO - _PXXPFS(port, bit) &= ~PDR_MASK; // input - if (pull != 0) { + if (pull == GPIO_PULLUP) { _PXXPFS(port, bit) |= PCR_MASK; // set pullup - } else { - _PXXPFS(port, bit) &= ~PCR_MASK; // clear pullup } break; case GPIO_MODE_OUTPUT_PP: - _PXXPFS(port, bit) &= ~(PMR_MASK | ASEL_MASK); // GPIO _PXXPFS(port, bit) |= PDR_MASK; // output - _PXXPFS(port, bit) &= ~PCR_MASK; // pullup clear break; case GPIO_MODE_OUTPUT_OD: - _PXXPFS(port, bit) &= ~(PMR_MASK | ASEL_MASK); // GPIO _PXXPFS(port, bit) |= (PDR_MASK | NCODR_MASK); break; case GPIO_MODE_AF_PP: @@ -56,20 +50,23 @@ void ra_gpio_config(uint32_t pin, uint32_t mode, uint32_t pull, uint32_t drive, case GPIO_MODE_AF_OD: _PXXPFS(port, bit) |= (PMR_MASK | PDR_MASK | NCODR_MASK); break; + case GPIO_MODE_ANALOG: + _PXXPFS(port, bit) |= ASEL_MASK; + break; } switch (drive) { case GPIO_HIGH_POWER: _PXXPFS(port, bit) |= (DSCR1_MASK | DSCR_MASK); break; - case GPIO_MED_POWER: - _PXXPFS(port, bit) &= ~DSCR1_MASK; + case GPIO_MID_FAST_POWER: + _PXXPFS(port, bit) |= DSCR1_MASK; + break; + case GPIO_MID_POWER: _PXXPFS(port, bit) |= DSCR_MASK; break; case GPIO_LOW_POWER: - _PXXPFS(port, bit) &= ~(DSCR1_MASK | DSCR_MASK); - break; - default: /* GPIO_NOTOUCH_POWER */ - /* do not modify */ + default: + /* Bits are already cleared */ break; } _PXXPFS(port, bit) &= ~(uint32_t)(0x1f000000); @@ -102,7 +99,6 @@ void ra_gpio_toggle(uint32_t pin) { uint32_t port = GPIO_PORT(pin); uint32_t bit = GPIO_BIT(pin); pwpr_unprotect(); - _PXXPFS(port, bit) &= ~(PMR_MASK | ASEL_MASK); // GPIO _PXXPFS(port, bit) ^= 1; pwpr_protect(); } @@ -111,7 +107,6 @@ void ra_gpio_write(uint32_t pin, uint32_t value) { uint32_t port = GPIO_PORT(pin); uint32_t bit = GPIO_BIT(pin); pwpr_unprotect(); - _PXXPFS(port, bit) &= ~(PMR_MASK | ASEL_MASK); // GPIO if (value != 0) { _PXXPFS(port, bit) |= 1; } else { @@ -123,15 +118,26 @@ void ra_gpio_write(uint32_t pin, uint32_t value) { uint32_t ra_gpio_read(uint32_t pin) { uint32_t port = GPIO_PORT(pin); uint32_t bit = GPIO_BIT(pin); - return ((_PXXPFS(port, bit) &= PIDR_MASK) != 0) ? 1 : 0; + return ((_PXXPFS(port, bit) & PIDR_MASK) != 0) ? 1 : 0; } uint32_t ra_gpio_get_mode(uint32_t pin) { uint8_t mode = 0; - uint32_t port = GPIO_PORT(pin); - uint32_t bit = GPIO_BIT(pin); - if ((_PXXPFS(port, bit) &= PDR_MASK) != 0) { - mode = GPIO_MODE_OUTPUT_PP; + uint32_t pfs = _PXXPFS(GPIO_PORT(pin), GPIO_BIT(pin)); + if ((pfs & ASEL_MASK) != 0) { + mode = GPIO_MODE_ANALOG; + } else if ((pfs & PMR_MASK) != 0) { + if ((pfs & NCODR_MASK) != 0) { + mode = GPIO_MODE_AF_OD; + } else { + mode = GPIO_MODE_AF_PP; + } + } else if ((pfs & PDR_MASK) != 0) { + if ((pfs & NCODR_MASK) != 0) { + mode = GPIO_MODE_OUTPUT_OD; + } else { + mode = GPIO_MODE_OUTPUT_PP; + } } else { mode = GPIO_MODE_INPUT; } @@ -142,7 +148,7 @@ uint32_t ra_gpio_get_pull(uint32_t pin) { uint8_t pull = 0; uint32_t port = GPIO_PORT(pin); uint32_t bit = GPIO_BIT(pin); - if ((_PXXPFS(port, bit) &= PCR_MASK) != 0) { + if ((_PXXPFS(port, bit) & PCR_MASK) != 0) { pull = GPIO_PULLUP; } else { pull = GPIO_NOPULL; @@ -153,19 +159,22 @@ uint32_t ra_gpio_get_pull(uint32_t pin) { uint32_t ra_gpio_get_af(uint32_t pin) { uint32_t port = GPIO_PORT(pin); uint32_t bit = GPIO_BIT(pin); - return (_PXXPFS(port, bit) &= PMR_MASK) != 0; + return (_PXXPFS(port, bit) & PMR_MASK) != 0; } uint32_t ra_gpio_get_drive(uint32_t pin) { uint8_t drive = 0; uint32_t port = GPIO_PORT(pin); uint32_t bit = GPIO_BIT(pin); - switch (_PXXPFS(port, bit) &= (DSCR1_MASK | DSCR_MASK)) { + switch (_PXXPFS(port, bit) & (DSCR1_MASK | DSCR_MASK)) { case (DSCR1_MASK | DSCR_MASK): drive = GPIO_HIGH_POWER; break; + case DSCR1_MASK: + drive = GPIO_MID_FAST_POWER; + break; case DSCR_MASK: - drive = GPIO_MED_POWER; + drive = GPIO_MID_POWER; break; case 0: default: diff --git a/ports/renesas-ra/ra/ra_gpio.h b/ports/renesas-ra/ra/ra_gpio.h index 7b76016635..8c16fe3ba1 100644 --- a/ports/renesas-ra/ra/ra_gpio.h +++ b/ports/renesas-ra/ra/ra_gpio.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2021 Renesas Electronics Corporation + * Copyright (c) 2021,2022 Renesas Electronics Corporation * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -69,47 +69,42 @@ enum AF_INDEX { AF_END = 0xff, }; -#define GPIO_MODE_INPUT 1 -#define GPIO_MODE_OUTPUT_PP 2 -#define GPIO_MODE_OUTPUT_OD 3 -#define GPIO_MODE_AF_PP 4 -#define GPIO_MODE_AF_OD 5 -#define GPIO_MODE_ANALOG 6 -#define GPIO_MODE_IT_RISING 7 -#define GPIO_MODE_IT_FALLING 8 -#define GPIO_MODE_IT_RISING_FALLING 9 -#define GPIO_MODE_EVT_RISING 10 -#define GPIO_MODE_EVT_FALLING 11 -#define GPIO_MODE_EVT_RISING_FALLING 12 -#define GPIO_NOPULL 13 -#define GPIO_PULLUP 14 -#define GPIO_PULLDOWN 15 -#define GPIO_PULLHOLD 16 -#define GPIO_LOW_POWER 17 -#define GPIO_MED_POWER 18 -#define GPIO_HIGH_POWER 19 -#define GPIO_NOTOUCH_POWER 20 -#define GPIO_IRQ_LOWLEVEL 21 -#define GPIO_IRQ_HIGHLEVEL 22 +#define GPIO_MODE_INPUT 0 +#define GPIO_MODE_OUTPUT_PP 1 +#define GPIO_MODE_OUTPUT_OD 2 +#define GPIO_MODE_AF_PP 3 +#define GPIO_MODE_AF_OD 4 +#define GPIO_MODE_ANALOG 5 + +#define GPIO_IRQ_FALLING 0x1 +#define GPIO_IRQ_RISING 0x2 +#define GPIO_IRQ_LOWLEVEL 0x4 +#define GPIO_IRQ_HIGHLEVEL 0x8 + +#define GPIO_NOPULL 0 +#define GPIO_PULLUP 1 +#define GPIO_PULLDOWN 2 + +#define GPIO_LOW_POWER 0 +#define GPIO_MID_POWER 1 +#define GPIO_MID_FAST_POWER 2 +#define GPIO_HIGH_POWER 3 #define IS_GPIO_MODE(MODE) (((MODE) == GPIO_MODE_INPUT) || \ ((MODE) == GPIO_MODE_OUTPUT_PP) || \ ((MODE) == GPIO_MODE_OUTPUT_OD) || \ ((MODE) == GPIO_MODE_AF_PP) || \ ((MODE) == GPIO_MODE_AF_OD) || \ - ((MODE) == GPIO_MODE_IT_RISING) || \ - ((MODE) == GPIO_MODE_IT_FALLING) || \ - ((MODE) == GPIO_MODE_IT_RISING_FALLING) || \ - ((MODE) == GPIO_MODE_EVT_RISING) || \ - ((MODE) == GPIO_MODE_EVT_FALLING) || \ - ((MODE) == GPIO_MODE_EVT_RISING_FALLING) || \ ((MODE) == GPIO_MODE_ANALOG)) #define IS_GPIO_DRIVE(DRIVE) (((DRIVE) == GPIO_LOW_POWER) || \ - ((DRIVE) == GPIO_MED_POWER) || \ + ((DRIVE) == GPIO_MID_POWER) || \ + ((DRIVE) == GPIO_MID_FAST_POWER) || \ ((DRIVE) == GPIO_HIGH_POWER)) -#define IS_GPIO_PULL(PULL) (((PULL) == GPIO_NOPULL) || ((PULL) == GPIO_PULLUP)) +#define IS_GPIO_PULL(PULL) (((PULL) == GPIO_NOPULL) || \ + ((PULL) == GPIO_PULLUP) || \ + ((PULL) == GPIO_PULLDOWN)) #define IS_GPIO_AF(AF) ((AF) <= (uint8_t)0x1F) diff --git a/ports/renesas-ra/ra/ra_i2c.c b/ports/renesas-ra/ra/ra_i2c.c index 64bbd6f501..ad1e3a74e0 100644 --- a/ports/renesas-ra/ra/ra_i2c.c +++ b/ports/renesas-ra/ra/ra_i2c.c @@ -362,8 +362,8 @@ void ra_i2c_set_baudrate(R_IIC0_Type *i2c_inst, uint32_t baudrate) { void ra_i2c_init(R_IIC0_Type *i2c_inst, uint32_t scl, uint32_t sda, uint32_t baudrate) { ra_i2c_module_start(i2c_inst); - ra_gpio_config(scl, GPIO_MODE_AF_OD, 0, GPIO_NOTOUCH_POWER, AF_I2C); - ra_gpio_config(sda, GPIO_MODE_AF_OD, 0, GPIO_NOTOUCH_POWER, AF_I2C); + ra_gpio_config(scl, GPIO_MODE_AF_OD, GPIO_NOPULL, GPIO_LOW_POWER, AF_I2C); + ra_gpio_config(sda, GPIO_MODE_AF_OD, GPIO_NOPULL, GPIO_LOW_POWER, AF_I2C); ra_i2c_priority(i2c_inst, RA_PRI_I2C); i2c_inst->ICCR1_b.ICE = 0; // I2C disable i2c_inst->ICCR1_b.IICRST = 1; // I2C internal reset diff --git a/ports/renesas-ra/ra/ra_sci.c b/ports/renesas-ra/ra/ra_sci.c index 8cf26680cc..2e7c81c4ac 100644 --- a/ports/renesas-ra/ra/ra_sci.c +++ b/ports/renesas-ra/ra/ra_sci.c @@ -788,7 +788,7 @@ static void ra_sci_tx_set_pin(uint32_t pin) { uint32_t af; find = ra_af_find_ch_af((ra_af_pin_t *)&ra_sci_tx_pins, SCI_TX_PINS_SIZE, pin, &ch, &af); if (find) { - ra_gpio_config(pin, GPIO_MODE_AF_PP, 0, 0, af); + ra_gpio_config(pin, GPIO_MODE_AF_PP, GPIO_NOPULL, GPIO_LOW_POWER, af); } } @@ -798,7 +798,7 @@ static void ra_sci_rx_set_pin(uint32_t pin) { uint32_t af; find = ra_af_find_ch_af((ra_af_pin_t *)&ra_sci_rx_pins, SCI_RX_PINS_SIZE, pin, &ch, &af); if (find) { - ra_gpio_config(pin, GPIO_MODE_INPUT, 1, 0, af); + ra_gpio_config(pin, GPIO_MODE_INPUT, GPIO_PULLUP, GPIO_LOW_POWER, af); } } @@ -808,7 +808,7 @@ static void ra_sci_cts_set_pin(uint32_t pin) { uint32_t af; find = ra_af_find_ch_af((ra_af_pin_t *)&ra_sci_cts_pins, SCI_CTS_PINS_SIZE, pin, &ch, &af); if (find) { - ra_gpio_config(pin, GPIO_MODE_INPUT, 1, 0, af); + ra_gpio_config(pin, GPIO_MODE_INPUT, GPIO_PULLUP, GPIO_LOW_POWER, af); } } @@ -1134,7 +1134,7 @@ void ra_sci_init_with_flow(uint32_t ch, uint32_t tx_pin, uint32_t rx_pin, uint32 } if (rts_pin != (uint32_t)PIN_END) { m_rts_pin[idx] = rts_pin; - ra_gpio_config(rts_pin, GPIO_MODE_OUTPUT_PP, false, 0, 0); + ra_gpio_config(rts_pin, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_LOW_POWER, 0); ra_gpio_write(rts_pin, 0); } } diff --git a/ports/renesas-ra/ra/ra_spi.c b/ports/renesas-ra/ra/ra_spi.c index b7f78cd6de..096519ffd6 100644 --- a/ports/renesas-ra/ra/ra_spi.c +++ b/ports/renesas-ra/ra/ra_spi.c @@ -196,9 +196,9 @@ static void ra_spi_module_stop(uint32_t ch) { static void ra_spi_set_pin(uint32_t pin, bool miso) { if (miso) { - ra_gpio_config(pin, GPIO_MODE_INPUT, 1, 0, AF_SPI); + ra_gpio_config(pin, GPIO_MODE_INPUT, GPIO_PULLUP, GPIO_LOW_POWER, AF_SPI); } else { - ra_gpio_config(pin, GPIO_MODE_AF_PP, 0, 0, AF_SPI); + ra_gpio_config(pin, GPIO_MODE_AF_PP, GPIO_NOPULL, GPIO_LOW_POWER, AF_SPI); } } diff --git a/ports/renesas-ra/usrsw.c b/ports/renesas-ra/usrsw.c index 5e11f48e63..572510816b 100644 --- a/ports/renesas-ra/usrsw.c +++ b/ports/renesas-ra/usrsw.c @@ -54,7 +54,7 @@ // this function inits the switch GPIO so that it can be used void switch_init0(void) { - mp_hal_pin_config(MICROPY_HW_USRSW_PIN, MP_HAL_PIN_MODE_INPUT, MICROPY_HW_USRSW_PULL, GPIO_LOW_POWER, 0); + mp_hal_pin_config(MICROPY_HW_USRSW_PIN, MP_HAL_PIN_MODE_INPUT, MICROPY_HW_USRSW_PULL, MP_HAL_PIN_DRIVE_0, 0); } int switch_get(void) { From 2f2fd36713c2c02f56093338e8c1f3cd7b8d403a Mon Sep 17 00:00:00 2001 From: Takeo Takahashi Date: Thu, 23 Jun 2022 22:28:35 +0900 Subject: [PATCH 0356/1041] tests/renesas-ra: Update pin test to support all boards. Signed-off-by: Takeo Takahashi --- tests/renesas-ra/pin.py | 48 ++++++++----------------------------- tests/renesas-ra/pin.py.exp | 12 ++-------- 2 files changed, 12 insertions(+), 48 deletions(-) diff --git a/tests/renesas-ra/pin.py b/tests/renesas-ra/pin.py index 61d76cca7c..4617cce111 100644 --- a/tests/renesas-ra/pin.py +++ b/tests/renesas-ra/pin.py @@ -1,43 +1,15 @@ from machine import Pin -import os -n = os.uname().machine -if "RA4W1_EK" in n: - try_pin = "P004" - try_s = "Pin(Pin.cpu.P004, mode=Pin.IN, pull=Pin.PULL_NONE, drive=Pin.LOW_POWER)" +p = Pin("SW1", Pin.IN) +if p.value() == 1: + print("pass") else: - try_pin = "P000" - try_s = "Pin(Pin.cpu.P000, mode=Pin.IN, pull=Pin.PULL_NONE, drive=Pin.LOW_POWER)" + print("FAIL") -p = Pin(try_pin, Pin.IN) -if str(p) == try_s: - print("OK") -else: - print("NG") - print("exp: " + try_s) - print("out: " + str(p)) - -p.init(p.IN, p.PULL_UP) -p.init(p.IN, pull=p.PULL_UP) -p.init(mode=p.IN, pull=p.PULL_UP) -print(p.value()) - -p.init(p.OUT) -p.init(p.OPEN_DRAIN) -p.low() -print(p.value()) +p = Pin("LED1", Pin.OUT) p.high() -print(p.value()) -p.value(0) -print(p.value()) -p.value(1) -print(p.value()) -p.value(False) -print(p.value()) -p.value(True) -print(p.value()) -p.off() -print(p.value()) -p.on() -print(p.value()) -p.off() +if p.value() == 1: + print("pass") +else: + print("FAIL") +p.low() diff --git a/tests/renesas-ra/pin.py.exp b/tests/renesas-ra/pin.py.exp index 4c8cc50b0c..0c34cd7a39 100644 --- a/tests/renesas-ra/pin.py.exp +++ b/tests/renesas-ra/pin.py.exp @@ -1,10 +1,2 @@ -OK -1 -0 -1 -0 -1 -0 -1 -0 -1 +pass +pass From af100b70290d20d7e9c3e7d49713e3916b6f05b6 Mon Sep 17 00:00:00 2001 From: Takeo Takahashi Date: Thu, 23 Jun 2022 22:29:00 +0900 Subject: [PATCH 0357/1041] docs/renesas-ra: Add pin drive keyword argument description. Signed-off-by: Takeo Takahashi --- docs/renesas-ra/quickref.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/renesas-ra/quickref.rst b/docs/renesas-ra/quickref.rst index 23ffab50eb..47b49575bd 100644 --- a/docs/renesas-ra/quickref.rst +++ b/docs/renesas-ra/quickref.rst @@ -110,6 +110,24 @@ Use the :ref:`machine.Pin ` class:: Pin id is available corresponding to the RA MCU's pin name which are Pin.cpu.P106 and 'P106'. The RA MCU has many feature's pins. However, there are some cases that pin feature is fixed or not connected by the board. Please confirm the board manual for the pin mapping. +The following *drive* keyword argument are available if the port drive capability of the Pin is supported by the MCU:: + + Pin.DRIVE_0: Low drive + Pin.DRIVE_1: Middle drive + Pin.DRIVE_2: Middle drive for I2C Fast-mode + Pin.DRIVE_3: High drive + +The *alt* keyword argument is not supported. + +The following functions are not supported:: + + Pin.irq(priority=) # priority keyword argument is not supported + Pin.irq(wake=) # wake keyword argument is not supported + Pin.irq(hard=) # hard keyword argument is ignored because hardware interrupt is used + Pin.mode() + Pin.pull() + Pin.drive() + UART (serial bus) ----------------- From 0b26efe73dd3396bdc2b77651a78d9f2edeb9004 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 28 Aug 2022 18:14:53 +0200 Subject: [PATCH 0358/1041] extmod/machine_i2c: Call MICROPY_PY_EVENT_HOOK during i2c.scan(). Avoiding a watchdog reset during i2c.scan() if the hardware is not properly set up (eg on esp8266), and also allowing to stop the scan with a KeyboardInterrupt. Fixes issue #8876. --- extmod/machine_i2c.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c index 2aa217914b..ff597b58c5 100644 --- a/extmod/machine_i2c.c +++ b/extmod/machine_i2c.c @@ -328,6 +328,9 @@ STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) { if (ret == 0) { mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); } + #ifdef MICROPY_EVENT_POLL_HOOK + MICROPY_EVENT_POLL_HOOK + #endif } return list; } From da7f2537a124191371cbc3bc625ed96a43dc29c7 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 10 Aug 2022 22:53:39 +1000 Subject: [PATCH 0359/1041] top: Use micropython-lib unconditionally in manifests. micropython-lib is now a submodule, and the manifest compilation process will ensure it is available, so manifests no longer need to check that it is available. Signed-off-by: Jim Mussared --- ports/esp8266/boards/GENERIC/manifest.py | 18 ++++++++---------- .../ARDUINO_NANO_RP2040_CONNECT/manifest.py | 3 +-- ports/rp2/boards/PICO_W/manifest.py | 3 +-- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/ports/esp8266/boards/GENERIC/manifest.py b/ports/esp8266/boards/GENERIC/manifest.py index 9ce3ffe3aa..ef25040ef8 100644 --- a/ports/esp8266/boards/GENERIC/manifest.py +++ b/ports/esp8266/boards/GENERIC/manifest.py @@ -7,15 +7,13 @@ include("$(MPY_DIR)/extmod/uasyncio/manifest.py") # drivers freeze("$(MPY_DIR)/drivers/display", "ssd1306.py") -# Libraries from micropython-lib, include only if the library directory exists -if os.path.isdir(convert_path("$(MPY_LIB_DIR)")): - # file utilities - freeze("$(MPY_LIB_DIR)/micropython/upysh", "upysh.py") +# micropython-lib: file utilities +freeze("$(MPY_LIB_DIR)/micropython/upysh", "upysh.py") - # requests - freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py") - freeze("$(MPY_LIB_DIR)/micropython/urllib.urequest", "urllib/urequest.py") +# micropython-lib: requests +freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py") +freeze("$(MPY_LIB_DIR)/micropython/urllib.urequest", "urllib/urequest.py") - # umqtt - freeze("$(MPY_LIB_DIR)/micropython/umqtt.simple", "umqtt/simple.py") - freeze("$(MPY_LIB_DIR)/micropython/umqtt.robust", "umqtt/robust.py") +# micropython-lib: umqtt +freeze("$(MPY_LIB_DIR)/micropython/umqtt.simple", "umqtt/simple.py") +freeze("$(MPY_LIB_DIR)/micropython/umqtt.robust", "umqtt/robust.py") diff --git a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py index 0448aa89a1..7a2f1c9e27 100644 --- a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py +++ b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py @@ -8,5 +8,4 @@ include( l2cap=True, security=True, ) -if os.path.isdir(convert_path("$(MPY_LIB_DIR)")): - freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py") +freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py") diff --git a/ports/rp2/boards/PICO_W/manifest.py b/ports/rp2/boards/PICO_W/manifest.py index eb748da485..d2c76602af 100644 --- a/ports/rp2/boards/PICO_W/manifest.py +++ b/ports/rp2/boards/PICO_W/manifest.py @@ -4,5 +4,4 @@ freeze("$(MPY_DIR)/tools", "upip.py") freeze("$(MPY_DIR)/tools", "upip_utarfile.py") freeze("$(MPY_DIR)/extmod", "ntptime.py") -if os.path.isdir(convert_path("$(MPY_LIB_DIR)")): - freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py") +freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py") From f3cdb052db1784b38e02f043cb72bda5a57b8696 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 13 Jul 2022 23:36:45 +1000 Subject: [PATCH 0360/1041] tools/manifestfile.py: Add library for working with manifests. This splits the manifest file loading logic from makemanifest.py and updates makemanifest.py to use it. This will allow non-freezing uses of manifests, such as defining packages and dependencies in micropython-lib. Also adds additional methods to the manifest "API": - require() - to get a package from micropython-lib. - module() - to define a single-file module - package() - to define a multi-file package module() and package() should replace most uses of freeze() and can also be also used in non-freezing scenarios. Signed-off-by: Jim Mussared --- tools/makemanifest.py | 296 ++++++------------------------ tools/manifestfile.py | 416 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 474 insertions(+), 238 deletions(-) create mode 100644 tools/manifestfile.py diff --git a/tools/makemanifest.py b/tools/makemanifest.py index e69698d3f2..800a25435e 100644 --- a/tools/makemanifest.py +++ b/tools/makemanifest.py @@ -29,127 +29,10 @@ import sys import os import subprocess - -########################################################################### -# Public functions to be used in the manifest - - -def include(manifest, **kwargs): - """Include another manifest. - - The manifest argument can be a string (filename) or an iterable of - strings. - - Relative paths are resolved with respect to the current manifest file. - - Optional kwargs can be provided which will be available to the - included script via the `options` variable. - - e.g. include("path.py", extra_features=True) - - in path.py: - options.defaults(standard_features=True) - - # freeze minimal modules. - if options.standard_features: - # freeze standard modules. - if options.extra_features: - # freeze extra modules. - """ - - if not isinstance(manifest, str): - for m in manifest: - include(m) - else: - manifest = convert_path(manifest) - with open(manifest) as f: - # Make paths relative to this manifest file while processing it. - # Applies to includes and input files. - prev_cwd = os.getcwd() - os.chdir(os.path.dirname(manifest)) - exec(f.read(), globals(), {"options": IncludeOptions(**kwargs)}) - os.chdir(prev_cwd) - - -def freeze(path, script=None, opt=0): - """Freeze the input, automatically determining its type. A .py script - will be compiled to a .mpy first then frozen, and a .mpy file will be - frozen directly. - - `path` must be a directory, which is the base directory to search for - files from. When importing the resulting frozen modules, the name of - the module will start after `path`, ie `path` is excluded from the - module name. - - If `path` is relative, it is resolved to the current manifest.py. - Use $(MPY_DIR), $(MPY_LIB_DIR), $(PORT_DIR), $(BOARD_DIR) if you need - to access specific paths. - - If `script` is None all files in `path` will be frozen. - - If `script` is an iterable then freeze() is called on all items of the - iterable (with the same `path` and `opt` passed through). - - If `script` is a string then it specifies the file or directory to - freeze, and can include extra directories before the file or last - directory. The file or directory will be searched for in `path`. If - `script` is a directory then all files in that directory will be frozen. - - `opt` is the optimisation level to pass to mpy-cross when compiling .py - to .mpy. - """ - - freeze_internal(KIND_AUTO, path, script, opt) - - -def freeze_as_str(path): - """Freeze the given `path` and all .py scripts within it as a string, - which will be compiled upon import. - """ - - freeze_internal(KIND_AS_STR, path, None, 0) - - -def freeze_as_mpy(path, script=None, opt=0): - """Freeze the input (see above) by first compiling the .py scripts to - .mpy files, then freezing the resulting .mpy files. - """ - - freeze_internal(KIND_AS_MPY, path, script, opt) - - -def freeze_mpy(path, script=None, opt=0): - """Freeze the input (see above), which must be .mpy files that are - frozen directly. - """ - - freeze_internal(KIND_MPY, path, script, opt) - - -########################################################################### -# Internal implementation - -KIND_AUTO = 0 -KIND_AS_STR = 1 -KIND_AS_MPY = 2 -KIND_MPY = 3 +import manifestfile VARS = {} -manifest_list = [] - - -class IncludeOptions: - def __init__(self, **kwargs): - self._kwargs = kwargs - self._defaults = {} - - def defaults(self, **kwargs): - self._defaults = kwargs - - def __getattr__(self, name): - return self._kwargs.get(name, self._defaults.get(name, None)) - class FreezeError(Exception): pass @@ -163,15 +46,6 @@ def system(cmd): return -1, er.output -def convert_path(path): - # Perform variable substituion. - for name, value in VARS.items(): - path = path.replace("$({})".format(name), value) - # Convert to absolute path (so that future operations don't rely on - # still being chdir'ed). - return os.path.abspath(path) - - def get_timestamp(path, default=None): try: stat = os.stat(path) @@ -182,119 +56,64 @@ def get_timestamp(path, default=None): return default -def get_timestamp_newest(path): - ts_newest = 0 - for dirpath, dirnames, filenames in os.walk(path, followlinks=True): - for f in filenames: - ts_newest = max(ts_newest, get_timestamp(os.path.join(dirpath, f))) - return ts_newest - - def mkdir(filename): path = os.path.dirname(filename) if not os.path.isdir(path): os.makedirs(path) -def freeze_internal(kind, path, script, opt): - path = convert_path(path) - if not os.path.isdir(path): - raise FreezeError("freeze path must be a directory: {}".format(path)) - if script is None and kind == KIND_AS_STR: - manifest_list.append((KIND_AS_STR, path, script, opt)) - elif script is None or isinstance(script, str) and script.find(".") == -1: - # Recursively search `path` for files to freeze, optionally restricted - # to a subdirectory specified by `script` - if script is None: - subdir = "" - else: - subdir = "/" + script - for dirpath, dirnames, filenames in os.walk(path + subdir, followlinks=True): - for f in filenames: - freeze_internal(kind, path, (dirpath + "/" + f)[len(path) + 1 :], opt) - elif not isinstance(script, str): - # `script` is an iterable of items to freeze - for s in script: - freeze_internal(kind, path, s, opt) - else: - # `script` should specify an individual file to be frozen - extension_kind = {KIND_AS_MPY: ".py", KIND_MPY: ".mpy"} - if kind == KIND_AUTO: - for k, ext in extension_kind.items(): - if script.endswith(ext): - kind = k - break - else: - print("warn: unsupported file type, skipped freeze: {}".format(script)) - return - wanted_extension = extension_kind[kind] - if not script.endswith(wanted_extension): - raise FreezeError("expecting a {} file, got {}".format(wanted_extension, script)) - manifest_list.append((kind, path, script, opt)) - - # Formerly make-frozen.py. # This generates: # - MP_FROZEN_STR_NAMES macro # - mp_frozen_str_sizes # - mp_frozen_str_content -def generate_frozen_str_content(paths): - def module_name(f): - return f +def generate_frozen_str_content(modules): + output = [ + b"#include \n", + b"#define MP_FROZEN_STR_NAMES \\\n", + ] - modules = [] - output = [b"#include \n"] - - for path in paths: - root = path.rstrip("/") - root_len = len(root) - - for dirpath, dirnames, filenames in os.walk(root): - for f in filenames: - fullpath = dirpath + "/" + f - st = os.stat(fullpath) - modules.append((path, fullpath[root_len + 1 :], st)) - - output.append(b"#define MP_FROZEN_STR_NAMES \\\n") - for _path, f, st in modules: - m = module_name(f) - output.append(b'"%s\\0" \\\n' % m.encode()) + for _, target_path in modules: + print("STR", target_path) + output.append(b'"%s\\0" \\\n' % target_path.encode()) output.append(b"\n") output.append(b"const uint32_t mp_frozen_str_sizes[] = { ") - for _path, f, st in modules: + for full_path, _ in modules: + st = os.stat(full_path) output.append(b"%d, " % st.st_size) output.append(b"0 };\n") output.append(b"const char mp_frozen_str_content[] = {\n") - for path, f, st in modules: - data = open(path + "/" + f, "rb").read() + for full_path, _ in modules: + with open(full_path, "rb") as f: + data = f.read() - # We need to properly escape the script data to create a C string. - # When C parses hex characters of the form \x00 it keeps parsing the hex - # data until it encounters a non-hex character. Thus one must create - # strings of the form "data\x01" "abc" to properly encode this kind of - # data. We could just encode all characters as hex digits but it's nice - # to be able to read the resulting C code as ASCII when possible. + # We need to properly escape the script data to create a C string. + # When C parses hex characters of the form \x00 it keeps parsing the hex + # data until it encounters a non-hex character. Thus one must create + # strings of the form "data\x01" "abc" to properly encode this kind of + # data. We could just encode all characters as hex digits but it's nice + # to be able to read the resulting C code as ASCII when possible. - data = bytearray(data) # so Python2 extracts each byte as an integer - esc_dict = {ord("\n"): b"\\n", ord("\r"): b"\\r", ord('"'): b'\\"', ord("\\"): b"\\\\"} - output.append(b'"') - break_str = False - for c in data: - try: - output.append(esc_dict[c]) - except KeyError: - if 32 <= c <= 126: - if break_str: - output.append(b'" "') - break_str = False - output.append(chr(c).encode()) - else: - output.append(b"\\x%02x" % c) - break_str = True - output.append(b'\\0"\n') + data = bytearray(data) # so Python2 extracts each byte as an integer + esc_dict = {ord("\n"): b"\\n", ord("\r"): b"\\r", ord('"'): b'\\"', ord("\\"): b"\\\\"} + output.append(b'"') + break_str = False + for c in data: + try: + output.append(esc_dict[c]) + except KeyError: + if 32 <= c <= 126: + if break_str: + output.append(b'" "') + break_str = False + output.append(chr(c).encode()) + else: + output.append(b"\\x%02x" % c) + break_str = True + output.append(b'\\0"\n') output.append(b'"\\0"\n};\n\n') return b"".join(output) @@ -340,14 +159,13 @@ def main(): print("mpy-cross not found at {}, please build it first".format(MPY_CROSS)) sys.exit(1) + manifest = manifestfile.ManifestFile(manifestfile.MODE_FREEZE, VARS) + # Include top-level inputs, to generate the manifest for input_manifest in args.files: try: - if input_manifest.endswith(".py"): - include(input_manifest) - else: - exec(input_manifest) - except FreezeError as er: + manifest.execute(input_manifest) + except manifestfile.ManifestFileError as er: print('freeze error executing "{}": {}'.format(input_manifest, er.args[0])) sys.exit(1) @@ -355,22 +173,25 @@ def main(): str_paths = [] mpy_files = [] ts_newest = 0 - for kind, path, script, opt in manifest_list: - if kind == KIND_AS_STR: - str_paths.append(path) - ts_outfile = get_timestamp_newest(path) - elif kind == KIND_AS_MPY: - infile = "{}/{}".format(path, script) - outfile = "{}/frozen_mpy/{}.mpy".format(args.build_dir, script[:-3]) - ts_infile = get_timestamp(infile) + for full_path, target_path, timestamp, kind, version, opt in manifest.files(): + if kind == manifestfile.KIND_FREEZE_AS_STR: + str_paths.append( + ( + full_path, + target_path, + ) + ) + ts_outfile = timestamp + elif kind == manifestfile.KIND_FREEZE_AS_MPY: + outfile = "{}/frozen_mpy/{}.mpy".format(args.build_dir, target_path[:-3]) ts_outfile = get_timestamp(outfile, 0) - if ts_infile >= ts_outfile: - print("MPY", script) + if timestamp >= ts_outfile: + print("MPY", target_path) mkdir(outfile) res, out = system( [MPY_CROSS] + args.mpy_cross_flags.split() - + ["-o", outfile, "-s", script, "-O{}".format(opt), infile] + + ["-o", outfile, "-s", target_path, "-O{}".format(opt), full_path] ) if res != 0: print("error compiling {}:".format(infile)) @@ -379,10 +200,9 @@ def main(): ts_outfile = get_timestamp(outfile) mpy_files.append(outfile) else: - assert kind == KIND_MPY - infile = "{}/{}".format(path, script) - mpy_files.append(infile) - ts_outfile = get_timestamp(infile) + assert kind == manifestfile.KIND_FREEZE_MPY + mpy_files.append(full_path) + ts_outfile = timestamp ts_newest = max(ts_newest, ts_outfile) # Check if output file needs generating diff --git a/tools/manifestfile.py b/tools/manifestfile.py new file mode 100644 index 0000000000..cb155da210 --- /dev/null +++ b/tools/manifestfile.py @@ -0,0 +1,416 @@ +#!/usr/bin/env python3 +# +# This file is part of the MicroPython project, http://micropython.org/ +# +# The MIT License (MIT) +# +# Copyright (c) 2022 Jim Mussared +# Copyright (c) 2019 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. + +from __future__ import print_function +import os +import sys +import glob + +__all__ = ["ManifestFileError", "ManifestFile"] + +# Allow freeze*() etc. +MODE_FREEZE = 1 +# Only allow include/require/module/package. +MODE_COMPILE = 2 + + +# In compile mode, .py -> KIND_COMPILE_AS_MPY +# In freeze mode, .py -> KIND_FREEZE_AS_MPY, .mpy->KIND_FREEZE_MPY +KIND_AUTO = 1 +# Freeze-mode only, .py -> KIND_FREEZE_AS_MPY, .mpy->KIND_FREEZE_MPY +KIND_FREEZE_AUTO = 2 + +# Freeze-mode only, The .py file will be frozen as text. +KIND_FREEZE_AS_STR = 3 +# Freeze-mode only, The .py file will be compiled and frozen as bytecode. +KIND_FREEZE_AS_MPY = 4 +# Freeze-mode only, The .mpy file will be frozen directly. +KIND_FREEZE_MPY = 5 +# Compile mode only, the .py file should be compiled to .mpy. +KIND_COMPILE_AS_MPY = 6 + +# File on the local filesystem. +FILE_TYPE_LOCAL = 1 +# URL to file. (TODO) +FILE_TYPE_HTTP = 2 + + +class ManifestFileError(Exception): + pass + + +# Turns a dict of options into a object with attributes used to turn the +# kwargs passed to include() and require into the "options" global in the +# included manifest. +# options = IncludeOptions(foo="bar", blah="stuff") +# options.foo # "bar" +# options.blah # "stuff" +class IncludeOptions: + def __init__(self, **kwargs): + self._kwargs = kwargs + self._defaults = {} + + def defaults(self, **kwargs): + self._defaults = kwargs + + def __getattr__(self, name): + return self._kwargs.get(name, self._defaults.get(name, None)) + + +class ManifestFile: + def __init__(self, mode, path_vars=None): + # Either MODE_FREEZE or MODE_COMPILE. + self._mode = mode + # Path substition variables. + self._path_vars = path_vars or {} + # List of files references by this manifest. + # Tuple of (file_type, full_path, target_path, timestamp, kind, version, opt) + self._manifest_files = [] + # Don't allow including the same file twice. + self._visited = set() + + def _resolve_path(self, path): + # Convert path to an absolute path, applying variable substitutions. + for name, value in self._path_vars.items(): + if value is not None: + path = path.replace("$({})".format(name), value) + return os.path.abspath(path) + + def _manifest_globals(self, kwargs): + # This is the "API" available to a manifest file. + return { + "metadata": self.metadata, + "include": self.include, + "require": self.require, + "package": self.package, + "module": self.module, + "freeze": self.freeze, + "freeze_as_str": self.freeze_as_str, + "freeze_as_mpy": self.freeze_as_mpy, + "freeze_mpy": self.freeze_mpy, + "options": IncludeOptions(**kwargs), + } + + def files(self): + return self._manifest_files + + def execute(self, manifest_file): + if manifest_file.endswith(".py"): + # Execute file from filesystem. + self.include(manifest_file) + else: + # Execute manifest code snippet. + try: + exec(manifest_file, self._manifest_globals({})) + except Exception as er: + raise ManifestFileError("Error in manifest: {}".format(er)) + + def _add_file(self, full_path, target_path, kind=KIND_AUTO, version=None, opt=None): + # Check file exists and get timestamp. + try: + stat = os.stat(full_path) + timestamp = stat.st_mtime + except OSError: + raise ManifestFileError("cannot stat {}".format(full_path)) + + # Map the AUTO kinds to their actual kind based on mode and extension. + _, ext = os.path.splitext(full_path) + if self._mode == MODE_FREEZE: + if kind in ( + KIND_AUTO, + KIND_FREEZE_AUTO, + ): + if ext.lower() == ".py": + kind = KIND_FREEZE_AS_MPY + elif ext.lower() == ".mpy": + kind = KIND_FREEZE_MPY + else: + if kind != KIND_AUTO: + raise ManifestFileError("Not in freeze mode") + if ext.lower() != ".py": + raise ManifestFileError("Expected .py file") + kind = KIND_COMPILE_AS_MPY + + self._manifest_files.append( + (FILE_TYPE_LOCAL, full_path, target_path, timestamp, kind, version, opt) + ) + + def _search(self, base_path, package_path, files, exts, kind, opt=None, strict=False): + base_path = self._resolve_path(base_path) + + if files: + # Use explicit list of files (relative to package_path). + for file in files: + if package_path: + file = os.path.join(package_path, file) + self._add_file( + os.path.join(base_path, file), file, kind=kind, version=None, opt=opt + ) + else: + if base_path: + prev_cwd = os.getcwd() + os.chdir(self._resolve_path(base_path)) + + # Find all candidate files. + for dirpath, _, filenames in os.walk(package_path or ".", followlinks=True): + for file in filenames: + file = os.path.relpath(os.path.join(dirpath, file), ".") + _, ext = os.path.splitext(file) + if ext.lower() in exts: + self._add_file( + os.path.join(base_path, file), + file, + kind=kind, + version=None, + opt=opt, + ) + elif strict: + raise ManifestFileError("Unexpected file type") + + if base_path: + os.chdir(prev_cwd) + + def metadata(self, description=None, version=None): + # TODO + pass + + def include_maybe(self, manifest_path, **kwargs): + """ + Include the manifest file if it exists. See docs for include(). + """ + if os.path.exists(manifest_path): + self.include(manifest_path, **kwargs) + + def include(self, manifest_path, **kwargs): + """ + Include another manifest. + + The manifest argument can be a string (filename) or an iterable of + strings. + + Relative paths are resolved with respect to the current manifest file. + + Optional kwargs can be provided which will be available to the + included script via the `options` variable. + + e.g. include("path.py", extra_features=True) + + in path.py: + options.defaults(standard_features=True) + + # freeze minimal modules. + if options.standard_features: + # freeze standard modules. + if options.extra_features: + # freeze extra modules. + """ + if not isinstance(manifest_path, str): + for m in manifest_path: + self.include(m) + else: + manifest_path = self._resolve_path(manifest_path) + if manifest_path in self._visited: + return + self._visited.add(manifest_path) + with open(manifest_path) as f: + # Make paths relative to this manifest file while processing it. + # Applies to includes and input files. + prev_cwd = os.getcwd() + os.chdir(os.path.dirname(manifest_path)) + try: + exec(f.read(), self._manifest_globals(kwargs)) + except Exception as er: + raise ManifestFileError( + "Error in manifest file: {}: {}".format(manifest_path, er) + ) + os.chdir(prev_cwd) + + def require(self, name, version=None, **kwargs): + """ + Require a module by name from micropython-lib. + + This is a shortcut for + """ + if self._path_vars["MPY_LIB_DIR"]: + for manifest_path in glob.glob( + os.path.join(self._path_vars["MPY_LIB_DIR"], "**", name, "manifest.py"), + recursive=True, + ): + self.include(manifest_path, **kwargs) + return + raise ValueError("Library not found in local micropython-lib: {}".format(name)) + else: + # TODO: HTTP request to obtain URLs from manifest.json. + raise ValueError("micropython-lib not available for require('{}').", name) + + def package(self, package_path, files=None, base_path=".", opt=None): + """ + Define a package, optionally restricting to a set of files. + + Simple case, a package in the current directory: + package("foo") + will include all .py files in foo, and will be stored as foo/bar/baz.py. + + If the package isn't in the current directory, use base_path: + package("foo", base_path="src") + + To restrict to certain files in the package use files (note: paths should be relative to the package): + package("foo", files=["bar/baz.py"]) + """ + # Include "base_path/package_path/**/*.py" --> "package_path/**/*.py" + self._search(base_path, package_path, files, exts=(".py",), kind=KIND_AUTO, opt=opt) + + def module(self, module_path, base_path=".", opt=None): + """ + Include a single Python file as a module. + + If the file is in the current directory: + module("foo.py") + + Otherwise use base_path to locate the file: + module("foo.py", "src/drivers") + """ + # Include "base_path/module_path" --> "module_path" + base_path = self._resolve_path(base_path) + _, ext = os.path.splitext(module_path) + if ext.lower() != ".py": + raise ManifestFileError("module must be .py file") + # TODO: version None + self._add_file(os.path.join(base_path, module_path), module_path, version=None, opt=opt) + + def _freeze_internal(self, path, script, exts, kind, opt): + if script is None: + self._search(path, None, None, exts=exts, kind=kind, opt=opt) + elif isinstance(script, str) and os.path.isdir(os.path.join(path, script)): + self._search(path, script, None, exts=exts, kind=kind, opt=opt) + elif not isinstance(script, str): + self._search(path, None, script, exts=exts, kind=kind, opt=opt) + else: + self._search(path, None, (script,), exts=exts, kind=kind, opt=opt) + + def freeze(self, path, script=None, opt=None): + """ + Freeze the input, automatically determining its type. A .py script + will be compiled to a .mpy first then frozen, and a .mpy file will be + frozen directly. + + `path` must be a directory, which is the base directory to _search for + files from. When importing the resulting frozen modules, the name of + the module will start after `path`, ie `path` is excluded from the + module name. + + If `path` is relative, it is resolved to the current manifest.py. + Use $(MPY_DIR), $(MPY_LIB_DIR), $(PORT_DIR), $(BOARD_DIR) if you need + to access specific paths. + + If `script` is None all files in `path` will be frozen. + + If `script` is an iterable then freeze() is called on all items of the + iterable (with the same `path` and `opt` passed through). + + If `script` is a string then it specifies the file or directory to + freeze, and can include extra directories before the file or last + directory. The file or directory will be _searched for in `path`. If + `script` is a directory then all files in that directory will be frozen. + + `opt` is the optimisation level to pass to mpy-cross when compiling .py + to .mpy. + """ + self._freeze_internal(path, script, exts=(".py", ".mpy"), kind=KIND_FREEZE_AUTO, opt=opt) + + def freeze_as_str(self, path): + """ + Freeze the given `path` and all .py scripts within it as a string, + which will be compiled upon import. + """ + self._search(path, None, None, exts=(".py"), kind=KIND_FREEZE_AS_STR) + + def freeze_as_mpy(self, path, script=None, opt=None): + """ + Freeze the input (see above) by first compiling the .py scripts to + .mpy files, then freezing the resulting .mpy files. + """ + self._freeze_internal(path, script, exts=(".py"), kind=KIND_FREEZE_AS_MPY, opt=opt) + + def freeze_mpy(self, path, script=None, opt=None): + """ + Freeze the input (see above), which must be .mpy files that are + frozen directly. + """ + self._freeze_internal(path, script, exts=(".mpy"), kind=KIND_FREEZE_MPY, opt=opt) + + +def main(): + import argparse + + cmd_parser = argparse.ArgumentParser(description="List the files referenced by a manifest.") + cmd_parser.add_argument("--freeze", action="store_true", help="freeze mode") + cmd_parser.add_argument("--compile", action="store_true", help="compile mode") + cmd_parser.add_argument( + "--lib", + default=os.path.join(os.path.dirname(__file__), "../lib/micropython-lib"), + help="path to micropython-lib repo", + ) + cmd_parser.add_argument("--port", default=None, help="path to port dir") + cmd_parser.add_argument("--board", default=None, help="path to board dir") + cmd_parser.add_argument( + "--top", + default=os.path.join(os.path.dirname(__file__), ".."), + help="path to micropython repo", + ) + cmd_parser.add_argument("files", nargs="+", help="input manifest.py") + args = cmd_parser.parse_args() + + path_vars = { + "MPY_DIR": os.path.abspath(args.top) if args.top else None, + "BOARD_DIR": os.path.abspath(args.board) if args.board else None, + "PORT_DIR": os.path.abspath(args.port) if args.port else None, + "MPY_LIB_DIR": os.path.abspath(args.lib) if args.lib else None, + } + + mode = None + if args.freeze: + mode = MODE_FREEZE + elif args.compile: + mode = MODE_COMPILE + else: + print("Error: No mode specified.", file=sys.stderr) + exit(1) + + m = ManifestFile(mode, path_vars) + for manifest_file in args.files: + try: + m.execute(manifest_file) + except ManifestFileError as er: + print(er, file=sys.stderr) + exit(1) + for f in m.files(): + print(f) + + +if __name__ == "__main__": + main() From e42809531f735b376409d458e51e25f9708ec551 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 15 Jul 2022 23:01:06 +1000 Subject: [PATCH 0361/1041] mpy-cross/mpy_cross: Add Python wrapper for mpy-cross. Rather than invoking mpy-cross directly via system/subprocess in our build tools and other tools, this provides a Python interface for it. Based on https://gitlab.com/alelec/mpy_cross (with the intention of eventually replacing that as the "official" pypi distribution once setup.py etc are added). Signed-off-by: Jim Mussared --- mpy-cross/mpy_cross/__init__.py | 113 ++++++++++++++++++++++++++++++++ mpy-cross/mpy_cross/__main__.py | 38 +++++++++++ 2 files changed, 151 insertions(+) create mode 100644 mpy-cross/mpy_cross/__init__.py create mode 100644 mpy-cross/mpy_cross/__main__.py diff --git a/mpy-cross/mpy_cross/__init__.py b/mpy-cross/mpy_cross/__init__.py new file mode 100644 index 0000000000..d4c0930bb9 --- /dev/null +++ b/mpy-cross/mpy_cross/__init__.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +# +# This file is part of the MicroPython project, http://micropython.org/ +# +# The MIT License (MIT) +# +# Copyright (c) 2022 Andrew Leech +# Copyright (c) 2022 Jim Mussared +# +# 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. + +from __future__ import print_function +import os +import stat +import subprocess + +NATIVE_ARCH_X86 = "x86" +NATIVE_ARCH_X64 = "x64" +NATIVE_ARCH_ARMV6 = "armv6" +NATIVE_ARCH_ARMV6M = "armv6m" +NATIVE_ARCH_ARMV7M = "armv7m" +NATIVE_ARCH_ARMV7EM = "armv7em" +NATIVE_ARCH_ARMV7EMSP = "armv7emsp" +NATIVE_ARCH_ARMV7EMDP = "armv7emdp" +NATIVE_ARCH_XTENSA = "xtensa" +NATIVE_ARCH_XTENSAWIN = "xtensawin" + +NATIVE_ARCHS = [ + NATIVE_ARCH_X86, + NATIVE_ARCH_X64, + NATIVE_ARCH_ARMV6, + NATIVE_ARCH_ARMV6M, + NATIVE_ARCH_ARMV7M, + NATIVE_ARCH_ARMV7EM, + NATIVE_ARCH_ARMV7EMSP, + NATIVE_ARCH_ARMV7EMDP, + NATIVE_ARCH_XTENSA, + NATIVE_ARCH_XTENSAWIN, +] + +__all__ = ["compile", "run", "CrossCompileError"] + + +class CrossCompileError(Exception): + pass + + +def find_mpy_cross_binary(mpy_cross): + if mpy_cross: + return mpy_cross + return os.path.abspath(os.path.join(os.path.dirname(__file__), "../mpy-cross")) + + +def compile(src, dest=None, src_path=None, opt=None, march=None, mpy_cross=None, extra_args=None): + if not src: + raise ValueError("src is required") + if not os.path.exists(src): + raise CrossCompileError("Input .py file not found: {}.".format(src_py)) + + args = [] + + if src_path: + args += ["-s", src_path] + + if dest: + args += ["-o", dest] + + if march: + args += ["-march", march] + + if opt is not None: + args += ["-O{}".format(opt)] + + if extra_args: + args += extra_args + + args += [src] + + run(args, mpy_cross) + + +def run(args, mpy_cross=None): + mpy_cross = find_mpy_cross_binary(mpy_cross) + + if not os.path.exists(mpy_cross): + raise CrossCompileError("mpy-cross binary not found at {}.".format(mpy_cross)) + + try: + st = os.stat(mpy_cross) + os.chmod(mpy_cross, st.st_mode | stat.S_IEXEC) + except OSError: + pass + + try: + subprocess.check_output([mpy_cross] + args, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as er: + raise CrossCompileError(er.output) diff --git a/mpy-cross/mpy_cross/__main__.py b/mpy-cross/mpy_cross/__main__.py new file mode 100644 index 0000000000..9d957bca02 --- /dev/null +++ b/mpy-cross/mpy_cross/__main__.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +# +# This file is part of the MicroPython project, http://micropython.org/ +# +# The MIT License (MIT) +# +# Copyright (c) 2022 Andrew Leech +# Copyright (c) 2022 Jim Mussared +# +# 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. + +from __future__ import print_function +import argparse +import sys + +from . import run, CrossCompileError + +try: + run(sys.argv[1:]) +except CrossCompileError as er: + print(er.args[0], file=sys.stderr) + raise SystemExit(1) From 6bd0ec7a70496dc51d8dc6c706919ef398b0346e Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 15 Jul 2022 23:06:15 +1000 Subject: [PATCH 0362/1041] tools/makemanifest.py: Update to use mpy_cross module. Signed-off-by: Jim Mussared --- tools/makemanifest.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/tools/makemanifest.py b/tools/makemanifest.py index 800a25435e..2e7021040d 100644 --- a/tools/makemanifest.py +++ b/tools/makemanifest.py @@ -29,6 +29,9 @@ import sys import os import subprocess +sys.path.append(os.path.join(os.path.dirname(__file__), "../mpy-cross")) +import mpy_cross + import manifestfile VARS = {} @@ -173,7 +176,7 @@ def main(): str_paths = [] mpy_files = [] ts_newest = 0 - for full_path, target_path, timestamp, kind, version, opt in manifest.files(): + for _file_type, full_path, target_path, timestamp, kind, version, opt in manifest.files(): if kind == manifestfile.KIND_FREEZE_AS_STR: str_paths.append( ( @@ -188,14 +191,18 @@ def main(): if timestamp >= ts_outfile: print("MPY", target_path) mkdir(outfile) - res, out = system( - [MPY_CROSS] - + args.mpy_cross_flags.split() - + ["-o", outfile, "-s", target_path, "-O{}".format(opt), full_path] - ) - if res != 0: - print("error compiling {}:".format(infile)) - sys.stdout.buffer.write(out) + try: + mpy_cross.compile( + full_path, + dest=outfile, + src_path=target_path, + opt=opt, + mpy_cross=MPY_CROSS, + extra_args=args.mpy_cross_flags.split(), + ) + except mpy_cross.CrossCompileError as ex: + print("error compiling {}:".format(target_path)) + print(ex.args[0]) raise SystemExit(1) ts_outfile = get_timestamp(outfile) mpy_files.append(outfile) From e9a28ce312b75a4f2b3b7a8c3e38b7766cb567b3 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 15 Jul 2022 23:42:51 +1000 Subject: [PATCH 0363/1041] tools/manifestfile.py: Allow include of directory path. If an include path is a directory, then it implicitly grabs the manifest.py file inside that directory. This simplifies most manifest.py files. Signed-off-by: Jim Mussared --- tools/manifestfile.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tools/manifestfile.py b/tools/manifestfile.py index cb155da210..bf626c22b3 100644 --- a/tools/manifestfile.py +++ b/tools/manifestfile.py @@ -198,13 +198,6 @@ class ManifestFile: # TODO pass - def include_maybe(self, manifest_path, **kwargs): - """ - Include the manifest file if it exists. See docs for include(). - """ - if os.path.exists(manifest_path): - self.include(manifest_path, **kwargs) - def include(self, manifest_path, **kwargs): """ Include another manifest. @@ -214,6 +207,9 @@ class ManifestFile: Relative paths are resolved with respect to the current manifest file. + If the path is to a directory, then it implicitly includes the + manifest.py file inside that directory. + Optional kwargs can be provided which will be available to the included script via the `options` variable. @@ -233,6 +229,9 @@ class ManifestFile: self.include(m) else: manifest_path = self._resolve_path(manifest_path) + # Including a directory grabs the manifest.py inside it. + if os.path.isdir(manifest_path): + manifest_path = os.path.join(manifest_path, "manifest.py") if manifest_path in self._visited: return self._visited.add(manifest_path) From bc23f207cefed82172551288ebb8686ee2c512a3 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 11 Aug 2022 00:16:48 +1000 Subject: [PATCH 0364/1041] tools/manifestfile.py: Allow require() to specify unix packages. By default, don't include micropython-lib/unix-ffi in the search. If unix_ffi=True is passed to require(), then include unix-ffi and make it take precedence over the other locations (e.g. python-stdlib). This does two things: - Prevents non-unix builds from using unix-only packages. - Allows the unix build to optionally use a more full-featured (e.g. ffi) based package, even with the same name as one from e.g. stdlib. Signed-off-by: Jim Mussared --- tools/manifestfile.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/tools/manifestfile.py b/tools/manifestfile.py index bf626c22b3..61560e4565 100644 --- a/tools/manifestfile.py +++ b/tools/manifestfile.py @@ -248,19 +248,28 @@ class ManifestFile: ) os.chdir(prev_cwd) - def require(self, name, version=None, **kwargs): + def require(self, name, version=None, unix_ffi=False, **kwargs): """ Require a module by name from micropython-lib. - This is a shortcut for + Optionally specify unix_ffi=True to use a module from the unix-ffi directory. """ if self._path_vars["MPY_LIB_DIR"]: - for manifest_path in glob.glob( - os.path.join(self._path_vars["MPY_LIB_DIR"], "**", name, "manifest.py"), - recursive=True, - ): - self.include(manifest_path, **kwargs) - return + lib_dirs = ["micropython", "python-stdlib", "python-ecosys"] + if unix_ffi: + # Search unix-ffi only if unix_ffi=True, and make unix-ffi modules + # take precedence. + lib_dirs = ["unix-ffi"] + lib_dirs + + for lib_dir in lib_dirs: + for manifest_path in glob.glob( + os.path.join( + self._path_vars["MPY_LIB_DIR"], lib_dir, "**", name, "manifest.py" + ), + recursive=True, + ): + self.include(manifest_path, **kwargs) + return raise ValueError("Library not found in local micropython-lib: {}".format(name)) else: # TODO: HTTP request to obtain URLs from manifest.json. From 5852fd7708d02d6ca85e4a5ed01d8263e3962631 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 12 Aug 2022 11:30:56 +1000 Subject: [PATCH 0365/1041] tools/manifestfile.py: Allow manifests to set metadata. The metadata can be version, description, and license. After executing a manifest, the top-level metadata can be queried, and also each file output from the manifest will have the metadata of the containing manifest. Use the version metadata to "tag" files before freezing such that they have __version__ available. --- tools/makemanifest.py | 46 +++++++++++----------- tools/manifestfile.py | 92 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 102 insertions(+), 36 deletions(-) diff --git a/tools/makemanifest.py b/tools/makemanifest.py index 2e7021040d..d059d4a266 100644 --- a/tools/makemanifest.py +++ b/tools/makemanifest.py @@ -176,34 +176,36 @@ def main(): str_paths = [] mpy_files = [] ts_newest = 0 - for _file_type, full_path, target_path, timestamp, kind, version, opt in manifest.files(): - if kind == manifestfile.KIND_FREEZE_AS_STR: + for result in manifest.files(): + if result.kind == manifestfile.KIND_FREEZE_AS_STR: str_paths.append( ( - full_path, - target_path, + result.full_path, + result.target_path, ) ) - ts_outfile = timestamp - elif kind == manifestfile.KIND_FREEZE_AS_MPY: - outfile = "{}/frozen_mpy/{}.mpy".format(args.build_dir, target_path[:-3]) + ts_outfile = result.timestamp + elif result.kind == manifestfile.KIND_FREEZE_AS_MPY: + outfile = "{}/frozen_mpy/{}.mpy".format(args.build_dir, result.target_path[:-3]) ts_outfile = get_timestamp(outfile, 0) - if timestamp >= ts_outfile: - print("MPY", target_path) + if result.timestamp >= ts_outfile: + print("MPY", result.target_path) mkdir(outfile) - try: - mpy_cross.compile( - full_path, - dest=outfile, - src_path=target_path, - opt=opt, - mpy_cross=MPY_CROSS, - extra_args=args.mpy_cross_flags.split(), - ) - except mpy_cross.CrossCompileError as ex: - print("error compiling {}:".format(target_path)) - print(ex.args[0]) - raise SystemExit(1) + # Add __version__ to the end of the file before compiling. + with manifestfile.tagged_py_file(result.full_path, result.metadata) as tagged_path: + try: + mpy_cross.compile( + tagged_path, + dest=outfile, + src_path=result.target_path, + opt=result.opt, + mpy_cross=MPY_CROSS, + extra_args=args.mpy_cross_flags.split(), + ) + except mpy_cross.CrossCompileError as ex: + print("error compiling {}:".format(target_path)) + print(ex.args[0]) + raise SystemExit(1) ts_outfile = get_timestamp(outfile) mpy_files.append(outfile) else: diff --git a/tools/manifestfile.py b/tools/manifestfile.py index 61560e4565..84c79ed82b 100644 --- a/tools/manifestfile.py +++ b/tools/manifestfile.py @@ -26,9 +26,12 @@ # THE SOFTWARE. from __future__ import print_function +import contextlib import os import sys import glob +import tempfile +from collections import namedtuple __all__ = ["ManifestFileError", "ManifestFile"] @@ -63,6 +66,37 @@ class ManifestFileError(Exception): pass +# The set of files that this manifest references. +ManifestOutput = namedtuple( + "ManifestOutput", + [ + "file_type", # FILE_TYPE_*. + "full_path", # The input file full path. + "target_path", # The target path on the device. + "timestamp", # Last modified date of the input file. + "kind", # KIND_*. + "metadata", # Metadata for the containing package. + "opt", # Optimisation level (or None). + ], +) + + +# Represent the metadata for a package. +class ManifestMetadata: + def __init__(self): + self.version = None + self.description = None + self.license = None + + def update(self, description=None, version=None, license=None): + if description: + self.description = description + if version: + self.version = version + if license: + self.license = version + + # Turns a dict of options into a object with attributes used to turn the # kwargs passed to include() and require into the "options" global in the # included manifest. @@ -87,11 +121,12 @@ class ManifestFile: self._mode = mode # Path substition variables. self._path_vars = path_vars or {} - # List of files references by this manifest. - # Tuple of (file_type, full_path, target_path, timestamp, kind, version, opt) + # List of files (as ManifestFileResult) references by this manifest. self._manifest_files = [] # Don't allow including the same file twice. self._visited = set() + # Stack of metadata for each level. + self._metadata = [ManifestMetadata()] def _resolve_path(self, path): # Convert path to an absolute path, applying variable substitutions. @@ -121,7 +156,7 @@ class ManifestFile: def execute(self, manifest_file): if manifest_file.endswith(".py"): # Execute file from filesystem. - self.include(manifest_file) + self.include(manifest_file, top_level=True) else: # Execute manifest code snippet. try: @@ -129,7 +164,7 @@ class ManifestFile: except Exception as er: raise ManifestFileError("Error in manifest: {}".format(er)) - def _add_file(self, full_path, target_path, kind=KIND_AUTO, version=None, opt=None): + def _add_file(self, full_path, target_path, kind=KIND_AUTO, opt=None): # Check file exists and get timestamp. try: stat = os.stat(full_path) @@ -156,7 +191,9 @@ class ManifestFile: kind = KIND_COMPILE_AS_MPY self._manifest_files.append( - (FILE_TYPE_LOCAL, full_path, target_path, timestamp, kind, version, opt) + ManifestOutput( + FILE_TYPE_LOCAL, full_path, target_path, timestamp, kind, self._metadata[-1], opt + ) ) def _search(self, base_path, package_path, files, exts, kind, opt=None, strict=False): @@ -167,9 +204,7 @@ class ManifestFile: for file in files: if package_path: file = os.path.join(package_path, file) - self._add_file( - os.path.join(base_path, file), file, kind=kind, version=None, opt=opt - ) + self._add_file(os.path.join(base_path, file), file, kind=kind, opt=opt) else: if base_path: prev_cwd = os.getcwd() @@ -185,7 +220,6 @@ class ManifestFile: os.path.join(base_path, file), file, kind=kind, - version=None, opt=opt, ) elif strict: @@ -194,11 +228,19 @@ class ManifestFile: if base_path: os.chdir(prev_cwd) - def metadata(self, description=None, version=None): - # TODO - pass + def metadata(self, description=None, version=None, license=None): + """ + From within a manifest file, use this to set the metadata for the + package described by current manifest. - def include(self, manifest_path, **kwargs): + After executing a manifest file (via execute()), call this + to obtain the metadata for the top-level manifest file. + """ + + self._metadata[-1].update(description, version, license) + return self._metadata[-1] + + def include(self, manifest_path, top_level=False, **kwargs): """ Include another manifest. @@ -235,6 +277,8 @@ class ManifestFile: if manifest_path in self._visited: return self._visited.add(manifest_path) + if not top_level: + self._metadata.append(ManifestMetadata()) with open(manifest_path) as f: # Make paths relative to this manifest file while processing it. # Applies to includes and input files. @@ -247,6 +291,8 @@ class ManifestFile: "Error in manifest file: {}: {}".format(manifest_path, er) ) os.chdir(prev_cwd) + if not top_level: + self._metadata.pop() def require(self, name, version=None, unix_ffi=False, **kwargs): """ @@ -308,7 +354,7 @@ class ManifestFile: if ext.lower() != ".py": raise ManifestFileError("module must be .py file") # TODO: version None - self._add_file(os.path.join(base_path, module_path), module_path, version=None, opt=opt) + self._add_file(os.path.join(base_path, module_path), module_path, opt=opt) def _freeze_internal(self, path, script, exts, kind, opt): if script is None: @@ -372,6 +418,24 @@ class ManifestFile: self._freeze_internal(path, script, exts=(".mpy"), kind=KIND_FREEZE_MPY, opt=opt) +# Generate a temporary file with a line appended to the end that adds __version__. +@contextlib.contextmanager +def tagged_py_file(path, metadata): + dest_fd, dest_path = tempfile.mkstemp(suffix=".py", text=True) + try: + with os.fdopen(dest_fd, "w") as dest: + with open(path, "r") as src: + contents = src.read() + dest.write(contents) + + # Don't overwrite a version definition if the file already has one in it. + if metadata.version and "__version__ =" not in contents: + dest.write("\n\n__version__ = {}\n".format(repr(metadata.version))) + yield dest_path + finally: + os.unlink(dest_path) + + def main(): import argparse From ccd210984e7a959694b2af4937ce953a822c2ea5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 5 Sep 2022 18:23:11 +1000 Subject: [PATCH 0366/1041] lib/micropython-lib: Update to latest version with manifest changes. Signed-off-by: Damien George --- lib/micropython-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/micropython-lib b/lib/micropython-lib index 70e422dc2e..f3cfc52ab0 160000 --- a/lib/micropython-lib +++ b/lib/micropython-lib @@ -1 +1 @@ -Subproject commit 70e422dc2e885bbaafe6eb7e3d81118e17d4b555 +Subproject commit f3cfc52ab076fc913dc6e266fb7370b418c8f542 From 203dae41fbaceeea9a04dc540b22de4ddd0d5a69 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 15 Jul 2022 23:46:28 +1000 Subject: [PATCH 0367/1041] all: Update all manifest.py files to use new features. Changes in this commit: - Manifest include's now use the directory path where possible (no longer necessary to include the manifest.py file explicitly). - Add manifest.py for all drivers and components that are referenced by port/board manifests. - Replace all uses of freeze() with package()/module(), except for port and board modules. - Use opt=3 everywhere, for consistency and to reduce code size. - Use require() instead of include() for all micropython-lib references. - Remove support for optional board-level manifest.py in mimxrt port, to make it behave the same as other ports (the board must set FROZEN_MANIFEST to a custom manifest.py, which can optionally include the default, port-level manifest). - Also reinstates modules that were accidentally removed from the esp8266 512k build in fbe9417b90474dd1a08749b3a79311a8007a98fb. Signed-off-by: Jim Mussared Signed-off-by: Damien George --- drivers/codec/manifest.py | 1 + drivers/dht/manifest.py | 1 + drivers/display/manifest.py | 11 ++++++++ drivers/hts221/manifest.py | 1 + drivers/lps22h/manifest.py | 1 + drivers/lsm6dsox/manifest.py | 1 + drivers/lsm9ds1/manifest.py | 1 + drivers/neopixel/manifest.py | 6 +---- drivers/nrf24l01/manifest.py | 1 + drivers/onewire/manifest.py | 6 +++++ drivers/sdcard/manifest.py | 1 + extmod/uasyncio/manifest.py | 20 ++++++++------- extmod/webrepl/manifest.py | 3 ++- .../boards/LILYGO_TTGO_LORA32/manifest.py | 2 +- ports/esp32/boards/LOLIN_S2_PICO/manifest.py | 2 +- ports/esp32/boards/UM_FEATHERS2/manifest.py | 2 +- ports/esp32/boards/manifest.py | 25 ++++++++++--------- ports/esp8266/boards/GENERIC/manifest.py | 14 +++++------ ports/esp8266/boards/GENERIC_512K/manifest.py | 13 ++++++---- ports/esp8266/boards/manifest.py | 13 +++++----- ports/mimxrt/boards/manifest.py | 10 +++----- .../arduino_nano_33_ble_sense/manifest.py | 6 ++--- ports/nrf/modules/manifest.py | 4 +-- .../boards/RA4M1_CLICKER/manifest.py | 2 +- ports/renesas-ra/boards/RA4M1_EK/manifest.py | 2 +- ports/renesas-ra/boards/manifest.py | 8 +++--- .../ARDUINO_NANO_RP2040_CONNECT/manifest.py | 20 +++++++-------- ports/rp2/boards/PICO_W/manifest.py | 8 +++--- ports/rp2/boards/manifest.py | 8 +++--- .../boards/ARDUINO_PORTENTA_H7/manifest.py | 10 ++------ .../GARATRONIC_PYBSTICK26_F411/manifest.py | 2 +- ports/stm32/boards/LEGO_HUB_NO6/manifest.py | 2 ++ ports/stm32/boards/LEGO_HUB_NO7/manifest.py | 7 ++---- ports/stm32/boards/PYBD_SF2/manifest.py | 2 +- ports/stm32/boards/manifest.py | 9 ++++--- ports/unix/variants/dev/manifest.py | 2 +- ports/unix/variants/manifest.py | 4 +-- ports/windows/variants/dev/manifest.py | 2 +- 38 files changed, 126 insertions(+), 107 deletions(-) create mode 100644 drivers/codec/manifest.py create mode 100644 drivers/dht/manifest.py create mode 100644 drivers/display/manifest.py create mode 100644 drivers/hts221/manifest.py create mode 100644 drivers/lps22h/manifest.py create mode 100644 drivers/lsm6dsox/manifest.py create mode 100644 drivers/lsm9ds1/manifest.py create mode 100644 drivers/nrf24l01/manifest.py create mode 100644 drivers/onewire/manifest.py create mode 100644 drivers/sdcard/manifest.py diff --git a/drivers/codec/manifest.py b/drivers/codec/manifest.py new file mode 100644 index 0000000000..4ff5d9fc44 --- /dev/null +++ b/drivers/codec/manifest.py @@ -0,0 +1 @@ +module("wm8960.py", opt=3) diff --git a/drivers/dht/manifest.py b/drivers/dht/manifest.py new file mode 100644 index 0000000000..72a4e0d24f --- /dev/null +++ b/drivers/dht/manifest.py @@ -0,0 +1 @@ +module("dht.py", opt=3) diff --git a/drivers/display/manifest.py b/drivers/display/manifest.py new file mode 100644 index 0000000000..d1ddff3374 --- /dev/null +++ b/drivers/display/manifest.py @@ -0,0 +1,11 @@ +# TODO: Split these into separate directories with their own manifests. +options.defaults(lcd160cr=False, ssd1306=False, test=True) + +if options.lcd160cr: + module("lcd160cr.py", opt=3) + + if options.test: + module("lcd160cr_test.py", opt=3) + +if options.ssd1306: + module("ssd1306.py", opt=3) diff --git a/drivers/hts221/manifest.py b/drivers/hts221/manifest.py new file mode 100644 index 0000000000..5f17926659 --- /dev/null +++ b/drivers/hts221/manifest.py @@ -0,0 +1 @@ +module("hts221.py", opt=3) diff --git a/drivers/lps22h/manifest.py b/drivers/lps22h/manifest.py new file mode 100644 index 0000000000..d30108d93d --- /dev/null +++ b/drivers/lps22h/manifest.py @@ -0,0 +1 @@ +module("lps22h.py", opt=3) diff --git a/drivers/lsm6dsox/manifest.py b/drivers/lsm6dsox/manifest.py new file mode 100644 index 0000000000..28f4b3565e --- /dev/null +++ b/drivers/lsm6dsox/manifest.py @@ -0,0 +1 @@ +module("lsm6dsox.py", opt=3) diff --git a/drivers/lsm9ds1/manifest.py b/drivers/lsm9ds1/manifest.py new file mode 100644 index 0000000000..6779362de7 --- /dev/null +++ b/drivers/lsm9ds1/manifest.py @@ -0,0 +1 @@ +module("lsm9ds1.py", opt=3) diff --git a/drivers/neopixel/manifest.py b/drivers/neopixel/manifest.py index 27f610adc0..561d19574a 100644 --- a/drivers/neopixel/manifest.py +++ b/drivers/neopixel/manifest.py @@ -1,5 +1 @@ -freeze( - ".", - "neopixel.py", - opt=3, -) +module("neopixel.py", opt=3) diff --git a/drivers/nrf24l01/manifest.py b/drivers/nrf24l01/manifest.py new file mode 100644 index 0000000000..babdb7a52a --- /dev/null +++ b/drivers/nrf24l01/manifest.py @@ -0,0 +1 @@ +module("nrf24l01.py", opt=3) diff --git a/drivers/onewire/manifest.py b/drivers/onewire/manifest.py new file mode 100644 index 0000000000..f500a65d78 --- /dev/null +++ b/drivers/onewire/manifest.py @@ -0,0 +1,6 @@ +options.defaults(ds18x20=False) + +module("onewire.py", opt=3) + +if options.ds18x20: + module("ds18x20.py", opt=3) diff --git a/drivers/sdcard/manifest.py b/drivers/sdcard/manifest.py new file mode 100644 index 0000000000..e584b97d9c --- /dev/null +++ b/drivers/sdcard/manifest.py @@ -0,0 +1 @@ +module("sdcard.py", opt=3) diff --git a/extmod/uasyncio/manifest.py b/extmod/uasyncio/manifest.py index f5fa27bfca..d425a467b3 100644 --- a/extmod/uasyncio/manifest.py +++ b/extmod/uasyncio/manifest.py @@ -1,13 +1,15 @@ -# This list of frozen files doesn't include task.py because that's provided by the C module. -freeze( - "..", +# This list of package files doesn't include task.py because that's provided +# by the C module. +package( + "uasyncio", ( - "uasyncio/__init__.py", - "uasyncio/core.py", - "uasyncio/event.py", - "uasyncio/funcs.py", - "uasyncio/lock.py", - "uasyncio/stream.py", + "__init__.py", + "core.py", + "event.py", + "funcs.py", + "lock.py", + "stream.py", ), + base_path="..", opt=3, ) diff --git a/extmod/webrepl/manifest.py b/extmod/webrepl/manifest.py index c504c7305c..6d1a314219 100644 --- a/extmod/webrepl/manifest.py +++ b/extmod/webrepl/manifest.py @@ -1 +1,2 @@ -freeze(".", ("webrepl.py", "webrepl_setup.py")) +module("webrepl.py", opt=3) +module("webrepl_setup.py", opt=3) diff --git a/ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py b/ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py index 0709f8597c..6c491c8f66 100644 --- a/ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py +++ b/ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py @@ -1,4 +1,4 @@ include("$(PORT_DIR)/boards/manifest.py") freeze("modules") -freeze("$(MPY_DIR)/drivers/display", "ssd1306.py") +include("$(MPY_DIR)/drivers/display", ssd1306=True) diff --git a/ports/esp32/boards/LOLIN_S2_PICO/manifest.py b/ports/esp32/boards/LOLIN_S2_PICO/manifest.py index 98d4247c60..efc37137b2 100644 --- a/ports/esp32/boards/LOLIN_S2_PICO/manifest.py +++ b/ports/esp32/boards/LOLIN_S2_PICO/manifest.py @@ -1,4 +1,4 @@ include("$(PORT_DIR)/boards/manifest.py") freeze("./modules") -freeze("$(MPY_DIR)/drivers/display", "ssd1306.py") +include("$(MPY_DIR)/drivers/display", ssd1306=True) diff --git a/ports/esp32/boards/UM_FEATHERS2/manifest.py b/ports/esp32/boards/UM_FEATHERS2/manifest.py index 82ad0c7e49..3fda1dd827 100644 --- a/ports/esp32/boards/UM_FEATHERS2/manifest.py +++ b/ports/esp32/boards/UM_FEATHERS2/manifest.py @@ -1,3 +1,3 @@ include("$(PORT_DIR)/boards/manifest.py") -freeze("$(PORT_DIR)/boards/UM_TINYPICO/modules", "dotstar.py") +module("dotstar.py", base_path="$(PORT_DIR)/boards/UM_TINYPICO/modules", opt=3) freeze("modules") diff --git a/ports/esp32/boards/manifest.py b/ports/esp32/boards/manifest.py index 23252442ea..658d11d585 100644 --- a/ports/esp32/boards/manifest.py +++ b/ports/esp32/boards/manifest.py @@ -1,14 +1,15 @@ freeze("$(PORT_DIR)/modules") -freeze("$(MPY_DIR)/tools", ("upip.py", "upip_utarfile.py")) -freeze("$(MPY_DIR)/extmod", "ntptime.py") -freeze("$(MPY_DIR)/drivers/dht", "dht.py") -freeze("$(MPY_DIR)/drivers/onewire") -include("$(MPY_DIR)/extmod/uasyncio/manifest.py") -include("$(MPY_DIR)/extmod/webrepl/manifest.py") -include("$(MPY_DIR)/drivers/neopixel/manifest.py") +module("upip.py", base_path="$(MPY_DIR)/tools", opt=3) +module("upip_utarfile.py", base_path="$(MPY_DIR)/tools", opt=3) +module("ntptime.py", base_path="$(MPY_DIR)/extmod", opt=3) +include("$(MPY_DIR)/drivers/dht") +include("$(MPY_DIR)/drivers/onewire") +include("$(MPY_DIR)/drivers/neopixel") +include("$(MPY_DIR)/extmod/uasyncio") +include("$(MPY_DIR)/extmod/webrepl") -# Freeze some micropython-lib modules. -freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py") -freeze("$(MPY_LIB_DIR)/micropython/upysh", "upysh.py") -freeze("$(MPY_LIB_DIR)/micropython/umqtt.simple", "umqtt/simple.py") -freeze("$(MPY_LIB_DIR)/micropython/umqtt.robust", "umqtt/robust.py") +# Require some micropython-lib modules. +require("urequests") +require("upysh") +require("umqtt.simple") +require("umqtt.robust") diff --git a/ports/esp8266/boards/GENERIC/manifest.py b/ports/esp8266/boards/GENERIC/manifest.py index ef25040ef8..54b916546c 100644 --- a/ports/esp8266/boards/GENERIC/manifest.py +++ b/ports/esp8266/boards/GENERIC/manifest.py @@ -2,18 +2,18 @@ include("$(PORT_DIR)/boards/manifest.py") # uasyncio -include("$(MPY_DIR)/extmod/uasyncio/manifest.py") +include("$(MPY_DIR)/extmod/uasyncio") # drivers -freeze("$(MPY_DIR)/drivers/display", "ssd1306.py") +include("$(MPY_DIR)/drivers/display", ssd1306=True) # micropython-lib: file utilities -freeze("$(MPY_LIB_DIR)/micropython/upysh", "upysh.py") +require("upysh") # micropython-lib: requests -freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py") -freeze("$(MPY_LIB_DIR)/micropython/urllib.urequest", "urllib/urequest.py") +require("urequests") +require("urllib.urequest") # micropython-lib: umqtt -freeze("$(MPY_LIB_DIR)/micropython/umqtt.simple", "umqtt/simple.py") -freeze("$(MPY_LIB_DIR)/micropython/umqtt.robust", "umqtt/robust.py") +require("umqtt.simple") +require("umqtt.robust") diff --git a/ports/esp8266/boards/GENERIC_512K/manifest.py b/ports/esp8266/boards/GENERIC_512K/manifest.py index e43d94843f..57970a6b4d 100644 --- a/ports/esp8266/boards/GENERIC_512K/manifest.py +++ b/ports/esp8266/boards/GENERIC_512K/manifest.py @@ -1,5 +1,8 @@ -freeze("$(BOARD_DIR)", "_boot.py", opt=3) -freeze("$(MPY_DIR)/drivers/dht", "dht.py") -freeze("$(MPY_DIR)/drivers/onewire") -include("$(MPY_DIR)/extmod/webrepl/manifest.py") -include("$(MPY_DIR)/drivers/neopixel/manifest.py") +module("_boot.py", opt=3) +module("apa102.py", base_path="$(PORT_DIR)/modules", opt=3) +module("port_diag.py", base_path="$(PORT_DIR)/modules", opt=3) +module("ntptime.py", base_path="$(MPY_DIR)/extmod", opt=3) +include("$(MPY_DIR)/drivers/dht") +include("$(MPY_DIR)/drivers/onewire") +include("$(MPY_DIR)/extmod/webrepl") +include("$(MPY_DIR)/drivers/neopixel") diff --git a/ports/esp8266/boards/manifest.py b/ports/esp8266/boards/manifest.py index c5809717e6..abcee253ff 100644 --- a/ports/esp8266/boards/manifest.py +++ b/ports/esp8266/boards/manifest.py @@ -1,7 +1,8 @@ freeze("$(PORT_DIR)/modules") -freeze("$(MPY_DIR)/extmod", "ntptime.py") -freeze("$(MPY_DIR)/tools", ("upip.py", "upip_utarfile.py")) -freeze("$(MPY_DIR)/drivers/dht", "dht.py") -freeze("$(MPY_DIR)/drivers/onewire") -include("$(MPY_DIR)/extmod/webrepl/manifest.py") -include("$(MPY_DIR)/drivers/neopixel/manifest.py") +module("upip.py", base_path="$(MPY_DIR)/tools", opt=3) +module("upip_utarfile.py", base_path="$(MPY_DIR)/tools", opt=3) +module("ntptime.py", base_path="$(MPY_DIR)/extmod", opt=3) +include("$(MPY_DIR)/drivers/dht") +include("$(MPY_DIR)/drivers/onewire") +include("$(MPY_DIR)/extmod/webrepl") +include("$(MPY_DIR)/drivers/neopixel") diff --git a/ports/mimxrt/boards/manifest.py b/ports/mimxrt/boards/manifest.py index 2e1a1d63d4..a273dfa370 100644 --- a/ports/mimxrt/boards/manifest.py +++ b/ports/mimxrt/boards/manifest.py @@ -1,8 +1,4 @@ freeze("$(PORT_DIR)/modules") -freeze("$(MPY_DIR)/drivers/onewire") -freeze("$(MPY_DIR)/drivers/dht", "dht.py") -include("$(MPY_DIR)/extmod/uasyncio/manifest.py") -try: - include("$(BOARD_DIR)/manifest.py") -except FileNotFoundError: - pass +include("$(MPY_DIR)/drivers/onewire") +include("$(MPY_DIR)/drivers/dht") +include("$(MPY_DIR)/extmod/uasyncio") diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py b/ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py index dbc8104dc2..2b0cc6c818 100644 --- a/ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py +++ b/ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py @@ -1,4 +1,4 @@ include("$(PORT_DIR)/modules/manifest.py") -freeze("$(MPY_DIR)/drivers/hts221", "hts221.py") -freeze("$(MPY_DIR)/drivers/lps22h", "lps22h.py") -freeze("$(MPY_DIR)/drivers/lsm9ds1", "lsm9ds1.py") +include("$(MPY_DIR)/drivers/hts221") +include("$(MPY_DIR)/drivers/lps22h") +include("$(MPY_DIR)/drivers/lsm9ds1") diff --git a/ports/nrf/modules/manifest.py b/ports/nrf/modules/manifest.py index b27d4648b7..6efaf62d79 100644 --- a/ports/nrf/modules/manifest.py +++ b/ports/nrf/modules/manifest.py @@ -1,2 +1,2 @@ -freeze("$(PORT_DIR)/modules/scripts", "_mkfs.py") -include("$(MPY_DIR)/extmod/uasyncio/manifest.py") +module("_mkfs.py", base_path="$(PORT_DIR)/modules/scripts", opt=3) +include("$(MPY_DIR)/extmod/uasyncio") diff --git a/ports/renesas-ra/boards/RA4M1_CLICKER/manifest.py b/ports/renesas-ra/boards/RA4M1_CLICKER/manifest.py index 4a387915d3..c25ae79887 100644 --- a/ports/renesas-ra/boards/RA4M1_CLICKER/manifest.py +++ b/ports/renesas-ra/boards/RA4M1_CLICKER/manifest.py @@ -1,2 +1,2 @@ # We do not want to include default frozen modules, -freeze("$(MPY_DIR)/drivers/sdcard", "sdcard.py") +include("$(MPY_DIR)/drivers/sdcard") diff --git a/ports/renesas-ra/boards/RA4M1_EK/manifest.py b/ports/renesas-ra/boards/RA4M1_EK/manifest.py index 4a387915d3..c25ae79887 100644 --- a/ports/renesas-ra/boards/RA4M1_EK/manifest.py +++ b/ports/renesas-ra/boards/RA4M1_EK/manifest.py @@ -1,2 +1,2 @@ # We do not want to include default frozen modules, -freeze("$(MPY_DIR)/drivers/sdcard", "sdcard.py") +include("$(MPY_DIR)/drivers/sdcard") diff --git a/ports/renesas-ra/boards/manifest.py b/ports/renesas-ra/boards/manifest.py index 836bf7ccc2..c66ec92015 100644 --- a/ports/renesas-ra/boards/manifest.py +++ b/ports/renesas-ra/boards/manifest.py @@ -1,4 +1,4 @@ -include("$(MPY_DIR)/extmod/uasyncio/manifest.py") -freeze("$(MPY_DIR)/drivers/dht", "dht.py") -freeze("$(MPY_DIR)/drivers/onewire", "onewire.py") -freeze("$(MPY_DIR)/drivers/sdcard", "sdcard.py") +include("$(MPY_DIR)/extmod/uasyncio") +include("$(MPY_DIR)/drivers/dht") +include("$(MPY_DIR)/drivers/onewire", ds18x20=False) +include("$(MPY_DIR)/drivers/sdcard") diff --git a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py index 7a2f1c9e27..e139c7d60b 100644 --- a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py +++ b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py @@ -1,11 +1,11 @@ include("$(PORT_DIR)/boards/manifest.py") -include("$(MPY_DIR)/extmod/webrepl/manifest.py") -freeze("$(MPY_DIR)/drivers/lsm6dsox/", "lsm6dsox.py") -include( - "$(MPY_LIB_DIR)/micropython/bluetooth/aioble/manifest.py", - client=True, - central=True, - l2cap=True, - security=True, -) -freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py") + +# Networking +include("$(MPY_DIR)/extmod/webrepl") +require("urequests") + +# Drivers +include("$(MPY_DIR)/drivers/lsm6dsox") + +# Bluetooth +require("aioble", client=True, central=True, l2cap=True, security=True) diff --git a/ports/rp2/boards/PICO_W/manifest.py b/ports/rp2/boards/PICO_W/manifest.py index d2c76602af..66ff26b0c8 100644 --- a/ports/rp2/boards/PICO_W/manifest.py +++ b/ports/rp2/boards/PICO_W/manifest.py @@ -1,7 +1,7 @@ include("../manifest.py") -freeze("$(MPY_DIR)/tools", "upip.py") -freeze("$(MPY_DIR)/tools", "upip_utarfile.py") -freeze("$(MPY_DIR)/extmod", "ntptime.py") +module("upip.py", base_path="$(MPY_DIR)/tools", opt=3) +module("upip_utarfile.py", base_path="$(MPY_DIR)/tools", opt=3) +module("ntptime.py", base_path="$(MPY_DIR)/extmod", opt=3) -freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py") +require("urequests") diff --git a/ports/rp2/boards/manifest.py b/ports/rp2/boards/manifest.py index b0e5e31554..9afcba17e8 100644 --- a/ports/rp2/boards/manifest.py +++ b/ports/rp2/boards/manifest.py @@ -1,5 +1,5 @@ freeze("$(PORT_DIR)/modules") -freeze("$(MPY_DIR)/drivers/onewire") -freeze("$(MPY_DIR)/drivers/dht", "dht.py") -include("$(MPY_DIR)/extmod/uasyncio/manifest.py") -include("$(MPY_DIR)/drivers/neopixel/manifest.py") +include("$(MPY_DIR)/drivers/onewire") +include("$(MPY_DIR)/drivers/dht") +include("$(MPY_DIR)/extmod/uasyncio") +include("$(MPY_DIR)/drivers/neopixel") diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/manifest.py b/ports/stm32/boards/ARDUINO_PORTENTA_H7/manifest.py index cd721d0ac4..0ecdcd2153 100644 --- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/manifest.py +++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/manifest.py @@ -1,9 +1,3 @@ include("$(PORT_DIR)/boards/manifest.py") -include("$(MPY_DIR)/extmod/webrepl/manifest.py") -include( - "$(MPY_LIB_DIR)/micropython/bluetooth/aioble/manifest.py", - client=True, - central=True, - l2cap=True, - security=True, -) +include("$(MPY_DIR)/extmod/webrepl") +require("aioble", client=True, central=True, l2cap=True, security=True) diff --git a/ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/manifest.py b/ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/manifest.py index b09c7ab920..69da2897ae 100644 --- a/ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/manifest.py +++ b/ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/manifest.py @@ -1,2 +1,2 @@ -include("$(MPY_DIR)/extmod/uasyncio/manifest.py") +# Note: Freezes to display.ssd1306, so must use deprecated "freeze" function. freeze("$(MPY_DIR)/drivers/", ("display/ssd1306.py")) diff --git a/ports/stm32/boards/LEGO_HUB_NO6/manifest.py b/ports/stm32/boards/LEGO_HUB_NO6/manifest.py index dc09d04c9f..107001c38e 100644 --- a/ports/stm32/boards/LEGO_HUB_NO6/manifest.py +++ b/ports/stm32/boards/LEGO_HUB_NO6/manifest.py @@ -1,3 +1,5 @@ +# Shared manifest for LEGO_HUB_NO6 & LEGO_HUB_NO7. + include("$(PORT_DIR)/boards/manifest.py") # Modules for application firmware update. diff --git a/ports/stm32/boards/LEGO_HUB_NO7/manifest.py b/ports/stm32/boards/LEGO_HUB_NO7/manifest.py index d746381637..ee79864a98 100644 --- a/ports/stm32/boards/LEGO_HUB_NO7/manifest.py +++ b/ports/stm32/boards/LEGO_HUB_NO7/manifest.py @@ -1,5 +1,2 @@ -include("$(PORT_DIR)/boards/manifest.py") - -# Modules for application firmware update. -freeze("$(PORT_DIR)/mboot", "fwupdate.py", opt=3) -freeze("$(PORT_DIR)/boards/LEGO_HUB_NO6", ("spiflash.py", "appupdate.py"), opt=3) +# Use shared manifest. +include("$(PORT_DIR)/boards/LEGO_HUB_NO6") diff --git a/ports/stm32/boards/PYBD_SF2/manifest.py b/ports/stm32/boards/PYBD_SF2/manifest.py index 3819aa01b3..e4736f693a 100644 --- a/ports/stm32/boards/PYBD_SF2/manifest.py +++ b/ports/stm32/boards/PYBD_SF2/manifest.py @@ -1,2 +1,2 @@ include("$(PORT_DIR)/boards/manifest.py") -include("$(MPY_DIR)/extmod/webrepl/manifest.py") +include("$(MPY_DIR)/extmod/webrepl") diff --git a/ports/stm32/boards/manifest.py b/ports/stm32/boards/manifest.py index 81b8583410..4bb224e2d8 100644 --- a/ports/stm32/boards/manifest.py +++ b/ports/stm32/boards/manifest.py @@ -1,4 +1,5 @@ -include("$(MPY_DIR)/extmod/uasyncio/manifest.py") -freeze("$(MPY_DIR)/drivers/dht", "dht.py") -freeze("$(MPY_DIR)/drivers/display", ("lcd160cr.py", "lcd160cr_test.py")) -freeze("$(MPY_DIR)/drivers/onewire", "onewire.py") +include("$(MPY_DIR)/extmod/uasyncio") + +include("$(MPY_DIR)/drivers/dht") +include("$(MPY_DIR)/drivers/display", lcd160cr=True, test=True) +include("$(MPY_DIR)/drivers/onewire", ds18x20=False) diff --git a/ports/unix/variants/dev/manifest.py b/ports/unix/variants/dev/manifest.py index 92a681116a..dd521258e1 100644 --- a/ports/unix/variants/dev/manifest.py +++ b/ports/unix/variants/dev/manifest.py @@ -1,3 +1,3 @@ include("$(PORT_DIR)/variants/manifest.py") -include("$(MPY_DIR)/extmod/uasyncio/manifest.py") +include("$(MPY_DIR)/extmod/uasyncio") diff --git a/ports/unix/variants/manifest.py b/ports/unix/variants/manifest.py index 7708e598db..bf7ce992ad 100644 --- a/ports/unix/variants/manifest.py +++ b/ports/unix/variants/manifest.py @@ -1,2 +1,2 @@ -freeze_as_mpy("$(MPY_DIR)/tools", "upip.py") -freeze_as_mpy("$(MPY_DIR)/tools", "upip_utarfile.py", opt=3) +module("upip.py", base_path="$(MPY_DIR)/tools", opt=3) +module("upip_utarfile.py", base_path="$(MPY_DIR)/tools", opt=3) diff --git a/ports/windows/variants/dev/manifest.py b/ports/windows/variants/dev/manifest.py index 88a6937b4f..f65a3d35e9 100644 --- a/ports/windows/variants/dev/manifest.py +++ b/ports/windows/variants/dev/manifest.py @@ -1,2 +1,2 @@ include("$(PORT_DIR)/variants/manifest.py") -include("$(MPY_DIR)/extmod/uasyncio/manifest.py") +include("$(MPY_DIR)/extmod/uasyncio") From fb20dbe4d123c69a7770e70911e827cefef01aa3 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 6 Sep 2022 10:57:33 +1000 Subject: [PATCH 0368/1041] stm32/boards/LEGO_HUB_NO6: Update manifest to new format. This was added after 203dae41f and missed in the rebase. Signed-off-by: Jim Mussared --- ports/stm32/boards/LEGO_HUB_NO6/manifest.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/LEGO_HUB_NO6/manifest.py b/ports/stm32/boards/LEGO_HUB_NO6/manifest.py index 107001c38e..1be4246e37 100644 --- a/ports/stm32/boards/LEGO_HUB_NO6/manifest.py +++ b/ports/stm32/boards/LEGO_HUB_NO6/manifest.py @@ -3,5 +3,6 @@ include("$(PORT_DIR)/boards/manifest.py") # Modules for application firmware update. -freeze("$(PORT_DIR)/mboot", "fwupdate.py", opt=3) -freeze("$(BOARD_DIR)", ("spiflash.py", "appupdate.py"), opt=3) +module("fwupdate.py", base_path="$(PORT_DIR)/mboot", opt=3) +module("spiflash.py", opt=3) +module("appupdate.py", opt=3) From 655c29351a7c4ef74612edf6088036b07f39e6c7 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 6 Sep 2022 11:52:46 +1000 Subject: [PATCH 0369/1041] drivers/display: Don't include tests by default. The tests can be copied to the board if needed. Also update the docs to reflect this change. Signed-off-by: Damien George --- docs/pyboard/tutorial/lcd160cr_skin.rst | 4 ++-- docs/reference/mpremote.rst | 2 ++ drivers/display/manifest.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/pyboard/tutorial/lcd160cr_skin.rst b/docs/pyboard/tutorial/lcd160cr_skin.rst index fc9d635382..fa0debcb1c 100644 --- a/docs/pyboard/tutorial/lcd160cr_skin.rst +++ b/docs/pyboard/tutorial/lcd160cr_skin.rst @@ -40,9 +40,9 @@ Testing the display There is a test program which you can use to test the features of the display, and which also serves as a basis to start creating your own code that uses the -LCD. This test program is included in recent versions of the pyboard firmware -and is also available on GitHub +LCD. This test program is available on GitHub `here `__. +Copy it to the board over USB mass storage, or by using `mpremote`. To run the test from the MicroPython prompt do:: diff --git a/docs/reference/mpremote.rst b/docs/reference/mpremote.rst index a48df9953f..e3902f8e5d 100644 --- a/docs/reference/mpremote.rst +++ b/docs/reference/mpremote.rst @@ -1,3 +1,5 @@ +.. _mpremote: + MicroPython remote control: mpremote ==================================== diff --git a/drivers/display/manifest.py b/drivers/display/manifest.py index d1ddff3374..16f93a7d4e 100644 --- a/drivers/display/manifest.py +++ b/drivers/display/manifest.py @@ -1,5 +1,5 @@ # TODO: Split these into separate directories with their own manifests. -options.defaults(lcd160cr=False, ssd1306=False, test=True) +options.defaults(lcd160cr=False, ssd1306=False, test=False) if options.lcd160cr: module("lcd160cr.py", opt=3) From 4e4c28bf27ff4a9e1a2ce5b6fffa641d9a332507 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 6 Sep 2022 11:53:36 +1000 Subject: [PATCH 0370/1041] stm32/boards: Only freeze LCD160CR driver in PYB board firmware. Although this driver and associated hardware can be used on any board, it makes to only freeze it for PYB and PYBD boards. It can be easily copied to any board if needed. Fixes issue #8056. Signed-off-by: Damien George --- ports/stm32/boards/PYBD_SF2/manifest.py | 1 + ports/stm32/boards/PYBLITEV10/mpconfigboard.mk | 3 +++ ports/stm32/boards/PYBV10/manifest.py | 2 ++ ports/stm32/boards/PYBV10/mpconfigboard.mk | 3 +++ ports/stm32/boards/PYBV11/mpconfigboard.mk | 3 +++ ports/stm32/boards/manifest.py | 1 - ports/stm32/boards/manifest_pyboard.py | 1 + 7 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 ports/stm32/boards/PYBV10/manifest.py create mode 100644 ports/stm32/boards/manifest_pyboard.py diff --git a/ports/stm32/boards/PYBD_SF2/manifest.py b/ports/stm32/boards/PYBD_SF2/manifest.py index e4736f693a..a9e92848d5 100644 --- a/ports/stm32/boards/PYBD_SF2/manifest.py +++ b/ports/stm32/boards/PYBD_SF2/manifest.py @@ -1,2 +1,3 @@ include("$(PORT_DIR)/boards/manifest.py") +include("$(PORT_DIR)/boards/manifest_pyboard.py") include("$(MPY_DIR)/extmod/webrepl") diff --git a/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk b/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk index 8aeaf0e40c..7469866476 100644 --- a/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk +++ b/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk @@ -24,3 +24,6 @@ endif ifeq ($(BOARD_VARIANT),"network") MICROPY_PY_NETWORK_WIZNET5K=5200 endif + +# PYB-specific frozen modules +FROZEN_MANIFEST ?= boards/PYBV10/manifest.py diff --git a/ports/stm32/boards/PYBV10/manifest.py b/ports/stm32/boards/PYBV10/manifest.py new file mode 100644 index 0000000000..ec0d4a26b7 --- /dev/null +++ b/ports/stm32/boards/PYBV10/manifest.py @@ -0,0 +1,2 @@ +include("$(PORT_DIR)/boards/manifest.py") +include("$(PORT_DIR)/boards/manifest_pyboard.py") diff --git a/ports/stm32/boards/PYBV10/mpconfigboard.mk b/ports/stm32/boards/PYBV10/mpconfigboard.mk index 97af22b5e1..af28782678 100644 --- a/ports/stm32/boards/PYBV10/mpconfigboard.mk +++ b/ports/stm32/boards/PYBV10/mpconfigboard.mk @@ -34,3 +34,6 @@ endif ifeq ($(BOARD_VARIANT),"network") MICROPY_PY_NETWORK_WIZNET5K=5200 endif + +# PYB-specific frozen modules +FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py diff --git a/ports/stm32/boards/PYBV11/mpconfigboard.mk b/ports/stm32/boards/PYBV11/mpconfigboard.mk index 97af22b5e1..cf7884cfc6 100644 --- a/ports/stm32/boards/PYBV11/mpconfigboard.mk +++ b/ports/stm32/boards/PYBV11/mpconfigboard.mk @@ -34,3 +34,6 @@ endif ifeq ($(BOARD_VARIANT),"network") MICROPY_PY_NETWORK_WIZNET5K=5200 endif + +# PYB-specific frozen modules +FROZEN_MANIFEST ?= boards/PYBV10/manifest.py diff --git a/ports/stm32/boards/manifest.py b/ports/stm32/boards/manifest.py index 4bb224e2d8..723caa3eb6 100644 --- a/ports/stm32/boards/manifest.py +++ b/ports/stm32/boards/manifest.py @@ -1,5 +1,4 @@ include("$(MPY_DIR)/extmod/uasyncio") include("$(MPY_DIR)/drivers/dht") -include("$(MPY_DIR)/drivers/display", lcd160cr=True, test=True) include("$(MPY_DIR)/drivers/onewire", ds18x20=False) diff --git a/ports/stm32/boards/manifest_pyboard.py b/ports/stm32/boards/manifest_pyboard.py new file mode 100644 index 0000000000..e4fb0a8c4d --- /dev/null +++ b/ports/stm32/boards/manifest_pyboard.py @@ -0,0 +1 @@ +include("$(MPY_DIR)/drivers/display", lcd160cr=True) From 8770cd2f4d24b1ad14c934b4161e42108fe98f84 Mon Sep 17 00:00:00 2001 From: yn386 Date: Sun, 28 Aug 2022 15:40:00 +0900 Subject: [PATCH 0371/1041] stm32/adc: Make ADCAll.read_channel reject invalid channels. pyb.ADC(channel) checks whether specified channel is valid or have ADC capability but pyb.ADCAll().read_channel() does not. This change adds checking whether specified channel is valid and throw ValueError if channel is invalid. This is same as pyb.ADC(). --- ports/stm32/adc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index 9b7788e59e..9d58cf2e7c 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -856,6 +856,9 @@ STATIC mp_obj_t adc_all_make_new(const mp_obj_type_t *type, size_t n_args, size_ STATIC mp_obj_t adc_all_read_channel(mp_obj_t self_in, mp_obj_t channel) { pyb_adc_all_obj_t *self = MP_OBJ_TO_PTR(self_in); uint32_t chan = adc_get_internal_channel(mp_obj_get_int(channel)); + if (!is_adcx_channel(chan)) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("not a valid ADC Channel: %d"), chan); + } uint32_t data = adc_config_and_read_channel(&self->handle, chan); return mp_obj_new_int(data); } From da50827657d6bc3024dd6acea76cb315d1cbbae1 Mon Sep 17 00:00:00 2001 From: yn386 Date: Wed, 31 Aug 2022 19:13:00 +0900 Subject: [PATCH 0372/1041] stm32/pyb_i2c: Fix pyb.I2C to work with dma=True on F4 MCUs. Prior to this commit, excuting this code: i2c = I2C(1, I2C.CONTROLLER, dma=True) i2c.send(data, addr=i2c_addr) the call to i2c.send() does not return and the board needs a reset. This code works when dma=False. According to the specification, I2Cx_EV_IRQHandler should: - Write DR to address when Start condition generated. - Clear ADDR by reading SR2 after reading SR2 when address sent. These processes are included in HAL_I2C_EV_IRQHandler(), however the firmware size increses about 2KB if HAL_I2C_EV_IRQHandler is called. This commit adds above processes to i2c_ev_irq_handler, and increases firmware by less than 100 bytes. Fixes issue #2643. --- ports/stm32/pyb_i2c.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ports/stm32/pyb_i2c.c b/ports/stm32/pyb_i2c.c index 436b1c9bc2..e9877422ca 100644 --- a/ports/stm32/pyb_i2c.c +++ b/ports/stm32/pyb_i2c.c @@ -472,7 +472,17 @@ void i2c_ev_irq_handler(mp_uint_t i2c_id) { #if defined(STM32F4) - if (hi2c->Instance->SR1 & I2C_FLAG_BTF && hi2c->State == HAL_I2C_STATE_BUSY_TX) { + if (hi2c->Instance->SR1 & I2C_FLAG_SB) { + if (hi2c->State == HAL_I2C_STATE_BUSY_TX) { + hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(hi2c->Devaddress); + } else { + hi2c->Instance->DR = I2C_7BIT_ADD_READ(hi2c->Devaddress); + } + } else if (hi2c->Instance->SR1 & I2C_FLAG_ADDR) { + __IO uint32_t tmp_sr2; + tmp_sr2 = hi2c->Instance->SR2; + UNUSED(tmp_sr2); + } else if (hi2c->Instance->SR1 & I2C_FLAG_BTF && hi2c->State == HAL_I2C_STATE_BUSY_TX) { if (hi2c->XferCount != 0U) { hi2c->Instance->DR = *hi2c->pBuffPtr++; hi2c->XferCount--; From 989b8c728b296969e6489908b8e94ed23625a1e8 Mon Sep 17 00:00:00 2001 From: yn386 Date: Thu, 1 Sep 2022 18:08:18 +0900 Subject: [PATCH 0373/1041] stm32/timer: Fix use of timer channel callback() method on L4 MCUs. Since L4 HAL version 1.17.0, HAL_TIM_IC_Start_IT() checks whether specified channel of timer is busy or not, which is the case if this function is called more than once without first calling HAL_TIM_IC_Stop_IT(). The fix in this commit is to call the stop function before calling start. The PWM and OC modes have the same issue with the same fix. Fixes issue #8732. --- ports/stm32/timer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index 0cef60cb62..518a2e23b4 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -1576,6 +1576,7 @@ STATIC mp_obj_t pyb_timer_channel_callback(mp_obj_t self_in, mp_obj_t callback) switch (self->mode) { case CHANNEL_MODE_PWM_NORMAL: case CHANNEL_MODE_PWM_INVERTED: + HAL_TIM_PWM_Stop_IT(&self->timer->tim, TIMER_CHANNEL(self)); HAL_TIM_PWM_Start_IT(&self->timer->tim, TIMER_CHANNEL(self)); break; case CHANNEL_MODE_OC_TIMING: @@ -1584,9 +1585,11 @@ STATIC mp_obj_t pyb_timer_channel_callback(mp_obj_t self_in, mp_obj_t callback) case CHANNEL_MODE_OC_TOGGLE: case CHANNEL_MODE_OC_FORCED_ACTIVE: case CHANNEL_MODE_OC_FORCED_INACTIVE: + HAL_TIM_OC_Stop_IT(&self->timer->tim, TIMER_CHANNEL(self)); HAL_TIM_OC_Start_IT(&self->timer->tim, TIMER_CHANNEL(self)); break; case CHANNEL_MODE_IC: + HAL_TIM_IC_Stop_IT(&self->timer->tim, TIMER_CHANNEL(self)); HAL_TIM_IC_Start_IT(&self->timer->tim, TIMER_CHANNEL(self)); break; } From 719dbbf5639cdeff99bf629c45d66b18007e9958 Mon Sep 17 00:00:00 2001 From: yn386 Date: Fri, 2 Sep 2022 18:46:10 +0900 Subject: [PATCH 0374/1041] stm32/boards: Add alternate function list for STM32F446RE. Signed-off-by: Damien George --- .../boards/NUCLEO_F446RE/mpconfigboard.mk | 2 +- ports/stm32/boards/stm32f446_af.csv | 116 ++++++++++++++++++ 2 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 ports/stm32/boards/stm32f446_af.csv diff --git a/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.mk index 64a80e992b..3a922acebf 100644 --- a/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.mk @@ -1,6 +1,6 @@ MCU_SERIES = f4 CMSIS_MCU = STM32F446xx -AF_FILE = boards/stm32f429_af.csv +AF_FILE = boards/stm32f446_af.csv LD_FILES = boards/stm32f411.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 diff --git a/ports/stm32/boards/stm32f446_af.csv b/ports/stm32/boards/stm32f446_af.csv new file mode 100644 index 0000000000..0838ed089d --- /dev/null +++ b/ports/stm32/boards/stm32f446_af.csv @@ -0,0 +1,116 @@ +Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, +,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11/CEC,I2C1/2/3/4/CEC,SPI1/2/3/4,SPI2/3/4/SAI1,SPI2/3/USART1/2/3/UART5/SPDIFRX,SAI/USART6/UART4/5/SPDIFRX,CAN1/2/TIM12/13/14/QUADSPI,SAI2/QUADSPI/OTG2_HS/OTG1_FS,OTG1_FS,FMC/SDIO/OTG2_FS,DCMI,,SYS, +PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,,,,,EVENTOUT,ADC123_IN0 +PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,QUADSPI_BK1_IO3,SAI2_MCLK_B,,,,,EVENTOUT,ADC123_IN1 +PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,SAI2_SCK_B,,,,,,,EVENTOUT,ADC123_IN2 +PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,SAI1_FS_A,USART2_RX,,,OTG_HS_ULPI_D0,,,,,EVENTOUT,ADC123_IN3 +PortA,PA4,,,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,,EVENTOUT,ADC12_IN4 +PortA,PA5,,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK/I2S1_CK,,,,,OTG_HS_ULPI_CK,,,,,EVENTOUT,ADC12_IN5 +PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,I2S2_MCK,,,TIM13_CH1,,,,DCMI_PIXCLK,,EVENTOUT,ADC12_IN6 +PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI/I2S1_SD,,,,TIM14_CH1,,,FMC_SDNWE,,,EVENTOUT,ADC12_IN7 +PortA,PA8,MCO1,TIM1_CH1,,,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,,,,,EVENTOUT, +PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,SPI2_SCK/I2S2_CK,SAI1_SD_B,USART1_TX,,,,,,DCMI_D0,,EVENTOUT, +PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,,,DCMI_D1,,EVENTOUT, +PortA,PA11,,TIM1_CH4,,,,,,USART1_CTS,,CAN1_RX,OTG_FS_DM,,,,,EVENTOUT, +PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS,SAI2_FS_B,CAN1_TX,OTG_FS_DP,,,,,EVENTOUT, +PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT, +PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT, +PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,HDMI_CEC,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,,UART4_RTS,,,,,,,EVENTOUT, +PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,SPI3_MOSI/I2S3_SD,UART4_CTS,,OTG_HS_ULPI_D1,,SDIO_D1,,,EVENTOUT,ADC12_IN8 +PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,,,,,OTG_HS_ULPI_D2,,SDIO_D2,,,EVENTOUT,ADC12_IN9 +PortB,PB2,,TIM2_CH4,,,,,SAI1_SD_A,SPI3_MOSI/I2S3_SD,,QUADSPI_CLK,OTG_HS_ULPI_D4,,SDIO_CK,,,EVENTOUT, +PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,I2C2_SDA,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,,,,,,,,,EVENTOUT, +PortB,PB4,NJTRST,,TIM3_CH1,,I2C3_SDA,SPI1_MISO,SPI3_MISO,SPI2_NSS/I2S2_WS,,,,,,,,EVENTOUT, +PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI/I2S1_SD,SPI3_MOSI/I2S3_SD,,,CAN2_RX,OTG_HS_ULPI_D7,,FMC_SDCKE1,DCMI_D10,,EVENTOUT, +PortB,PB6,,,TIM4_CH1,HDMI_CEC,I2C1_SCL,,,USART1_TX,,CAN2_TX,QUADSPI_BK1_NCS,,FMC_SDNE1,DCMI_D5,,EVENTOUT, +PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,SPDIF_RX0,,,,FMC_NL,DCMI_VSYNC,,EVENTOUT, +PortB,PB8,,TIM2_CH1/TIM2_ETR,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,CAN1_RX,,,SDIO_D4,DCMI_D6,,EVENTOUT, +PortB,PB9,,TIM2_CH2,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,SAI1_FS_B,,,CAN1_TX,,,SDIO_D5,DCMI_D7,,EVENTOUT, +PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,SAI1_SCK_A,USART3_TX,,,OTG_HS_ULPI_D3,,,,,EVENTOUT, +PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,,USART3_RX,SAI2_SD_A,,,,,,,EVENTOUT, +PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,SAI1_SCK_B,USART3_CK,,CAN2_RX,OTG_HS_ULPI_D5,,OTG_HS_ID,,,EVENTOUT, +PortB,PB13,,TIM1_CH1N,,,,SPI2_SCK/I2S2_CK,,USART3_CTS,,CAN2_TX,OTG_HS_ULPI_D6,,,,,EVENTOUT, +PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,,SPI2_MISO,,USART3_RTS,,TIM12_CH1,,,OTG_HS_DM,,,EVENTOUT, +PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI/I2S2_SD,,,,TIM12_CH2,,,OTG_HS_DP,,,EVENTOUT, +PortC,PC0,,,,,,,SAI1_MCLK_B,,,,OTG_HS_ULPI_STP,,FMC_SDNWE,,,EVENTOUT,ADC123_IN10 +PortC,PC1,,,,,,SPI3_MOSI/I2S3_SD,SAI1_SD_A,SPI2_MOSI/I2S2_SD,,,,,,,,EVENTOUT,ADC123_IN11 +PortC,PC2,,,,,,SPI2_MISO,,,,,OTG_HS_ULPI_DIR,,FMC_SDNE0,,,EVENTOUT,ADC123_IN12 +PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,,FMC_SDCKE0,,,EVENTOUT,ADC123_IN13 +PortC,PC4,,,,,,I2S1_MCK,,,SPDIF_RX2,,,,FMC_SDNE0,,,EVENTOUT,ADC12_IN14 +PortC,PC5,,,,,,,,USART3_RX,SPDIF_RX3,,,,FMC_SDCKE0,,,EVENTOUT,ADC12_IN15 +PortC,PC6,,,TIM3_CH1,TIM8_CH1,FMPI2C1_SCL,I2S2_MCK,,,USART6_TX,,,,SDIO_D6,DCMI_D0,,EVENTOUT, +PortC,PC7,,,TIM3_CH2,TIM8_CH2,FMPI2C1_SDA,SPI2_SCK/I2S2_CK,I2S3_MCK,SPDIF_RX1,USART6_RX,,,,SDIO_D7,DCMI_D1,,EVENTOUT, +PortC,PC8,TRACED0,,TIM3_CH3,TIM8_CH3,,,,UART5_RTS,USART6_CK,,,,SDIO_D0,DCMI_D2,,EVENTOUT, +PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S_CKIN,,UART5_CTS,,QUADSPI_BK1_IO0,,,SDIO_D1,DCMI_D3,,EVENTOUT, +PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,QUADSPI_BK1_IO1,,,SDIO_D2,DCMI_D8,,EVENTOUT, +PortC,PC11,,,,,,,SPI3_MISO,USART3_RX,UART4_RX,QUADSPI_BK2_NCS,,,SDIO_D3,DCMI_D4,,EVENTOUT, +PortC,PC12,,,,,I2C2_SDA,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,,,SDIO_CK,DCMI_D9,,EVENTOUT, +PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, +PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, +PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, +PortD,PD0,,,,,,SPI4_MISO,SPI3_MOSI/I2S3_SD,,,CAN1_RX,,,FMC_D2,,,EVENTOUT, +PortD,PD1,,,,,,,,SPI2_NSS/I2S2_WS,,CAN1_TX,,,FMC_D3,,,EVENTOUT, +PortD,PD2,,,TIM3_ETR,,,,,,UART5_RX,,,,SDIO_CMD,DCMI_D11,,EVENTOUT, +PortD,PD3,TRACED1,,,,,SPI2_SCK/I2S2_CK,,USART2_CTS,,QUADSPI_CLK,,,FMC_CLK,DCMI_D5,,EVENTOUT, +PortD,PD4,,,,,,,,USART2_RTS,,,,,FMC_NOE,,,EVENTOUT, +PortD,PD5,,,,,,,,USART2_TX,,,,,FMC_NWE,,,EVENTOUT, +PortD,PD6,,,,,,SPI3_MOSI/I2S3_SD,SAI1_SD_A,USART2_RX,,,,,FMC_NWAIT,DCMI_D10,,EVENTOUT, +PortD,PD7,,,,,,,,USART2_CK,SPDIF_RX0,,,,FMC_NE1,,,EVENTOUT, +PortD,PD8,,,,,,,,USART3_TX,SPDIF_RX1,,,,FMC_D13,,,EVENTOUT, +PortD,PD9,,,,,,,,USART3_RX,,,,,FMC_D14,,,EVENTOUT, +PortD,PD10,,,,,,,,USART3_CK,,,,,FMC_D15,,,EVENTOUT, +PortD,PD11,,,,,FMPI2C1_SMBA,,,USART3_CTS,,QUADSPI_BK1_IO0,SAI2_SD_A,,FMC_A16,,,EVENTOUT, +PortD,PD12,,,TIM4_CH1,,FMPI2C1_SCL,,,USART3_RTS,,QUADSPI_BK1_IO1,SAI2_FS_A,,FMC_A17,,,EVENTOUT, +PortD,PD13,,,TIM4_CH2,,FMPI2C1_SDA,,,,,QUADSPI_BK1_IO3,SAI2_SCK_A,,FMC_A18,,,EVENTOUT, +PortD,PD14,,,TIM4_CH3,,FMPI2C1_SCL,,,,SAI2_SCK_A,,,,FMC_D0,,,EVENTOUT, +PortD,PD15,,,TIM4_CH4,,FMPI2C1_SDA,,,,,,,,FMC_D1,,,EVENTOUT, +PortE,PE0,,,TIM4_ETR,,,,,,,,SAI2_MCLK_A,,FMC_NBL0,DCMI_D2,,EVENTOUT, +PortE,PE1,,,,,,,,,,,,,FMC_NBL1,DCMI_D3,,EVENTOUT, +PortE,PE2,TRACECLK,,,,,SPI4_SCK,SAI1_MCLK_A,,,QUADSPI_BK1_IO2,,,FMC_A23,,,EVENTOUT, +PortE,PE3,TRACED0,,,,,,SAI1_SD_B,,,,,,FMC_A19,,,EVENTOUT, +PortE,PE4,TRACED1,,,,,SPI4_NSS,SAI1_FS_A,,,,,,FMC_A20,DCMI_D4,,EVENTOUT, +PortE,PE5,TRACED2,,,TIM9_CH1,,SPI4_MISO,SAI1_SCK_A,,,,,,FMC_A21,DCMI_D6,,EVENTOUT, +PortE,PE6,TRACED3,,,TIM9_CH2,,SPI4_MOSI,SAI1_SD_A,,,,,,FMC_A22,DCMI_D7,,EVENTOUT, +PortE,PE7,,TIM1_ETR,,,,,,,UART5_RX,,QUADSPI_BK2_IO0,,FMC_D4,,,EVENTOUT, +PortE,PE8,,TIM1_CH1N,,,,,,,UART5_TX,,QUADSPI_BK2_IO1,,FMC_D5,,,EVENTOUT, +PortE,PE9,,TIM1_CH1,,,,,,,,,QUADSPI_BK2_IO2,,FMC_D6,,,EVENTOUT, +PortE,PE10,,TIM1_CH2N,,,,,,,,,QUADSPI_BK2_IO3,,FMC_D7,,,EVENTOUT, +PortE,PE11,,TIM1_CH2,,,,SPI4_NSS,,,,,SAI2_SD_B,,FMC_D8,,,EVENTOUT, +PortE,PE12,,TIM1_CH3N,,,,SPI4_SCK,,,,,SAI2_SCK_B,,FMC_D9,,,EVENTOUT, +PortE,PE13,,TIM1_CH3,,,,SPI4_MISO,,,,,SAI2_FS_B,,FMC_D10,,,EVENTOUT, +PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI,,,,,SAI2_MCLK_B,,FMC_D11,,,EVENTOUT, +PortE,PE15,,TIM1_BKIN,,,,,,,,,,,FMC_D12,,,EVENTOUT, +PortF,PF0,,,,,I2C2_SDA,,,,,,,,FMC_A0,,,EVENTOUT, +PortF,PF1,,,,,I2C2_SCL,,,,,,,,FMC_A1,,,EVENTOUT, +PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FMC_A2,,,EVENTOUT, +PortF,PF3,,,,,,,,,,,,,FMC_A3,,,EVENTOUT,ADC3_IN9 +PortF,PF4,,,,,,,,,,,,,FMC_A4,,,EVENTOUT,ADC3_IN14 +PortF,PF5,,,,,,,,,,,,,FMC_A5,,,EVENTOUT,ADC3_IN15 +PortF,PF6,,,,TIM10_CH1,,,SAI1_SD_B,,,QUADSPI_BK1_IO3,,,,,,EVENTOUT,ADC3_IN4 +PortF,PF7,,,,TIM11_CH1,,,SAI1_MCLK_B,,,QUADSPI_BK1_IO2,,,,,,EVENTOUT,ADC3_IN5 +PortF,PF8,,,,,,,SAI1_SCK_B,,,TIM13_CH1,QUADSPI_BK1_IO0,,,,,EVENTOUT,ADC3_IN6 +PortF,PF9,,,,,,,SAI1_FS_B,,,TIM14_CH1,QUADSPI_BK1_IO1,,,,,EVENTOUT,ADC3_IN7 +PortF,PF10,,,,,,,,,,,,,,DCMI_D11,,EVENTOUT,ADC3_IN8 +PortF,PF11,,,,,,,,,,,SAI2_SD_B,,FMC_SDNRAS,DCMI_D12,,EVENTOUT, +PortF,PF12,,,,,,,,,,,,,FMC_A6,,,EVENTOUT, +PortF,PF13,,,,,FMPI2C1_SMBA,,,,,,,,FMC_A7,,,EVENTOUT, +PortF,PF14,,,,,FMPI2C1_SCL,,,,,,,,FMC_A8,,,EVENTOUT, +PortF,PF15,,,,,FMPI2C1_SDA,,,,,,,,FMC_A9,,,EVENTOUT, +PortG,PG0,,,,,,,,,,,,,FMC_A10,,,EVENTOUT, +PortG,PG1,,,,,,,,,,,,,FMC_A11,,,EVENTOUT, +PortG,PG2,,,,,,,,,,,,,FMC_A12,,,EVENTOUT, +PortG,PG3,,,,,,,,,,,,,FMC_A13,,,EVENTOUT, +PortG,PG4,,,,,,,,,,,,,FMC_A14/FMC_BA0,,,EVENTOUT, +PortG,PG5,,,,,,,,,,,,,FMC_A15/FMC_BA1,,,EVENTOUT, +PortG,PG6,,,,,,,,,,,QUADSPI_BK1_NCS,,,DCMI_D12,,EVENTOUT, +PortG,PG7,,,,,,,,,USART6_CK,,,,FMC_INT,DCMI_D13,,EVENTOUT, +PortG,PG8,,,,,,,,SPDIFRX_IN2,USART6_RTS,,,,FMC_SDCLK,,,EVENTOUT, +PortG,PG9,,,,,,,,SPDIFRX_IN3,USART6_RX,QUADSPI_BK2_IO2,SAI2_FS_B,,FMC_NE2/FMC_NCE3,DCMI_VSYNC,,EVENTOUT, +PortG,PG10,,,,,,,,,,,SAI2_SD_B,,FMC_NE3,DCMI_D2,,EVENTOUT, +PortG,PG11,,,,,,,SPI4_SCK,SPDIFRX_IN0,,,,,,DCMI_D3,,EVENTOUT, +PortG,PG12,,,,,,,SPI4_MISO,SPDIFRX_IN1,USART6_RTS,,,,FMC_NE4,,,EVENTOUT, +PortG,PG13,TRACED2,,,,,,SPI4_MOSI,,USART6_CTS,,,,FMC_A24,,,EVENTOUT, +PortG,PG14,TRACED3,,,,,,SPI4_NSS,,USART6_TX,QUADSPI_BK2_IO3,,,FMC_A25,,,EVENTOUT, +PortG,PG15,,,,,,,,,USART6_CTS,,,,FMC_SDNCAS,DCMI_D13,,EVENTOUT, +PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT, +PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT, From e90b85cc98a24003f2d673bab2c255ab3dce66e7 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 5 Sep 2022 07:58:04 -0500 Subject: [PATCH 0375/1041] extmod/modure: Convert byte offsets to unicode indices when necessary. And add a test. Fixes issue #9202. Signed-off-by: Jeff Epler --- extmod/modure.c | 16 ++++++++++++++++ tests/unicode/unicode_ure.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 tests/unicode/unicode_ure.py diff --git a/extmod/modure.c b/extmod/modure.c index 799fef13b1..a674d66499 100644 --- a/extmod/modure.c +++ b/extmod/modure.c @@ -33,6 +33,10 @@ #include "py/objstr.h" #include "py/stackctrl.h" +#if MICROPY_PY_BUILTINS_STR_UNICODE +#include "py/unicode.h" +#endif + #if MICROPY_PY_URE #define re1_5_stack_chk() MP_STACK_CHECK() @@ -121,6 +125,18 @@ STATIC void match_span_helper(size_t n_args, const mp_obj_t *args, mp_obj_t span e = self->caps[no * 2 + 1] - begin; } + #if MICROPY_PY_BUILTINS_STR_UNICODE + if (mp_obj_get_type(self->str) == &mp_type_str) { + const byte *begin = (const byte *)mp_obj_str_get_str(self->str); + if (s != -1) { + s = utf8_ptr_to_index(begin, begin + s); + } + if (e != -1) { + e = utf8_ptr_to_index(begin, begin + e); + } + } + #endif + span[0] = mp_obj_new_int(s); span[1] = mp_obj_new_int(e); } diff --git a/tests/unicode/unicode_ure.py b/tests/unicode/unicode_ure.py new file mode 100644 index 0000000000..5a5dc60054 --- /dev/null +++ b/tests/unicode/unicode_ure.py @@ -0,0 +1,32 @@ +# test match.span() for unicode strings + +try: + import ure as re +except ImportError: + try: + import re + except ImportError: + print("SKIP") + raise SystemExit + +try: + m = re.match(".", "a") + m.span +except AttributeError: + print("SKIP") + raise SystemExit + + +def print_spans(match): + print("----") + try: + i = 0 + while True: + print(match.span(i), match.start(i), match.end(i)) + i += 1 + except IndexError: + pass + + +m = re.match(r"([0-9]*)(([a-z]*)([0-9]*))", "1234\u2764567") +print_spans(m) From aeff6911d750a2d203eeb1cacd74701de5313ee6 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 8 Sep 2022 11:24:18 +1000 Subject: [PATCH 0376/1041] lib/micropython-lib: Update submodule to latest. This brings in the drivers and libraries that were previously in this repo. Signed-off-by: Jim Mussared --- lib/micropython-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/micropython-lib b/lib/micropython-lib index f3cfc52ab0..58f8bec54d 160000 --- a/lib/micropython-lib +++ b/lib/micropython-lib @@ -1 +1 @@ -Subproject commit f3cfc52ab076fc913dc6e266fb7370b418c8f542 +Subproject commit 58f8bec54d5b3b959247b73a6e8f28e8493bd30b From d84c6ef0e8dd363881d80b2d8fb03447cc349830 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 6 Sep 2022 13:49:41 +1000 Subject: [PATCH 0377/1041] ports: Use micropython-lib version of drivers in manifests. --- .../esp32/boards/LILYGO_TTGO_LORA32/manifest.py | 3 +-- ports/esp32/boards/LOLIN_S2_PICO/manifest.py | 3 +-- ports/esp32/boards/manifest.py | 17 +++++++++-------- ports/esp8266/boards/GENERIC/manifest.py | 2 +- ports/esp8266/boards/GENERIC_512K/manifest.py | 11 ++++++----- ports/esp8266/boards/manifest.py | 11 ++++++----- ports/mimxrt/boards/manifest.py | 5 +++-- .../arduino_nano_33_ble_sense/manifest.py | 6 +++--- .../renesas-ra/boards/RA4M1_CLICKER/manifest.py | 2 +- ports/renesas-ra/boards/RA4M1_EK/manifest.py | 2 +- ports/renesas-ra/boards/manifest.py | 6 +++--- .../ARDUINO_NANO_RP2040_CONNECT/manifest.py | 4 ++-- ports/rp2/boards/PICO_W/manifest.py | 2 +- ports/rp2/boards/manifest.py | 7 ++++--- .../boards/ARDUINO_PORTENTA_H7/manifest.py | 2 +- .../GARATRONIC_PYBSTICK26_F411/manifest.py | 3 +-- ports/stm32/boards/PYBD_SF2/manifest.py | 2 +- ports/stm32/boards/manifest.py | 4 ++-- ports/stm32/boards/manifest_pyboard.py | 2 +- 19 files changed, 48 insertions(+), 46 deletions(-) diff --git a/ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py b/ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py index 6c491c8f66..e2cd6b3d01 100644 --- a/ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py +++ b/ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py @@ -1,4 +1,3 @@ include("$(PORT_DIR)/boards/manifest.py") freeze("modules") - -include("$(MPY_DIR)/drivers/display", ssd1306=True) +require("ssd1306") diff --git a/ports/esp32/boards/LOLIN_S2_PICO/manifest.py b/ports/esp32/boards/LOLIN_S2_PICO/manifest.py index efc37137b2..9ac8ade827 100644 --- a/ports/esp32/boards/LOLIN_S2_PICO/manifest.py +++ b/ports/esp32/boards/LOLIN_S2_PICO/manifest.py @@ -1,4 +1,3 @@ include("$(PORT_DIR)/boards/manifest.py") freeze("./modules") - -include("$(MPY_DIR)/drivers/display", ssd1306=True) +require("ssd1306") diff --git a/ports/esp32/boards/manifest.py b/ports/esp32/boards/manifest.py index 658d11d585..fcc48d7218 100644 --- a/ports/esp32/boards/manifest.py +++ b/ports/esp32/boards/manifest.py @@ -1,15 +1,16 @@ freeze("$(PORT_DIR)/modules") module("upip.py", base_path="$(MPY_DIR)/tools", opt=3) module("upip_utarfile.py", base_path="$(MPY_DIR)/tools", opt=3) -module("ntptime.py", base_path="$(MPY_DIR)/extmod", opt=3) -include("$(MPY_DIR)/drivers/dht") -include("$(MPY_DIR)/drivers/onewire") -include("$(MPY_DIR)/drivers/neopixel") include("$(MPY_DIR)/extmod/uasyncio") -include("$(MPY_DIR)/extmod/webrepl") # Require some micropython-lib modules. -require("urequests") -require("upysh") -require("umqtt.simple") +require("dht") +require("ds18x20") +require("neopixel") +require("ntptime") +require("onewire") require("umqtt.robust") +require("umqtt.simple") +require("upysh") +require("urequests") +require("webrepl") diff --git a/ports/esp8266/boards/GENERIC/manifest.py b/ports/esp8266/boards/GENERIC/manifest.py index 54b916546c..ef70884624 100644 --- a/ports/esp8266/boards/GENERIC/manifest.py +++ b/ports/esp8266/boards/GENERIC/manifest.py @@ -5,7 +5,7 @@ include("$(PORT_DIR)/boards/manifest.py") include("$(MPY_DIR)/extmod/uasyncio") # drivers -include("$(MPY_DIR)/drivers/display", ssd1306=True) +require("ssd1306") # micropython-lib: file utilities require("upysh") diff --git a/ports/esp8266/boards/GENERIC_512K/manifest.py b/ports/esp8266/boards/GENERIC_512K/manifest.py index 57970a6b4d..15f6cffc3f 100644 --- a/ports/esp8266/boards/GENERIC_512K/manifest.py +++ b/ports/esp8266/boards/GENERIC_512K/manifest.py @@ -1,8 +1,9 @@ module("_boot.py", opt=3) module("apa102.py", base_path="$(PORT_DIR)/modules", opt=3) module("port_diag.py", base_path="$(PORT_DIR)/modules", opt=3) -module("ntptime.py", base_path="$(MPY_DIR)/extmod", opt=3) -include("$(MPY_DIR)/drivers/dht") -include("$(MPY_DIR)/drivers/onewire") -include("$(MPY_DIR)/extmod/webrepl") -include("$(MPY_DIR)/drivers/neopixel") +require("ntptime") +require("dht") +require("onewire") +require("ds18x20") +require("webrepl") +require("neopixel") diff --git a/ports/esp8266/boards/manifest.py b/ports/esp8266/boards/manifest.py index abcee253ff..e7defd0bb7 100644 --- a/ports/esp8266/boards/manifest.py +++ b/ports/esp8266/boards/manifest.py @@ -1,8 +1,9 @@ freeze("$(PORT_DIR)/modules") module("upip.py", base_path="$(MPY_DIR)/tools", opt=3) module("upip_utarfile.py", base_path="$(MPY_DIR)/tools", opt=3) -module("ntptime.py", base_path="$(MPY_DIR)/extmod", opt=3) -include("$(MPY_DIR)/drivers/dht") -include("$(MPY_DIR)/drivers/onewire") -include("$(MPY_DIR)/extmod/webrepl") -include("$(MPY_DIR)/drivers/neopixel") +require("ntptime") +require("dht") +require("onewire") +require("ds18x20") +require("neopixel") +require("webrepl") diff --git a/ports/mimxrt/boards/manifest.py b/ports/mimxrt/boards/manifest.py index a273dfa370..e4e5a236a3 100644 --- a/ports/mimxrt/boards/manifest.py +++ b/ports/mimxrt/boards/manifest.py @@ -1,4 +1,5 @@ freeze("$(PORT_DIR)/modules") -include("$(MPY_DIR)/drivers/onewire") -include("$(MPY_DIR)/drivers/dht") include("$(MPY_DIR)/extmod/uasyncio") +require("onewire") +require("ds18x20") +require("dht") diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py b/ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py index 2b0cc6c818..8396e0249c 100644 --- a/ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py +++ b/ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py @@ -1,4 +1,4 @@ include("$(PORT_DIR)/modules/manifest.py") -include("$(MPY_DIR)/drivers/hts221") -include("$(MPY_DIR)/drivers/lps22h") -include("$(MPY_DIR)/drivers/lsm9ds1") +require("hts221") +require("lps22h") +require("lsm9ds1") diff --git a/ports/renesas-ra/boards/RA4M1_CLICKER/manifest.py b/ports/renesas-ra/boards/RA4M1_CLICKER/manifest.py index c25ae79887..99b9c94051 100644 --- a/ports/renesas-ra/boards/RA4M1_CLICKER/manifest.py +++ b/ports/renesas-ra/boards/RA4M1_CLICKER/manifest.py @@ -1,2 +1,2 @@ # We do not want to include default frozen modules, -include("$(MPY_DIR)/drivers/sdcard") +require("sdcard") diff --git a/ports/renesas-ra/boards/RA4M1_EK/manifest.py b/ports/renesas-ra/boards/RA4M1_EK/manifest.py index c25ae79887..99b9c94051 100644 --- a/ports/renesas-ra/boards/RA4M1_EK/manifest.py +++ b/ports/renesas-ra/boards/RA4M1_EK/manifest.py @@ -1,2 +1,2 @@ # We do not want to include default frozen modules, -include("$(MPY_DIR)/drivers/sdcard") +require("sdcard") diff --git a/ports/renesas-ra/boards/manifest.py b/ports/renesas-ra/boards/manifest.py index c66ec92015..01699c3d6e 100644 --- a/ports/renesas-ra/boards/manifest.py +++ b/ports/renesas-ra/boards/manifest.py @@ -1,4 +1,4 @@ include("$(MPY_DIR)/extmod/uasyncio") -include("$(MPY_DIR)/drivers/dht") -include("$(MPY_DIR)/drivers/onewire", ds18x20=False) -include("$(MPY_DIR)/drivers/sdcard") +require("dht") +require("onewire") +require("sdcard") diff --git a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py index e139c7d60b..dbd45fa408 100644 --- a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py +++ b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py @@ -1,11 +1,11 @@ include("$(PORT_DIR)/boards/manifest.py") # Networking -include("$(MPY_DIR)/extmod/webrepl") +require("webrepl") require("urequests") # Drivers -include("$(MPY_DIR)/drivers/lsm6dsox") +require("lsm6dsox") # Bluetooth require("aioble", client=True, central=True, l2cap=True, security=True) diff --git a/ports/rp2/boards/PICO_W/manifest.py b/ports/rp2/boards/PICO_W/manifest.py index 66ff26b0c8..4d9eb87f20 100644 --- a/ports/rp2/boards/PICO_W/manifest.py +++ b/ports/rp2/boards/PICO_W/manifest.py @@ -2,6 +2,6 @@ include("../manifest.py") module("upip.py", base_path="$(MPY_DIR)/tools", opt=3) module("upip_utarfile.py", base_path="$(MPY_DIR)/tools", opt=3) -module("ntptime.py", base_path="$(MPY_DIR)/extmod", opt=3) +require("ntptime") require("urequests") diff --git a/ports/rp2/boards/manifest.py b/ports/rp2/boards/manifest.py index 9afcba17e8..e62d02f308 100644 --- a/ports/rp2/boards/manifest.py +++ b/ports/rp2/boards/manifest.py @@ -1,5 +1,6 @@ freeze("$(PORT_DIR)/modules") -include("$(MPY_DIR)/drivers/onewire") -include("$(MPY_DIR)/drivers/dht") include("$(MPY_DIR)/extmod/uasyncio") -include("$(MPY_DIR)/drivers/neopixel") +require("onewire") +require("ds18x20") +require("dht") +require("neopixel") diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/manifest.py b/ports/stm32/boards/ARDUINO_PORTENTA_H7/manifest.py index 0ecdcd2153..4fa92b7205 100644 --- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/manifest.py +++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/manifest.py @@ -1,3 +1,3 @@ include("$(PORT_DIR)/boards/manifest.py") -include("$(MPY_DIR)/extmod/webrepl") +require("webrepl") require("aioble", client=True, central=True, l2cap=True, security=True) diff --git a/ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/manifest.py b/ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/manifest.py index 69da2897ae..2600fc5062 100644 --- a/ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/manifest.py +++ b/ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/manifest.py @@ -1,2 +1 @@ -# Note: Freezes to display.ssd1306, so must use deprecated "freeze" function. -freeze("$(MPY_DIR)/drivers/", ("display/ssd1306.py")) +require("ssd1306") diff --git a/ports/stm32/boards/PYBD_SF2/manifest.py b/ports/stm32/boards/PYBD_SF2/manifest.py index a9e92848d5..0ee11baf4b 100644 --- a/ports/stm32/boards/PYBD_SF2/manifest.py +++ b/ports/stm32/boards/PYBD_SF2/manifest.py @@ -1,3 +1,3 @@ include("$(PORT_DIR)/boards/manifest.py") include("$(PORT_DIR)/boards/manifest_pyboard.py") -include("$(MPY_DIR)/extmod/webrepl") +require("webrepl") diff --git a/ports/stm32/boards/manifest.py b/ports/stm32/boards/manifest.py index 723caa3eb6..e6b77f8ab3 100644 --- a/ports/stm32/boards/manifest.py +++ b/ports/stm32/boards/manifest.py @@ -1,4 +1,4 @@ include("$(MPY_DIR)/extmod/uasyncio") -include("$(MPY_DIR)/drivers/dht") -include("$(MPY_DIR)/drivers/onewire", ds18x20=False) +require("dht") +require("onewire") diff --git a/ports/stm32/boards/manifest_pyboard.py b/ports/stm32/boards/manifest_pyboard.py index e4fb0a8c4d..789365a433 100644 --- a/ports/stm32/boards/manifest_pyboard.py +++ b/ports/stm32/boards/manifest_pyboard.py @@ -1 +1 @@ -include("$(MPY_DIR)/drivers/display", lcd160cr=True) +require("lcd160cr") From 24678fe452e9c0d0b96575424f81fb4a5f5f4302 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 6 Sep 2022 13:49:10 +1000 Subject: [PATCH 0378/1041] drivers: Remove drivers that are now in micropython-lib. Signed-off-by: Jim Mussared --- drivers/README.md | 2 +- drivers/codec/manifest.py | 1 - drivers/codec/wm8960.py | 753 ----------------------------- drivers/dht/dht.py | 46 -- drivers/dht/manifest.py | 1 - drivers/display/lcd160cr.py | 482 ------------------ drivers/display/lcd160cr_test.py | 187 ------- drivers/display/manifest.py | 11 - drivers/display/ssd1306.py | 163 ------- drivers/hts221/hts221.py | 91 ---- drivers/hts221/manifest.py | 1 - drivers/lps22h/lps22h.py | 109 ----- drivers/lps22h/manifest.py | 1 - drivers/lsm6dsox/lsm6dsox.py | 271 ----------- drivers/lsm6dsox/lsm6dsox_basic.py | 15 - drivers/lsm6dsox/lsm6dsox_mlc.py | 48 -- drivers/lsm6dsox/manifest.py | 1 - drivers/lsm9ds1/lsm9ds1.py | 189 -------- drivers/lsm9ds1/manifest.py | 1 - drivers/neopixel/manifest.py | 1 - drivers/neopixel/neopixel.py | 50 -- drivers/nrf24l01/manifest.py | 1 - drivers/nrf24l01/nrf24l01.py | 252 ---------- drivers/nrf24l01/nrf24l01test.py | 150 ------ drivers/onewire/ds18x20.py | 52 -- drivers/onewire/manifest.py | 6 - drivers/onewire/onewire.py | 92 ---- drivers/sdcard/manifest.py | 1 - drivers/sdcard/sdcard.py | 299 ------------ drivers/sdcard/sdtest.py | 61 --- extmod/ntptime.py | 48 -- extmod/webrepl/manifest.py | 2 - extmod/webrepl/webrepl.py | 177 ------- extmod/webrepl/webrepl_setup.py | 107 ---- 34 files changed, 1 insertion(+), 3671 deletions(-) delete mode 100644 drivers/codec/manifest.py delete mode 100644 drivers/codec/wm8960.py delete mode 100644 drivers/dht/dht.py delete mode 100644 drivers/dht/manifest.py delete mode 100644 drivers/display/lcd160cr.py delete mode 100644 drivers/display/lcd160cr_test.py delete mode 100644 drivers/display/manifest.py delete mode 100644 drivers/display/ssd1306.py delete mode 100644 drivers/hts221/hts221.py delete mode 100644 drivers/hts221/manifest.py delete mode 100644 drivers/lps22h/lps22h.py delete mode 100644 drivers/lps22h/manifest.py delete mode 100644 drivers/lsm6dsox/lsm6dsox.py delete mode 100644 drivers/lsm6dsox/lsm6dsox_basic.py delete mode 100644 drivers/lsm6dsox/lsm6dsox_mlc.py delete mode 100644 drivers/lsm6dsox/manifest.py delete mode 100644 drivers/lsm9ds1/lsm9ds1.py delete mode 100644 drivers/lsm9ds1/manifest.py delete mode 100644 drivers/neopixel/manifest.py delete mode 100644 drivers/neopixel/neopixel.py delete mode 100644 drivers/nrf24l01/manifest.py delete mode 100644 drivers/nrf24l01/nrf24l01.py delete mode 100644 drivers/nrf24l01/nrf24l01test.py delete mode 100644 drivers/onewire/ds18x20.py delete mode 100644 drivers/onewire/manifest.py delete mode 100644 drivers/onewire/onewire.py delete mode 100644 drivers/sdcard/manifest.py delete mode 100644 drivers/sdcard/sdcard.py delete mode 100644 drivers/sdcard/sdtest.py delete mode 100644 extmod/ntptime.py delete mode 100644 extmod/webrepl/manifest.py delete mode 100644 extmod/webrepl/webrepl.py delete mode 100644 extmod/webrepl/webrepl_setup.py diff --git a/drivers/README.md b/drivers/README.md index 854acc50b6..e4fac9fe8d 100644 --- a/drivers/README.md +++ b/drivers/README.md @@ -1,2 +1,2 @@ -This directory contains drivers for specific hardware. The drivers are +This directory contains C drivers for specific hardware. The drivers are intended to work across multiple ports. diff --git a/drivers/codec/manifest.py b/drivers/codec/manifest.py deleted file mode 100644 index 4ff5d9fc44..0000000000 --- a/drivers/codec/manifest.py +++ /dev/null @@ -1 +0,0 @@ -module("wm8960.py", opt=3) diff --git a/drivers/codec/wm8960.py b/drivers/codec/wm8960.py deleted file mode 100644 index ad1cb1cbf8..0000000000 --- a/drivers/codec/wm8960.py +++ /dev/null @@ -1,753 +0,0 @@ -# -# Driver class for the WM8960 Codec to be used e.g. with MIMXRT_1xxx Boards. -# Derived from the NXP SDK drivers. -# -# Copyright (c) 2015, Freescale Semiconductor, Inc., (C-Code) -# Copyright 2016-2021 NXP, (C-Code) -# All rights reserved. -# -# Translated to MicroPython by Robert Hammelrath, 2022 -# -# SPDX-License-Identifier: BSD-3-Clause -# - -import array -from micropython import const - -# Define the register addresses of WM8960. -_LINVOL = const(0x0) -_RINVOL = const(0x1) -_LOUT1 = const(0x2) -_ROUT1 = const(0x3) -_CLOCK1 = const(0x4) -_DACCTL1 = const(0x5) -_DACCTL2 = const(0x6) -_IFACE1 = const(0x7) -_CLOCK2 = const(0x8) -_IFACE2 = const(0x9) -_LDAC = const(0xA) -_RDAC = const(0xB) -_RESET = const(0xF) -_3D = const(0x10) -_ALC1 = const(0x11) -_ALC2 = const(0x12) -_ALC3 = const(0x13) -_NOISEG = const(0x14) -_LADC = const(0x15) -_RADC = const(0x16) -_ADDCTL1 = const(0x17) -# Register _ADDCTL2 = const(0x18) -_POWER1 = const(0x19) -_POWER2 = const(0x1A) -_ADDCTL3 = const(0x1B) -# Register _APOP1 = const(0x1C) -# Register _APOP2 = const(0x1D) -_LINPATH = const(0x20) -_RINPATH = const(0x21) -_LOUTMIX = const(0x22) -_ROUTMIX = const(0x25) -_MONOMIX1 = const(0x26) -_MONOMIX2 = const(0x27) -_LOUT2 = const(0x28) -_ROUT2 = const(0x29) -_MONO = const(0x2A) -_INBMIX1 = const(0x2B) -_INBMIX2 = const(0x2C) -_BYPASS1 = const(0x2D) -_BYPASS2 = const(0x2E) -_POWER3 = const(0x2F) -_ADDCTL4 = const(0x30) -_CLASSD1 = const(0x31) -# Register _CLASSD3 = const(0x33) -_PLL1 = const(0x34) -_PLL2 = const(0x35) -_PLL3 = const(0x36) -_PLL4 = const(0x37) - -# WM8960 PLLN range */ -_PLL_N_MIN_VALUE = const(6) -_PLL_N_MAX_VALUE = const(12) - -# WM8960 CLOCK2 bits -_CLOCK2_BCLK_DIV_MASK = const(0x0F) -_CLOCK2_DCLK_DIV_MASK = const(0x1C0) -_CLOCK2_DCLK_DIV_SHIFT = const(0x06) - -# Register _IFACE1 -_IFACE1_FORMAT_MASK = const(0x03) -_IFACE1_WL_MASK = const(0x0C) -_IFACE1_WL_SHIFT = const(0x02) -_IFACE1_LRP_MASK = const(0x10) -_IFACE1_MS_MASK = const(0x40) -_IFACE1_DLRSWAP_MASK = const(0x20) -_IFACE1_ALRSWAP_MASK = const(0x100) - -# Register _POWER1 -_POWER1_VREF_MASK = const(0x40) -_POWER1_VREF_SHIFT = const(0x06) -_POWER1_AINL_MASK = const(0x20) -_POWER1_AINR_MASK = const(0x10) -_POWER1_ADCL_MASK = const(0x08) -_POWER1_ADCR_MASK = const(0x0) -_POWER1_MICB_MASK = const(0x02) -_POWER1_MICB_SHIFT = const(0x01) - -# Register _POWER2 -_POWER2_DACL_MASK = const(0x100) -_POWER2_DACR_MASK = const(0x80) -_POWER2_LOUT1_MASK = const(0x40) -_POWER2_ROUT1_MASK = const(0x20) -_POWER2_SPKL_MASK = const(0x10) -_POWER2_SPKR_MASK = const(0x08) -_POWER3_LMIC_MASK = const(0x20) -_POWER3_RMIC_MASK = const(0x10) -_POWER3_LOMIX_MASK = const(0x08) -_POWER3_ROMIX_MASK = const(0x04) - -# Register _DACCTL1 .. 3 -_DACCTL1_MONOMIX_MASK = const(0x10) -_DACCTL1_MONOMIX_SHIFT = const(0x4) -_DACCTL1_DACMU_MASK = const(0x08) -_DACCTL1_DEEM_MASK = const(0x06) -_DACCTL1_DEEM_SHIFT = const(0x01) -_DACCTL2_DACSMM_MASK = const(0x08) -_DACCTL2_DACMR_MASK = const(0x04) -_DACCTL3_ALCSR_MASK = const(0x07) - -# _WM8060_ALC1 .. 3 -_ALC_CHANNEL_MASK = const(0x180) -_ALC_CHANNEL_SHIFT = const(0x7) -_ALC_MODE_MASK = const(0x100) -_ALC_MODE_SHIFT = const(0x8) -_ALC_GAIN_MASK = const(0x70) -_ALC_GAIN_SHIFT = const(0x4) -_ALC_TARGET_MASK = const(0x0F) -_ALC_ATTACK_MASK = const(0x0F) -_ALC_DECAY_MASK = const(0xF0) -_ALC_DECAY_SHIFT = const(4) -_ALC_HOLD_MASK = const(0xF) - -# Register _NOISEG -_NOISEG_LEVEL_SHIFT = const(3) - -_I2C_ADDR = const(0x1A) - -# WM8960 maximum volume values -_MAX_VOLUME_ADC = const(0xFF) -_MAX_VOLUME_DAC = const(0xFF) -_MAX_VOLUME_HEADPHONE = const(0x7F) -_MAX_VOLUME_LINEIN = const(0x3F) -_MAX_VOLUME_SPEAKER = const(0x7F) - -# Config symbol names -# Modules -MODULE_ADC = const(0) # ADC module in WM8960 -MODULE_DAC = const(1) # DAC module in WM8960 -MODULE_VREF = const(2) # VREF module -MODULE_HEADPHONE = const(3) # Headphone -MODULE_MIC_BIAS = const(4) # Mic bias -MODULE_MIC = const(5) # Input Mic -MODULE_LINE_IN = const(6) # Analog in PGA -MODULE_LINE_OUT = const(7) # Line out module -MODULE_SPEAKER = const(8) # Speaker module -MODULE_OMIX = const(9) # Output mixer -MODULE_MONO_OUT = const(10) # Mono mix - -# Route -ROUTE_BYPASS = const(0) # LINEIN->Headphone. -ROUTE_PLAYBACK = const(1) # I2SIN->DAC->Headphone. -ROUTE_PLAYBACK_RECORD = const(2) # I2SIN->DAC->Headphone, LINEIN->ADC->I2SOUT. -ROUTE_RECORD = const(5) # LINEIN->ADC->I2SOUT. - -# Input -INPUT_CLOSED = const(0) # Input device is closed -INPUT_MIC1 = const(1) # Input as single ended mic, only use L/RINPUT1 -INPUT_MIC2 = const(2) # Input as diff. mic, use L/RINPUT1 and L/RINPUT2 -INPUT_MIC3 = const(3) # Input as diff. mic, use L/RINPUT1 and L/RINPUT3 -INPUT_LINE2 = const(4) # Input as line input, only use L/RINPUT2 -INPUT_LINE3 = const(5) # Input as line input, only use L/RINPUT3 - -# ADC sync input -SYNC_ADC = const(0) # Use ADCLRC pin for ADC sync -SYNC_DAC = const(1) # used DACLRC pin for ADC sync - -# Protocol type -BUS_I2S = const(2) # I2S type -BUS_LEFT_JUSTIFIED = const(1) # Left justified mode -BUS_RIGHT_JUSTIFIED = const(0) # Right justified mode -BUS_PCMA = const(3) # PCM A mode -BUS_PCMB = const(3 | (1 << 4)) # PCM B mode - -# Channel swap -SWAP_NONE = const(0) -SWAP_INPUT = const(1) -SWAP_OUTPUT = const(2) - -# Mute settings -MUTE_FAST = const(0) -MUTE_SLOW = const(1) - -# ALC settings -ALC_OFF = const(0) -ALC_RIGHT = const(1) -ALC_LEFT = const(2) -ALC_STEREO = const(3) -ALC_MODE = const(0) # ALC mode -ALC_LIMITER = const(1) # Limiter mode - -# Clock Source -SYSCLK_MCLK = const(0) # sysclk source from external MCLK -SYSCLK_PLL = const(1) # sysclk source from internal PLL - - -class Regs: - # register cache of 56 register. Since registers cannot be read back, they are - # kept in the table for modification - # fmt: off - cache = array.array("H", ( - 0x0097, 0x0097, 0x0000, 0x0000, 0x0000, 0x0008, 0x0000, - 0x000a, 0x01c0, 0x0000, 0x00ff, 0x00ff, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x007b, 0x0100, 0x0032, 0x0000, - 0x00c3, 0x00c3, 0x01c0, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0100, 0x0050, - 0x0050, 0x0050, 0x0050, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0040, 0x0000, 0x0000, 0x0050, 0x0050, 0x0000, 0x0002, - 0x0037, 0x004d, 0x0080, 0x0008, 0x0031, 0x0026, 0x00e9 - )) - # fmt: on - - def __init__(self, i2c, i2c_address=_I2C_ADDR): - self.value_buffer = bytearray(2) - self.i2c = i2c - self.i2c_address = i2c_address - - def __getitem__(self, reg): - return self.cache[reg] - - def __setitem__(self, reg, value): - if type(reg) is tuple: - if type(value) is tuple: - self[reg[0]] = value[0] - self[reg[1]] = value[1] - else: - self[reg[0]] = value - self[reg[1]] = value - else: - if type(value) is tuple: - val = (self.cache[reg] & (~value[0] & 0xFFFF)) | value[1] - else: - val = value - self.cache[reg] = val - self.value_buffer[0] = (reg << 1) | ((val >> 8) & 0x01) - self.value_buffer[1] = val & 0xFF - self.i2c.writeto(self.i2c_address, self.value_buffer) - - -class WM8960: - - _bit_clock_divider_table = { - 2: 0, - 3: 1, - 4: 2, - 6: 3, - 8: 4, - 11: 5, - 12: 6, - 16: 7, - 22: 8, - 24: 9, - 32: 10, - 44: 11, - 48: 12, - } - - _dac_divider_table = { - 1.0 * 256: 0b000, - 1.5 * 256: 0b001, - 2 * 256: 0b010, - 3 * 256: 0b011, - 4 * 256: 0b100, - 5.5 * 256: 0b101, - 6 * 256: 0b110, - } - - _audio_word_length_table = { - 16: 0b00, - 20: 0b01, - 24: 0b10, - 32: 0b11, - } - - _alc_sample_rate_table = { - 48000: 0, - 44100: 0, - 32000: 1, - 24000: 2, - 22050: 2, - 16000: 3, - 12000: 4, - 11025: 4, - 8000: 5, - } - - _volume_config_table = { - MODULE_ADC: (_MAX_VOLUME_ADC, _LADC, 0x100), - MODULE_DAC: (_MAX_VOLUME_DAC, _LDAC, 0x100), - MODULE_HEADPHONE: (_MAX_VOLUME_HEADPHONE, _LOUT1, 0x180), - MODULE_LINE_IN: (_MAX_VOLUME_LINEIN, _LINVOL, 0x140), - MODULE_SPEAKER: (_MAX_VOLUME_SPEAKER, _LOUT2, 0x180), - } - - _input_config_table = { - INPUT_CLOSED: None, - INPUT_MIC1: (0x138, 0x117), - INPUT_MIC2: (0x178, 0x117), - INPUT_MIC3: (0x1B8, 0x117), - INPUT_LINE2: (0, 0xE), - INPUT_LINE3: (0, 0x70), - } - - def __init__( - self, - i2c, - sample_rate=16000, - bits=16, - swap=SWAP_NONE, - route=ROUTE_PLAYBACK_RECORD, - left_input=INPUT_MIC3, - right_input=INPUT_MIC2, - sysclk_source=SYSCLK_MCLK, - mclk_freq=None, - primary=False, - adc_sync=SYNC_DAC, - protocol=BUS_I2S, - i2c_address=_I2C_ADDR, - ): - self.regs = regs = Regs(i2c, i2c_address) - self.sample_rate = sample_rate - - # check parameter consistency and set the sysclk value - if sysclk_source == SYSCLK_PLL: - if sample_rate in (11025, 22050, 44100): - sysclk = 11289600 - else: - sysclk = 12288000 - if sysclk < sample_rate * 256: - sysclk = sample_rate * 256 - if mclk_freq is None: - mclk_freq = sysclk - else: # sysclk_source == SYSCLK_MCLK - if mclk_freq is None: - mclk_freq = sample_rate * 256 - sysclk = mclk_freq - - regs[_RESET] = 0x00 - # VMID=50K, Enable VREF, AINL, AINR, ADCL and ADCR - # I2S_IN (bit 0), I2S_OUT (bit 1), DAP (bit 4), DAC (bit 5), ADC (bit 6) are powered on - regs[_POWER1] = 0xFE - # Enable DACL, DACR, LOUT1, ROUT1, PLL down, SPKL, SPKR - regs[_POWER2] = 0x1F8 - # Enable left and right channel input PGA, left and right output mixer - regs[_POWER3] = 0x3C - - if adc_sync == SYNC_ADC: - # ADC and DAC use different Frame Clock Pins - regs[_IFACE2] = 0x00 # ADCLRC 0x00:Input 0x40:output. - else: - # ADC and DAC use the same Frame Clock Pin - regs[_IFACE2] = 0x40 # ADCLRC 0x00:Input 0x40:output. - self.set_data_route(route) - self.set_protocol(protocol) - - if sysclk_source == SYSCLK_PLL: - self.set_internal_pll_config(mclk_freq, sysclk) - if primary: - self.set_master_clock(sysclk, sample_rate, bits) - # set master bit. - self.regs[_IFACE1] = (0, _IFACE1_MS_MASK) - - self.set_speaker_clock(sysclk) - - # swap channels - if swap & SWAP_INPUT: - regs[_IFACE1] = (0, _IFACE1_ALRSWAP_MASK) - if swap & SWAP_OUTPUT: - regs[_IFACE1] = (0, _IFACE1_DLRSWAP_MASK) - - self.set_left_input(left_input) - self.set_right_input(right_input) - - regs[_ADDCTL1] = 0x0C0 - regs[_ADDCTL4] = 0x60 # Set GPIO1 to 0. - - regs[_BYPASS1] = regs[_BYPASS2] = 0x0 - # ADC volume, 0dB - regs[_LADC, _RADC] = 0x1C3 - # Digital DAC volume, 0dB - regs[_LDAC, _RDAC] = 0x1FF - # Headphone volume, LOUT1 and ROUT1, 0dB - regs[_LOUT1, _ROUT1] = 0x16F - # speaker volume 6dB - regs[_LOUT2, _ROUT2] = 0x1FF - # enable class D output - regs[_CLASSD1] = 0xF7 - # Unmute DAC. - regs[_DACCTL1] = 0x0000 - # Input PGA volume 0 dB - regs[_LINVOL, _RINVOL] = 0x117 - - self.config_data_format(sysclk, sample_rate, bits) - - def deinit(self): - - self.set_module(MODULE_ADC, False) - self.set_module(MODULE_DAC, False) - self.set_module(MODULE_VREF, False) - self.set_module(MODULE_LINE_IN, False) - self.set_module(MODULE_LINE_OUT, False) - self.set_module(MODULE_SPEAKER, False) - - def set_internal_pll_config(self, input_mclk, output_clk): - regs = self.regs - pllF2 = output_clk * 4 - pll_prescale = 0 - sysclk_div = 1 - frac_mode = 0 - - # disable PLL power - regs[_POWER2] = (1, 0) - regs[_CLOCK1] = (7, 0) - - pllN = pllF2 // input_mclk - if pllN < _PLL_N_MIN_VALUE: - input_mclk //= 2 - pll_prescale = 1 - pllN = pllF2 // input_mclk - if pllN < _PLL_N_MIN_VALUE: - sysclk_div = 2 - pllF2 *= 2 - pllN = pllF2 // input_mclk - - if (pllN < _PLL_N_MIN_VALUE) or (pllN > _PLL_N_MAX_VALUE): - raise ValueError("Invalid MCLK vs. sysclk ratio") - - pllK = ((pllF2 % input_mclk) * (1 << 24)) // input_mclk - if pllK != 0: - frac_mode = 1 - - regs[_PLL1] = (frac_mode << 5) | (pll_prescale << 4) | (pllN & 0x0F) - regs[_PLL2] = (pllK >> 16) & 0xFF - regs[_PLL3] = (pllK >> 8) & 0xFF - regs[_PLL4] = pllK & 0xFF - # enable PLL power - regs[_POWER2] = (1, 1) - regs[_CLOCK1] = (7, ((0 if sysclk_div == 1 else sysclk_div) << 1) | 1) - - def set_master_clock(self, sysclk, sample_rate, bit_width): - bit_clock_divider = (sysclk * 2) // (sample_rate * bit_width * 2) - try: - reg_divider = self._bit_clock_divider_table[bit_clock_divider] - except: - raise ValueError("Invalid ratio of sysclk sample rate and bits") - # configure the master bit clock divider - self.regs[_CLOCK2] = (_CLOCK2_BCLK_DIV_MASK, reg_divider) - - def set_speaker_clock(self, sysclk): - speaker_divider_table = (1.5, 2, 3, 4, 6, 8, 12, 16) - for val in range(8): - divider = speaker_divider_table[val] - f = sysclk / divider - if 500_000 < f < 1_000_000: - break - else: - val = 7 - self.regs[_CLOCK2] = ( - _CLOCK2_DCLK_DIV_MASK, - val << _CLOCK2_DCLK_DIV_SHIFT, - ) - - def set_module(self, module, is_enabled): - - is_enabled = 1 if is_enabled else 0 - regs = self.regs - - if module == MODULE_ADC: - - regs[_POWER1] = ( - _POWER1_ADCL_MASK | _POWER1_ADCR_MASK, - (_POWER1_ADCL_MASK | _POWER1_ADCR_MASK) * is_enabled, - ) - - elif module == MODULE_DAC: - - regs[_POWER2] = ( - _POWER2_DACL_MASK | _POWER2_DACR_MASK, - (_POWER2_DACL_MASK | _POWER2_DACR_MASK) * is_enabled, - ) - - elif module == MODULE_VREF: - - regs[_POWER1] = ( - _POWER1_VREF_MASK, - (is_enabled << _POWER1_VREF_SHIFT), - ) - - elif module == MODULE_LINE_IN: - - regs[_POWER1] = ( - _POWER1_AINL_MASK | _POWER1_AINR_MASK, - (_POWER1_AINL_MASK | _POWER1_AINR_MASK) * is_enabled, - ) - regs[_POWER3] = ( - _POWER3_LMIC_MASK | _POWER3_RMIC_MASK, - (_POWER3_LMIC_MASK | _POWER3_RMIC_MASK) * is_enabled, - ) - - elif module == MODULE_LINE_OUT: - - regs[_POWER2] = ( - _POWER2_LOUT1_MASK | _POWER2_ROUT1_MASK, - (_POWER2_LOUT1_MASK | _POWER2_ROUT1_MASK) * is_enabled, - ) - - elif module == MODULE_MIC_BIAS: - - regs[_POWER1] = ( - _POWER1_MICB_MASK, - (is_enabled << _POWER1_MICB_SHIFT), - ) - - elif module == MODULE_SPEAKER: - - regs[_POWER2] = ( - _POWER2_SPKL_MASK | _POWER2_SPKR_MASK, - (_POWER2_SPKL_MASK | _POWER2_SPKR_MASK) * is_enabled, - ) - regs[_CLASSD1] = 0xF7 - - elif module == MODULE_OMIX: - - regs[_POWER3] = ( - _POWER3_LOMIX_MASK | _POWER3_ROMIX_MASK, - (_POWER3_LOMIX_MASK | _POWER3_ROMIX_MASK) * is_enabled, - ) - - elif module == MODULE_MONO_OUT: - - regs[_MONOMIX1] = regs[_MONOMIX2] = is_enabled << 7 - regs[_MONO] = is_enabled << 6 - - else: - raise ValueError("Invalid module") - - def enable_module(self, module): - self.set_module(module, True) - - def disable_module(self, module): - self.set_module(module, False) - - def set_data_route(self, route): - regs = self.regs - if route == ROUTE_BYPASS: - # Bypass means from line-in to HP - # Left LINPUT3 to left output mixer, LINPUT3 left output mixer volume = 0dB - # Right RINPUT3 to right output mixer, RINPUT3 right output mixer volume = 0dB - regs[_LOUTMIX, _ROUTMIX] = 0x80 - - elif route == ROUTE_PLAYBACK: - # Data route I2S_IN-> DAC-> HP - # - # Left DAC to left output mixer, LINPUT3 left output mixer volume = 0dB - # Right DAC to right output mixer, RINPUT3 right output mixer volume = 0dB - regs[_LOUTMIX, _ROUTMIX] = 0x100 - regs[_POWER3] = 0x0C - # Set power for DAC - self.set_module(MODULE_DAC, True) - self.set_module(MODULE_OMIX, True) - self.set_module(MODULE_LINE_OUT, True) - - elif route == ROUTE_PLAYBACK_RECORD: - # - # Left DAC to left output mixer, LINPUT3 left output mixer volume = 0dB - # Right DAC to right output mixer, RINPUT3 right output mixer volume = 0dB - regs[_LOUTMIX, _ROUTMIX] = 0x100 - regs[_POWER3] = 0x3C - self.set_module(MODULE_DAC, True) - self.set_module(MODULE_ADC, True) - self.set_module(MODULE_LINE_IN, True) - self.set_module(MODULE_OMIX, True) - self.set_module(MODULE_LINE_OUT, True) - - elif route == ROUTE_RECORD: - # LINE_IN->ADC->I2S_OUT - # Left and right input boost, LIN3BOOST and RIN3BOOST = 0dB - regs[_POWER3] = 0x30 - # Power up ADC and AIN - self.set_module(MODULE_LINE_IN, True) - self.set_module(MODULE_ADC, True) - - else: - raise ValueError("Invalid route") - - def set_left_input(self, input): - if not input in self._input_config_table.keys(): - raise ValueError("Invalid input") - - input = self._input_config_table[input] - - regs = self.regs - if input is None: - regs[_POWER1] = (_POWER1_AINL_MASK | _POWER1_ADCL_MASK, 0) - elif input[0] == 0: - regs[_POWER1] = (0, _POWER1_AINL_MASK | _POWER1_ADCL_MASK) - regs[_INBMIX1] = input - else: - regs[_POWER1] = (0, _POWER1_AINL_MASK | _POWER1_ADCL_MASK | _POWER1_MICB_MASK) - regs[_LINPATH] = input[0] - regs[_LINVOL] = input[1] - - def set_right_input(self, input): - if not input in self._input_config_table.keys(): - raise ValueError("Invalid input name") - - input = self._input_config_table[input] - - regs = self.regs - if input is None: - regs[_POWER1] = (_POWER1_AINR_MASK | _POWER1_ADCR_MASK, 0) - elif input[0] == 0: - regs[_POWER1] = (0, _POWER1_AINL_MASK | _POWER1_ADCR_MASK) - regs[_INBMIX2] = input - else: - regs[_POWER1] = (0, _POWER1_AINR_MASK | _POWER1_ADCR_MASK | _POWER1_MICB_MASK) - regs[_RINPATH] = input[0] - regs[_RINVOL] = input[1] - - def set_protocol(self, protocol): - self.regs[_IFACE1] = ( - _IFACE1_FORMAT_MASK | _IFACE1_LRP_MASK, - protocol, - ) - - def config_data_format(self, sysclk, sample_rate, bits): - # Compute sample rate divider, dac and adc are the same sample rate - try: - divider = self._dac_divider_table[sysclk // sample_rate] - wl = self._audio_word_length_table[bits] - except: - raise ValueError("Invalid ratio sysclk/sample_rate or invalid bit length") - - self.regs[_CLOCK1] = (0x1F8, divider << 6 | divider << 3) - self.regs[_IFACE1] = (_IFACE1_WL_MASK, wl << _IFACE1_WL_SHIFT) - - def volume(self, module, volume_l=None, volume_r=None): - if not module in self._volume_config_table.keys(): - raise ValueError("Invalid module") - - if volume_l is None: # get volume - vol_max, regnum, _ = self._volume_config_table[module] - return ( - int((self.regs[regnum] & vol_max) * 100 / vol_max + 0.5), - int((self.regs[regnum + 1] & vol_max) * 100 / vol_max + 0.5), - ) - else: # set volume - if volume_r is None: - volume_r = volume_l - - if not ((0 <= volume_l <= 100) and (0 <= volume_r <= 100)): - raise ValueError("Invalid value for volume") - elif not module in self._volume_config_table.keys(): - raise ValueError("Invalid module") - - vol_max, regnum, flags = self._volume_config_table[module] - self.regs[regnum] = int(volume_l * vol_max / 100 + 0.5) | flags - self.regs[regnum + 1] = int(volume_r * vol_max / 100 + 0.5) | flags - - def mute(self, enable, soft=True, ramp=MUTE_FAST): - enable = _DACCTL1_DACMU_MASK if enable else 0 - soft = _DACCTL2_DACSMM_MASK if soft else 0 - ramp = _DACCTL2_DACMR_MASK if ramp == MUTE_SLOW else 0 - self.regs[_DACCTL1] = (_DACCTL1_DACMU_MASK, enable) - self.regs[_DACCTL2] = ( - _DACCTL2_DACSMM_MASK | _DACCTL2_DACMR_MASK, - soft | ramp, - ) - - def expand_3d(self, depth=0): - depth &= 0x0F - cutoff = 0 if self.sample_rate >= 32000 else 0b1100000 - self.regs[_3D] = cutoff | depth << 1 | (1 if depth > 0 else 0) - - def mono(self, enable): - enable = 1 if enable else 0 - self.regs[_DACCTL1] = ( - _DACCTL1_MONOMIX_MASK, - enable << _DACCTL1_MONOMIX_SHIFT, - ) - - def alc_mode(self, channel, mode=ALC_MODE): - if mode != ALC_MODE: - mode = ALC_LIMITER - channel &= 3 - self.regs[_ALC1] = ( - _ALC_CHANNEL_MASK, - channel << _ALC_CHANNEL_SHIFT, - ) - self.regs[_ALC3] = (_ALC_MODE_MASK, mode << _ALC_MODE_SHIFT) - try: - rate = _alc_sample_rate_table[self.sample_rate] - except: - rate = 0 - self.regs[_ADDCTL3] = (_DACCTL3_ALCSR_MASK, rate) - - def alc_gain(self, target=-12, max_gain=30, min_gain=-17.25, noise_gate=-78): - def limit(value, minval, maxval): - value = int(value) - if value < minval: - value = minval - if value > maxval: - value = maxval - return value - - target = limit((16 + (target * 2) // 3), 0, 15) - max_gain = limit((max_gain + 12) // 6, 0, 7) - min_gain = limit((min_gain * 4 + 69) // 24, 0, 7) - noise_gate = limit((noise_gate * 2 + 153) // 3, -1, 31) - self.regs[_ALC1] = ( - _ALC_GAIN_MASK | _ALC_TARGET_MASK, - (max_gain << _ALC_GAIN_SHIFT) | target, - ) - self.regs[_ALC2] = (_ALC_GAIN_MASK, (min_gain << _ALC_GAIN_SHIFT)) - if noise_gate >= 0: - self.regs[_NOISEG] = noise_gate << _NOISEG_LEVEL_SHIFT | 1 - else: - self.regs[_NOISEG] = 0 - - def alc_time(self, attack=24, decay=192, hold=0): - def logb(value, limit): - value = int(value) - lb = 0 - while value > 1: - value >>= 1 - lb += 1 - if lb > limit: - lb = limit - return lb - - attack = logb(attack / 6, 7) - decay = logb(decay / 24, 7) - hold = logb((hold * 3) / 8, 15) - self.regs[_ALC2] = (_ALC_HOLD_MASK, hold) - self.regs[_ALC3] = ( - _ALC_DECAY_MASK | _ALC_ATTACK_MASK, - (decay << _ALC_DECAY_SHIFT) | attack, - ) - - def deemphasis(self, enable): - deem_table = (32000, 44100, 48000) - enable = not not enable - if enable and self.sample_rate in deem_table: - val = deem_table.index(self.sample_rate) + 1 - else: - val = 0 - self.regs[_DACCTL1] = (_DACCTL1_DEEM_MASK, val << _DACCTL1_DEEM_SHIFT) diff --git a/drivers/dht/dht.py b/drivers/dht/dht.py deleted file mode 100644 index 411e9a8d28..0000000000 --- a/drivers/dht/dht.py +++ /dev/null @@ -1,46 +0,0 @@ -# DHT11/DHT22 driver for MicroPython on ESP8266 -# MIT license; Copyright (c) 2016 Damien P. George - -import sys - -if sys.platform.startswith("esp"): - from esp import dht_readinto -elif sys.platform == "mimxrt": - from mimxrt import dht_readinto -elif sys.platform == "rp2": - from rp2 import dht_readinto -elif sys.platform == "pyboard": - from pyb import dht_readinto -else: - from machine import dht_readinto - - -class DHTBase: - def __init__(self, pin): - self.pin = pin - self.buf = bytearray(5) - - def measure(self): - buf = self.buf - dht_readinto(self.pin, buf) - if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xFF != buf[4]: - raise Exception("checksum error") - - -class DHT11(DHTBase): - def humidity(self): - return self.buf[0] - - def temperature(self): - return self.buf[2] - - -class DHT22(DHTBase): - def humidity(self): - return (self.buf[0] << 8 | self.buf[1]) * 0.1 - - def temperature(self): - t = ((self.buf[2] & 0x7F) << 8 | self.buf[3]) * 0.1 - if self.buf[2] & 0x80: - t = -t - return t diff --git a/drivers/dht/manifest.py b/drivers/dht/manifest.py deleted file mode 100644 index 72a4e0d24f..0000000000 --- a/drivers/dht/manifest.py +++ /dev/null @@ -1 +0,0 @@ -module("dht.py", opt=3) diff --git a/drivers/display/lcd160cr.py b/drivers/display/lcd160cr.py deleted file mode 100644 index f792418aa2..0000000000 --- a/drivers/display/lcd160cr.py +++ /dev/null @@ -1,482 +0,0 @@ -# Driver for official MicroPython LCD160CR display -# MIT license; Copyright (c) 2017 Damien P. George - -from micropython import const -from utime import sleep_ms -from ustruct import calcsize, pack_into -import uerrno, machine - -# for set_orient -PORTRAIT = const(0) -LANDSCAPE = const(1) -PORTRAIT_UPSIDEDOWN = const(2) -LANDSCAPE_UPSIDEDOWN = const(3) - -# for set_startup_deco; can be or'd -STARTUP_DECO_NONE = const(0) -STARTUP_DECO_MLOGO = const(1) -STARTUP_DECO_INFO = const(2) - -_uart_baud_table = { - 2400: 0, - 4800: 1, - 9600: 2, - 19200: 3, - 38400: 4, - 57600: 5, - 115200: 6, - 230400: 7, - 460800: 8, -} - - -class LCD160CR: - def __init__(self, connect=None, *, pwr=None, i2c=None, spi=None, i2c_addr=98): - if connect in ("X", "Y", "XY", "YX"): - i = connect[-1] - j = connect[0] - y = j + "4" - elif connect == "C": - i = 2 - j = 2 - y = "A7" - else: - if pwr is None or i2c is None or spi is None: - raise ValueError('must specify valid "connect" or all of "pwr", "i2c" and "spi"') - - if pwr is None: - pwr = machine.Pin(y, machine.Pin.OUT) - if i2c is None: - i2c = machine.I2C(i, freq=1000000) - if spi is None: - spi = machine.SPI(j, baudrate=13500000, polarity=0, phase=0) - - if not pwr.value(): - pwr(1) - sleep_ms(10) - # else: - # alread have power - # lets be optimistic... - - # set connections - self.pwr = pwr - self.i2c = i2c - self.spi = spi - self.i2c_addr = i2c_addr - - # create temp buffers and memoryviews - self.buf16 = bytearray(16) - self.buf19 = bytearray(19) - self.buf = [None] * 10 - for i in range(1, 10): - self.buf[i] = memoryview(self.buf16)[0:i] - self.buf1 = self.buf[1] - self.array4 = [0, 0, 0, 0] - - # set default orientation and window - self.set_orient(PORTRAIT) - self._fcmd2b("= n: - self.i2c.readfrom_into(self.i2c_addr, buf) - return - t -= 1 - sleep_ms(1) - raise OSError(uerrno.ETIMEDOUT) - - def oflush(self, n=255): - t = 5000 - while t: - self.i2c.readfrom_into(self.i2c_addr + 1, self.buf1) - r = self.buf1[0] - if r >= n: - return - t -= 1 - machine.idle() - raise OSError(uerrno.ETIMEDOUT) - - def iflush(self): - t = 5000 - while t: - self.i2c.readfrom_into(self.i2c_addr, self.buf16) - if self.buf16[0] == 0: - return - t -= 1 - sleep_ms(1) - raise OSError(uerrno.ETIMEDOUT) - - #### MISC METHODS #### - - @staticmethod - def rgb(r, g, b): - return ((b & 0xF8) << 8) | ((g & 0xFC) << 3) | (r >> 3) - - @staticmethod - def clip_line(c, w, h): - while True: - ca = ce = 0 - if c[1] < 0: - ca |= 8 - elif c[1] > h: - ca |= 4 - if c[0] < 0: - ca |= 1 - elif c[0] > w: - ca |= 2 - if c[3] < 0: - ce |= 8 - elif c[3] > h: - ce |= 4 - if c[2] < 0: - ce |= 1 - elif c[2] > w: - ce |= 2 - if ca & ce: - return False - elif ca | ce: - ca |= ce - if ca & 1: - if c[2] < c[0]: - c[0], c[2] = c[2], c[0] - c[1], c[3] = c[3], c[1] - c[1] += ((-c[0]) * (c[3] - c[1])) // (c[2] - c[0]) - c[0] = 0 - elif ca & 2: - if c[2] < c[0]: - c[0], c[2] = c[2], c[0] - c[1], c[3] = c[3], c[1] - c[3] += ((w - 1 - c[2]) * (c[3] - c[1])) // (c[2] - c[0]) - c[2] = w - 1 - elif ca & 4: - if c[0] == c[2]: - if c[1] >= h: - c[1] = h - 1 - if c[3] >= h: - c[3] = h - 1 - else: - if c[3] < c[1]: - c[0], c[2] = c[2], c[0] - c[1], c[3] = c[3], c[1] - c[2] += ((h - 1 - c[3]) * (c[2] - c[0])) // (c[3] - c[1]) - c[3] = h - 1 - else: - if c[0] == c[2]: - if c[1] < 0: - c[1] = 0 - if c[3] < 0: - c[3] = 0 - else: - if c[3] < c[1]: - c[0], c[2] = c[2], c[0] - c[1], c[3] = c[3], c[1] - c[0] += ((-c[1]) * (c[2] - c[0])) // (c[3] - c[1]) - c[1] = 0 - else: - return True - - #### SETUP COMMANDS #### - - def set_power(self, on): - self.pwr(on) - sleep_ms(15) - - def set_orient(self, orient): - self._fcmd2("= 2: - self.i2c.readfrom_into(self.i2c_addr, self.buf[3]) - return self.buf[3][1] | self.buf[3][2] << 8 - t -= 1 - sleep_ms(1) - raise OSError(uerrno.ETIMEDOUT) - - def get_line(self, x, y, buf): - l = len(buf) // 2 - self._fcmd2b("= l: - self.i2c.readfrom_into(self.i2c_addr, buf) - return - t -= 1 - sleep_ms(1) - raise OSError(uerrno.ETIMEDOUT) - - def screen_dump(self, buf, x=0, y=0, w=None, h=None): - if w is None: - w = self.w - x - if h is None: - h = self.h - y - if w <= 127: - line = bytearray(2 * w + 1) - line2 = None - else: - # split line if more than 254 bytes needed - buflen = (w + 1) // 2 - line = bytearray(2 * buflen + 1) - line2 = memoryview(line)[: 2 * (w - buflen) + 1] - for i in range(min(len(buf) // (2 * w), h)): - ix = i * w * 2 - self.get_line(x, y + i, line) - buf[ix : ix + len(line) - 1] = memoryview(line)[1:] - ix += len(line) - 1 - if line2: - self.get_line(x + buflen, y + i, line2) - buf[ix : ix + len(line2) - 1] = memoryview(line2)[1:] - ix += len(line2) - 1 - - def screen_load(self, buf): - l = self.w * self.h * 2 + 2 - self._fcmd2b("= 0x200: - self._send(ar[n : n + 0x200]) - n += 0x200 - else: - self._send(ar[n:]) - while n < self.w * self.h * 2: - self._send(b"\x00") - n += 1 - - #### TEXT COMMANDS #### - - def set_pos(self, x, y): - self._fcmd2("= self.w or y >= self.h: - return - elif x < 0 or y < 0: - left = top = True - if x < 0: - left = False - w += x - x = 0 - if y < 0: - top = False - h += y - y = 0 - if cmd == 0x51 or cmd == 0x72: - # draw interior - self._fcmd2b("> 7 != 0 - - def get_touch(self): - self._send(b"\x02T") # implicit LCD output flush - b = self.buf[4] - self._waitfor(3, b) - return b[1] >> 7, b[2], b[3] - - #### ADVANCED COMMANDS #### - - def set_spi_win(self, x, y, w, h): - pack_into( - " 32: - raise ValueError("length must be 32 or less") - self._fcmd2(" 0xFFFF: - raise ValueError("length must be 65535 or less") - self.oflush() - self._fcmd2(" 0: - s = "%6.3fV" % data[i] - else: - s = "%5.1f°C" % data[i] - if lcd.h == 160: - lcd.set_font(1, bold=0, scale=1) - else: - lcd.set_font(1, bold=0, scale=1, trans=1) - lcd.set_pos(45, lcd.h - 60 + i * 16) - lcd.write(s) - - -def test_features(lcd, orient=lcd160cr.PORTRAIT): - # if we run on pyboard then use ADC and RTC features - try: - import pyb - - adc = pyb.ADCAll(12, 0xF0000) - rtc = pyb.RTC() - except: - adc = None - rtc = None - - # set orientation and clear screen - lcd = get_lcd(lcd) - lcd.set_orient(orient) - lcd.set_pen(0, 0) - lcd.erase() - - # create M-logo - mlogo = framebuf.FrameBuffer(bytearray(17 * 17 * 2), 17, 17, framebuf.RGB565) - mlogo.fill(0) - mlogo.fill_rect(1, 1, 15, 15, 0xFFFFFF) - mlogo.vline(4, 4, 12, 0) - mlogo.vline(8, 1, 12, 0) - mlogo.vline(12, 4, 12, 0) - mlogo.vline(14, 13, 2, 0) - - # create inline framebuf - offx = 14 - offy = 19 - w = 100 - h = 75 - fbuf = framebuf.FrameBuffer(bytearray(w * h * 2), w, h, framebuf.RGB565) - lcd.set_spi_win(offx, offy, w, h) - - # initialise loop parameters - tx = ty = 0 - t0 = time.ticks_us() - - for i in range(300): - # update position of cross-hair - t, tx2, ty2 = lcd.get_touch() - if t: - tx2 -= offx - ty2 -= offy - if tx2 >= 0 and ty2 >= 0 and tx2 < w and ty2 < h: - tx, ty = tx2, ty2 - else: - tx = (tx + 1) % w - ty = (ty + 1) % h - - # create and show the inline framebuf - fbuf.fill(lcd.rgb(128 + int(64 * math.cos(0.1 * i)), 128, 192)) - fbuf.line( - w // 2, - h // 2, - w // 2 + int(40 * math.cos(0.2 * i)), - h // 2 + int(40 * math.sin(0.2 * i)), - lcd.rgb(128, 255, 64), - ) - fbuf.hline(0, ty, w, lcd.rgb(64, 64, 64)) - fbuf.vline(tx, 0, h, lcd.rgb(64, 64, 64)) - fbuf.rect(tx - 3, ty - 3, 7, 7, lcd.rgb(64, 64, 64)) - for phase in (-0.2, 0, 0.2): - x = w // 2 - 8 + int(50 * math.cos(0.05 * i + phase)) - y = h // 2 - 8 + int(32 * math.sin(0.05 * i + phase)) - fbuf.blit(mlogo, x, y) - for j in range(-3, 3): - fbuf.text( - "MicroPython", - 5, - h // 2 + 9 * j + int(20 * math.sin(0.1 * (i + j))), - lcd.rgb(128 + 10 * j, 0, 128 - 10 * j), - ) - lcd.show_framebuf(fbuf) - - # show results from the ADC - if adc: - show_adc(lcd, adc) - - # show the time - if rtc: - lcd.set_pos(2, 0) - lcd.set_font(1) - t = rtc.datetime() - lcd.write( - "%4d-%02d-%02d %2d:%02d:%02d.%01d" - % (t[0], t[1], t[2], t[4], t[5], t[6], t[7] // 100000) - ) - - # compute the frame rate - t1 = time.ticks_us() - dt = time.ticks_diff(t1, t0) - t0 = t1 - - # show the frame rate - lcd.set_pos(2, 9) - lcd.write("%.2f fps" % (1000000 / dt)) - - -def test_mandel(lcd, orient=lcd160cr.PORTRAIT): - # set orientation and clear screen - lcd = get_lcd(lcd) - lcd.set_orient(orient) - lcd.set_pen(0, 0xFFFF) - lcd.erase() - - # function to compute Mandelbrot pixels - def in_set(c): - z = 0 - for i in range(32): - z = z * z + c - if abs(z) > 100: - return i - return 0 - - # cache width and height of LCD - w = lcd.w - h = lcd.h - - # create the buffer for each line and set SPI parameters - line = bytearray(w * 2) - lcd.set_spi_win(0, 0, w, h) - spi = lcd.fast_spi() - - # draw the Mandelbrot set line-by-line - hh = (h - 1) / 3.2 - ww = (w - 1) / 2.4 - for v in range(h): - for u in range(w): - c = in_set((v / hh - 2.3) + (u / ww - 1.2) * 1j) - if c < 16: - rgb = c << 12 | c << 6 - else: - rgb = 0xF800 | c << 6 - line[2 * u] = rgb - line[2 * u + 1] = rgb >> 8 - spi.write(line) - - -def test_all(lcd, orient=lcd160cr.PORTRAIT): - lcd = get_lcd(lcd) - test_features(lcd, orient) - test_mandel(lcd, orient) - - -print("To run all tests: test_all()") -print("Individual tests are: test_features, test_mandel") -print(' argument should be a connection, eg "X", or an LCD160CR object') diff --git a/drivers/display/manifest.py b/drivers/display/manifest.py deleted file mode 100644 index 16f93a7d4e..0000000000 --- a/drivers/display/manifest.py +++ /dev/null @@ -1,11 +0,0 @@ -# TODO: Split these into separate directories with their own manifests. -options.defaults(lcd160cr=False, ssd1306=False, test=False) - -if options.lcd160cr: - module("lcd160cr.py", opt=3) - - if options.test: - module("lcd160cr_test.py", opt=3) - -if options.ssd1306: - module("ssd1306.py", opt=3) diff --git a/drivers/display/ssd1306.py b/drivers/display/ssd1306.py deleted file mode 100644 index a504cdadcc..0000000000 --- a/drivers/display/ssd1306.py +++ /dev/null @@ -1,163 +0,0 @@ -# MicroPython SSD1306 OLED driver, I2C and SPI interfaces - -from micropython import const -import framebuf - - -# register definitions -SET_CONTRAST = const(0x81) -SET_ENTIRE_ON = const(0xA4) -SET_NORM_INV = const(0xA6) -SET_DISP = const(0xAE) -SET_MEM_ADDR = const(0x20) -SET_COL_ADDR = const(0x21) -SET_PAGE_ADDR = const(0x22) -SET_DISP_START_LINE = const(0x40) -SET_SEG_REMAP = const(0xA0) -SET_MUX_RATIO = const(0xA8) -SET_IREF_SELECT = const(0xAD) -SET_COM_OUT_DIR = const(0xC0) -SET_DISP_OFFSET = const(0xD3) -SET_COM_PIN_CFG = const(0xDA) -SET_DISP_CLK_DIV = const(0xD5) -SET_PRECHARGE = const(0xD9) -SET_VCOM_DESEL = const(0xDB) -SET_CHARGE_PUMP = const(0x8D) - -# Subclassing FrameBuffer provides support for graphics primitives -# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html -class SSD1306(framebuf.FrameBuffer): - def __init__(self, width, height, external_vcc): - self.width = width - self.height = height - self.external_vcc = external_vcc - self.pages = self.height // 8 - self.buffer = bytearray(self.pages * self.width) - super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB) - self.init_display() - - def init_display(self): - for cmd in ( - SET_DISP, # display off - # address setting - SET_MEM_ADDR, - 0x00, # horizontal - # resolution and layout - SET_DISP_START_LINE, # start at line 0 - SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0 - SET_MUX_RATIO, - self.height - 1, - SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0 - SET_DISP_OFFSET, - 0x00, - SET_COM_PIN_CFG, - 0x02 if self.width > 2 * self.height else 0x12, - # timing and driving scheme - SET_DISP_CLK_DIV, - 0x80, - SET_PRECHARGE, - 0x22 if self.external_vcc else 0xF1, - SET_VCOM_DESEL, - 0x30, # 0.83*Vcc - # display - SET_CONTRAST, - 0xFF, # maximum - SET_ENTIRE_ON, # output follows RAM contents - SET_NORM_INV, # not inverted - SET_IREF_SELECT, - 0x30, # enable internal IREF during display on - # charge pump - SET_CHARGE_PUMP, - 0x10 if self.external_vcc else 0x14, - SET_DISP | 0x01, # display on - ): # on - self.write_cmd(cmd) - self.fill(0) - self.show() - - def poweroff(self): - self.write_cmd(SET_DISP) - - def poweron(self): - self.write_cmd(SET_DISP | 0x01) - - def contrast(self, contrast): - self.write_cmd(SET_CONTRAST) - self.write_cmd(contrast) - - def invert(self, invert): - self.write_cmd(SET_NORM_INV | (invert & 1)) - - def rotate(self, rotate): - self.write_cmd(SET_COM_OUT_DIR | ((rotate & 1) << 3)) - self.write_cmd(SET_SEG_REMAP | (rotate & 1)) - - def show(self): - x0 = 0 - x1 = self.width - 1 - if self.width != 128: - # narrow displays use centred columns - col_offset = (128 - self.width) // 2 - x0 += col_offset - x1 += col_offset - self.write_cmd(SET_COL_ADDR) - self.write_cmd(x0) - self.write_cmd(x1) - self.write_cmd(SET_PAGE_ADDR) - self.write_cmd(0) - self.write_cmd(self.pages - 1) - self.write_data(self.buffer) - - -class SSD1306_I2C(SSD1306): - def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False): - self.i2c = i2c - self.addr = addr - self.temp = bytearray(2) - self.write_list = [b"\x40", None] # Co=0, D/C#=1 - super().__init__(width, height, external_vcc) - - def write_cmd(self, cmd): - self.temp[0] = 0x80 # Co=1, D/C#=0 - self.temp[1] = cmd - self.i2c.writeto(self.addr, self.temp) - - def write_data(self, buf): - self.write_list[1] = buf - self.i2c.writevto(self.addr, self.write_list) - - -class SSD1306_SPI(SSD1306): - def __init__(self, width, height, spi, dc, res, cs, external_vcc=False): - self.rate = 10 * 1024 * 1024 - dc.init(dc.OUT, value=0) - res.init(res.OUT, value=0) - cs.init(cs.OUT, value=1) - self.spi = spi - self.dc = dc - self.res = res - self.cs = cs - import time - - self.res(1) - time.sleep_ms(1) - self.res(0) - time.sleep_ms(10) - self.res(1) - super().__init__(width, height, external_vcc) - - def write_cmd(self, cmd): - self.spi.init(baudrate=self.rate, polarity=0, phase=0) - self.cs(1) - self.dc(0) - self.cs(0) - self.spi.write(bytearray([cmd])) - self.cs(1) - - def write_data(self, buf): - self.spi.init(baudrate=self.rate, polarity=0, phase=0) - self.cs(1) - self.dc(1) - self.cs(0) - self.spi.write(buf) - self.cs(1) diff --git a/drivers/hts221/hts221.py b/drivers/hts221/hts221.py deleted file mode 100644 index fec52a7389..0000000000 --- a/drivers/hts221/hts221.py +++ /dev/null @@ -1,91 +0,0 @@ -""" -The MIT License (MIT) - -Copyright (c) 2013-2022 Ibrahim Abdelkader -Copyright (c) 2013-2022 Kwabena W. Agyeman - -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. - -HTS221 driver driver for MicroPython. -Original source: https://github.com/ControlEverythingCommunity/HTS221/blob/master/Python/HTS221.py - -Example usage: - -import time -import hts221 -from machine import Pin, I2C - -bus = I2C(1, scl=Pin(15), sda=Pin(14)) -hts = hts221.HTS221(bus) - -while (True): - rH = hts.humidity() - temp = hts.temperature() - print ("rH: %.2f%% T: %.2fC" %(rH, temp)) - time.sleep_ms(100) -""" - -import struct - - -class HTS221: - def __init__(self, i2c, data_rate=1, address=0x5F): - self.bus = i2c - self.odr = data_rate - self.slv_addr = address - - # Set configuration register - # Humidity and temperature average configuration - self.bus.writeto_mem(self.slv_addr, 0x10, b"\x1B") - - # Set control register - # PD | BDU | ODR - cfg = 0x80 | 0x04 | (self.odr & 0x3) - self.bus.writeto_mem(self.slv_addr, 0x20, bytes([cfg])) - - # Read Calibration values from non-volatile memory of the device - # Humidity Calibration values - self.H0 = self._read_reg(0x30, 1) / 2 - self.H1 = self._read_reg(0x31, 1) / 2 - self.H2 = self._read_reg(0x36, 2) - self.H3 = self._read_reg(0x3A, 2) - - # Temperature Calibration values - raw = self._read_reg(0x35, 1) - self.T0 = ((raw & 0x03) * 256) + self._read_reg(0x32, 1) - self.T1 = ((raw & 0x0C) * 64) + self._read_reg(0x33, 1) - self.T2 = self._read_reg(0x3C, 2) - self.T3 = self._read_reg(0x3E, 2) - - def _read_reg(self, reg_addr, size): - fmt = "B" if size == 1 else "H" - reg_addr = reg_addr if size == 1 else reg_addr | 0x80 - return struct.unpack(fmt, self.bus.readfrom_mem(self.slv_addr, reg_addr, size))[0] - - def humidity(self): - rH = self._read_reg(0x28, 2) - return (self.H1 - self.H0) * (rH - self.H2) / (self.H3 - self.H2) + self.H0 - - def temperature(self): - temp = self._read_reg(0x2A, 2) - if temp > 32767: - temp -= 65536 - return ((self.T1 - self.T0) / 8.0) * (temp - self.T2) / (self.T3 - self.T2) + ( - self.T0 / 8.0 - ) diff --git a/drivers/hts221/manifest.py b/drivers/hts221/manifest.py deleted file mode 100644 index 5f17926659..0000000000 --- a/drivers/hts221/manifest.py +++ /dev/null @@ -1 +0,0 @@ -module("hts221.py", opt=3) diff --git a/drivers/lps22h/lps22h.py b/drivers/lps22h/lps22h.py deleted file mode 100644 index ca29efce2d..0000000000 --- a/drivers/lps22h/lps22h.py +++ /dev/null @@ -1,109 +0,0 @@ -""" -The MIT License (MIT) - -Copyright (c) 2016-2019 shaoziyang -Copyright (c) 2022 Ibrahim Abdelkader - -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. - -LPS22HB/HH pressure sensor driver for MicroPython. - -Example usage: - -import time -from lps22h import LPS22H -from machine import Pin, I2C - -bus = I2C(1, scl=Pin(15), sda=Pin(14)) -lps = LPS22H(bus, oneshot=False) - -while (True): - print("Pressure: %.2f hPa Temperature: %.2f C"%(lps.pressure(), lps.temperature())) - time.sleep_ms(10) -""" -import machine - -_LPS22_CTRL_REG1 = const(0x10) -_LPS22_CTRL_REG2 = const(0x11) -_LPS22_STATUS = const(0x27) -_LPS22_TEMP_OUT_L = const(0x2B) -_LPS22_PRESS_OUT_XL = const(0x28) -_LPS22_PRESS_OUT_L = const(0x29) - - -class LPS22H: - def __init__(self, i2c, address=0x5C, oneshot=False): - self.i2c = i2c - self.addr = address - self.oneshot = oneshot - self.buf = bytearray(1) - # ODR=1 EN_LPFP=1 BDU=1 - self._write_reg(_LPS22_CTRL_REG1, 0x1A) - self.set_oneshot_mode(self.oneshot) - - def _int16(self, d): - return d if d < 0x8000 else d - 0x10000 - - def _write_reg(self, reg, dat): - self.buf[0] = dat - self.i2c.writeto_mem(self.addr, reg, self.buf) - - def _read_reg(self, reg, width=8): - self.i2c.readfrom_mem_into(self.addr, reg, self.buf) - val = self.buf[0] - if width == 16: - val |= self._read_reg(reg + 1) << 8 - return val - - def _tigger_oneshot(self, b): - if self.oneshot: - self._write_reg(_LPS22_CTRL_REG2, self._read_reg(_LPS22_CTRL_REG2) | 0x01) - self._read_reg(0x28 + b * 2) - while True: - if self._read_reg(_LPS22_STATUS) & b: - return - machine.idle() - - def set_oneshot_mode(self, oneshot): - self._read_reg(_LPS22_CTRL_REG1) - self.oneshot = oneshot - if oneshot: - self.buf[0] &= 0x0F - else: - self.buf[0] |= 0x10 - self._write_reg(_LPS22_CTRL_REG1, self.buf[0]) - - def pressure(self): - if self.oneshot: - self._tigger_oneshot(1) - return ( - self._read_reg(_LPS22_PRESS_OUT_XL) + self._read_reg(_LPS22_PRESS_OUT_L, 16) * 256 - ) / 4096 - - def temperature(self): - if self.oneshot: - self._tigger_oneshot(2) - return self._int16(self._read_reg(_LPS22_TEMP_OUT_L, 16)) / 100 - - def altitude(self): - return ( - (((1013.25 / self.pressure()) ** (1 / 5.257)) - 1.0) - * (self.temperature() + 273.15) - / 0.0065 - ) diff --git a/drivers/lps22h/manifest.py b/drivers/lps22h/manifest.py deleted file mode 100644 index d30108d93d..0000000000 --- a/drivers/lps22h/manifest.py +++ /dev/null @@ -1 +0,0 @@ -module("lps22h.py", opt=3) diff --git a/drivers/lsm6dsox/lsm6dsox.py b/drivers/lsm6dsox/lsm6dsox.py deleted file mode 100644 index 98e19fa4ca..0000000000 --- a/drivers/lsm6dsox/lsm6dsox.py +++ /dev/null @@ -1,271 +0,0 @@ -""" -LSM6DSOX STMicro driver for MicroPython based on LSM9DS1: -Source repo: https://github.com/hoihu/projects/tree/master/raspi-hat - -The MIT License (MIT) - -Copyright (c) 2021 Damien P. George -Copyright (c) 2021-2022 Ibrahim Abdelkader - -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. - -Basic example usage: - -import time -from lsm6dsox import LSM6DSOX - -from machine import Pin, SPI, I2C -# Init in I2C mode. -lsm = LSM6DSOX(I2C(0, scl=Pin(13), sda=Pin(12))) - -# Or init in SPI mode. -#lsm = LSM6DSOX(SPI(5), cs_pin=Pin(10)) - -while (True): - print('Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.read_accel())) - print('Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.read_gyro())) - print("") - time.sleep_ms(100) -""" - -import array -from micropython import const - - -class LSM6DSOX: - _CTRL3_C = const(0x12) - _CTRL1_XL = const(0x10) - _CTRL8_XL = const(0x17) - _CTRL9_XL = const(0x18) - - _CTRL2_G = const(0x11) - _CTRL7_G = const(0x16) - - _OUTX_L_G = const(0x22) - _OUTX_L_XL = const(0x28) - _MLC_STATUS = const(0x38) - - _DEFAULT_ADDR = const(0x6A) - _WHO_AM_I_REG = const(0x0F) - - _FUNC_CFG_ACCESS = const(0x01) - _FUNC_CFG_BANK_USER = const(0) - _FUNC_CFG_BANK_HUB = const(1) - _FUNC_CFG_BANK_EMBED = const(2) - - _MLC0_SRC = const(0x70) - _MLC_INT1 = const(0x0D) - _TAP_CFG0 = const(0x56) - - _EMB_FUNC_EN_A = const(0x04) - _EMB_FUNC_EN_B = const(0x05) - - def __init__( - self, - bus, - cs_pin=None, - address=_DEFAULT_ADDR, - gyro_odr=104, - accel_odr=104, - gyro_scale=2000, - accel_scale=4, - ucf=None, - ): - """Initalizes Gyro and Accelerator. - accel_odr: (0, 1.6Hz, 3.33Hz, 6.66Hz, 12.5Hz, 26Hz, 52Hz, 104Hz, 208Hz, 416Hz, 888Hz) - gyro_odr: (0, 1.6Hz, 3.33Hz, 6.66Hz, 12.5Hz, 26Hz, 52Hz, 104Hz, 208Hz, 416Hz, 888Hz) - gyro_scale: (245dps, 500dps, 1000dps, 2000dps) - accel_scale: (+/-2g, +/-4g, +/-8g, +-16g) - ucf: MLC program to load. - """ - self.bus = bus - self.cs_pin = cs_pin - self.address = address - self._use_i2c = hasattr(self.bus, "readfrom_mem") - - if not self._use_i2c and cs_pin is None: - raise ValueError("A CS pin must be provided in SPI mode") - - # check the id of the Accelerometer/Gyro - if self.__read_reg(_WHO_AM_I_REG) != 108: - raise OSError("No LSM6DS device was found at address 0x%x" % (self.address)) - - # allocate scratch buffer for efficient conversions and memread op's - self.scratch_int = array.array("h", [0, 0, 0]) - - SCALE_GYRO = {250: 0, 500: 1, 1000: 2, 2000: 3} - SCALE_ACCEL = {2: 0, 4: 2, 8: 3, 16: 1} - # XL_HM_MODE = 0 by default. G_HM_MODE = 0 by default. - ODR = { - 0: 0x00, - 1.6: 0x08, - 3.33: 0x09, - 6.66: 0x0A, - 12.5: 0x01, - 26: 0x02, - 52: 0x03, - 104: 0x04, - 208: 0x05, - 416: 0x06, - 888: 0x07, - } - - gyro_odr = round(gyro_odr, 2) - accel_odr = round(accel_odr, 2) - - # Sanity checks - if not gyro_odr in ODR: - raise ValueError("Invalid sampling rate: %d" % accel_odr) - if not gyro_scale in SCALE_GYRO: - raise ValueError("invalid gyro scaling: %d" % gyro_scale) - if not accel_odr in ODR: - raise ValueError("Invalid sampling rate: %d" % accel_odr) - if not accel_scale in SCALE_ACCEL: - raise ValueError("invalid accelerometer scaling: %d" % accel_scale) - - # Soft-reset the device. - self.reset() - - # Load and configure MLC if UCF file is provided - if ucf != None: - self.load_mlc(ucf) - - # Set Gyroscope datarate and scale. - # Note output from LPF2 second filtering stage is selected. See Figure 18. - self.__write_reg(_CTRL1_XL, (ODR[accel_odr] << 4) | (SCALE_ACCEL[accel_scale] << 2) | 2) - - # Enable LPF2 and HPF fast-settling mode, ODR/4 - self.__write_reg(_CTRL8_XL, 0x09) - - # Set Gyroscope datarate and scale. - self.__write_reg(_CTRL2_G, (ODR[gyro_odr] << 4) | (SCALE_GYRO[gyro_scale] << 2) | 0) - - self.gyro_scale = 32768 / gyro_scale - self.accel_scale = 32768 / accel_scale - - def __read_reg(self, reg, size=1): - if self._use_i2c: - buf = self.bus.readfrom_mem(self.address, reg, size) - else: - try: - self.cs_pin(0) - self.bus.write(bytes([reg | 0x80])) - buf = self.bus.read(size) - finally: - self.cs_pin(1) - if size == 1: - return int(buf[0]) - return [int(x) for x in buf] - - def __write_reg(self, reg, val): - if self._use_i2c: - self.bus.writeto_mem(self.address, reg, bytes([val])) - else: - try: - self.cs_pin(0) - self.bus.write(bytes([reg, val])) - finally: - self.cs_pin(1) - - def __read_reg_into(self, reg, buf): - if self._use_i2c: - self.bus.readfrom_mem_into(self.address, reg, buf) - else: - try: - self.cs_pin(0) - self.bus.write(bytes([reg | 0x80])) - self.bus.readinto(buf) - finally: - self.cs_pin(1) - - def reset(self): - self.__write_reg(_CTRL3_C, self.__read_reg(_CTRL3_C) | 0x1) - for i in range(0, 10): - if (self.__read_reg(_CTRL3_C) & 0x01) == 0: - return - time.sleep_ms(10) - raise OSError("Failed to reset LSM6DS device.") - - def set_mem_bank(self, bank): - cfg = self.__read_reg(_FUNC_CFG_ACCESS) & 0x3F - self.__write_reg(_FUNC_CFG_ACCESS, cfg | (bank << 6)) - - def set_embedded_functions(self, enable, emb_ab=None): - self.set_mem_bank(_FUNC_CFG_BANK_EMBED) - if enable: - self.__write_reg(_EMB_FUNC_EN_A, emb_ab[0]) - self.__write_reg(_EMB_FUNC_EN_B, emb_ab[1]) - else: - emb_a = self.__read_reg(_EMB_FUNC_EN_A) - emb_b = self.__read_reg(_EMB_FUNC_EN_B) - self.__write_reg(_EMB_FUNC_EN_A, (emb_a & 0xC7)) - self.__write_reg(_EMB_FUNC_EN_B, (emb_b & 0xE6)) - emb_ab = (emb_a, emb_b) - - self.set_mem_bank(_FUNC_CFG_BANK_USER) - return emb_ab - - def load_mlc(self, ucf): - # Load MLC config from file - with open(ucf, "r") as ucf_file: - for l in ucf_file: - if l.startswith("Ac"): - v = [int(v, 16) for v in l.strip().split(" ")[1:3]] - self.__write_reg(v[0], v[1]) - - emb_ab = self.set_embedded_functions(False) - - # Disable I3C interface - self.__write_reg(_CTRL9_XL, self.__read_reg(_CTRL9_XL) | 0x01) - - # Enable Block Data Update - self.__write_reg(_CTRL3_C, self.__read_reg(_CTRL3_C) | 0x40) - - # Route signals on interrupt pin 1 - self.set_mem_bank(_FUNC_CFG_BANK_EMBED) - self.__write_reg(_MLC_INT1, self.__read_reg(_MLC_INT1) & 0x01) - self.set_mem_bank(_FUNC_CFG_BANK_USER) - - # Configure interrupt pin mode - self.__write_reg(_TAP_CFG0, self.__read_reg(_TAP_CFG0) | 0x41) - - self.set_embedded_functions(True, emb_ab) - - def read_mlc_output(self): - buf = None - if self.__read_reg(_MLC_STATUS) & 0x1: - self.__read_reg(0x1A, size=12) - self.set_mem_bank(_FUNC_CFG_BANK_EMBED) - buf = self.__read_reg(_MLC0_SRC, 8) - self.set_mem_bank(_FUNC_CFG_BANK_USER) - return buf - - def read_gyro(self): - """Returns gyroscope vector in degrees/sec.""" - mv = memoryview(self.scratch_int) - f = self.gyro_scale - self.__read_reg_into(_OUTX_L_G, mv) - return (mv[0] / f, mv[1] / f, mv[2] / f) - - def read_accel(self): - """Returns acceleration vector in gravity units (9.81m/s^2).""" - mv = memoryview(self.scratch_int) - f = self.accel_scale - self.__read_reg_into(_OUTX_L_XL, mv) - return (mv[0] / f, mv[1] / f, mv[2] / f) diff --git a/drivers/lsm6dsox/lsm6dsox_basic.py b/drivers/lsm6dsox/lsm6dsox_basic.py deleted file mode 100644 index 0ffe9e92b7..0000000000 --- a/drivers/lsm6dsox/lsm6dsox_basic.py +++ /dev/null @@ -1,15 +0,0 @@ -# LSM6DSOX Basic Example. -import time -from lsm6dsox import LSM6DSOX - -from machine import Pin, I2C - -lsm = LSM6DSOX(I2C(0, scl=Pin(13), sda=Pin(12))) -# Or init in SPI mode. -# lsm = LSM6DSOX(SPI(5), cs_pin=Pin(10)) - -while True: - print("Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}".format(*lsm.read_accel())) - print("Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}".format(*lsm.read_gyro())) - print("") - time.sleep_ms(100) diff --git a/drivers/lsm6dsox/lsm6dsox_mlc.py b/drivers/lsm6dsox/lsm6dsox_mlc.py deleted file mode 100644 index 866498d0ce..0000000000 --- a/drivers/lsm6dsox/lsm6dsox_mlc.py +++ /dev/null @@ -1,48 +0,0 @@ -# LSM6DSOX IMU MLC (Machine Learning Core) Example. -# Download the raw UCF file, copy to storage and reset. - -# NOTE: The pre-trained models (UCF files) for the examples can be found here: -# https://github.com/STMicroelectronics/STMems_Machine_Learning_Core/tree/master/application_examples/lsm6dsox - -import time -from lsm6dsox import LSM6DSOX -from machine import Pin, I2C - -INT_MODE = True # Run in interrupt mode. -INT_FLAG = False # Set True on interrupt. - - -def imu_int_handler(pin): - global INT_FLAG - INT_FLAG = True - - -if INT_MODE == True: - int_pin = Pin(24) - int_pin.irq(handler=imu_int_handler, trigger=Pin.IRQ_RISING) - -i2c = I2C(0, scl=Pin(13), sda=Pin(12)) - -# Vibration detection example -UCF_FILE = "lsm6dsox_vibration_monitoring.ucf" -UCF_LABELS = {0: "no vibration", 1: "low vibration", 2: "high vibration"} -# NOTE: Selected data rate and scale must match the MLC data rate and scale. -lsm = LSM6DSOX(i2c, gyro_odr=26, accel_odr=26, gyro_scale=2000, accel_scale=4, ucf=UCF_FILE) - -# Head gestures example -# UCF_FILE = "lsm6dsox_head_gestures.ucf" -# UCF_LABELS = {0:"Nod", 1:"Shake", 2:"Stationary", 3:"Swing", 4:"Walk"} -# NOTE: Selected data rate and scale must match the MLC data rate and scale. -# lsm = LSM6DSOX(i2c, gyro_odr=26, accel_odr=26, gyro_scale=250, accel_scale=2, ucf=UCF_FILE) - -print("MLC configured...") - -while True: - if INT_MODE: - if INT_FLAG: - INT_FLAG = False - print(UCF_LABELS[lsm.read_mlc_output()[0]]) - else: - buf = lsm.read_mlc_output() - if buf != None: - print(UCF_LABELS[buf[0]]) diff --git a/drivers/lsm6dsox/manifest.py b/drivers/lsm6dsox/manifest.py deleted file mode 100644 index 28f4b3565e..0000000000 --- a/drivers/lsm6dsox/manifest.py +++ /dev/null @@ -1 +0,0 @@ -module("lsm6dsox.py", opt=3) diff --git a/drivers/lsm9ds1/lsm9ds1.py b/drivers/lsm9ds1/lsm9ds1.py deleted file mode 100644 index 5d9942a7b3..0000000000 --- a/drivers/lsm9ds1/lsm9ds1.py +++ /dev/null @@ -1,189 +0,0 @@ -""" -The MIT License (MIT) - -Copyright (c) 2013, 2014 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. - - -LSM9DS1 - 9DOF inertial sensor of STMicro driver for MicroPython. -The sensor contains an accelerometer / gyroscope / magnetometer -Uses the internal FIFO to store up to 16 gyro/accel data, use the iter_accel_gyro generator to access it. - -Example usage: - -import time -from lsm9ds1 import LSM9DS1 -from machine import Pin, I2C - -lsm = LSM9DS1(I2C(1, scl=Pin(15), sda=Pin(14))) - -while (True): - #for g,a in lsm.iter_accel_gyro(): print(g,a) # using fifo - print('Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.accel())) - print('Magnetometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.magnet())) - print('Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.gyro())) - print("") - time.sleep_ms(100) -""" -import array - - -_WHO_AM_I = const(0xF) -_CTRL_REG1_G = const(0x10) -_INT_GEN_SRC_G = const(0x14) -_OUT_TEMP = const(0x15) -_OUT_G = const(0x18) -_CTRL_REG4_G = const(0x1E) -_STATUS_REG = const(0x27) -_OUT_XL = const(0x28) -_FIFO_CTRL_REG = const(0x2E) -_FIFO_SRC = const(0x2F) -_OFFSET_REG_X_M = const(0x05) -_CTRL_REG1_M = const(0x20) -_OUT_M = const(0x28) -_SCALE_GYRO = const(((245, 0), (500, 1), (2000, 3))) -_SCALE_ACCEL = const(((2, 0), (4, 2), (8, 3), (16, 1))) - - -class LSM9DS1: - def __init__(self, i2c, address_gyro=0x6B, address_magnet=0x1E): - self.i2c = i2c - self.address_gyro = address_gyro - self.address_magnet = address_magnet - # check id's of accelerometer/gyro and magnetometer - if (self.magent_id() != b"=") or (self.gyro_id() != b"h"): - raise OSError( - "Invalid LSM9DS1 device, using address {}/{}".format(address_gyro, address_magnet) - ) - # allocate scratch buffer for efficient conversions and memread op's - self.scratch = array.array("B", [0, 0, 0, 0, 0, 0]) - self.scratch_int = array.array("h", [0, 0, 0]) - self.init_gyro_accel() - self.init_magnetometer() - - def init_gyro_accel(self, sample_rate=6, scale_gyro=0, scale_accel=0): - """Initalizes Gyro and Accelerator. - sample rate: 0-6 (off, 14.9Hz, 59.5Hz, 119Hz, 238Hz, 476Hz, 952Hz) - scale_gyro: 0-2 (245dps, 500dps, 2000dps ) - scale_accel: 0-3 (+/-2g, +/-4g, +/-8g, +-16g) - """ - assert sample_rate <= 6, "invalid sampling rate: %d" % sample_rate - assert scale_gyro <= 2, "invalid gyro scaling: %d" % scale_gyro - assert scale_accel <= 3, "invalid accelerometer scaling: %d" % scale_accel - - i2c = self.i2c - addr = self.address_gyro - mv = memoryview(self.scratch) - # angular control registers 1-3 / Orientation - mv[0] = ((sample_rate & 0x07) << 5) | ((_SCALE_GYRO[scale_gyro][1] & 0x3) << 3) - mv[1:4] = b"\x00\x00\x00" - i2c.writeto_mem(addr, _CTRL_REG1_G, mv[:5]) - # ctrl4 - enable x,y,z, outputs, no irq latching, no 4D - # ctrl5 - enable all axes, no decimation - # ctrl6 - set scaling and sample rate of accel - # ctrl7,8 - leave at default values - # ctrl9 - FIFO enabled - mv[0] = mv[1] = 0x38 - mv[2] = ((sample_rate & 7) << 5) | ((_SCALE_ACCEL[scale_accel][1] & 0x3) << 3) - mv[3] = 0x00 - mv[4] = 0x4 - mv[5] = 0x2 - i2c.writeto_mem(addr, _CTRL_REG4_G, mv[:6]) - - # fifo: use continous mode (overwrite old data if overflow) - i2c.writeto_mem(addr, _FIFO_CTRL_REG, b"\x00") - i2c.writeto_mem(addr, _FIFO_CTRL_REG, b"\xc0") - - self.scale_gyro = 32768 / _SCALE_GYRO[scale_gyro][0] - self.scale_accel = 32768 / _SCALE_ACCEL[scale_accel][0] - - def init_magnetometer(self, sample_rate=7, scale_magnet=0): - """ - sample rates = 0-7 (0.625, 1.25, 2.5, 5, 10, 20, 40, 80Hz) - scaling = 0-3 (+/-4, +/-8, +/-12, +/-16 Gauss) - """ - assert sample_rate < 8, "invalid sample rate: %d (0-7)" % sample_rate - assert scale_magnet < 4, "invalid scaling: %d (0-3)" % scale_magnet - i2c = self.i2c - addr = self.address_magnet - mv = memoryview(self.scratch) - mv[0] = 0x40 | (sample_rate << 2) # ctrl1: high performance mode - mv[1] = scale_magnet << 5 # ctrl2: scale, normal mode, no reset - mv[2] = 0x00 # ctrl3: continous conversion, no low power, I2C - mv[3] = 0x08 # ctrl4: high performance z-axis - mv[4] = 0x00 # ctr5: no fast read, no block update - i2c.writeto_mem(addr, _CTRL_REG1_M, mv[:5]) - self.scale_factor_magnet = 32768 / ((scale_magnet + 1) * 4) - - def calibrate_magnet(self, offset): - """ - offset is a magnet vecor that will be substracted by the magnetometer - for each measurement. It is written to the magnetometer's offset register - """ - offset = [int(i * self.scale_factor_magnet) for i in offset] - mv = memoryview(self.scratch) - mv[0] = offset[0] & 0xFF - mv[1] = offset[0] >> 8 - mv[2] = offset[1] & 0xFF - mv[3] = offset[1] >> 8 - mv[4] = offset[2] & 0xFF - mv[5] = offset[2] >> 8 - self.i2c.writeto_mem(self.address_magnet, _OFFSET_REG_X_M, mv[:6]) - - def gyro_id(self): - return self.i2c.readfrom_mem(self.address_gyro, _WHO_AM_I, 1) - - def magent_id(self): - return self.i2c.readfrom_mem(self.address_magnet, _WHO_AM_I, 1) - - def magnet(self): - """Returns magnetometer vector in gauss. - raw_values: if True, the non-scaled adc values are returned - """ - mv = memoryview(self.scratch_int) - f = self.scale_factor_magnet - self.i2c.readfrom_mem_into(self.address_magnet, _OUT_M | 0x80, mv) - return (mv[0] / f, mv[1] / f, mv[2] / f) - - def gyro(self): - """Returns gyroscope vector in degrees/sec.""" - mv = memoryview(self.scratch_int) - f = self.scale_gyro - self.i2c.readfrom_mem_into(self.address_gyro, _OUT_G | 0x80, mv) - return (mv[0] / f, mv[1] / f, mv[2] / f) - - def accel(self): - """Returns acceleration vector in gravity units (9.81m/s^2).""" - mv = memoryview(self.scratch_int) - f = self.scale_accel - self.i2c.readfrom_mem_into(self.address_gyro, _OUT_XL | 0x80, mv) - return (mv[0] / f, mv[1] / f, mv[2] / f) - - def iter_accel_gyro(self): - """A generator that returns tuples of (gyro,accelerometer) data from the fifo.""" - while True: - fifo_state = int.from_bytes( - self.i2c.readfrom_mem(self.address_gyro, _FIFO_SRC, 1), "big" - ) - if fifo_state & 0x3F: - # print("Available samples=%d" % (fifo_state & 0x1f)) - yield self.gyro(), self.accel() - else: - break diff --git a/drivers/lsm9ds1/manifest.py b/drivers/lsm9ds1/manifest.py deleted file mode 100644 index 6779362de7..0000000000 --- a/drivers/lsm9ds1/manifest.py +++ /dev/null @@ -1 +0,0 @@ -module("lsm9ds1.py", opt=3) diff --git a/drivers/neopixel/manifest.py b/drivers/neopixel/manifest.py deleted file mode 100644 index 561d19574a..0000000000 --- a/drivers/neopixel/manifest.py +++ /dev/null @@ -1 +0,0 @@ -module("neopixel.py", opt=3) diff --git a/drivers/neopixel/neopixel.py b/drivers/neopixel/neopixel.py deleted file mode 100644 index caa12dc845..0000000000 --- a/drivers/neopixel/neopixel.py +++ /dev/null @@ -1,50 +0,0 @@ -# NeoPixel driver for MicroPython -# MIT license; Copyright (c) 2016 Damien P. George, 2021 Jim Mussared - -from machine import bitstream - - -class NeoPixel: - # G R B W - ORDER = (1, 0, 2, 3) - - def __init__(self, pin, n, bpp=3, timing=1): - self.pin = pin - self.n = n - self.bpp = bpp - self.buf = bytearray(n * bpp) - self.pin.init(pin.OUT) - # Timing arg can either be 1 for 800kHz or 0 for 400kHz, - # or a user-specified timing ns tuple (high_0, low_0, high_1, low_1). - self.timing = ( - ((400, 850, 800, 450) if timing else (800, 1700, 1600, 900)) - if isinstance(timing, int) - else timing - ) - - def __len__(self): - return self.n - - def __setitem__(self, i, v): - offset = i * self.bpp - for i in range(self.bpp): - self.buf[offset + self.ORDER[i]] = v[i] - - def __getitem__(self, i): - offset = i * self.bpp - return tuple(self.buf[offset + self.ORDER[i]] for i in range(self.bpp)) - - def fill(self, v): - b = self.buf - l = len(self.buf) - bpp = self.bpp - for i in range(bpp): - c = v[i] - j = self.ORDER[i] - while j < l: - b[j] = c - j += bpp - - def write(self): - # BITSTREAM_TYPE_HIGH_LOW = 0 - bitstream(self.pin, 0, self.timing, self.buf) diff --git a/drivers/nrf24l01/manifest.py b/drivers/nrf24l01/manifest.py deleted file mode 100644 index babdb7a52a..0000000000 --- a/drivers/nrf24l01/manifest.py +++ /dev/null @@ -1 +0,0 @@ -module("nrf24l01.py", opt=3) diff --git a/drivers/nrf24l01/nrf24l01.py b/drivers/nrf24l01/nrf24l01.py deleted file mode 100644 index 76d55312f8..0000000000 --- a/drivers/nrf24l01/nrf24l01.py +++ /dev/null @@ -1,252 +0,0 @@ -"""NRF24L01 driver for MicroPython -""" - -from micropython import const -import utime - -# nRF24L01+ registers -CONFIG = const(0x00) -EN_RXADDR = const(0x02) -SETUP_AW = const(0x03) -SETUP_RETR = const(0x04) -RF_CH = const(0x05) -RF_SETUP = const(0x06) -STATUS = const(0x07) -RX_ADDR_P0 = const(0x0A) -TX_ADDR = const(0x10) -RX_PW_P0 = const(0x11) -FIFO_STATUS = const(0x17) -DYNPD = const(0x1C) - -# CONFIG register -EN_CRC = const(0x08) # enable CRC -CRCO = const(0x04) # CRC encoding scheme; 0=1 byte, 1=2 bytes -PWR_UP = const(0x02) # 1=power up, 0=power down -PRIM_RX = const(0x01) # RX/TX control; 0=PTX, 1=PRX - -# RF_SETUP register -POWER_0 = const(0x00) # -18 dBm -POWER_1 = const(0x02) # -12 dBm -POWER_2 = const(0x04) # -6 dBm -POWER_3 = const(0x06) # 0 dBm -SPEED_1M = const(0x00) -SPEED_2M = const(0x08) -SPEED_250K = const(0x20) - -# STATUS register -RX_DR = const(0x40) # RX data ready; write 1 to clear -TX_DS = const(0x20) # TX data sent; write 1 to clear -MAX_RT = const(0x10) # max retransmits reached; write 1 to clear - -# FIFO_STATUS register -RX_EMPTY = const(0x01) # 1 if RX FIFO is empty - -# constants for instructions -R_RX_PL_WID = const(0x60) # read RX payload width -R_RX_PAYLOAD = const(0x61) # read RX payload -W_TX_PAYLOAD = const(0xA0) # write TX payload -FLUSH_TX = const(0xE1) # flush TX FIFO -FLUSH_RX = const(0xE2) # flush RX FIFO -NOP = const(0xFF) # use to read STATUS register - - -class NRF24L01: - def __init__(self, spi, cs, ce, channel=46, payload_size=16): - assert payload_size <= 32 - - self.buf = bytearray(1) - - # store the pins - self.spi = spi - self.cs = cs - self.ce = ce - - # init the SPI bus and pins - self.init_spi(4000000) - - # reset everything - ce.init(ce.OUT, value=0) - cs.init(cs.OUT, value=1) - - self.payload_size = payload_size - self.pipe0_read_addr = None - utime.sleep_ms(5) - - # set address width to 5 bytes and check for device present - self.reg_write(SETUP_AW, 0b11) - if self.reg_read(SETUP_AW) != 0b11: - raise OSError("nRF24L01+ Hardware not responding") - - # disable dynamic payloads - self.reg_write(DYNPD, 0) - - # auto retransmit delay: 1750us - # auto retransmit count: 8 - self.reg_write(SETUP_RETR, (6 << 4) | 8) - - # set rf power and speed - self.set_power_speed(POWER_3, SPEED_250K) # Best for point to point links - - # init CRC - self.set_crc(2) - - # clear status flags - self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT) - - # set channel - self.set_channel(channel) - - # flush buffers - self.flush_rx() - self.flush_tx() - - def init_spi(self, baudrate): - try: - master = self.spi.MASTER - except AttributeError: - self.spi.init(baudrate=baudrate, polarity=0, phase=0) - else: - self.spi.init(master, baudrate=baudrate, polarity=0, phase=0) - - def reg_read(self, reg): - self.cs(0) - self.spi.readinto(self.buf, reg) - self.spi.readinto(self.buf) - self.cs(1) - return self.buf[0] - - def reg_write_bytes(self, reg, buf): - self.cs(0) - self.spi.readinto(self.buf, 0x20 | reg) - self.spi.write(buf) - self.cs(1) - return self.buf[0] - - def reg_write(self, reg, value): - self.cs(0) - self.spi.readinto(self.buf, 0x20 | reg) - ret = self.buf[0] - self.spi.readinto(self.buf, value) - self.cs(1) - return ret - - def flush_rx(self): - self.cs(0) - self.spi.readinto(self.buf, FLUSH_RX) - self.cs(1) - - def flush_tx(self): - self.cs(0) - self.spi.readinto(self.buf, FLUSH_TX) - self.cs(1) - - # power is one of POWER_x defines; speed is one of SPEED_x defines - def set_power_speed(self, power, speed): - setup = self.reg_read(RF_SETUP) & 0b11010001 - self.reg_write(RF_SETUP, setup | power | speed) - - # length in bytes: 0, 1 or 2 - def set_crc(self, length): - config = self.reg_read(CONFIG) & ~(CRCO | EN_CRC) - if length == 0: - pass - elif length == 1: - config |= EN_CRC - else: - config |= EN_CRC | CRCO - self.reg_write(CONFIG, config) - - def set_channel(self, channel): - self.reg_write(RF_CH, min(channel, 125)) - - # address should be a bytes object 5 bytes long - def open_tx_pipe(self, address): - assert len(address) == 5 - self.reg_write_bytes(RX_ADDR_P0, address) - self.reg_write_bytes(TX_ADDR, address) - self.reg_write(RX_PW_P0, self.payload_size) - - # address should be a bytes object 5 bytes long - # pipe 0 and 1 have 5 byte address - # pipes 2-5 use same 4 most-significant bytes as pipe 1, plus 1 extra byte - def open_rx_pipe(self, pipe_id, address): - assert len(address) == 5 - assert 0 <= pipe_id <= 5 - if pipe_id == 0: - self.pipe0_read_addr = address - if pipe_id < 2: - self.reg_write_bytes(RX_ADDR_P0 + pipe_id, address) - else: - self.reg_write(RX_ADDR_P0 + pipe_id, address[0]) - self.reg_write(RX_PW_P0 + pipe_id, self.payload_size) - self.reg_write(EN_RXADDR, self.reg_read(EN_RXADDR) | (1 << pipe_id)) - - def start_listening(self): - self.reg_write(CONFIG, self.reg_read(CONFIG) | PWR_UP | PRIM_RX) - self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT) - - if self.pipe0_read_addr is not None: - self.reg_write_bytes(RX_ADDR_P0, self.pipe0_read_addr) - - self.flush_rx() - self.flush_tx() - self.ce(1) - utime.sleep_us(130) - - def stop_listening(self): - self.ce(0) - self.flush_tx() - self.flush_rx() - - # returns True if any data available to recv - def any(self): - return not bool(self.reg_read(FIFO_STATUS) & RX_EMPTY) - - def recv(self): - # get the data - self.cs(0) - self.spi.readinto(self.buf, R_RX_PAYLOAD) - buf = self.spi.read(self.payload_size) - self.cs(1) - # clear RX ready flag - self.reg_write(STATUS, RX_DR) - - return buf - - # blocking wait for tx complete - def send(self, buf, timeout=500): - self.send_start(buf) - start = utime.ticks_ms() - result = None - while result is None and utime.ticks_diff(utime.ticks_ms(), start) < timeout: - result = self.send_done() # 1 == success, 2 == fail - if result == 2: - raise OSError("send failed") - - # non-blocking tx - def send_start(self, buf): - # power up - self.reg_write(CONFIG, (self.reg_read(CONFIG) | PWR_UP) & ~PRIM_RX) - utime.sleep_us(150) - # send the data - self.cs(0) - self.spi.readinto(self.buf, W_TX_PAYLOAD) - self.spi.write(buf) - if len(buf) < self.payload_size: - self.spi.write(b"\x00" * (self.payload_size - len(buf))) # pad out data - self.cs(1) - - # enable the chip so it can send the data - self.ce(1) - utime.sleep_us(15) # needs to be >10us - self.ce(0) - - # returns None if send still in progress, 1 for success, 2 for fail - def send_done(self): - if not (self.reg_read(STATUS) & (TX_DS | MAX_RT)): - return None # tx not finished - - # either finished or failed: get and clear status flags, power down - status = self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT) - self.reg_write(CONFIG, self.reg_read(CONFIG) & ~PWR_UP) - return 1 if status & TX_DS else 2 diff --git a/drivers/nrf24l01/nrf24l01test.py b/drivers/nrf24l01/nrf24l01test.py deleted file mode 100644 index 56bdb6e26e..0000000000 --- a/drivers/nrf24l01/nrf24l01test.py +++ /dev/null @@ -1,150 +0,0 @@ -"""Test for nrf24l01 module. Portable between MicroPython targets.""" - -import usys -import ustruct as struct -import utime -from machine import Pin, SPI -from nrf24l01 import NRF24L01 -from micropython import const - -# Slave pause between receiving data and checking for further packets. -_RX_POLL_DELAY = const(15) -# Slave pauses an additional _SLAVE_SEND_DELAY ms after receiving data and before -# transmitting to allow the (remote) master time to get into receive mode. The -# master may be a slow device. Value tested with Pyboard, ESP32 and ESP8266. -_SLAVE_SEND_DELAY = const(10) - -if usys.platform == "pyboard": - cfg = {"spi": 2, "miso": "Y7", "mosi": "Y8", "sck": "Y6", "csn": "Y5", "ce": "Y4"} -elif usys.platform == "esp8266": # Hardware SPI - cfg = {"spi": 1, "miso": 12, "mosi": 13, "sck": 14, "csn": 4, "ce": 5} -elif usys.platform == "esp32": # Software SPI - cfg = {"spi": -1, "miso": 32, "mosi": 33, "sck": 25, "csn": 26, "ce": 27} -else: - raise ValueError("Unsupported platform {}".format(usys.platform)) - -# Addresses are in little-endian format. They correspond to big-endian -# 0xf0f0f0f0e1, 0xf0f0f0f0d2 -pipes = (b"\xe1\xf0\xf0\xf0\xf0", b"\xd2\xf0\xf0\xf0\xf0") - - -def master(): - csn = Pin(cfg["csn"], mode=Pin.OUT, value=1) - ce = Pin(cfg["ce"], mode=Pin.OUT, value=0) - if cfg["spi"] == -1: - spi = SPI(-1, sck=Pin(cfg["sck"]), mosi=Pin(cfg["mosi"]), miso=Pin(cfg["miso"])) - nrf = NRF24L01(spi, csn, ce, payload_size=8) - else: - nrf = NRF24L01(SPI(cfg["spi"]), csn, ce, payload_size=8) - - nrf.open_tx_pipe(pipes[0]) - nrf.open_rx_pipe(1, pipes[1]) - nrf.start_listening() - - num_needed = 16 - num_successes = 0 - num_failures = 0 - led_state = 0 - - print("NRF24L01 master mode, sending %d packets..." % num_needed) - - while num_successes < num_needed and num_failures < num_needed: - # stop listening and send packet - nrf.stop_listening() - millis = utime.ticks_ms() - led_state = max(1, (led_state << 1) & 0x0F) - print("sending:", millis, led_state) - try: - nrf.send(struct.pack("ii", millis, led_state)) - except OSError: - pass - - # start listening again - nrf.start_listening() - - # wait for response, with 250ms timeout - start_time = utime.ticks_ms() - timeout = False - while not nrf.any() and not timeout: - if utime.ticks_diff(utime.ticks_ms(), start_time) > 250: - timeout = True - - if timeout: - print("failed, response timed out") - num_failures += 1 - - else: - # recv packet - (got_millis,) = struct.unpack("i", nrf.recv()) - - # print response and round-trip delay - print( - "got response:", - got_millis, - "(delay", - utime.ticks_diff(utime.ticks_ms(), got_millis), - "ms)", - ) - num_successes += 1 - - # delay then loop - utime.sleep_ms(250) - - print("master finished sending; successes=%d, failures=%d" % (num_successes, num_failures)) - - -def slave(): - csn = Pin(cfg["csn"], mode=Pin.OUT, value=1) - ce = Pin(cfg["ce"], mode=Pin.OUT, value=0) - if cfg["spi"] == -1: - spi = SPI(-1, sck=Pin(cfg["sck"]), mosi=Pin(cfg["mosi"]), miso=Pin(cfg["miso"])) - nrf = NRF24L01(spi, csn, ce, payload_size=8) - else: - nrf = NRF24L01(SPI(cfg["spi"]), csn, ce, payload_size=8) - - nrf.open_tx_pipe(pipes[1]) - nrf.open_rx_pipe(1, pipes[0]) - nrf.start_listening() - - print("NRF24L01 slave mode, waiting for packets... (ctrl-C to stop)") - - while True: - if nrf.any(): - while nrf.any(): - buf = nrf.recv() - millis, led_state = struct.unpack("ii", buf) - print("received:", millis, led_state) - for led in leds: - if led_state & 1: - led.on() - else: - led.off() - led_state >>= 1 - utime.sleep_ms(_RX_POLL_DELAY) - - # Give master time to get into receive mode. - utime.sleep_ms(_SLAVE_SEND_DELAY) - nrf.stop_listening() - try: - nrf.send(struct.pack("i", millis)) - except OSError: - pass - print("sent response") - nrf.start_listening() - - -try: - import pyb - - leds = [pyb.LED(i + 1) for i in range(4)] -except: - leds = [] - -print("NRF24L01 test module loaded") -print("NRF24L01 pinout for test:") -print(" CE on", cfg["ce"]) -print(" CSN on", cfg["csn"]) -print(" SCK on", cfg["sck"]) -print(" MISO on", cfg["miso"]) -print(" MOSI on", cfg["mosi"]) -print("run nrf24l01test.slave() on slave, then nrf24l01test.master() on master") diff --git a/drivers/onewire/ds18x20.py b/drivers/onewire/ds18x20.py deleted file mode 100644 index ad2d9f52cd..0000000000 --- a/drivers/onewire/ds18x20.py +++ /dev/null @@ -1,52 +0,0 @@ -# DS18x20 temperature sensor driver for MicroPython. -# MIT license; Copyright (c) 2016 Damien P. George - -from micropython import const - -_CONVERT = const(0x44) -_RD_SCRATCH = const(0xBE) -_WR_SCRATCH = const(0x4E) - - -class DS18X20: - def __init__(self, onewire): - self.ow = onewire - self.buf = bytearray(9) - - def scan(self): - return [rom for rom in self.ow.scan() if rom[0] in (0x10, 0x22, 0x28)] - - def convert_temp(self): - self.ow.reset(True) - self.ow.writebyte(self.ow.SKIP_ROM) - self.ow.writebyte(_CONVERT) - - def read_scratch(self, rom): - self.ow.reset(True) - self.ow.select_rom(rom) - self.ow.writebyte(_RD_SCRATCH) - self.ow.readinto(self.buf) - if self.ow.crc8(self.buf): - raise Exception("CRC error") - return self.buf - - def write_scratch(self, rom, buf): - self.ow.reset(True) - self.ow.select_rom(rom) - self.ow.writebyte(_WR_SCRATCH) - self.ow.write(buf) - - def read_temp(self, rom): - buf = self.read_scratch(rom) - if rom[0] == 0x10: - if buf[1]: - t = buf[0] >> 1 | 0x80 - t = -((~t + 1) & 0xFF) - else: - t = buf[0] >> 1 - return t - 0.25 + (buf[7] - buf[6]) / buf[7] - else: - t = buf[1] << 8 | buf[0] - if t & 0x8000: # sign bit set - t = -((t ^ 0xFFFF) + 1) - return t / 16 diff --git a/drivers/onewire/manifest.py b/drivers/onewire/manifest.py deleted file mode 100644 index f500a65d78..0000000000 --- a/drivers/onewire/manifest.py +++ /dev/null @@ -1,6 +0,0 @@ -options.defaults(ds18x20=False) - -module("onewire.py", opt=3) - -if options.ds18x20: - module("ds18x20.py", opt=3) diff --git a/drivers/onewire/onewire.py b/drivers/onewire/onewire.py deleted file mode 100644 index 4c6da741c7..0000000000 --- a/drivers/onewire/onewire.py +++ /dev/null @@ -1,92 +0,0 @@ -# 1-Wire driver for MicroPython -# MIT license; Copyright (c) 2016 Damien P. George - -import _onewire as _ow - - -class OneWireError(Exception): - pass - - -class OneWire: - SEARCH_ROM = 0xF0 - MATCH_ROM = 0x55 - SKIP_ROM = 0xCC - - def __init__(self, pin): - self.pin = pin - self.pin.init(pin.OPEN_DRAIN, pin.PULL_UP) - - def reset(self, required=False): - reset = _ow.reset(self.pin) - if required and not reset: - raise OneWireError - return reset - - def readbit(self): - return _ow.readbit(self.pin) - - def readbyte(self): - return _ow.readbyte(self.pin) - - def readinto(self, buf): - for i in range(len(buf)): - buf[i] = _ow.readbyte(self.pin) - - def writebit(self, value): - return _ow.writebit(self.pin, value) - - def writebyte(self, value): - return _ow.writebyte(self.pin, value) - - def write(self, buf): - for b in buf: - _ow.writebyte(self.pin, b) - - def select_rom(self, rom): - self.reset() - self.writebyte(self.MATCH_ROM) - self.write(rom) - - def scan(self): - devices = [] - diff = 65 - rom = False - for i in range(0xFF): - rom, diff = self._search_rom(rom, diff) - if rom: - devices += [rom] - if diff == 0: - break - return devices - - def _search_rom(self, l_rom, diff): - if not self.reset(): - return None, 0 - self.writebyte(self.SEARCH_ROM) - if not l_rom: - l_rom = bytearray(8) - rom = bytearray(8) - next_diff = 0 - i = 64 - for byte in range(8): - r_b = 0 - for bit in range(8): - b = self.readbit() - if self.readbit(): - if b: # there are no devices or there is an error on the bus - return None, 0 - else: - if not b: # collision, two devices with different bit meaning - if diff > i or ((l_rom[byte] & (1 << bit)) and diff != i): - b = 1 - next_diff = i - self.writebit(b) - if b: - r_b |= 1 << bit - i -= 1 - rom[byte] = r_b - return rom, next_diff - - def crc8(self, data): - return _ow.crc8(data) diff --git a/drivers/sdcard/manifest.py b/drivers/sdcard/manifest.py deleted file mode 100644 index e584b97d9c..0000000000 --- a/drivers/sdcard/manifest.py +++ /dev/null @@ -1 +0,0 @@ -module("sdcard.py", opt=3) diff --git a/drivers/sdcard/sdcard.py b/drivers/sdcard/sdcard.py deleted file mode 100644 index df28bd9534..0000000000 --- a/drivers/sdcard/sdcard.py +++ /dev/null @@ -1,299 +0,0 @@ -""" -MicroPython driver for SD cards using SPI bus. - -Requires an SPI bus and a CS pin. Provides readblocks and writeblocks -methods so the device can be mounted as a filesystem. - -Example usage on pyboard: - - import pyb, sdcard, os - sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5) - pyb.mount(sd, '/sd2') - os.listdir('/') - -Example usage on ESP8266: - - import machine, sdcard, os - sd = sdcard.SDCard(machine.SPI(1), machine.Pin(15)) - os.mount(sd, '/sd') - os.listdir('/') - -""" - -from micropython import const -import time - - -_CMD_TIMEOUT = const(100) - -_R1_IDLE_STATE = const(1 << 0) -# R1_ERASE_RESET = const(1 << 1) -_R1_ILLEGAL_COMMAND = const(1 << 2) -# R1_COM_CRC_ERROR = const(1 << 3) -# R1_ERASE_SEQUENCE_ERROR = const(1 << 4) -# R1_ADDRESS_ERROR = const(1 << 5) -# R1_PARAMETER_ERROR = const(1 << 6) -_TOKEN_CMD25 = const(0xFC) -_TOKEN_STOP_TRAN = const(0xFD) -_TOKEN_DATA = const(0xFE) - - -class SDCard: - def __init__(self, spi, cs, baudrate=1320000): - self.spi = spi - self.cs = cs - - self.cmdbuf = bytearray(6) - self.dummybuf = bytearray(512) - self.tokenbuf = bytearray(1) - for i in range(512): - self.dummybuf[i] = 0xFF - self.dummybuf_memoryview = memoryview(self.dummybuf) - - # initialise the card - self.init_card(baudrate) - - def init_spi(self, baudrate): - try: - master = self.spi.MASTER - except AttributeError: - # on ESP8266 - self.spi.init(baudrate=baudrate, phase=0, polarity=0) - else: - # on pyboard - self.spi.init(master, baudrate=baudrate, phase=0, polarity=0) - - def init_card(self, baudrate): - - # init CS pin - self.cs.init(self.cs.OUT, value=1) - - # init SPI bus; use low data rate for initialisation - self.init_spi(100000) - - # clock card at least 100 cycles with cs high - for i in range(16): - self.spi.write(b"\xff") - - # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts) - for _ in range(5): - if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE: - break - else: - raise OSError("no SD card") - - # CMD8: determine card version - r = self.cmd(8, 0x01AA, 0x87, 4) - if r == _R1_IDLE_STATE: - self.init_card_v2() - elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND): - self.init_card_v1() - else: - raise OSError("couldn't determine SD card version") - - # get the number of sectors - # CMD9: response R2 (R1 byte + 16-byte block read) - if self.cmd(9, 0, 0, 0, False) != 0: - raise OSError("no response from SD card") - csd = bytearray(16) - self.readinto(csd) - if csd[0] & 0xC0 == 0x40: # CSD version 2.0 - self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024 - elif csd[0] & 0xC0 == 0x00: # CSD version 1.0 (old, <=2GB) - c_size = (csd[6] & 0b11) << 10 | csd[7] << 2 | csd[8] >> 6 - c_size_mult = (csd[9] & 0b11) << 1 | csd[10] >> 7 - read_bl_len = csd[5] & 0b1111 - capacity = (c_size + 1) * (2 ** (c_size_mult + 2)) * (2**read_bl_len) - self.sectors = capacity // 512 - else: - raise OSError("SD card CSD format not supported") - # print('sectors', self.sectors) - - # CMD16: set block length to 512 bytes - if self.cmd(16, 512, 0) != 0: - raise OSError("can't set 512 block size") - - # set to high data rate now that it's initialised - self.init_spi(baudrate) - - def init_card_v1(self): - for i in range(_CMD_TIMEOUT): - time.sleep_ms(50) - self.cmd(55, 0, 0) - if self.cmd(41, 0, 0) == 0: - # SDSC card, uses byte addressing in read/write/erase commands - self.cdv = 512 - # print("[SDCard] v1 card") - return - raise OSError("timeout waiting for v1 card") - - def init_card_v2(self): - for i in range(_CMD_TIMEOUT): - time.sleep_ms(50) - self.cmd(58, 0, 0, 4) - self.cmd(55, 0, 0) - if self.cmd(41, 0x40000000, 0) == 0: - self.cmd(58, 0, 0, -4) # 4-byte response, negative means keep the first byte - ocr = self.tokenbuf[0] # get first byte of response, which is OCR - if not ocr & 0x40: - # SDSC card, uses byte addressing in read/write/erase commands - self.cdv = 512 - else: - # SDHC/SDXC card, uses block addressing in read/write/erase commands - self.cdv = 1 - # print("[SDCard] v2 card") - return - raise OSError("timeout waiting for v2 card") - - def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False): - self.cs(0) - - # create and send the command - buf = self.cmdbuf - buf[0] = 0x40 | cmd - buf[1] = arg >> 24 - buf[2] = arg >> 16 - buf[3] = arg >> 8 - buf[4] = arg - buf[5] = crc - self.spi.write(buf) - - if skip1: - self.spi.readinto(self.tokenbuf, 0xFF) - - # wait for the response (response[7] == 0) - for i in range(_CMD_TIMEOUT): - self.spi.readinto(self.tokenbuf, 0xFF) - response = self.tokenbuf[0] - if not (response & 0x80): - # this could be a big-endian integer that we are getting here - # if final<0 then store the first byte to tokenbuf and discard the rest - if final < 0: - self.spi.readinto(self.tokenbuf, 0xFF) - final = -1 - final - for j in range(final): - self.spi.write(b"\xff") - if release: - self.cs(1) - self.spi.write(b"\xff") - return response - - # timeout - self.cs(1) - self.spi.write(b"\xff") - return -1 - - def readinto(self, buf): - self.cs(0) - - # read until start byte (0xff) - for i in range(_CMD_TIMEOUT): - self.spi.readinto(self.tokenbuf, 0xFF) - if self.tokenbuf[0] == _TOKEN_DATA: - break - time.sleep_ms(1) - else: - self.cs(1) - raise OSError("timeout waiting for response") - - # read data - mv = self.dummybuf_memoryview - if len(buf) != len(mv): - mv = mv[: len(buf)] - self.spi.write_readinto(mv, buf) - - # read checksum - self.spi.write(b"\xff") - self.spi.write(b"\xff") - - self.cs(1) - self.spi.write(b"\xff") - - def write(self, token, buf): - self.cs(0) - - # send: start of block, data, checksum - self.spi.read(1, token) - self.spi.write(buf) - self.spi.write(b"\xff") - self.spi.write(b"\xff") - - # check the response - if (self.spi.read(1, 0xFF)[0] & 0x1F) != 0x05: - self.cs(1) - self.spi.write(b"\xff") - return - - # wait for write to finish - while self.spi.read(1, 0xFF)[0] == 0: - pass - - self.cs(1) - self.spi.write(b"\xff") - - def write_token(self, token): - self.cs(0) - self.spi.read(1, token) - self.spi.write(b"\xff") - # wait for write to finish - while self.spi.read(1, 0xFF)[0] == 0x00: - pass - - self.cs(1) - self.spi.write(b"\xff") - - def readblocks(self, block_num, buf): - nblocks = len(buf) // 512 - assert nblocks and not len(buf) % 512, "Buffer length is invalid" - if nblocks == 1: - # CMD17: set read address for single block - if self.cmd(17, block_num * self.cdv, 0, release=False) != 0: - # release the card - self.cs(1) - raise OSError(5) # EIO - # receive the data and release card - self.readinto(buf) - else: - # CMD18: set read address for multiple blocks - if self.cmd(18, block_num * self.cdv, 0, release=False) != 0: - # release the card - self.cs(1) - raise OSError(5) # EIO - offset = 0 - mv = memoryview(buf) - while nblocks: - # receive the data and release card - self.readinto(mv[offset : offset + 512]) - offset += 512 - nblocks -= 1 - if self.cmd(12, 0, 0xFF, skip1=True): - raise OSError(5) # EIO - - def writeblocks(self, block_num, buf): - nblocks, err = divmod(len(buf), 512) - assert nblocks and not err, "Buffer length is invalid" - if nblocks == 1: - # CMD24: set write address for single block - if self.cmd(24, block_num * self.cdv, 0) != 0: - raise OSError(5) # EIO - - # send the data - self.write(_TOKEN_DATA, buf) - else: - # CMD25: set write address for first block - if self.cmd(25, block_num * self.cdv, 0) != 0: - raise OSError(5) # EIO - # send the data - offset = 0 - mv = memoryview(buf) - while nblocks: - self.write(_TOKEN_CMD25, mv[offset : offset + 512]) - offset += 512 - nblocks -= 1 - self.write_token(_TOKEN_STOP_TRAN) - - def ioctl(self, op, arg): - if op == 4: # get number of blocks - return self.sectors - if op == 5: # get block size in bytes - return 512 diff --git a/drivers/sdcard/sdtest.py b/drivers/sdcard/sdtest.py deleted file mode 100644 index 018ef7c64a..0000000000 --- a/drivers/sdcard/sdtest.py +++ /dev/null @@ -1,61 +0,0 @@ -# Test for sdcard block protocol -# Peter hinch 30th Jan 2016 -import os, sdcard, machine - - -def sdtest(): - spi = machine.SPI(1) - spi.init() # Ensure right baudrate - sd = sdcard.SDCard(spi, machine.Pin.board.X21) # Compatible with PCB - vfs = os.VfsFat(sd) - os.mount(vfs, "/fc") - print("Filesystem check") - print(os.listdir("/fc")) - - line = "abcdefghijklmnopqrstuvwxyz\n" - lines = line * 200 # 5400 chars - short = "1234567890\n" - - fn = "/fc/rats.txt" - print() - print("Multiple block read/write") - with open(fn, "w") as f: - n = f.write(lines) - print(n, "bytes written") - n = f.write(short) - print(n, "bytes written") - n = f.write(lines) - print(n, "bytes written") - - with open(fn, "r") as f: - result1 = f.read() - print(len(result1), "bytes read") - - fn = "/fc/rats1.txt" - print() - print("Single block read/write") - with open(fn, "w") as f: - n = f.write(short) # one block - print(n, "bytes written") - - with open(fn, "r") as f: - result2 = f.read() - print(len(result2), "bytes read") - - os.umount("/fc") - - print() - print("Verifying data read back") - success = True - if result1 == "".join((lines, short, lines)): - print("Large file Pass") - else: - print("Large file Fail") - success = False - if result2 == short: - print("Small file Pass") - else: - print("Small file Fail") - success = False - print() - print("Tests", "passed" if success else "failed") diff --git a/extmod/ntptime.py b/extmod/ntptime.py deleted file mode 100644 index 05d7e9717d..0000000000 --- a/extmod/ntptime.py +++ /dev/null @@ -1,48 +0,0 @@ -import utime - -try: - import usocket as socket -except: - import socket -try: - import ustruct as struct -except: - import struct - -# The NTP host can be configured at runtime by doing: ntptime.host = 'myhost.org' -host = "pool.ntp.org" - - -def time(): - NTP_QUERY = bytearray(48) - NTP_QUERY[0] = 0x1B - addr = socket.getaddrinfo(host, 123)[0][-1] - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - try: - s.settimeout(1) - res = s.sendto(NTP_QUERY, addr) - msg = s.recv(48) - finally: - s.close() - val = struct.unpack("!I", msg[40:44])[0] - - EPOCH_YEAR = utime.gmtime(0)[0] - if EPOCH_YEAR == 2000: - # (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60 - NTP_DELTA = 3155673600 - elif EPOCH_YEAR == 1970: - # (date(1970, 1, 1) - date(1900, 1, 1)).days * 24*60*60 - NTP_DELTA = 2208988800 - else: - raise Exception("Unsupported epoch: {}".format(EPOCH_YEAR)) - - return val - NTP_DELTA - - -# There's currently no timezone support in MicroPython, and the RTC is set in UTC time. -def settime(): - t = time() - import machine - - tm = utime.gmtime(t) - machine.RTC().datetime((tm[0], tm[1], tm[2], tm[6] + 1, tm[3], tm[4], tm[5], 0)) diff --git a/extmod/webrepl/manifest.py b/extmod/webrepl/manifest.py deleted file mode 100644 index 6d1a314219..0000000000 --- a/extmod/webrepl/manifest.py +++ /dev/null @@ -1,2 +0,0 @@ -module("webrepl.py", opt=3) -module("webrepl_setup.py", opt=3) diff --git a/extmod/webrepl/webrepl.py b/extmod/webrepl/webrepl.py deleted file mode 100644 index 56767d8b71..0000000000 --- a/extmod/webrepl/webrepl.py +++ /dev/null @@ -1,177 +0,0 @@ -# This module should be imported from REPL, not run from command line. -import binascii -import hashlib -import network -import os -import socket -import sys -import websocket -import _webrepl - -listen_s = None -client_s = None - -DEBUG = 0 - -_DEFAULT_STATIC_HOST = const("https://micropython.org/webrepl/") -static_host = _DEFAULT_STATIC_HOST - - -def server_handshake(cl): - req = cl.makefile("rwb", 0) - # Skip HTTP GET line. - l = req.readline() - if DEBUG: - sys.stdout.write(repr(l)) - - webkey = None - upgrade = False - websocket = False - - while True: - l = req.readline() - if not l: - # EOF in headers. - return False - if l == b"\r\n": - break - if DEBUG: - sys.stdout.write(l) - h, v = [x.strip() for x in l.split(b":", 1)] - if DEBUG: - print((h, v)) - if h == b"Sec-WebSocket-Key": - webkey = v - elif h == b"Connection" and b"Upgrade" in v: - upgrade = True - elif h == b"Upgrade" and v == b"websocket": - websocket = True - - if not (upgrade and websocket and webkey): - return False - - if DEBUG: - print("Sec-WebSocket-Key:", webkey, len(webkey)) - - d = hashlib.sha1(webkey) - d.update(b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11") - respkey = d.digest() - respkey = binascii.b2a_base64(respkey)[:-1] - if DEBUG: - print("respkey:", respkey) - - cl.send( - b"""\ -HTTP/1.1 101 Switching Protocols\r -Upgrade: websocket\r -Connection: Upgrade\r -Sec-WebSocket-Accept: """ - ) - cl.send(respkey) - cl.send("\r\n\r\n") - - return True - - -def send_html(cl): - cl.send( - b"""\ -HTTP/1.0 200 OK\r -\r -\r -\r -""" - ) - cl.close() - - -def setup_conn(port, accept_handler): - global listen_s - listen_s = socket.socket() - listen_s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - - ai = socket.getaddrinfo("0.0.0.0", port) - addr = ai[0][4] - - listen_s.bind(addr) - listen_s.listen(1) - if accept_handler: - listen_s.setsockopt(socket.SOL_SOCKET, 20, accept_handler) - for i in (network.AP_IF, network.STA_IF): - iface = network.WLAN(i) - if iface.active(): - print("WebREPL server started on http://%s:%d/" % (iface.ifconfig()[0], port)) - return listen_s - - -def accept_conn(listen_sock): - global client_s - cl, remote_addr = listen_sock.accept() - - if not server_handshake(cl): - send_html(cl) - return False - - prev = os.dupterm(None) - os.dupterm(prev) - if prev: - print("\nConcurrent WebREPL connection from", remote_addr, "rejected") - cl.close() - return False - print("\nWebREPL connection from:", remote_addr) - client_s = cl - - ws = websocket.websocket(cl, True) - ws = _webrepl._webrepl(ws) - cl.setblocking(False) - # notify REPL on socket incoming data (ESP32/ESP8266-only) - if hasattr(os, "dupterm_notify"): - cl.setsockopt(socket.SOL_SOCKET, 20, os.dupterm_notify) - os.dupterm(ws) - - return True - - -def stop(): - global listen_s, client_s - os.dupterm(None) - if client_s: - client_s.close() - if listen_s: - listen_s.close() - - -def start(port=8266, password=None, accept_handler=accept_conn): - global static_host - stop() - webrepl_pass = password - if webrepl_pass is None: - try: - import webrepl_cfg - - webrepl_pass = webrepl_cfg.PASS - if hasattr(webrepl_cfg, "BASE"): - static_host = webrepl_cfg.BASE - except: - print("WebREPL is not configured, run 'import webrepl_setup'") - - _webrepl.password(webrepl_pass) - s = setup_conn(port, accept_handler) - - if accept_handler is None: - print("Starting webrepl in foreground mode") - # Run accept_conn to serve HTML until we get a websocket connection. - while not accept_conn(s): - pass - elif password is None: - print("Started webrepl in normal mode") - else: - print("Started webrepl in manual override mode") - - -def start_foreground(port=8266, password=None): - start(port, password, None) diff --git a/extmod/webrepl/webrepl_setup.py b/extmod/webrepl/webrepl_setup.py deleted file mode 100644 index 16e5f76e65..0000000000 --- a/extmod/webrepl/webrepl_setup.py +++ /dev/null @@ -1,107 +0,0 @@ -import sys - -import os -import machine - -RC = "./boot.py" -CONFIG = "./webrepl_cfg.py" - - -def input_choice(prompt, choices): - while 1: - resp = input(prompt) - if resp in choices: - return resp - - -def getpass(prompt): - return input(prompt) - - -def input_pass(): - while 1: - passwd1 = getpass("New password (4-9 chars): ") - if len(passwd1) < 4 or len(passwd1) > 9: - print("Invalid password length") - continue - passwd2 = getpass("Confirm password: ") - if passwd1 == passwd2: - return passwd1 - print("Passwords do not match") - - -def exists(fname): - try: - with open(fname): - pass - return True - except OSError: - return False - - -def get_daemon_status(): - with open(RC) as f: - for l in f: - if "webrepl" in l: - if l.startswith("#"): - return False - return True - return None - - -def change_daemon(action): - LINES = ("import webrepl", "webrepl.start()") - with open(RC) as old_f, open(RC + ".tmp", "w") as new_f: - found = False - for l in old_f: - for patt in LINES: - if patt in l: - found = True - if action and l.startswith("#"): - l = l[1:] - elif not action and not l.startswith("#"): - l = "#" + l - new_f.write(l) - if not found: - new_f.write("import webrepl\nwebrepl.start()\n") - # FatFs rename() is not POSIX compliant, will raise OSError if - # dest file exists. - os.remove(RC) - os.rename(RC + ".tmp", RC) - - -def main(): - status = get_daemon_status() - - print("WebREPL daemon auto-start status:", "enabled" if status else "disabled") - print("\nWould you like to (E)nable or (D)isable it running on boot?") - print("(Empty line to quit)") - resp = input("> ").upper() - - if resp == "E": - if exists(CONFIG): - resp2 = input_choice( - "Would you like to change WebREPL password? (y/n) ", ("y", "n", "") - ) - else: - print("To enable WebREPL, you must set password for it") - resp2 = "y" - - if resp2 == "y": - passwd = input_pass() - with open(CONFIG, "w") as f: - f.write("PASS = %r\n" % passwd) - - if resp not in ("D", "E") or (resp == "D" and not status) or (resp == "E" and status): - print("No further action required") - sys.exit() - - change_daemon(resp == "E") - - print("Changes will be activated after reboot") - resp = input_choice("Would you like to reboot now? (y/n) ", ("y", "n", "")) - if resp == "y": - machine.reset() - - -main() From 6aa3c946347281875165392c09753547d8c77fc3 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 5 Sep 2022 11:20:10 +0100 Subject: [PATCH 0379/1041] rp2/rp2_flash: Add start/len support to rp2.Flash() constructor. This allows support for partitioned flash on rp2 boards. See issue #9208. Signed-off-by: Phil Howard --- ports/rp2/rp2_flash.c | 45 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/ports/rp2/rp2_flash.c b/ports/rp2/rp2_flash.c index db6b9f3bfe..47c95ea5c8 100644 --- a/ports/rp2/rp2_flash.c +++ b/ports/rp2/rp2_flash.c @@ -70,16 +70,45 @@ bi_decl(bi_block_device( BINARY_INFO_BLOCK_DEV_FLAG_PT_UNKNOWN)); STATIC mp_obj_t rp2_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - // Check args. - mp_arg_check_num(n_args, n_kw, 0, 0, false); + // Parse arguments + enum { ARG_start, ARG_len }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - #ifndef NDEBUG - extern char __flash_binary_end; - assert((uintptr_t)&__flash_binary_end - XIP_BASE <= MICROPY_HW_FLASH_STORAGE_BASE); - #endif + if (args[ARG_start].u_int == -1 && args[ARG_len].u_int == -1) { + #ifndef NDEBUG + extern char __flash_binary_end; + assert((uintptr_t)&__flash_binary_end - XIP_BASE <= MICROPY_HW_FLASH_STORAGE_BASE); + #endif - // Return singleton object. - return MP_OBJ_FROM_PTR(&rp2_flash_obj); + // Default singleton object that accesses entire flash + return MP_OBJ_FROM_PTR(&rp2_flash_obj); + } + + rp2_flash_obj_t *self = mp_obj_malloc(rp2_flash_obj_t, &rp2_flash_type); + + mp_int_t start = args[ARG_start].u_int; + if (start == -1) { + start = 0; + } else if (!(0 <= start && start < MICROPY_HW_FLASH_STORAGE_BYTES && start % BLOCK_SIZE_BYTES == 0)) { + mp_raise_ValueError(NULL); + } + + mp_int_t len = args[ARG_len].u_int; + if (len == -1) { + len = MICROPY_HW_FLASH_STORAGE_BYTES - start; + } else if (!(0 < len && start + len <= MICROPY_HW_FLASH_STORAGE_BYTES && len % BLOCK_SIZE_BYTES == 0)) { + mp_raise_ValueError(NULL); + } + + self->flash_base = MICROPY_HW_FLASH_STORAGE_BASE + start; + self->flash_size = len; + + return MP_OBJ_FROM_PTR(self); } STATIC mp_obj_t rp2_flash_readblocks(size_t n_args, const mp_obj_t *args) { From c364301817d828eeb6df74095b3ea8083e8fbef6 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 6 Sep 2022 23:32:11 +1000 Subject: [PATCH 0380/1041] rp2/boards: Set PICO_BOARD correctly for each board. In most cases, it's calculated automatically from the board name, and so doesn't need to be set at all. Signed-off-by: Jim Mussared --- .../rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.cmake | 2 -- ports/rp2/boards/PICO_W/mpconfigboard.cmake | 2 -- ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.cmake | 2 +- ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.cmake | 2 +- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.cmake b/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.cmake index 311e114b29..11fcb3d087 100644 --- a/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.cmake +++ b/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.cmake @@ -1,3 +1 @@ # cmake file - -set(PICO_BOARD garatronic_pybstick26_rp2040) diff --git a/ports/rp2/boards/PICO_W/mpconfigboard.cmake b/ports/rp2/boards/PICO_W/mpconfigboard.cmake index d3fbce6993..681e0dec44 100644 --- a/ports/rp2/boards/PICO_W/mpconfigboard.cmake +++ b/ports/rp2/boards/PICO_W/mpconfigboard.cmake @@ -1,6 +1,4 @@ # cmake file for Raspberry Pi Pico W -set(MICROPY_BOARD PICO_W) - set(MICROPY_PY_LWIP ON) set(MICROPY_PY_NETWORK_CYW43 ON) diff --git a/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.cmake b/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.cmake index bc5d1ea65e..4746c6e267 100644 --- a/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.cmake +++ b/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.cmake @@ -1,4 +1,4 @@ # cmake file for Wiznet W5100S-EVB-Pico. -set(PICO_BOARD pico) +set(PICO_BOARD wiznet_w5100s_evb_pico) set(MICROPY_PY_NETWORK_WIZNET5K W5100S) set(MICROPY_PY_LWIP 1) diff --git a/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.cmake b/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.cmake index 875b89f2be..f7f2650bfa 100644 --- a/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.cmake +++ b/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.cmake @@ -1,4 +1,4 @@ # cmake file for Wiznet W5500-EVB-Pico. -set(PICO_BOARD pico) +set(PICO_BOARD wiznet_w5100s_evb_pico) set(MICROPY_PY_NETWORK_WIZNET5K W5500) set(MICROPY_PY_LWIP 1) From 29437205f29976db71dc12d61ce756732e6f813a Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 6 Sep 2022 22:54:40 +1000 Subject: [PATCH 0381/1041] rp2/machine_spi: Use pico-sdk's default pins for SPI. Rather than hardcoding the defaults, use pico-sdk's board definition. Signed-off-by: Jim Mussared --- ports/rp2/machine_spi.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/ports/rp2/machine_spi.c b/ports/rp2/machine_spi.c index 42998664a7..104bd1fd53 100644 --- a/ports/rp2/machine_spi.c +++ b/ports/rp2/machine_spi.c @@ -40,20 +40,36 @@ #define DEFAULT_SPI_FIRSTBIT (SPI_MSB_FIRST) #ifndef MICROPY_HW_SPI0_SCK +#if PICO_DEFAULT_SPI == 0 +#define MICROPY_HW_SPI0_SCK (PICO_DEFAULT_SPI_SCK_PIN) +#define MICROPY_HW_SPI0_MOSI (PICO_DEFAULT_SPI_TX_PIN) +#define MICROPY_HW_SPI0_MISO (PICO_DEFAULT_SPI_RX_PIN) +#else #define MICROPY_HW_SPI0_SCK (6) #define MICROPY_HW_SPI0_MOSI (7) #define MICROPY_HW_SPI0_MISO (4) #endif +#endif #ifndef MICROPY_HW_SPI1_SCK +#if PICO_DEFAULT_SPI == 1 +#define MICROPY_HW_SPI1_SCK (PICO_DEFAULT_SPI_SCK_PIN) +#define MICROPY_HW_SPI1_MOSI (PICO_DEFAULT_SPI_TX_PIN) +#define MICROPY_HW_SPI1_MISO (PICO_DEFAULT_SPI_RX_PIN) +#else #define MICROPY_HW_SPI1_SCK (10) #define MICROPY_HW_SPI1_MOSI (11) #define MICROPY_HW_SPI1_MISO (8) #endif +#endif +// SPI0 can be GP{0..7,16..23}, SPI1 can be GP{8..15,24..29}. #define IS_VALID_PERIPH(spi, pin) ((((pin) & 8) >> 3) == (spi)) +// GP{2,6,10,14,...} #define IS_VALID_SCK(spi, pin) (((pin) & 3) == 2 && IS_VALID_PERIPH(spi, pin)) +// GP{3,7,11,15,...} #define IS_VALID_MOSI(spi, pin) (((pin) & 3) == 3 && IS_VALID_PERIPH(spi, pin)) +// GP{0,4,8,10,...} #define IS_VALID_MISO(spi, pin) (((pin) & 3) == 0 && IS_VALID_PERIPH(spi, pin)) typedef struct _machine_spi_obj_t { From 315e74236fb7be7c72f708832038596d668979b7 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 6 Sep 2022 23:28:50 +1000 Subject: [PATCH 0382/1041] rp2/machine_i2c: Use pico-sdk's default pins for I2C. Inherits the default values for whichever instance is PICO_DEFAULT_I2C. Signed-off-by: Jim Mussared --- ports/rp2/machine_i2c.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ports/rp2/machine_i2c.c b/ports/rp2/machine_i2c.c index f785ad7ded..3390cc4210 100644 --- a/ports/rp2/machine_i2c.c +++ b/ports/rp2/machine_i2c.c @@ -35,14 +35,24 @@ #define DEFAULT_I2C_FREQ (400000) #ifndef MICROPY_HW_I2C0_SCL +#if PICO_DEFAULT_I2C == 0 +#define MICROPY_HW_I2C0_SCL (PICO_DEFAULT_I2C_SCL_PIN) +#define MICROPY_HW_I2C0_SDA (PICO_DEFAULT_I2C_SDA_PIN) +#else #define MICROPY_HW_I2C0_SCL (9) #define MICROPY_HW_I2C0_SDA (8) #endif +#endif #ifndef MICROPY_HW_I2C1_SCL +#if PICO_DEFAULT_I2C == 1 +#define MICROPY_HW_I2C1_SCL (PICO_DEFAULT_I2C_SCL_PIN) +#define MICROPY_HW_I2C1_SDA (PICO_DEFAULT_I2C_SDA_PIN) +#else #define MICROPY_HW_I2C1_SCL (7) #define MICROPY_HW_I2C1_SDA (6) #endif +#endif // SDA/SCL on even/odd pins, I2C0/I2C1 on even/odd pairs of pins. #define IS_VALID_SCL(i2c, pin) (((pin) & 1) == 1 && (((pin) & 2) >> 1) == (i2c)) From dec0ff7a10efee286037812287d5bfcad611f64f Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 6 Sep 2022 23:32:34 +1000 Subject: [PATCH 0383/1041] rp2/boards: Remove all I2C,SPI pin defs that already match pico-sdk. I.e. for whichever SPI/I2C instance is PICO_DEFAULT_I2C, there's no need to set MICROPY_HW_SPIn_SCK. The only ones remaining are for the non-default instance. Signed-off-by: Jim Mussared --- .../rp2/boards/ADAFRUIT_FEATHER_RP2040/mpconfigboard.h | 8 -------- .../boards/ADAFRUIT_ITSYBITSY_RP2040/mpconfigboard.h | 7 ------- ports/rp2/boards/ADAFRUIT_QTPY_RP2040/mpconfigboard.h | 9 +-------- .../boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h | 8 ++------ .../rp2/boards/PIMORONI_PICOLIPO_16MB/mpconfigboard.h | 8 -------- ports/rp2/boards/PIMORONI_PICOLIPO_4MB/mpconfigboard.h | 8 -------- ports/rp2/boards/PIMORONI_TINY2040/mpconfigboard.h | 1 + ports/rp2/boards/SPARKFUN_PROMICRO/mpconfigboard.h | 8 -------- ports/rp2/boards/SPARKFUN_THINGPLUS/mpconfigboard.h | 10 +--------- 9 files changed, 5 insertions(+), 62 deletions(-) diff --git a/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/mpconfigboard.h b/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/mpconfigboard.h index 84d2bf20db..f9cd030d46 100644 --- a/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/mpconfigboard.h +++ b/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/mpconfigboard.h @@ -7,14 +7,6 @@ #define MICROPY_HW_USB_VID (0x239A) #define MICROPY_HW_USB_PID (0x80F2) -// STEMMA QT / Qwiic on I2C1 -#define MICROPY_HW_I2C1_SCL (3) -#define MICROPY_HW_I2C1_SDA (2) - -#define MICROPY_HW_SPI0_SCK (18) -#define MICROPY_HW_SPI0_MOSI (19) -#define MICROPY_HW_SPI0_MISO (20) - // NeoPixel GPIO16, power not toggleable // Red user LED GPIO13 diff --git a/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/mpconfigboard.h b/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/mpconfigboard.h index 8f5551172b..be950f4f99 100644 --- a/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/mpconfigboard.h +++ b/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/mpconfigboard.h @@ -7,13 +7,6 @@ #define MICROPY_HW_USB_VID (0x239A) #define MICROPY_HW_USB_PID (0x80FE) -#define MICROPY_HW_I2C0_SCL (3) -#define MICROPY_HW_I2C0_SDA (2) - -#define MICROPY_HW_SPI0_SCK (18) -#define MICROPY_HW_SPI0_MOSI (19) -#define MICROPY_HW_SPI0_MISO (20) - // NeoPixel data GPIO17, power GPIO16 // Red user LED GPIO11 diff --git a/ports/rp2/boards/ADAFRUIT_QTPY_RP2040/mpconfigboard.h b/ports/rp2/boards/ADAFRUIT_QTPY_RP2040/mpconfigboard.h index ca341cedd8..6d834fd4f5 100644 --- a/ports/rp2/boards/ADAFRUIT_QTPY_RP2040/mpconfigboard.h +++ b/ports/rp2/boards/ADAFRUIT_QTPY_RP2040/mpconfigboard.h @@ -12,17 +12,10 @@ #define MICROPY_HW_UART1_CTS (10) #define MICROPY_HW_UART1_RTS (7) -#define MICROPY_HW_I2C0_SCL (25) -#define MICROPY_HW_I2C0_SDA (24) - -// STEMMA QT / Qwiic on I2C1 +// STEMMA QT / Qwiic on (non-default) I2C1 #define MICROPY_HW_I2C1_SCL (23) #define MICROPY_HW_I2C1_SDA (22) -#define MICROPY_HW_SPI0_SCK (6) -#define MICROPY_HW_SPI0_MOSI (3) -#define MICROPY_HW_SPI0_MISO (4) - // NeoPixel data GPIO12, power GPIO11 // Boot button GPIO21 diff --git a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h index 87b9187659..5ea9b8cdb8 100644 --- a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h +++ b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h @@ -22,16 +22,12 @@ #define MICROPY_HW_UART1_CTS (10) #define MICROPY_HW_UART1_RTS (11) -// SPI 1 config. +// SPI 1 config (non-default). #define MICROPY_HW_SPI1_SCK (14) #define MICROPY_HW_SPI1_MOSI (11) #define MICROPY_HW_SPI1_MISO (8) -// I2C0 config. -#define MICROPY_HW_I2C0_SCL (13) -#define MICROPY_HW_I2C0_SDA (12) - -// I2C1 config. +// I2C1 config (non-default). #define MICROPY_HW_I2C1_SCL (27) #define MICROPY_HW_I2C1_SDA (26) diff --git a/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/mpconfigboard.h b/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/mpconfigboard.h index 134c2ff784..a90ef6783d 100644 --- a/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/mpconfigboard.h +++ b/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/mpconfigboard.h @@ -11,14 +11,6 @@ #define MICROPY_HW_UART1_CTS (10) #define MICROPY_HW_UART1_RTS (11) -// Qwiic on I2C0 -#define MICROPY_HW_I2C0_SCL (4) -#define MICROPY_HW_I2C0_SDA (5) - -#define MICROPY_HW_SPI0_SCK (18) -#define MICROPY_HW_SPI0_MOSI (19) -#define MICROPY_HW_SPI0_MISO (16) - // User LED GPIO25 // VBUS_SENSE GPIO24 diff --git a/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/mpconfigboard.h b/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/mpconfigboard.h index fd45547e1b..53ade72915 100644 --- a/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/mpconfigboard.h +++ b/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/mpconfigboard.h @@ -11,14 +11,6 @@ #define MICROPY_HW_UART1_CTS (10) #define MICROPY_HW_UART1_RTS (11) -// Qwiic on I2C0 -#define MICROPY_HW_I2C0_SCL (4) -#define MICROPY_HW_I2C0_SDA (5) - -#define MICROPY_HW_SPI0_SCK (18) -#define MICROPY_HW_SPI0_MOSI (19) -#define MICROPY_HW_SPI0_MISO (16) - // User LED GPIO25 // VBUS_SENSE GPIO24 diff --git a/ports/rp2/boards/PIMORONI_TINY2040/mpconfigboard.h b/ports/rp2/boards/PIMORONI_TINY2040/mpconfigboard.h index 50cb2bd599..ea40a8071b 100644 --- a/ports/rp2/boards/PIMORONI_TINY2040/mpconfigboard.h +++ b/ports/rp2/boards/PIMORONI_TINY2040/mpconfigboard.h @@ -6,6 +6,7 @@ #define MICROPY_HW_USB_VID (0x16D0) #define MICROPY_HW_USB_PID (0x08C7) +// I2C0 (non-default) #define MICROPY_HW_I2C0_SCL (4) #define MICROPY_HW_I2C0_SDA (5) diff --git a/ports/rp2/boards/SPARKFUN_PROMICRO/mpconfigboard.h b/ports/rp2/boards/SPARKFUN_PROMICRO/mpconfigboard.h index 65b29eecd1..72a9aeb373 100644 --- a/ports/rp2/boards/SPARKFUN_PROMICRO/mpconfigboard.h +++ b/ports/rp2/boards/SPARKFUN_PROMICRO/mpconfigboard.h @@ -11,12 +11,4 @@ #define MICROPY_HW_UART1_CTS (10) #define MICROPY_HW_UART1_RTS (11) -// Qwiic on I2C0 -#define MICROPY_HW_I2C0_SCL (17) -#define MICROPY_HW_I2C0_SDA (16) - -#define MICROPY_HW_SPI0_SCK (22) -#define MICROPY_HW_SPI0_MOSI (23) -#define MICROPY_HW_SPI0_MISO (20) - // NeoPixel data GPIO25, power not toggleable diff --git a/ports/rp2/boards/SPARKFUN_THINGPLUS/mpconfigboard.h b/ports/rp2/boards/SPARKFUN_THINGPLUS/mpconfigboard.h index f88ba5dd63..c2ca90b968 100644 --- a/ports/rp2/boards/SPARKFUN_THINGPLUS/mpconfigboard.h +++ b/ports/rp2/boards/SPARKFUN_THINGPLUS/mpconfigboard.h @@ -9,15 +9,7 @@ #define MICROPY_HW_I2C0_SCL (17) #define MICROPY_HW_I2C0_SDA (16) -// Qwiic on I2C1 -#define MICROPY_HW_I2C1_SCL (7) -#define MICROPY_HW_I2C1_SDA (6) - -#define MICROPY_HW_SPI0_SCK (2) -#define MICROPY_HW_SPI0_MOSI (3) -#define MICROPY_HW_SPI0_MISO (4) - -// MicroSD on SPI1 +// MicroSD on SPI1 (non-default) #define MICROPY_HW_SPI1_SCK (14) #define MICROPY_HW_SPI1_MOSI (15) #define MICROPY_HW_SPI1_MISO (12) From 9070a2494022383586e1f86745ae4c9af52389f6 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 8 Sep 2022 13:55:50 +1000 Subject: [PATCH 0384/1041] tools/autobuild: Use distinct directory for building stm32 variants. Previous the build directory just used the board name, now make it use the variant name too. This shouldn't have any change because the existing directory should not exist (all builds run by these scripts remove their build directory after completion), but it makes debugging easier. Signed-off-by: Jim Mussared --- tools/autobuild/build-stm32-extra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/autobuild/build-stm32-extra.sh b/tools/autobuild/build-stm32-extra.sh index feb269e356..887e3cd246 100755 --- a/tools/autobuild/build-stm32-extra.sh +++ b/tools/autobuild/build-stm32-extra.sh @@ -10,7 +10,7 @@ function do_build() { for variant in `$MICROPY_AUTOBUILD_MAKE BOARD=$board query-variants | grep VARIANTS: | cut -d' ' -f2-`; do target=$descr-$variant echo "building $target $board" - build_dir=/tmp/stm-build-$board + build_dir=/tmp/stm-build-$board-$variant $MICROPY_AUTOBUILD_MAKE $@ BOARD=$board BOARD_VARIANT=$variant BUILD=$build_dir || exit 1 mv $build_dir/firmware.dfu $dest_dir/$target$fw_tag.dfu mv $build_dir/firmware.hex $dest_dir/$target$fw_tag.hex From 6e75d177e778caebe791add7eb4cc9eff3a33b6a Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 8 Sep 2022 13:58:03 +1000 Subject: [PATCH 0385/1041] stm32/boards/PYB: Fix handling of BOARD_VARIANT selection. The matches should not have been quoted. Signed-off-by: Jim Mussared --- ports/stm32/boards/PYBLITEV10/mpconfigboard.mk | 8 ++++---- ports/stm32/boards/PYBV10/mpconfigboard.mk | 8 ++++---- ports/stm32/boards/PYBV11/mpconfigboard.mk | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk b/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk index 7469866476..461886b63c 100644 --- a/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk +++ b/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk @@ -8,20 +8,20 @@ TEXT1_ADDR = 0x08020000 # Provide different variants for the downloads page. BOARD_VARIANTS += "dp thread dp-thread network" -ifeq ($(BOARD_VARIANT),"dp") +ifeq ($(BOARD_VARIANT),dp) MICROPY_FLOAT_IMPL=double endif -ifeq ($(BOARD_VARIANT),"thread") +ifeq ($(BOARD_VARIANT),thread) CFLAGS += -DMICROPY_PY_THREAD=1 endif -ifeq ($(BOARD_VARIANT),"dp-thread") +ifeq ($(BOARD_VARIANT),dp-thread) MICROPY_FLOAT_IMPL=double CFLAGS += -DMICROPY_PY_THREAD=1 endif -ifeq ($(BOARD_VARIANT),"network") +ifeq ($(BOARD_VARIANT),network) MICROPY_PY_NETWORK_WIZNET5K=5200 endif diff --git a/ports/stm32/boards/PYBV10/mpconfigboard.mk b/ports/stm32/boards/PYBV10/mpconfigboard.mk index af28782678..363f6b4806 100644 --- a/ports/stm32/boards/PYBV10/mpconfigboard.mk +++ b/ports/stm32/boards/PYBV10/mpconfigboard.mk @@ -18,20 +18,20 @@ MICROPY_VFS_LFS2 = 1 # Provide different variants for the downloads page. BOARD_VARIANTS += "dp thread dp-thread network" -ifeq ($(BOARD_VARIANT),"dp") +ifeq ($(BOARD_VARIANT),dp) MICROPY_FLOAT_IMPL=double endif -ifeq ($(BOARD_VARIANT),"thread") +ifeq ($(BOARD_VARIANT),thread) CFLAGS += -DMICROPY_PY_THREAD=1 endif -ifeq ($(BOARD_VARIANT),"dp-thread") +ifeq ($(BOARD_VARIANT),dp-thread) MICROPY_FLOAT_IMPL=double CFLAGS += -DMICROPY_PY_THREAD=1 endif -ifeq ($(BOARD_VARIANT),"network") +ifeq ($(BOARD_VARIANT),network) MICROPY_PY_NETWORK_WIZNET5K=5200 endif diff --git a/ports/stm32/boards/PYBV11/mpconfigboard.mk b/ports/stm32/boards/PYBV11/mpconfigboard.mk index cf7884cfc6..857049f215 100644 --- a/ports/stm32/boards/PYBV11/mpconfigboard.mk +++ b/ports/stm32/boards/PYBV11/mpconfigboard.mk @@ -18,20 +18,20 @@ MICROPY_VFS_LFS2 = 1 # Provide different variants for the downloads page. BOARD_VARIANTS += "dp thread dp-thread network" -ifeq ($(BOARD_VARIANT),"dp") +ifeq ($(BOARD_VARIANT),dp) MICROPY_FLOAT_IMPL=double endif -ifeq ($(BOARD_VARIANT),"thread") +ifeq ($(BOARD_VARIANT),thread) CFLAGS += -DMICROPY_PY_THREAD=1 endif -ifeq ($(BOARD_VARIANT),"dp-thread") +ifeq ($(BOARD_VARIANT),dp-thread) MICROPY_FLOAT_IMPL=double CFLAGS += -DMICROPY_PY_THREAD=1 endif -ifeq ($(BOARD_VARIANT),"network") +ifeq ($(BOARD_VARIANT),network) MICROPY_PY_NETWORK_WIZNET5K=5200 endif From 82fc16f2982b38f6dfd0145b8012b34308d13605 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 9 Aug 2022 16:48:04 +1000 Subject: [PATCH 0386/1041] extmod/modbluetooth: Fix descriptor registration with empty tuple. Incorrect use of "continue" when the tuple was length zero meant it broke the rest of the argument handling. Signed-off-by: Jim Mussared --- extmod/modbluetooth.c | 56 +++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 4645ae6c98..c2cbf0e70a 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -529,43 +529,41 @@ STATIC int bluetooth_gatts_register_service(mp_obj_t uuid_in, mp_obj_t character // Optional third element, iterable of descriptors. if (characteristic_len >= 3) { - mp_obj_t descriptors_len_in = mp_obj_len(characteristic_items[2]); - num_descriptors[characteristic_index] = mp_obj_get_int(descriptors_len_in); + mp_int_t n = mp_obj_get_int(mp_obj_len(characteristic_items[2])); + if (n) { + num_descriptors[characteristic_index] = n; - if (num_descriptors[characteristic_index] == 0) { - continue; - } + // Grow the flattened uuids and flags arrays with this many more descriptors. + descriptor_uuids = m_renew(mp_obj_bluetooth_uuid_t *, descriptor_uuids, descriptor_index, descriptor_index + num_descriptors[characteristic_index]); + descriptor_flags = m_renew(uint16_t, descriptor_flags, descriptor_index, descriptor_index + num_descriptors[characteristic_index]); - // Grow the flattened uuids and flags arrays with this many more descriptors. - descriptor_uuids = m_renew(mp_obj_bluetooth_uuid_t *, descriptor_uuids, descriptor_index, descriptor_index + num_descriptors[characteristic_index]); - descriptor_flags = m_renew(uint16_t, descriptor_flags, descriptor_index, descriptor_index + num_descriptors[characteristic_index]); + // Also grow the handles array. + *handles = m_renew(uint16_t, *handles, *num_handles, *num_handles + num_descriptors[characteristic_index]); - // Also grow the handles array. - *handles = m_renew(uint16_t, *handles, *num_handles, *num_handles + num_descriptors[characteristic_index]); + mp_obj_iter_buf_t iter_buf_desc; + mp_obj_t iterable_desc = mp_getiter(characteristic_items[2], &iter_buf_desc); + mp_obj_t descriptor_obj; - mp_obj_iter_buf_t iter_buf_desc; - mp_obj_t iterable_desc = mp_getiter(characteristic_items[2], &iter_buf_desc); - mp_obj_t descriptor_obj; + // Extract out descriptors for this characteristic. + while ((descriptor_obj = mp_iternext(iterable_desc)) != MP_OBJ_STOP_ITERATION) { + // (uuid, flags,) + mp_obj_t *descriptor_items; + mp_obj_get_array_fixed_n(descriptor_obj, 2, &descriptor_items); + mp_obj_t desc_uuid_obj = descriptor_items[0]; + if (!mp_obj_is_type(desc_uuid_obj, &mp_type_bluetooth_uuid)) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid descriptor UUID")); + } - // Extract out descriptors for this characteristic. - while ((descriptor_obj = mp_iternext(iterable_desc)) != MP_OBJ_STOP_ITERATION) { - // (uuid, flags,) - mp_obj_t *descriptor_items; - mp_obj_get_array_fixed_n(descriptor_obj, 2, &descriptor_items); - mp_obj_t desc_uuid_obj = descriptor_items[0]; - if (!mp_obj_is_type(desc_uuid_obj, &mp_type_bluetooth_uuid)) { - mp_raise_ValueError(MP_ERROR_TEXT("invalid descriptor UUID")); + descriptor_uuids[descriptor_index] = MP_OBJ_TO_PTR(desc_uuid_obj); + descriptor_flags[descriptor_index] = mp_obj_get_int(descriptor_items[1]); + ++descriptor_index; + + (*handles)[handle_index++] = 0xffff; } - descriptor_uuids[descriptor_index] = MP_OBJ_TO_PTR(desc_uuid_obj); - descriptor_flags[descriptor_index] = mp_obj_get_int(descriptor_items[1]); - ++descriptor_index; - - (*handles)[handle_index++] = 0xffff; + // Reflect that we've grown the handles array. + *num_handles += num_descriptors[characteristic_index]; } - - // Reflect that we've grown the handles array. - *num_handles += num_descriptors[characteristic_index]; } characteristic_uuids[characteristic_index] = MP_OBJ_TO_PTR(uuid_obj); From cacc96d98c2a70dc7e5194331ea70746c39746ec Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 9 Aug 2022 16:50:58 +1000 Subject: [PATCH 0387/1041] extmod/modbluetooth: Replace def_handle with end_handle in char IRQ. This is technically a breaking change, but: a) We need the end handle to do descriptor discovery properly. b) We have no possible use for the existing definition handle in the characteristic result IRQ. None of the methods can use it, and therefore no existing code should be using it in a way that changing it to a different integer value should break. Unfortunately NimBLE doesn't make it easy to get the end handle, so also implement a mechanism to use the following characteristic to calculate the previous characteristic's end handle. Signed-off-by: Jim Mussared --- docs/library/bluetooth.rst | 2 +- extmod/btstack/modbluetooth_btstack.c | 2 +- extmod/modbluetooth.c | 12 +++-- extmod/modbluetooth.h | 2 +- extmod/nimble/modbluetooth_nimble.c | 70 +++++++++++++++++++++++---- extmod/nimble/modbluetooth_nimble.h | 15 ++++++ 6 files changed, 86 insertions(+), 17 deletions(-) diff --git a/docs/library/bluetooth.rst b/docs/library/bluetooth.rst index 052f7a5c78..8f7041e8d3 100644 --- a/docs/library/bluetooth.rst +++ b/docs/library/bluetooth.rst @@ -166,7 +166,7 @@ Event Handling conn_handle, status = data elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT: # Called for each characteristic found by gattc_discover_services(). - conn_handle, def_handle, value_handle, properties, uuid = data + conn_handle, end_handle, value_handle, properties, uuid = data elif event == _IRQ_GATTC_CHARACTERISTIC_DONE: # Called once service discovery is complete. # Note: Status will be zero on success, implementation-specific value otherwise. diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c index d41c671d68..b58be78a99 100644 --- a/extmod/btstack/modbluetooth_btstack.c +++ b/extmod/btstack/modbluetooth_btstack.c @@ -450,7 +450,7 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t gatt_client_characteristic_t characteristic; gatt_event_characteristic_query_result_get_characteristic(packet, &characteristic); mp_obj_bluetooth_uuid_t characteristic_uuid = create_mp_uuid(characteristic.uuid16, characteristic.uuid128); - mp_bluetooth_gattc_on_characteristic_result(conn_handle, characteristic.start_handle, characteristic.value_handle, characteristic.properties, &characteristic_uuid); + mp_bluetooth_gattc_on_characteristic_result(conn_handle, characteristic.value_handle, characteristic.end_handle, characteristic.properties, &characteristic_uuid); } else if (event_type == GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT) { DEBUG_printf(" --> gatt descriptor query result\n"); uint16_t conn_handle = gatt_event_all_characteristic_descriptors_query_result_get_handle(packet); diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index c2cbf0e70a..bd4d9b7179 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -1101,7 +1101,7 @@ STATIC mp_obj_t bluetooth_ble_invoke_irq(mp_obj_t none_in) { // conn_handle, start_handle, end_handle, uuid ringbuf_extract(&o->ringbuf, data_tuple, 3, 0, NULL, 0, &o->irq_data_uuid, NULL); } else if (event == MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT) { - // conn_handle, def_handle, value_handle, properties, uuid + // conn_handle, end_handle, value_handle, properties, uuid ringbuf_extract(&o->ringbuf, data_tuple, 3, 1, NULL, 0, &o->irq_data_uuid, NULL); } else if (event == MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT) { // conn_handle, handle, uuid @@ -1375,8 +1375,9 @@ void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT, args, 3, 0, NULL_ADDR, service_uuid, NULL_DATA, NULL_DATA_LEN, 0); } -void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) { - mp_int_t args[] = {conn_handle, def_handle, value_handle, properties}; +void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t value_handle, uint16_t end_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) { + // Note: "end_handle" replaces "def_handle" from the original version of this event. + mp_int_t args[] = {conn_handle, end_handle, value_handle, properties}; invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT, args, 4, 0, NULL_ADDR, characteristic_uuid, NULL_DATA, NULL_DATA_LEN, 0); } @@ -1588,12 +1589,13 @@ void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t schedule_ringbuf(atomic_state); } -void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) { +void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t value_handle, uint16_t end_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); if (enqueue_irq(o, 2 + 2 + 2 + 1 + characteristic_uuid->type, MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT)) { ringbuf_put16(&o->ringbuf, conn_handle); - ringbuf_put16(&o->ringbuf, def_handle); + // Note: "end_handle" replaces "def_handle" from the original version of this event. + ringbuf_put16(&o->ringbuf, end_handle); ringbuf_put16(&o->ringbuf, value_handle); ringbuf_put(&o->ringbuf, properties); ringbuf_put_uuid(&o->ringbuf, characteristic_uuid); diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index 52053045f8..d490346278 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -459,7 +459,7 @@ void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uin void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, mp_obj_bluetooth_uuid_t *service_uuid); // Notify modbluetooth that a characteristic was found (either by discover-all-on-service, or discover-by-uuid-on-service). -void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid); +void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t value_handle, uint16_t end_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid); // Notify modbluetooth that a descriptor was found. void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t handle, mp_obj_bluetooth_uuid_t *descriptor_uuid); diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c index c26c09e61a..b0194446bd 100644 --- a/extmod/nimble/modbluetooth_nimble.c +++ b/extmod/nimble/modbluetooth_nimble.c @@ -1310,15 +1310,51 @@ int mp_bluetooth_gattc_discover_primary_services(uint16_t conn_handle, const mp_ return ble_hs_err_to_errno(err); } +STATIC bool match_char_uuid(const mp_obj_bluetooth_uuid_t *filter_uuid, const ble_uuid_any_t *result_uuid) { + if (!filter_uuid) { + return true; + } + ble_uuid_any_t filter_uuid_nimble; + create_nimble_uuid(filter_uuid, &filter_uuid_nimble); + return ble_uuid_cmp(&result_uuid->u, &filter_uuid_nimble.u) == 0; +} + STATIC int ble_gattc_characteristic_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_chr *characteristic, void *arg) { DEBUG_printf("ble_gattc_characteristic_cb: conn_handle=%d status=%d def_handle=%d val_handle=%d\n", conn_handle, error->status, characteristic ? characteristic->def_handle : -1, characteristic ? characteristic->val_handle : -1); if (!mp_bluetooth_is_active()) { return 0; } + + mp_bluetooth_nimble_pending_characteristic_t *pending = &MP_STATE_PORT(bluetooth_nimble_root_pointers)->pending_char_result; + if (pending->ready) { + // If there's a pending characteristic, we now know what it's end handle is, report it up to modbluetooth. + pending->ready = 0; + + // The end handle will either be the end of the query range (there are + // no more results), or one before the current result's definition + // handle. + uint16_t end_handle = MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_disc_end_handle; + if (error->status == 0) { + end_handle = characteristic->def_handle - 1; + } + + // Assume same conn_handle because we're limiting to a single active discovery. + mp_bluetooth_gattc_on_characteristic_result(conn_handle, pending->value_handle, end_handle, pending->properties, &pending->uuid); + } + if (error->status == 0) { - mp_obj_bluetooth_uuid_t characteristic_uuid = create_mp_uuid(&characteristic->uuid); - mp_bluetooth_gattc_on_characteristic_result(conn_handle, characteristic->def_handle, characteristic->val_handle, characteristic->properties, &characteristic_uuid); + // If there's no filter, or the filter matches, then save this result. + if (match_char_uuid(MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_filter_uuid, &characteristic->uuid)) { + pending->value_handle = characteristic->val_handle; + pending->properties = characteristic->properties; + pending->uuid = create_mp_uuid(&characteristic->uuid); + pending->ready = 1; + } } else { + // Finished (or failed). Allow another characteristic discovery to start. + MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_disc_end_handle = 0; + + // Report completion. mp_bluetooth_gattc_on_discover_complete(MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_DONE, conn_handle, error->status == BLE_HS_EDONE ? 0 : error->status); } return 0; @@ -1328,13 +1364,29 @@ int mp_bluetooth_gattc_discover_characteristics(uint16_t conn_handle, uint16_t s if (!mp_bluetooth_is_active()) { return ERRNO_BLUETOOTH_NOT_ACTIVE; } - int err; - if (uuid) { - ble_uuid_any_t nimble_uuid; - create_nimble_uuid(uuid, &nimble_uuid); - err = ble_gattc_disc_chrs_by_uuid(conn_handle, start_handle, end_handle, &nimble_uuid.u, &ble_gattc_characteristic_cb, NULL); - } else { - err = ble_gattc_disc_all_chrs(conn_handle, start_handle, end_handle, &ble_gattc_characteristic_cb, NULL); + + // The implementation of characteristic discovery queries for all + // characteristics, and then UUID filtering is applied by NimBLE on each + // characteristic. Unfortunately, each characteristic result does not + // include its end handle, so you need to know the next characteristic + // before you can raise the previous one to modbluetooth. But if we let + // NimBLE do the filtering, then we don't necessarily see the next one. + // So we make NimBLE return all results and do the filtering here instead. + + if (MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_disc_end_handle) { + // Only allow a single discovery (otherwise we'd need to track a + // pending characteristic per conn handle). + return MP_EBUSY; + } + + // Set the uuid filter (if any). This needs to be a root pointer, + // otherwise we'd use ble_gattc_disc_all_chrs's arg param. + MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_filter_uuid = uuid; + + int err = ble_gattc_disc_all_chrs(conn_handle, start_handle, end_handle, &ble_gattc_characteristic_cb, NULL); + if (!err) { + // Lock out concurrent characteristic discovery. + MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_disc_end_handle = end_handle; } return ble_hs_err_to_errno(err); } diff --git a/extmod/nimble/modbluetooth_nimble.h b/extmod/nimble/modbluetooth_nimble.h index 15648a9959..d9bef64920 100644 --- a/extmod/nimble/modbluetooth_nimble.h +++ b/extmod/nimble/modbluetooth_nimble.h @@ -31,6 +31,13 @@ #define MP_BLUETOOTH_NIMBLE_MAX_SERVICES (8) +typedef struct _mp_bluetooth_nimble_pending_characteristic_t { + uint16_t value_handle; + uint8_t properties; + mp_obj_bluetooth_uuid_t uuid; + uint8_t ready; +} mp_bluetooth_nimble_pending_characteristic_t; + typedef struct _mp_bluetooth_nimble_root_pointers_t { // Characteristic (and descriptor) value storage. mp_gatts_db_t gatts_db; @@ -44,6 +51,14 @@ typedef struct _mp_bluetooth_nimble_root_pointers_t { struct _mp_bluetooth_nimble_l2cap_channel_t *l2cap_chan; bool l2cap_listening; #endif + + #if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT + // Workaround to allow us to get the end_handle of each characteristic + // during discovery. See mp_bluetooth_gattc_discover_characteristics(). + uint16_t char_disc_end_handle; + const mp_obj_bluetooth_uuid_t *char_filter_uuid; + mp_bluetooth_nimble_pending_characteristic_t pending_char_result; + #endif } mp_bluetooth_nimble_root_pointers_t; enum { From 1d4228ccc1f4b6760007a8370d75a3ae3339c801 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 9 Sep 2022 14:14:31 +1000 Subject: [PATCH 0388/1041] zephyr/boards: Add config for bbc_microbit_v2. This enables the bluetooth module. GAP scanning and advertising works. Signed-off-by: Damien George --- ports/zephyr/boards/bbc_microbit_v2.conf | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 ports/zephyr/boards/bbc_microbit_v2.conf diff --git a/ports/zephyr/boards/bbc_microbit_v2.conf b/ports/zephyr/boards/bbc_microbit_v2.conf new file mode 100644 index 0000000000..31872244ca --- /dev/null +++ b/ports/zephyr/boards/bbc_microbit_v2.conf @@ -0,0 +1,8 @@ +CONFIG_CONSOLE_SUBSYS=n +CONFIG_NETWORKING=n +CONFIG_BT=y +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y + +CONFIG_MICROPY_HEAP_SIZE=98304 From 4903e48e340bd9741577f30cacb31605cc70cf20 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 9 Sep 2022 18:12:55 +1000 Subject: [PATCH 0389/1041] tools/makemanifest.py: Force the repo version of the mpy_cross package. In case the version from pypi is installed or some other version is available in sys.path, prepend `$(TOP)/mpy-cross` to sys.path instead. Signed-off-by: Jim Mussared --- tools/makemanifest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/makemanifest.py b/tools/makemanifest.py index d059d4a266..9dd8815aac 100644 --- a/tools/makemanifest.py +++ b/tools/makemanifest.py @@ -29,7 +29,8 @@ import sys import os import subprocess -sys.path.append(os.path.join(os.path.dirname(__file__), "../mpy-cross")) +# Always use the mpy-cross from this repo. +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../mpy-cross")) import mpy_cross import manifestfile From 582b3e4e7864809e30eac694251600f61db52a3c Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Fri, 9 Sep 2022 09:48:01 +1000 Subject: [PATCH 0390/1041] py/objpolyiter: Add a new polyiter type with finaliser support. --- py/obj.h | 3 +++ py/objpolyiter.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/py/obj.h b/py/obj.h index e048cf0c28..8949830282 100644 --- a/py/obj.h +++ b/py/obj.h @@ -677,6 +677,9 @@ extern const mp_obj_type_t mp_type_stringio; extern const mp_obj_type_t mp_type_bytesio; extern const mp_obj_type_t mp_type_reversed; extern const mp_obj_type_t mp_type_polymorph_iter; +#if MICROPY_ENABLE_FINALISER +extern const mp_obj_type_t mp_type_polymorph_iter_with_finaliser; +#endif // Exceptions extern const mp_obj_type_t mp_type_BaseException; diff --git a/py/objpolyiter.c b/py/objpolyiter.c index 01880bff9c..16fd1f486c 100644 --- a/py/objpolyiter.c +++ b/py/objpolyiter.c @@ -51,3 +51,37 @@ const mp_obj_type_t mp_type_polymorph_iter = { .getiter = mp_identity_getiter, .iternext = polymorph_it_iternext, }; + +#if MICROPY_ENABLE_FINALISER +// mp_type_polymorph_iter_with_finaliser is a variant of the universal iterator +// above which has a finaliser function attached. This function will be run when +// the GC collects the iter object and can be used to close file handles etc. + +// Any instance should have these 3 fields at the beginning +typedef struct _mp_obj_polymorph_iter_with_finaliser_t { + mp_obj_base_t base; + mp_fun_1_t iternext; + mp_fun_1_t finaliser; +} mp_obj_polymorph_with_finaliser_iter_t; + +STATIC mp_obj_t mp_obj_polymorph_iter_del(mp_obj_t self_in) { + mp_obj_polymorph_with_finaliser_iter_t *self = MP_OBJ_TO_PTR(self_in); + // Redirect call to object instance's iternext method + return self->finaliser(self_in); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_obj_polymorph_iter_del_obj, mp_obj_polymorph_iter_del); + +STATIC const mp_rom_map_elem_t mp_obj_polymorph_iter_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_obj_polymorph_iter_del_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(mp_obj_polymorph_iter_locals_dict, mp_obj_polymorph_iter_locals_dict_table); + +const mp_obj_type_t mp_type_polymorph_iter_with_finaliser = { + { &mp_type_type }, + .name = MP_QSTR_iterator, + .getiter = mp_identity_getiter, + .iternext = polymorph_it_iternext, + .locals_dict = (mp_obj_dict_t *)&mp_obj_polymorph_iter_locals_dict, +}; + +#endif From 4e0964b59f44b25ebaa5239f9ea4273b804ebe64 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Fri, 9 Sep 2022 09:48:01 +1000 Subject: [PATCH 0391/1041] extmod/vfs: Add finaliser to ilistdir to close directory handle. When iterating over filesystem/folders with os.iterdir(), an open file (directory) handle is used internally. Currently this file handle is only closed once the iterator is completely drained, eg. once all entries have been looped over / converted into list etc. If a program opens an iterdir but does not loop over it, or starts to loop over the iterator but breaks out of the loop, then the handle never gets closed. In this state, when the iter object is cleaned up by the garbage collector this open handle can cause corruption of the filesystem. Fixes issues #6568 and #8506. --- extmod/vfs_fat.c | 16 ++++- extmod/vfs_lfsx.c | 25 +++++++- extmod/vfs_posix.c | 19 +++++- tests/extmod/vfs_fat_ilistdir_del.py | 75 ++++++++++++++++++++++ tests/extmod/vfs_fat_ilistdir_del.py.exp | 30 +++++++++ tests/extmod/vfs_lfs_ilistdir_del.py | 75 ++++++++++++++++++++++ tests/extmod/vfs_lfs_ilistdir_del.py.exp | 30 +++++++++ tests/extmod/vfs_posix_ilistdir_del.py | 70 ++++++++++++++++++++ tests/extmod/vfs_posix_ilistdir_del.py.exp | 30 +++++++++ tools/ci.sh | 4 +- 10 files changed, 368 insertions(+), 6 deletions(-) create mode 100644 tests/extmod/vfs_fat_ilistdir_del.py create mode 100644 tests/extmod/vfs_fat_ilistdir_del.py.exp create mode 100644 tests/extmod/vfs_lfs_ilistdir_del.py create mode 100644 tests/extmod/vfs_lfs_ilistdir_del.py.exp create mode 100644 tests/extmod/vfs_posix_ilistdir_del.py create mode 100644 tests/extmod/vfs_posix_ilistdir_del.py.exp diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 27681ca770..7d8b51efeb 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -28,6 +28,10 @@ #include "py/mpconfig.h" #if MICROPY_VFS_FAT +#if !MICROPY_ENABLE_FINALISER +#error "MICROPY_VFS_FAT requires MICROPY_ENABLE_FINALISER" +#endif + #if !MICROPY_VFS #error "with MICROPY_VFS_FAT enabled, must also enable MICROPY_VFS" #endif @@ -118,6 +122,7 @@ STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(fat_vfs_mkfs_obj, MP_ROM_PTR(&fat_vfs_mk typedef struct _mp_vfs_fat_ilistdir_it_t { mp_obj_base_t base; mp_fun_1_t iternext; + mp_fun_1_t finaliser; bool is_str; FF_DIR dir; } mp_vfs_fat_ilistdir_it_t; @@ -162,6 +167,13 @@ STATIC mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) { return MP_OBJ_STOP_ITERATION; } +STATIC mp_obj_t mp_vfs_fat_ilistdir_it_del(mp_obj_t self_in) { + mp_vfs_fat_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); + // ignore result / error because we may be closing a second time. + f_closedir(&self->dir); + return mp_const_none; +} + STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(args[0]); bool is_str_type = true; @@ -176,8 +188,10 @@ STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) { } // Create a new iterator object to list the dir - mp_vfs_fat_ilistdir_it_t *iter = mp_obj_malloc(mp_vfs_fat_ilistdir_it_t, &mp_type_polymorph_iter); + mp_vfs_fat_ilistdir_it_t *iter = m_new_obj_with_finaliser(mp_vfs_fat_ilistdir_it_t); + iter->base.type = &mp_type_polymorph_iter_with_finaliser; iter->iternext = mp_vfs_fat_ilistdir_it_iternext; + iter->finaliser = mp_vfs_fat_ilistdir_it_del; iter->is_str = is_str_type; FRESULT res = f_opendir(&self->fatfs, &iter->dir, path); if (res != FR_OK) { diff --git a/extmod/vfs_lfsx.c b/extmod/vfs_lfsx.c index dbd32338cf..fbfeaa5ccf 100644 --- a/extmod/vfs_lfsx.c +++ b/extmod/vfs_lfsx.c @@ -36,6 +36,10 @@ #include "extmod/vfs.h" #include "shared/timeutils/timeutils.h" +#if !MICROPY_ENABLE_FINALISER +#error "MICROPY_VFS_LFS requires MICROPY_ENABLE_FINALISER" +#endif + STATIC int MP_VFS_LFSx(dev_ioctl)(const struct LFSx_API (config) * c, int cmd, int arg, bool must_return_int) { mp_obj_t ret = mp_vfs_blockdev_ioctl(c->context, cmd, arg); int ret_i = 0; @@ -155,6 +159,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(MP_VFS_LFSx(open_obj), MP_VFS_LFSx(file_open)); typedef struct MP_VFS_LFSx (_ilistdir_it_t) { mp_obj_base_t base; mp_fun_1_t iternext; + mp_fun_1_t finaliser; bool is_str; MP_OBJ_VFS_LFSx *vfs; LFSx_API(dir_t) dir; @@ -163,11 +168,16 @@ typedef struct MP_VFS_LFSx (_ilistdir_it_t) { STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_iternext)(mp_obj_t self_in) { MP_VFS_LFSx(ilistdir_it_t) * self = MP_OBJ_TO_PTR(self_in); + if (self->vfs == NULL) { + return MP_OBJ_STOP_ITERATION; + } + struct LFSx_API (info) info; for (;;) { int ret = LFSx_API(dir_read)(&self->vfs->lfs, &self->dir, &info); if (ret == 0) { LFSx_API(dir_close)(&self->vfs->lfs, &self->dir); + self->vfs = NULL; return MP_OBJ_STOP_ITERATION; } if (!(info.name[0] == '.' && (info.name[1] == '\0' @@ -190,6 +200,14 @@ STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_iternext)(mp_obj_t self_in) { return MP_OBJ_FROM_PTR(t); } +STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_del)(mp_obj_t self_in) { + MP_VFS_LFSx(ilistdir_it_t) * self = MP_OBJ_TO_PTR(self_in); + if (self->vfs != NULL) { + LFSx_API(dir_close)(&self->vfs->lfs, &self->dir); + } + return mp_const_none; +} + STATIC mp_obj_t MP_VFS_LFSx(ilistdir_func)(size_t n_args, const mp_obj_t *args) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(args[0]); bool is_str_type = true; @@ -203,14 +221,17 @@ STATIC mp_obj_t MP_VFS_LFSx(ilistdir_func)(size_t n_args, const mp_obj_t *args) path = vstr_null_terminated_str(&self->cur_dir); } - MP_VFS_LFSx(ilistdir_it_t) * iter = mp_obj_malloc(MP_VFS_LFSx(ilistdir_it_t), &mp_type_polymorph_iter); + MP_VFS_LFSx(ilistdir_it_t) * iter = m_new_obj_with_finaliser(MP_VFS_LFSx(ilistdir_it_t)); + iter->base.type = &mp_type_polymorph_iter_with_finaliser; + iter->iternext = MP_VFS_LFSx(ilistdir_it_iternext); + iter->finaliser = MP_VFS_LFSx(ilistdir_it_del); iter->is_str = is_str_type; - iter->vfs = self; int ret = LFSx_API(dir_open)(&self->lfs, &iter->dir, path); if (ret < 0) { mp_raise_OSError(-ret); } + iter->vfs = self; return MP_OBJ_FROM_PTR(iter); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(MP_VFS_LFSx(ilistdir_obj), 1, 2, MP_VFS_LFSx(ilistdir_func)); diff --git a/extmod/vfs_posix.c b/extmod/vfs_posix.c index 9b00365817..36b211b84d 100644 --- a/extmod/vfs_posix.c +++ b/extmod/vfs_posix.c @@ -33,6 +33,10 @@ #if MICROPY_VFS_POSIX +#if !MICROPY_ENABLE_FINALISER +#error "MICROPY_VFS_POSIX requires MICROPY_ENABLE_FINALISER" +#endif + #include #include #include @@ -162,6 +166,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_getcwd_obj, vfs_posix_getcwd); typedef struct _vfs_posix_ilistdir_it_t { mp_obj_base_t base; mp_fun_1_t iternext; + mp_fun_1_t finaliser; bool is_str; DIR *dir; } vfs_posix_ilistdir_it_t; @@ -226,10 +231,22 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) { } } +STATIC mp_obj_t vfs_posix_ilistdir_it_del(mp_obj_t self_in) { + vfs_posix_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); + if (self->dir != NULL) { + MP_THREAD_GIL_EXIT(); + closedir(self->dir); + MP_THREAD_GIL_ENTER(); + } + return mp_const_none; +} + STATIC mp_obj_t vfs_posix_ilistdir(mp_obj_t self_in, mp_obj_t path_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); - vfs_posix_ilistdir_it_t *iter = mp_obj_malloc(vfs_posix_ilistdir_it_t, &mp_type_polymorph_iter); + vfs_posix_ilistdir_it_t *iter = m_new_obj_with_finaliser(vfs_posix_ilistdir_it_t); + iter->base.type = &mp_type_polymorph_iter_with_finaliser; iter->iternext = vfs_posix_ilistdir_it_iternext; + iter->finaliser = vfs_posix_ilistdir_it_del; iter->is_str = mp_obj_get_type(path_in) == &mp_type_str; const char *path = vfs_posix_get_path_str(self, path_in); if (path[0] == '\0') { diff --git a/tests/extmod/vfs_fat_ilistdir_del.py b/tests/extmod/vfs_fat_ilistdir_del.py new file mode 100644 index 0000000000..a833e9ac12 --- /dev/null +++ b/tests/extmod/vfs_fat_ilistdir_del.py @@ -0,0 +1,75 @@ +# Test ilistdir __del__ for VfsFat using a RAM device. +import gc + +try: + import uos + + uos.VfsFat +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + + +class RAMBlockDevice: + ERASE_BLOCK_SIZE = 4096 + + def __init__(self, blocks): + self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) + + def readblocks(self, block, buf, off=0): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + buf[i] = self.data[addr + i] + + def writeblocks(self, block, buf, off=0): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + self.data[addr + i] = buf[i] + + def ioctl(self, op, arg): + if op == 4: # block count + return len(self.data) // self.ERASE_BLOCK_SIZE + if op == 5: # block size + return self.ERASE_BLOCK_SIZE + if op == 6: # erase block + return 0 + + +def test(bdev, vfs_class): + vfs_class.mkfs(bdev) + vfs = vfs_class(bdev) + vfs.mkdir("/test_d1") + vfs.mkdir("/test_d2") + vfs.mkdir("/test_d3") + + for i in range(10): + print(i) + + # We want to partially iterate the ilistdir iterator to leave it in an + # open state, which will then test the finaliser when it's garbage collected. + idir = vfs.ilistdir("/") + print(any(idir)) + + # Alternate way of partially iterating the ilistdir object, modifying the + # filesystem while it's open. + for dname, *_ in vfs.ilistdir("/"): + vfs.rmdir(dname) + break + vfs.mkdir(dname) + + # Also create a fully drained iterator and ensure trying to re-use it + # throws the correct exception. + idir_emptied = vfs.ilistdir("/") + l = list(idir_emptied) + print(len(l)) + try: + next(idir_emptied) + except StopIteration: + pass + + gc.collect() + vfs.open("/test", "w").close() + + +bdev = RAMBlockDevice(30) +test(bdev, uos.VfsFat) diff --git a/tests/extmod/vfs_fat_ilistdir_del.py.exp b/tests/extmod/vfs_fat_ilistdir_del.py.exp new file mode 100644 index 0000000000..0ab2b019f4 --- /dev/null +++ b/tests/extmod/vfs_fat_ilistdir_del.py.exp @@ -0,0 +1,30 @@ +0 +True +3 +1 +True +4 +2 +True +4 +3 +True +4 +4 +True +4 +5 +True +4 +6 +True +4 +7 +True +4 +8 +True +4 +9 +True +4 diff --git a/tests/extmod/vfs_lfs_ilistdir_del.py b/tests/extmod/vfs_lfs_ilistdir_del.py new file mode 100644 index 0000000000..073576986d --- /dev/null +++ b/tests/extmod/vfs_lfs_ilistdir_del.py @@ -0,0 +1,75 @@ +# Test ilistdir __del__ for VfsLittle using a RAM device. +import gc + +try: + import uos + + uos.VfsLfs2 +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + + +class RAMBlockDevice: + ERASE_BLOCK_SIZE = 1024 + + def __init__(self, blocks): + self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) + + def readblocks(self, block, buf, off): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + buf[i] = self.data[addr + i] + + def writeblocks(self, block, buf, off): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + self.data[addr + i] = buf[i] + + def ioctl(self, op, arg): + if op == 4: # block count + return len(self.data) // self.ERASE_BLOCK_SIZE + if op == 5: # block size + return self.ERASE_BLOCK_SIZE + if op == 6: # erase block + return 0 + + +def test(bdev, vfs_class): + vfs_class.mkfs(bdev) + vfs = vfs_class(bdev) + vfs.mkdir("/test_d1") + vfs.mkdir("/test_d2") + vfs.mkdir("/test_d3") + + for i in range(10): + print(i) + + # We want to partially iterate the ilistdir iterator to leave it in an + # open state, which will then test the finaliser when it's garbage collected. + idir = vfs.ilistdir("/") + print(any(idir)) + + # Alternate way of partially iterating the ilistdir object, modifying the + # filesystem while it's open. + for dname, *_ in vfs.ilistdir("/"): + vfs.rmdir(dname) + break + vfs.mkdir(dname) + + # Also create a fully drained iterator and ensure trying to re-use it + # throws the correct exception. + idir_emptied = vfs.ilistdir("/") + l = list(idir_emptied) + print(len(l)) + try: + next(idir_emptied) + except StopIteration: + pass + + gc.collect() + vfs.open("/test", "w").close() + + +bdev = RAMBlockDevice(30) +test(bdev, uos.VfsLfs2) diff --git a/tests/extmod/vfs_lfs_ilistdir_del.py.exp b/tests/extmod/vfs_lfs_ilistdir_del.py.exp new file mode 100644 index 0000000000..0ab2b019f4 --- /dev/null +++ b/tests/extmod/vfs_lfs_ilistdir_del.py.exp @@ -0,0 +1,30 @@ +0 +True +3 +1 +True +4 +2 +True +4 +3 +True +4 +4 +True +4 +5 +True +4 +6 +True +4 +7 +True +4 +8 +True +4 +9 +True +4 diff --git a/tests/extmod/vfs_posix_ilistdir_del.py b/tests/extmod/vfs_posix_ilistdir_del.py new file mode 100644 index 0000000000..edb50dfd62 --- /dev/null +++ b/tests/extmod/vfs_posix_ilistdir_del.py @@ -0,0 +1,70 @@ +# Test ilistdir __del__ for VfsPosix. +import gc + +try: + import os + + os.VfsPosix +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + + +def test(testdir): + vfs = os.VfsPosix(testdir) + vfs.mkdir("/test_d1") + vfs.mkdir("/test_d2") + vfs.mkdir("/test_d3") + + for i in range(10): + print(i) + + # We want to partially iterate the ilistdir iterator to leave it in an + # open state, which will then test the finaliser when it's garbage collected. + idir = vfs.ilistdir("/") + print(any(idir)) + + # Alternate way of partially iterating the ilistdir object, modifying the + # filesystem while it's open. + for dname, *_ in vfs.ilistdir("/"): + vfs.rmdir(dname) + break + vfs.mkdir(dname) + + # Also create a fully drained iterator and ensure trying to re-use it + # throws the correct exception. + idir_emptied = vfs.ilistdir("/") + l = list(idir_emptied) + print(len(l)) + try: + next(idir_emptied) + except StopIteration: + pass + + gc.collect() + + # Create and delete a file, try to flush out any filesystem + # corruption that may be caused over the loops. + vfs.open("/test", "w").close() + vfs.remove("/test") + + +# We need an empty directory for testing. +# Skip the test if it already exists. +temp_dir = "vfs_posix_ilistdir_del_test_dir" +try: + os.stat(temp_dir) + print("SKIP") + raise SystemExit +except OSError: + pass + +os.mkdir(temp_dir) + +test(temp_dir) + +# Remove tempdir. +for td in os.listdir(temp_dir): + os.rmdir("/".join((temp_dir, td))) + +os.rmdir(temp_dir) diff --git a/tests/extmod/vfs_posix_ilistdir_del.py.exp b/tests/extmod/vfs_posix_ilistdir_del.py.exp new file mode 100644 index 0000000000..c30ba41326 --- /dev/null +++ b/tests/extmod/vfs_posix_ilistdir_del.py.exp @@ -0,0 +1,30 @@ +0 +True +3 +1 +True +3 +2 +True +3 +3 +True +3 +4 +True +3 +5 +True +3 +6 +True +3 +7 +True +3 +8 +True +3 +9 +True +3 diff --git a/tools/ci.sh b/tools/ci.sh index b4cb7dc2e3..8f1d729a13 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -632,7 +632,7 @@ function ci_unix_qemu_mips_run_tests { # - (i)listdir does not work, it always returns the empty list (it's an issue with the underlying C call) # - ffi tests do not work file ./ports/unix/build-coverage/micropython - (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py --exclude 'vfs_posix.py' --exclude 'ffi_(callback|float|float2).py') + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py --exclude 'vfs_posix.*\.py' --exclude 'ffi_(callback|float|float2).py') } function ci_unix_qemu_arm_setup { @@ -652,7 +652,7 @@ function ci_unix_qemu_arm_run_tests { # - (i)listdir does not work, it always returns the empty list (it's an issue with the underlying C call) export QEMU_LD_PREFIX=/usr/arm-linux-gnueabi file ./ports/unix/build-coverage/micropython - (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py --exclude 'vfs_posix.py') + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py --exclude 'vfs_posix.*\.py') } ######################################################################################## From 86676a43aa9de47bfdf52c7a71751de1bb512c64 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 12 Sep 2022 08:41:39 +1000 Subject: [PATCH 0392/1041] unix/mpconfigport: Enable MICROPY_ENABLE_FINALISER when VFS is used. --- ports/unix/mpconfigport.h | 2 +- ports/unix/variants/minimal/mpconfigvariant.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index dd73f61e24..cb389d9a53 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -45,7 +45,6 @@ #ifndef MICROPY_OPT_MAP_LOOKUP_CACHE #define MICROPY_OPT_MAP_LOOKUP_CACHE (1) #endif -#define MICROPY_ENABLE_FINALISER (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_HELPER_REPL (1) @@ -124,6 +123,7 @@ #ifndef MICROPY_GC_SPLIT_HEAP_N_HEAPS #define MICROPY_GC_SPLIT_HEAP_N_HEAPS (1) #endif +#define MICROPY_ENABLE_FINALISER (1) #define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1) #define MICROPY_MEM_STATS (1) #define MICROPY_DEBUG_PRINTERS (1) diff --git a/ports/unix/variants/minimal/mpconfigvariant.h b/ports/unix/variants/minimal/mpconfigvariant.h index 2e2c1de0cc..d9d2a6c48e 100644 --- a/ports/unix/variants/minimal/mpconfigvariant.h +++ b/ports/unix/variants/minimal/mpconfigvariant.h @@ -37,8 +37,8 @@ #define MICROPY_ALLOC_PARSE_CHUNK_INIT (64) #define MICROPY_ALLOC_PATH_MAX (PATH_MAX) #define MICROPY_ENABLE_GC (1) +#define MICROPY_ENABLE_FINALISER (1) #define MICROPY_GC_ALLOC_THRESHOLD (0) -#define MICROPY_ENABLE_FINALISER (0) #define MICROPY_STACK_CHECK (0) #define MICROPY_COMP_CONST (0) #define MICROPY_MEM_STATS (0) From afc7e1d298add00eacf38be0ae9455f0f09aed2e Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 12 Sep 2022 08:45:56 +1000 Subject: [PATCH 0393/1041] zephyr/mpconfigport: Enable MICROPY_ENABLE_FINALISER when VFS is used. --- ports/zephyr/mpconfigport.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/zephyr/mpconfigport.h b/ports/zephyr/mpconfigport.h index 4c8096b441..71836768a4 100644 --- a/ports/zephyr/mpconfigport.h +++ b/ports/zephyr/mpconfigport.h @@ -39,6 +39,7 @@ #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_ENABLE_GC (1) +#define MICROPY_ENABLE_FINALISER (MICROPY_VFS) #define MICROPY_HELPER_REPL (1) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_KBD_EXCEPTION (1) From 2d4e7e99bfcfaaed252564f9498176ca3ad88fee Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 12 Sep 2022 08:47:02 +1000 Subject: [PATCH 0394/1041] samd/mpconfigport: Enable MICROPY_ENABLE_FINALISER when VFS is used. --- ports/samd/mpconfigport.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 0b16b5e817..2c6052149b 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -41,6 +41,7 @@ // Python internal features #define MICROPY_ENABLE_GC (1) +#define MICROPY_ENABLE_FINALISER (1) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) From 57fd66b80f8352e4859e6b71536b6083f9d7279c Mon Sep 17 00:00:00 2001 From: Wind-stormger Date: Tue, 30 Aug 2022 11:30:12 +0800 Subject: [PATCH 0395/1041] tools/pyboard.py: Support Windows pathname separators. Addresses issue #9132. --- tools/pyboard.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/pyboard.py b/tools/pyboard.py index 436bc5ab1b..60cc06508e 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -582,12 +582,12 @@ def filesystem_command(pyb, args, progress_callback=None, verbose=False): return src def fname_cp_dest(src, dest): - src = src.rsplit("/", 1)[-1] + _, src = os.path.split(src) if dest is None or dest == "": dest = src elif dest == ".": - dest = "./" + src - elif dest.endswith("/"): + dest = os.path.join(".", src) + elif dest.endswith(os.path.sep): dest += src return dest From 89a0fefb6c5c730a7b740cf31e44a6c76c3993b1 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 13 Sep 2022 14:57:24 +1000 Subject: [PATCH 0396/1041] py/mpconfig: Add LFS1/LFS2 options to match FAT/posix. Also fixes the #ifndef for FAT & posix. Signed-off-by: Jim Mussared --- py/mpconfig.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/py/mpconfig.h b/py/mpconfig.h index d478c654d0..b8cc61b2ad 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -920,15 +920,25 @@ typedef double mp_float_t; #endif // Support for VFS POSIX component, to mount a POSIX filesystem within VFS -#ifndef MICROPY_VFS +#ifndef MICROPY_VFS_POSIX #define MICROPY_VFS_POSIX (0) #endif // Support for VFS FAT component, to mount a FAT filesystem within VFS -#ifndef MICROPY_VFS +#ifndef MICROPY_VFS_FAT #define MICROPY_VFS_FAT (0) #endif +// Support for VFS LittleFS v1 component, to mount a LFSv1 filesystem within VFS +#ifndef MICROPY_VFS_LFS1 +#define MICROPY_VFS_LFS1 (0) +#endif + +// Support for VFS LittleFS v2 component, to mount a LFSv2 filesystem within VFS +#ifndef MICROPY_VFS_LFS2 +#define MICROPY_VFS_LFS2 (0) +#endif + /*****************************************************************************/ /* Fine control over Python builtins, classes, modules, etc */ From 605266ee9a1258003032abb2fbfa58ef354ded25 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 16 Aug 2022 01:28:31 +1000 Subject: [PATCH 0397/1041] py/mpconfig: Make feature levels available to mpconfigport.h. Signed-off-by: Jim Mussared --- py/mpconfig.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/py/mpconfig.h b/py/mpconfig.h index b8cc61b2ad..5da7e453ec 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -56,12 +56,6 @@ // release vs debug configs, etc. Note that if you switch from one config // to another, you must rebuild from scratch using "-B" switch to make. -#ifdef MP_CONFIGFILE -#include MP_CONFIGFILE -#else -#include -#endif - // Disable all optional features (i.e. minimal port). #define MICROPY_CONFIG_ROM_LEVEL_MINIMUM (0) // Only enable core features (constrained flash, e.g. STM32L072) @@ -75,6 +69,12 @@ // Enable everything (e.g. coverage) #define MICROPY_CONFIG_ROM_LEVEL_EVERYTHING (50) +#ifdef MP_CONFIGFILE +#include MP_CONFIGFILE +#else +#include +#endif + // Ports/boards should set this, but default to level=core. #ifndef MICROPY_CONFIG_ROM_LEVEL #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES) From f4fed02537e5b1b1a06912c8339c47ce500d18c6 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 15 Aug 2022 11:56:03 +1000 Subject: [PATCH 0398/1041] unix/variants: Remove freedos and fast variants. The freedos variant is untested by CI and is difficult to maintain. The fast variant is not a good name for what it does. Signed-off-by: Jim Mussared --- ports/unix/variants/fast/mpconfigvariant.h | 34 ----------------- ports/unix/variants/fast/mpconfigvariant.mk | 5 --- ports/unix/variants/freedos/mpconfigvariant.h | 38 ------------------- .../unix/variants/freedos/mpconfigvariant.mk | 18 --------- 4 files changed, 95 deletions(-) delete mode 100644 ports/unix/variants/fast/mpconfigvariant.h delete mode 100644 ports/unix/variants/fast/mpconfigvariant.mk delete mode 100644 ports/unix/variants/freedos/mpconfigvariant.h delete mode 100644 ports/unix/variants/freedos/mpconfigvariant.mk diff --git a/ports/unix/variants/fast/mpconfigvariant.h b/ports/unix/variants/fast/mpconfigvariant.h deleted file mode 100644 index 8a531b056a..0000000000 --- a/ports/unix/variants/fast/mpconfigvariant.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 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. - */ - -// This config file is intended to configure artificially fast uPy build for -// synthetic benchmarking, at the expense of features supported and memory -// usage. This config is not intended to be used in production. - -#define MICROPY_PY___FILE__ (0) -// 91 is a magic number proposed by @dpgeorge, which make pystone run ~ at tie -// with CPython 3.4. -#define MICROPY_MODULE_DICT_SIZE (91) diff --git a/ports/unix/variants/fast/mpconfigvariant.mk b/ports/unix/variants/fast/mpconfigvariant.mk deleted file mode 100644 index b8fe69e487..0000000000 --- a/ports/unix/variants/fast/mpconfigvariant.mk +++ /dev/null @@ -1,5 +0,0 @@ -# build synthetically fast interpreter for benchmarking - -COPT += -fno-crossjumping -O2 - -FROZEN_MANIFEST = diff --git a/ports/unix/variants/freedos/mpconfigvariant.h b/ports/unix/variants/freedos/mpconfigvariant.h deleted file mode 100644 index 562c783ca3..0000000000 --- a/ports/unix/variants/freedos/mpconfigvariant.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 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. - */ - -// options to control how MicroPython is built - -#define MICROPY_PY_USELECT_POSIX (0) - -#define MICROPY_STREAMS_NON_BLOCK (0) - -#define MICROPY_PY_SYS_PLATFORM "freedos" - -// djgpp dirent struct does not have d_ino field -#undef _DIRENT_HAVE_D_INO - -#define MICROPY_USE_INTERNAL_ERRNO (1) diff --git a/ports/unix/variants/freedos/mpconfigvariant.mk b/ports/unix/variants/freedos/mpconfigvariant.mk deleted file mode 100644 index 86ab6864f4..0000000000 --- a/ports/unix/variants/freedos/mpconfigvariant.mk +++ /dev/null @@ -1,18 +0,0 @@ -CC = i586-pc-msdosdjgpp-gcc - -STRIP = i586-pc-msdosdjgpp-strip - -SIZE = i586-pc-msdosdjgpp-size - -CFLAGS += \ - -DMICROPY_NLR_SETJMP \ - -Dtgamma=gamma \ - -DMICROPY_EMIT_X86=0 \ - -DMICROPY_NO_ALLOCA=1 \ - -MICROPY_PY_SOCKET = 0 -MICROPY_PY_FFI = 0 -MICROPY_PY_JNI = 0 -MICROPY_PY_BTREE = 0 -MICROPY_PY_THREAD = 0 -MICROPY_PY_USSL = 0 From c1530a0ce8e83811f88fbd4558ea7aaf27919ed8 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 15 Aug 2022 13:58:34 +1000 Subject: [PATCH 0399/1041] unix: Refactor mpconfigport.h and mpconfigvariant.h. This is a no-op for coverage and minimal. The standard and dev variants have been merged and enable the same feature set as a typical bare-metal board. And remove the CI for the dev build. Signed-off-by: Jim Mussared --- .github/workflows/ports_unix.yml | 12 - ports/unix/main.c | 5 + ports/unix/mpconfigport.h | 303 ++++++------------ .../unix/variants/coverage/mpconfigvariant.h | 5 +- ports/unix/variants/dev/mpconfigvariant.h | 40 --- ports/unix/variants/dev/mpconfigvariant.mk | 8 - ports/unix/variants/minimal/mpconfigvariant.h | 135 ++------ ports/unix/variants/mpconfigvariant_common.h | 124 +++++++ ports/unix/variants/nanbox/mpconfigvariant.h | 5 + .../variants/{dev => standard}/manifest.py | 0 .../unix/variants/standard/mpconfigvariant.h | 17 +- .../unix/variants/standard/mpconfigvariant.mk | 7 + tools/ci.sh | 10 - 13 files changed, 278 insertions(+), 393 deletions(-) delete mode 100644 ports/unix/variants/dev/mpconfigvariant.h delete mode 100644 ports/unix/variants/dev/mpconfigvariant.mk create mode 100644 ports/unix/variants/mpconfigvariant_common.h rename ports/unix/variants/{dev => standard}/manifest.py (100%) diff --git a/.github/workflows/ports_unix.yml b/.github/workflows/ports_unix.yml index 45cc87e723..3b738634a6 100644 --- a/.github/workflows/ports_unix.yml +++ b/.github/workflows/ports_unix.yml @@ -49,18 +49,6 @@ jobs: if: failure() run: tests/run-tests.py --print-failures - dev: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Build - run: source tools/ci.sh && ci_unix_dev_build - - name: Run main test suite - run: source tools/ci.sh && ci_unix_dev_run_tests - - name: Print failures - if: failure() - run: tests/run-tests.py --print-failures - coverage: runs-on: ubuntu-latest steps: diff --git a/ports/unix/main.c b/ports/unix/main.c index c388106a64..4f019b6c2c 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -63,6 +63,11 @@ STATIC uint emit_opt = MP_EMIT_OPT_NONE; long heap_size = 1024 * 1024 * (sizeof(mp_uint_t) / 4); #endif +// Number of heaps to assign by default if MICROPY_GC_SPLIT_HEAP=1 +#ifndef MICROPY_GC_SPLIT_HEAP_N_HEAPS +#define MICROPY_GC_SPLIT_HEAP_N_HEAPS (1) +#endif + STATIC void stderr_print_strn(void *env, const char *str, size_t len) { (void)env; ssize_t ret; diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index cb389d9a53..08ddd21f63 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -24,85 +24,36 @@ * THE SOFTWARE. */ -// Options to control how MicroPython is built for this port, -// overriding defaults in py/mpconfig.h. +// Options to control how MicroPython is built for this port, overriding +// defaults in py/mpconfig.h. This file is mostly about configuring the +// features to work on Unix-like systems, see mpconfigvariant.h (and +// mpconfigvariant_common.h) for feature enabling. + +// For size_t and ssize_t +#include // Variant-specific definitions. #include "mpconfigvariant.h" -// The minimal variant's config covers everything. -// If we're building the minimal variant, ignore the rest of this file. -#ifndef MICROPY_UNIX_MINIMAL - -// If the variant did not set a feature level then configure a set of features. #ifndef MICROPY_CONFIG_ROM_LEVEL -#define MICROPY_COMP_MODULE_CONST (1) -#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) -#define MICROPY_COMP_RETURN_IF_EXPR (1) -#ifndef MICROPY_OPT_LOAD_ATTR_FAST_PATH -#define MICROPY_OPT_LOAD_ATTR_FAST_PATH (1) -#endif -#ifndef MICROPY_OPT_MAP_LOOKUP_CACHE -#define MICROPY_OPT_MAP_LOOKUP_CACHE (1) -#endif -#define MICROPY_STACK_CHECK (1) -#define MICROPY_KBD_EXCEPTION (1) -#define MICROPY_HELPER_REPL (1) -#define MICROPY_REPL_EMACS_KEYS (1) -#define MICROPY_REPL_AUTO_INDENT (1) -#define MICROPY_ENABLE_SOURCE_LINE (1) -#ifndef MICROPY_STREAMS_NON_BLOCK -#define MICROPY_STREAMS_NON_BLOCK (1) -#endif -#define MICROPY_MODULE_WEAK_LINKS (1) -#define MICROPY_CAN_OVERRIDE_BUILTINS (1) -#define MICROPY_PY_FUNCTION_ATTRS (1) -#define MICROPY_PY_DESCRIPTORS (1) -#define MICROPY_PY_DELATTR_SETATTR (1) -#define MICROPY_PY_FSTRINGS (1) -#define MICROPY_PY_BUILTINS_BYTES_HEX (1) -#define MICROPY_PY_BUILTINS_STR_UNICODE (1) -#define MICROPY_PY_BUILTINS_STR_CENTER (1) -#define MICROPY_PY_BUILTINS_STR_PARTITION (1) -#define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) -#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) -#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) -#define MICROPY_PY_BUILTINS_SLICE_INDICES (1) -#define MICROPY_PY_BUILTINS_FROZENSET (1) -#define MICROPY_PY_BUILTINS_ROUND_INT (1) -#define MICROPY_PY_ALL_SPECIAL_METHODS (1) -#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) -#define MICROPY_PY_BUILTINS_COMPILE (1) -#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) -#define MICROPY_PY_BUILTINS_INPUT (1) -#define MICROPY_PY_BUILTINS_POW3 (1) -#define MICROPY_PY_MICROPYTHON_MEM_INFO (1) -#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) -#define MICROPY_PY_COLLECTIONS_DEQUE (1) -#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) -#ifndef MICROPY_PY_MATH_SPECIAL_FUNCTIONS -#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) -#endif -#define MICROPY_PY_MATH_ISCLOSE (MICROPY_PY_MATH_SPECIAL_FUNCTIONS) -#define MICROPY_PY_CMATH (1) -#define MICROPY_PY_IO_IOBASE (1) -#define MICROPY_PY_SYS_MAXSIZE (1) -#define MICROPY_PY_SYS_STDFILES (1) -#define MICROPY_PY_UERRNO (1) -#define MICROPY_PY_UCTYPES (1) -#define MICROPY_PY_UZLIB (1) -#define MICROPY_PY_UJSON (1) -#define MICROPY_PY_UOS (1) -#define MICROPY_PY_URE (1) -#define MICROPY_PY_UHEAPQ (1) -#define MICROPY_PY_UHASHLIB (1) -#define MICROPY_PY_UBINASCII (1) -#define MICROPY_PY_UBINASCII_CRC32 (1) -#define MICROPY_PY_URANDOM (1) +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES) #endif -#define MICROPY_ALLOC_PATH_MAX (PATH_MAX) -#define MICROPY_PERSISTENT_CODE_LOAD (1) +#ifndef MICROPY_PY_SYS_PLATFORM +#if defined(__APPLE__) && defined(__MACH__) + #define MICROPY_PY_SYS_PLATFORM "darwin" +#else + #define MICROPY_PY_SYS_PLATFORM "linux" +#endif +#endif + +#ifndef MICROPY_PY_SYS_PATH_DEFAULT +#define MICROPY_PY_SYS_PATH_DEFAULT ".frozen:~/.micropython/lib:/usr/lib/micropython" +#endif + +#define MP_STATE_PORT MP_STATE_VM + +// Configure which emitter to use for this target. #if !defined(MICROPY_EMIT_X64) && defined(__x86_64__) #define MICROPY_EMIT_X64 (1) #endif @@ -118,118 +69,8 @@ #if !defined(MICROPY_EMIT_ARM) && defined(__arm__) && !defined(__thumb2__) #define MICROPY_EMIT_ARM (1) #endif -#define MICROPY_ENABLE_GC (1) -// Number of heaps to assign if MICROPY_GC_SPLIT_HEAP=1 -#ifndef MICROPY_GC_SPLIT_HEAP_N_HEAPS -#define MICROPY_GC_SPLIT_HEAP_N_HEAPS (1) -#endif -#define MICROPY_ENABLE_FINALISER (1) -#define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1) -#define MICROPY_MEM_STATS (1) -#define MICROPY_DEBUG_PRINTERS (1) -// Printing debug to stderr may give tests which -// check stdout a chance to pass, etc. -#define MICROPY_DEBUG_PRINTER (&mp_stderr_print) -#define MICROPY_READER_POSIX (1) -#define MICROPY_READER_VFS (1) -#define MICROPY_USE_READLINE_HISTORY (1) -#ifndef MICROPY_READLINE_HISTORY_SIZE -#define MICROPY_READLINE_HISTORY_SIZE 50 -#endif -#define MICROPY_HELPER_LEXER_UNIX (1) -#ifndef MICROPY_FLOAT_IMPL -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) -#endif -#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) -#define MICROPY_STREAMS_POSIX_API (1) -#define MICROPY_OPT_COMPUTED_GOTO (1) -#define MICROPY_MODULE_OVERRIDE_MAIN_IMPORT (1) -#define MICROPY_VFS (1) -#define MICROPY_VFS_POSIX (1) -#define MICROPY_PY_SYS_PATH_ARGV_DEFAULTS (0) -#define MICROPY_PY_SYS_EXIT (1) -#define MICROPY_PY_SYS_ATEXIT (1) -#if MICROPY_PY_SYS_SETTRACE -#define MICROPY_PERSISTENT_CODE_SAVE (1) -#define MICROPY_COMP_CONST (0) -#endif -#ifndef MICROPY_PY_SYS_PLATFORM -#if defined(__APPLE__) && defined(__MACH__) - #define MICROPY_PY_SYS_PLATFORM "darwin" -#else - #define MICROPY_PY_SYS_PLATFORM "linux" -#endif -#endif -#ifndef MICROPY_PY_SYS_PATH_DEFAULT -#define MICROPY_PY_SYS_PATH_DEFAULT ".frozen:~/.micropython/lib:/usr/lib/micropython" -#endif -#define MICROPY_PY_SYS_EXC_INFO (1) -#define MICROPY_PY_GC_COLLECT_RETVAL (1) -#ifndef MICROPY_STACKLESS -#define MICROPY_STACKLESS (0) -#define MICROPY_STACKLESS_STRICT (0) -#endif - -#define MICROPY_PY_UOS_INCLUDEFILE "ports/unix/moduos.c" -#define MICROPY_PY_UOS_ERRNO (1) -#define MICROPY_PY_UOS_GETENV_PUTENV_UNSETENV (1) -#define MICROPY_PY_UOS_SEP (1) -#define MICROPY_PY_UOS_SYSTEM (1) -#define MICROPY_PY_UOS_URANDOM (1) -#define MICROPY_PY_UTIME (1) -#define MICROPY_PY_UTIME_MP_HAL (1) -#define MICROPY_PY_UTIMEQ (1) -#define MICROPY_PY_USOCKET_LISTEN_BACKLOG_DEFAULT (SOMAXCONN < 128 ? SOMAXCONN : 128) -#if MICROPY_PY_USSL -#define MICROPY_PY_UHASHLIB_MD5 (1) -#define MICROPY_PY_UHASHLIB_SHA1 (1) -#define MICROPY_PY_UCRYPTOLIB (1) -#endif -#ifndef MICROPY_PY_USELECT -#define MICROPY_PY_USELECT (0) -#endif -#ifndef MICROPY_PY_USELECT_POSIX -#define MICROPY_PY_USELECT_POSIX (!MICROPY_PY_USELECT) -#endif -#define MICROPY_PY_UWEBSOCKET (1) -#define MICROPY_PY_MACHINE (1) -#define MICROPY_PY_MACHINE_PULSE (1) -#define MICROPY_MACHINE_MEM_GET_READ_ADDR mod_machine_mem_get_addr -#define MICROPY_MACHINE_MEM_GET_WRITE_ADDR mod_machine_mem_get_addr - -#define MICROPY_FATFS_ENABLE_LFN (1) -#define MICROPY_FATFS_RPATH (2) -#define MICROPY_FATFS_MAX_SS (4096) -#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ - -// Define to MICROPY_ERROR_REPORTING_DETAILED to get function, etc. -// names in exception messages (may require more RAM). -#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED) -#define MICROPY_WARNINGS (1) -#define MICROPY_ERROR_PRINTER (&mp_stderr_print) -#define MICROPY_PY_STR_BYTES_CMP_WARN (1) - -// VFS stat functions should return time values relative to 1970/1/1 -#define MICROPY_EPOCH_IS_1970 (1) - -extern const struct _mp_print_t mp_stderr_print; - -#if !(defined(MICROPY_GCREGS_SETJMP) || defined(__x86_64__) || defined(__i386__) || defined(__thumb2__) || defined(__thumb__) || defined(__arm__)) -// Fall back to setjmp() implementation for discovery of GC pointers in registers. -#define MICROPY_GCREGS_SETJMP (1) -#endif - -#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) -#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256) -#define MICROPY_ASYNC_KBD_INTR (1) - -// type definitions for the specific machine - -// For size_t and ssize_t -#include - -// assume that if we already defined the obj repr then we also defined types +// Type definitions for the specific machine based on the word size. #ifndef MICROPY_OBJ_REPR #ifdef __LP64__ typedef long mp_int_t; // must be pointer size @@ -240,6 +81,8 @@ typedef unsigned long mp_uint_t; // must be pointer size typedef int mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size #endif +#else +// Assume that if we already defined the obj repr then we also defined types. #endif // Cannot include , as it may lead to symbol name clashes @@ -249,6 +92,77 @@ typedef long long mp_off_t; typedef long mp_off_t; #endif +// We need to provide a declaration/definition of alloca() +// unless support for it is disabled. +#if !defined(MICROPY_NO_ALLOCA) || MICROPY_NO_ALLOCA == 0 +#if defined(__FreeBSD__) || defined(__NetBSD__) +#include +#else +#include +#endif +#endif + +// Always enable GC. +#define MICROPY_ENABLE_GC (1) + +#if !(defined(MICROPY_GCREGS_SETJMP) || defined(__x86_64__) || defined(__i386__) || defined(__thumb2__) || defined(__thumb__) || defined(__arm__)) +// Fall back to setjmp() implementation for discovery of GC pointers in registers. +#define MICROPY_GCREGS_SETJMP (1) +#endif + +// Enable the VFS, and enable the posix "filesystem". +#define MICROPY_ENABLE_FINALISER (1) +#define MICROPY_VFS (1) +#define MICROPY_READER_VFS (1) +#define MICROPY_HELPER_LEXER_UNIX (1) +#define MICROPY_VFS_POSIX (1) +#define MICROPY_READER_POSIX (1) + +// VFS stat functions should return time values relative to 1970/1/1 +#define MICROPY_EPOCH_IS_1970 (1) + +// Assume that select() call, interrupted with a signal, and erroring +// with EINTR, updates remaining timeout value. +#define MICROPY_SELECT_REMAINING_TIME (1) + +// Disable stackless by default. +#ifndef MICROPY_STACKLESS +#define MICROPY_STACKLESS (0) +#define MICROPY_STACKLESS_STRICT (0) +#endif + +// If settrace is enabled then we need code saving. +#if MICROPY_PY_SYS_SETTRACE +#define MICROPY_PERSISTENT_CODE_SAVE (1) +#define MICROPY_COMP_CONST (0) +#endif + +// Unix-specific configuration of machine.mem*. +#define MICROPY_MACHINE_MEM_GET_READ_ADDR mod_machine_mem_get_addr +#define MICROPY_MACHINE_MEM_GET_WRITE_ADDR mod_machine_mem_get_addr + +#define MICROPY_FATFS_ENABLE_LFN (1) +#define MICROPY_FATFS_RPATH (2) +#define MICROPY_FATFS_MAX_SS (4096) +#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ + +#define MICROPY_ALLOC_PATH_MAX (PATH_MAX) + +// Ensure builtinimport.c works with -m. +#define MICROPY_MODULE_OVERRIDE_MAIN_IMPORT (1) + +// Don't default sys.argv because we do that in main. +#define MICROPY_PY_SYS_PATH_ARGV_DEFAULTS (0) + +#define MICROPY_PY_USOCKET_LISTEN_BACKLOG_DEFAULT (SOMAXCONN < 128 ? SOMAXCONN : 128) + +// Bare-metal ports don't have stderr. Printing debug to stderr may give tests +// which check stdout a chance to pass, etc. +extern const struct _mp_print_t mp_stderr_print; +#define MICROPY_DEBUG_PRINTER (&mp_stderr_print) +#define MICROPY_ERROR_PRINTER (&mp_stderr_print) + +// For the native emitter configure how to mark a region as executable. void mp_unix_alloc_exec(size_t min_size, void **ptr, size_t *size); void mp_unix_free_exec(void *ptr, size_t size); void mp_unix_mark_exec(void); @@ -260,8 +174,8 @@ void mp_unix_mark_exec(void); #define MICROPY_FORCE_PLAT_ALLOC_EXEC (1) #endif +// If enabled, configure how to seed random on init. #ifdef MICROPY_PY_URANDOM_SEED_INIT_FUNC -// Support for seeding the random module on import. #include void mp_hal_get_random(size_t n, void *buf); static inline unsigned long mp_urandom_seed_init(void) { @@ -276,10 +190,6 @@ static inline unsigned long mp_urandom_seed_init(void) { #define MICROPY_PLAT_DEV_MEM (1) #endif -// Assume that select() call, interrupted with a signal, and erroring -// with EINTR, updates remaining timeout value. -#define MICROPY_SELECT_REMAINING_TIME (1) - #ifdef __ANDROID__ #include #if __ANDROID_API__ < 4 @@ -289,18 +199,6 @@ static inline unsigned long mp_urandom_seed_init(void) { #endif #endif -#define MP_STATE_PORT MP_STATE_VM - -// We need to provide a declaration/definition of alloca() -// unless support for it is disabled. -#if !defined(MICROPY_NO_ALLOCA) || MICROPY_NO_ALLOCA == 0 -#if defined(__FreeBSD__) || defined(__NetBSD__) -#include -#else -#include -#endif -#endif - // From "man readdir": "Under glibc, programs can check for the availability // of the fields [in struct dirent] not defined in POSIX.1 by testing whether // the macros [...], _DIRENT_HAVE_D_TYPE are defined." @@ -320,11 +218,13 @@ static inline unsigned long mp_urandom_seed_init(void) { #include #endif +// If threading is enabled, configure the atomic section. #if MICROPY_PY_THREAD #define MICROPY_BEGIN_ATOMIC_SECTION() (mp_thread_unix_begin_atomic_section(), 0xffffffff) #define MICROPY_END_ATOMIC_SECTION(x) (void)x; mp_thread_unix_end_atomic_section() #endif +// In lieu of a WFI(), slow down polling from being a tight loop. #ifndef MICROPY_EVENT_POLL_HOOK #define MICROPY_EVENT_POLL_HOOK \ do { \ @@ -334,7 +234,6 @@ static inline unsigned long mp_urandom_seed_init(void) { } while (0); #endif +// Configure the implementation of machine.idle(). #include #define MICROPY_UNIX_MACHINE_IDLE sched_yield(); - -#endif // MICROPY_UNIX_MINIMAL diff --git a/ports/unix/variants/coverage/mpconfigvariant.h b/ports/unix/variants/coverage/mpconfigvariant.h index fb70d791ac..9857c66874 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.h +++ b/ports/unix/variants/coverage/mpconfigvariant.h @@ -30,6 +30,9 @@ // Set base feature level. #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EVERYTHING) +// Enable extra Unix features. +#include "../mpconfigvariant_common.h" + // Enable additional features. #define MICROPY_DEBUG_PARSE_RULE_NAME (1) #define MICROPY_GC_SPLIT_HEAP (1) @@ -45,11 +48,9 @@ #define MICROPY_PY_BUILTINS_RANGE_BINOP (1) #define MICROPY_PY_SYS_GETSIZEOF (1) #define MICROPY_PY_IO_BUFFEREDWRITER (1) -#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (mp_urandom_seed_init()) #define MICROPY_PY_URE_DEBUG (1) #define MICROPY_PY_URE_MATCH_GROUPS (1) #define MICROPY_PY_URE_MATCH_SPAN_START_END (1) #define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (1) -#define MICROPY_PY_UCRYPTOLIB (1) #define MICROPY_PY_UCRYPTOLIB_CTR (1) #define MICROPY_PY_MICROPYTHON_HEAP_LOCKED (1) diff --git a/ports/unix/variants/dev/mpconfigvariant.h b/ports/unix/variants/dev/mpconfigvariant.h deleted file mode 100644 index 2522f1861f..0000000000 --- a/ports/unix/variants/dev/mpconfigvariant.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 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. - */ - -// Set base feature level. -#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) - -// Enable some additional features. -#ifndef MICROPY_REPL_EMACS_WORDS_MOVE -#define MICROPY_REPL_EMACS_WORDS_MOVE (1) -#endif -#ifndef MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE -#define MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE (1) -#endif -#ifndef MICROPY_PY_SYS_SETTRACE -#define MICROPY_PY_SYS_SETTRACE (1) -#endif -#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (mp_urandom_seed_init()) diff --git a/ports/unix/variants/dev/mpconfigvariant.mk b/ports/unix/variants/dev/mpconfigvariant.mk deleted file mode 100644 index 058eda2f8d..0000000000 --- a/ports/unix/variants/dev/mpconfigvariant.mk +++ /dev/null @@ -1,8 +0,0 @@ -FROZEN_MANIFEST ?= $(VARIANT_DIR)/manifest.py - -MICROPY_ROM_TEXT_COMPRESSION = 1 -MICROPY_VFS_FAT ?= 1 -MICROPY_VFS_LFS1 ?= 1 -MICROPY_VFS_LFS2 ?= 1 - -MICROPY_PY_BLUETOOTH ?= 1 diff --git a/ports/unix/variants/minimal/mpconfigvariant.h b/ports/unix/variants/minimal/mpconfigvariant.h index d9d2a6c48e..6b107e7790 100644 --- a/ports/unix/variants/minimal/mpconfigvariant.h +++ b/ports/unix/variants/minimal/mpconfigvariant.h @@ -26,117 +26,44 @@ // options to control how MicroPython is built -// Prevent the rest of the default mpconfigport.h being used. -#define MICROPY_UNIX_MINIMAL (1) +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_MINIMUM) +// Disable native emitters. +#define MICROPY_EMIT_X86 (0) +#define MICROPY_EMIT_X64 (0) +#define MICROPY_EMIT_THUMB (0) +#define MICROPY_EMIT_ARM (0) + +// Tune the parser to use less RAM by default. #define MICROPY_ALLOC_QSTR_CHUNK_INIT (64) #define MICROPY_ALLOC_PARSE_RULE_INIT (8) #define MICROPY_ALLOC_PARSE_RULE_INC (8) #define MICROPY_ALLOC_PARSE_RESULT_INIT (8) #define MICROPY_ALLOC_PARSE_RESULT_INC (8) #define MICROPY_ALLOC_PARSE_CHUNK_INIT (64) -#define MICROPY_ALLOC_PATH_MAX (PATH_MAX) -#define MICROPY_ENABLE_GC (1) -#define MICROPY_ENABLE_FINALISER (1) -#define MICROPY_GC_ALLOC_THRESHOLD (0) -#define MICROPY_STACK_CHECK (0) -#define MICROPY_COMP_CONST (0) -#define MICROPY_MEM_STATS (0) -#define MICROPY_DEBUG_PRINTERS (0) -#define MICROPY_READER_POSIX (1) -#define MICROPY_READER_VFS (1) -#define MICROPY_HELPER_REPL (1) -#define MICROPY_HELPER_LEXER_UNIX (1) -#define MICROPY_ENABLE_SOURCE_LINE (0) -#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) -#define MICROPY_WARNINGS (0) -#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0) -#define MICROPY_KBD_EXCEPTION (1) -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) -#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) -#define MICROPY_STREAMS_NON_BLOCK (0) -#define MICROPY_OPT_COMPUTED_GOTO (0) -#define MICROPY_OPT_LOAD_ATTR_FAST_PATH (0) -#define MICROPY_OPT_MAP_LOOKUP_CACHE (0) -#define MICROPY_CAN_OVERRIDE_BUILTINS (0) -#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0) -#define MICROPY_VFS (1) -#define MICROPY_VFS_POSIX (1) -#define MICROPY_CPYTHON_COMPAT (0) -#define MICROPY_PY_BUILTINS_BYTEARRAY (0) -#define MICROPY_PY_BUILTINS_MEMORYVIEW (0) -#define MICROPY_PY_BUILTINS_COMPILE (0) -#define MICROPY_PY_BUILTINS_ENUMERATE (0) -#define MICROPY_PY_BUILTINS_FILTER (0) -#define MICROPY_PY_BUILTINS_FROZENSET (0) -#define MICROPY_PY_BUILTINS_REVERSED (0) -#define MICROPY_PY_BUILTINS_SET (0) -#define MICROPY_PY_BUILTINS_SLICE (0) -#define MICROPY_PY_BUILTINS_STR_COUNT (0) -#define MICROPY_PY_BUILTINS_STR_OP_MODULO (0) -#define MICROPY_PY_BUILTINS_STR_UNICODE (0) -#define MICROPY_PY_BUILTINS_PROPERTY (0) -#define MICROPY_PY_BUILTINS_MIN_MAX (0) -#define MICROPY_PY___FILE__ (0) -#define MICROPY_PY_MICROPYTHON_MEM_INFO (0) -#define MICROPY_PY_GC (0) -#define MICROPY_PY_GC_COLLECT_RETVAL (0) -#define MICROPY_PY_ARRAY (0) -#define MICROPY_PY_COLLECTIONS (0) -#define MICROPY_PY_MATH (0) -#define MICROPY_PY_CMATH (0) -#define MICROPY_PY_IO (0) -#define MICROPY_PY_STRUCT (0) -#define MICROPY_PY_SYS (1) -#define MICROPY_PY_SYS_EXIT (0) -#define MICROPY_PY_SYS_PLATFORM "linux" -#ifndef MICROPY_PY_SYS_PATH_DEFAULT -#define MICROPY_PY_SYS_PATH_DEFAULT ".frozen:~/.micropython/lib:/usr/lib/micropython" -#endif -#define MICROPY_PY_SYS_MAXSIZE (0) -#define MICROPY_PY_SYS_STDFILES (0) -#define MICROPY_PY_CMATH (0) -#define MICROPY_PY_UCTYPES (0) -#define MICROPY_PY_UTIME (0) -#define MICROPY_PY_UZLIB (0) -#define MICROPY_PY_UJSON (0) -#define MICROPY_PY_UOS (1) -#define MICROPY_PY_URE (0) -#define MICROPY_PY_UHEAPQ (0) -#define MICROPY_PY_UHASHLIB (0) -#define MICROPY_PY_UBINASCII (0) -////////////////////////////////////////// -// Do not change anything beyond this line -////////////////////////////////////////// +// Enable features that are not enabled by default with the minimum config. +#define MICROPY_COMP_CONST_FOLDING (1) +#define MICROPY_COMP_CONST_LITERAL (1) +#define MICROPY_COMP_CONST_TUPLE (1) +#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1) +#define MICROPY_ENABLE_COMPILER (1) +#define MICROPY_ENABLE_EXTERNAL_IMPORT (1) +#define MICROPY_FULL_CHECKS (1) +#define MICROPY_HELPER_REPL (1) +#define MICROPY_KBD_EXCEPTION (1) +#define MICROPY_MODULE_GETATTR (1) +#define MICROPY_MULTIPLE_INHERITANCE (1) +#define MICROPY_PY_ASSIGN_EXPR (1) +#define MICROPY_PY_ASYNC_AWAIT (1) +#define MICROPY_PY_ATTRTUPLE (1) +#define MICROPY_PY_BUILTINS_DICT_FROMKEYS (1) +#define MICROPY_PY_BUILTINS_RANGE_ATTRS (1) +#define MICROPY_PY_GENERATOR_PEND_THROW (1) -#if !(defined(MICROPY_GCREGS_SETJMP) || defined(__x86_64__) || defined(__i386__) || defined(__thumb2__) || defined(__thumb__) || defined(__arm__)) -// Fall back to setjmp() implementation for discovery of GC pointers in registers. -#define MICROPY_GCREGS_SETJMP (1) -#endif +// Enable just the sys and os built-in modules. +#define MICROPY_PY_SYS (1) +#define MICROPY_PY_UOS (1) -// type definitions for the specific machine - -#ifdef __LP64__ -typedef long mp_int_t; // must be pointer size -typedef unsigned long mp_uint_t; // must be pointer size -#else -// These are definitions for machines where sizeof(int) == sizeof(void*), -// regardless for actual size. -typedef int mp_int_t; // must be pointer size -typedef unsigned int mp_uint_t; // must be pointer size -#endif - -// Cannot include , as it may lead to symbol name clashes -#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) -typedef long long mp_off_t; -#else -typedef long mp_off_t; -#endif - -// We need to provide a declaration/definition of alloca() -#ifdef __FreeBSD__ -#include -#else -#include -#endif +// The minimum sets this to 1 to save flash. +#define MICROPY_QSTR_BYTES_IN_HASH (2) diff --git a/ports/unix/variants/mpconfigvariant_common.h b/ports/unix/variants/mpconfigvariant_common.h new file mode 100644 index 0000000000..1128f21d22 --- /dev/null +++ b/ports/unix/variants/mpconfigvariant_common.h @@ -0,0 +1,124 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Jim Mussared + * + * 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. + */ + +// This file enables and configures features common to all variants +// other than "minimal". + +// Send raise KeyboardInterrupt directly from the signal handler rather than +// scheduling it into the VM. +#define MICROPY_ASYNC_KBD_INTR (1) + +// Enable helpers for printing debugging information. +#ifndef MICROPY_DEBUG_PRINTERS +#define MICROPY_DEBUG_PRINTERS (1) +#endif + +// Enable floating point by default. +#ifndef MICROPY_FLOAT_IMPL +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) +#endif + +// Enable arbritrary precision long-int by default. +#ifndef MICROPY_LONGINT_IMPL +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) +#endif + +// Enable use of C libraries that need read/write/lseek/fsync, e.g. axtls. +#define MICROPY_STREAMS_POSIX_API (1) + +// REPL conveniences. +#define MICROPY_REPL_EMACS_WORDS_MOVE (1) +#define MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE (1) +#define MICROPY_USE_READLINE_HISTORY (1) +#ifndef MICROPY_READLINE_HISTORY_SIZE +#define MICROPY_READLINE_HISTORY_SIZE (50) +#endif + +// Seed random on import. +#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (mp_urandom_seed_init()) + +// Allow exception details in low-memory conditions. +#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) +#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256) + +// Allow loading of .mpy files. +#define MICROPY_PERSISTENT_CODE_LOAD (1) + +// Extra memory debugging. +#define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1) +#define MICROPY_MEM_STATS (1) + +// Enable a small performance boost for the VM. +#define MICROPY_OPT_COMPUTED_GOTO (1) + +// Return number of collected objects from gc.collect(). +#define MICROPY_PY_GC_COLLECT_RETVAL (1) + +// Enable detailed error messages and warnings. +#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED) +#define MICROPY_WARNINGS (1) +#define MICROPY_PY_STR_BYTES_CMP_WARN (1) + +// Configure the "sys" module with features not usually enabled on bare-metal. +#define MICROPY_PY_SYS_ATEXIT (1) +#define MICROPY_PY_SYS_EXC_INFO (1) + +// Configure the "os" module with extra unix features. +#define MICROPY_PY_UOS_INCLUDEFILE "ports/unix/moduos.c" +#define MICROPY_PY_UOS_ERRNO (1) +#define MICROPY_PY_UOS_GETENV_PUTENV_UNSETENV (1) +#define MICROPY_PY_UOS_SEP (1) +#define MICROPY_PY_UOS_SYSTEM (1) +#define MICROPY_PY_UOS_URANDOM (1) + +// Enable the unix-specific "time" module. +#define MICROPY_PY_UTIME (1) +#define MICROPY_PY_UTIME_MP_HAL (1) + +// Enable the utimeq module used by the previous (v2) version of uasyncio. +#define MICROPY_PY_UTIMEQ (1) + +#if MICROPY_PY_USSL +#define MICROPY_PY_UHASHLIB_MD5 (1) +#define MICROPY_PY_UHASHLIB_SHA1 (1) +#define MICROPY_PY_UCRYPTOLIB (1) +#endif + +// Use the posix implementation of the "select" module (unless the variant +// specifically asks for the MicroPython version). +#ifndef MICROPY_PY_USELECT +#define MICROPY_PY_USELECT (0) +#endif +#ifndef MICROPY_PY_USELECT_POSIX +#define MICROPY_PY_USELECT_POSIX (!MICROPY_PY_USELECT) +#endif + +// Enable the "websocket" module. +#define MICROPY_PY_UWEBSOCKET (1) + +// Enable the "machine" module, mostly for machine.mem*. +#define MICROPY_PY_MACHINE (1) +#define MICROPY_PY_MACHINE_PULSE (1) diff --git a/ports/unix/variants/nanbox/mpconfigvariant.h b/ports/unix/variants/nanbox/mpconfigvariant.h index f827158fb7..7b13b7dc6c 100644 --- a/ports/unix/variants/nanbox/mpconfigvariant.h +++ b/ports/unix/variants/nanbox/mpconfigvariant.h @@ -28,6 +28,11 @@ // continues to build (i.e. catches usage of mp_obj_t that don't work with // this representation). +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) + +// Enable extra Unix features. +#include "../mpconfigvariant_common.h" + // select nan-boxing object model #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_D) diff --git a/ports/unix/variants/dev/manifest.py b/ports/unix/variants/standard/manifest.py similarity index 100% rename from ports/unix/variants/dev/manifest.py rename to ports/unix/variants/standard/manifest.py diff --git a/ports/unix/variants/standard/mpconfigvariant.h b/ports/unix/variants/standard/mpconfigvariant.h index 31618652e9..75201e9abc 100644 --- a/ports/unix/variants/standard/mpconfigvariant.h +++ b/ports/unix/variants/standard/mpconfigvariant.h @@ -27,18 +27,5 @@ // Set base feature level. #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) -// Disable some features that come enabled by default with the feature level. -#define MICROPY_OPT_MPZ_BITWISE (0) -#define MICROPY_OPT_MATH_FACTORIAL (0) -#define MICROPY_MODULE_ATTR_DELEGATION (0) -#define MICROPY_MODULE_BUILTIN_INIT (0) -#define MICROPY_ENABLE_SCHEDULER (0) -#define MICROPY_PY_BUILTINS_EXECFILE (0) -#define MICROPY_PY_MATH_CONSTANTS (0) -#define MICROPY_PY_MATH_FACTORIAL (0) -#define MICROPY_PY_SYS_PS1_PS2 (0) -#define MICROPY_PY_SYS_STDIO_BUFFER (0) -#define MICROPY_PY_UASYNCIO (0) -#define MICROPY_PY_URE_SUB (0) -#define MICROPY_PY_URANDOM_EXTRA_FUNCS (0) -#define MICROPY_PY_FRAMEBUF (0) +// Enable extra Unix features. +#include "../mpconfigvariant_common.h" diff --git a/ports/unix/variants/standard/mpconfigvariant.mk b/ports/unix/variants/standard/mpconfigvariant.mk index def7987d8d..929a1aec11 100644 --- a/ports/unix/variants/standard/mpconfigvariant.mk +++ b/ports/unix/variants/standard/mpconfigvariant.mk @@ -1 +1,8 @@ # This is the default variant when you `make` the Unix port. + +FROZEN_MANIFEST ?= $(VARIANT_DIR)/manifest.py + +MICROPY_ROM_TEXT_COMPRESSION = 1 +MICROPY_VFS_FAT ?= 1 +MICROPY_VFS_LFS1 ?= 1 +MICROPY_VFS_LFS2 ?= 1 diff --git a/tools/ci.sh b/tools/ci.sh index 8f1d729a13..9c670b7be5 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -454,14 +454,6 @@ function ci_unix_standard_run_tests { ci_unix_run_tests_full_helper standard } -function ci_unix_dev_build { - ci_unix_build_helper VARIANT=dev -} - -function ci_unix_dev_run_tests { - ci_unix_run_tests_helper VARIANT=dev -} - function ci_unix_coverage_setup { sudo pip3 install setuptools sudo pip3 install pyelftools @@ -602,8 +594,6 @@ function ci_unix_macos_build { #make ${MAKEOPTS} -C ports/unix deplibs make ${MAKEOPTS} -C ports/unix # check for additional compiler errors/warnings - make ${MAKEOPTS} -C ports/unix VARIANT=dev submodules - make ${MAKEOPTS} -C ports/unix VARIANT=dev make ${MAKEOPTS} -C ports/unix VARIANT=coverage submodules make ${MAKEOPTS} -C ports/unix VARIANT=coverage } From 3e5b1be8cad9cc38af9af30f5e7fa3582f65ffd9 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 16 Aug 2022 01:41:03 +1000 Subject: [PATCH 0400/1041] py/mpconfig: Add "everything" features from unix coverage. Signed-off-by: Jim Mussared --- .../unix/variants/coverage/mpconfigvariant.h | 20 +++---------- py/mpconfig.h | 28 +++++++++---------- 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/ports/unix/variants/coverage/mpconfigvariant.h b/ports/unix/variants/coverage/mpconfigvariant.h index 9857c66874..6107a4a556 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.h +++ b/ports/unix/variants/coverage/mpconfigvariant.h @@ -33,24 +33,12 @@ // Enable extra Unix features. #include "../mpconfigvariant_common.h" -// Enable additional features. -#define MICROPY_DEBUG_PARSE_RULE_NAME (1) +// Enable testing of split heap. #define MICROPY_GC_SPLIT_HEAP (1) #define MICROPY_GC_SPLIT_HEAP_N_HEAPS (4) + +// Enable additional features. +#define MICROPY_DEBUG_PARSE_RULE_NAME (1) #define MICROPY_TRACKED_ALLOC (1) -#define MICROPY_FLOAT_HIGH_QUALITY_HASH (1) -#define MICROPY_REPL_EMACS_WORDS_MOVE (1) -#define MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE (1) #define MICROPY_WARNINGS_CATEGORY (1) -#define MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS (1) -#define MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE (1) -#define MICROPY_PY_BUILTINS_NEXT2 (1) -#define MICROPY_PY_BUILTINS_RANGE_BINOP (1) -#define MICROPY_PY_SYS_GETSIZEOF (1) -#define MICROPY_PY_IO_BUFFEREDWRITER (1) -#define MICROPY_PY_URE_DEBUG (1) -#define MICROPY_PY_URE_MATCH_GROUPS (1) -#define MICROPY_PY_URE_MATCH_SPAN_START_END (1) -#define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (1) #define MICROPY_PY_UCRYPTOLIB_CTR (1) -#define MICROPY_PY_MICROPYTHON_HEAP_LOCKED (1) diff --git a/py/mpconfig.h b/py/mpconfig.h index 5da7e453ec..698d264d2e 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -683,7 +683,7 @@ // This adds Alt+F, Alt+B, Alt+D and Alt+Backspace for forward-word, backward-word, forward-kill-word // and backward-kill-word, respectively. #ifndef MICROPY_REPL_EMACS_WORDS_MOVE -#define MICROPY_REPL_EMACS_WORDS_MOVE (0) +#define MICROPY_REPL_EMACS_WORDS_MOVE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to include extra convenience keys for word movement/kill in readline REPL. @@ -691,7 +691,7 @@ // respectively. Ctrl+Delete is not implemented because it's a very different escape sequence. // Depends on MICROPY_REPL_EMACS_WORDS_MOVE. #ifndef MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE -#define MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE (0) +#define MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to implement auto-indent in REPL @@ -802,7 +802,7 @@ typedef double mp_float_t; // Whether to provide a high-quality hash for float and complex numbers. // Otherwise the default is a very simple but correct hashing function. #ifndef MICROPY_FLOAT_HIGH_QUALITY_HASH -#define MICROPY_FLOAT_HIGH_QUALITY_HASH (0) +#define MICROPY_FLOAT_HIGH_QUALITY_HASH (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Enable features which improve CPython compatibility @@ -1054,7 +1054,7 @@ typedef double mp_float_t; // Whether to support memoryview.itemsize attribute #ifndef MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE -#define MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE (0) +#define MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to support set object @@ -1099,12 +1099,12 @@ typedef double mp_float_t; // the same object will compare as not-equal. With it enabled the semantics // match CPython and ranges are equal if they yield the same sequence of items. #ifndef MICROPY_PY_BUILTINS_RANGE_BINOP -#define MICROPY_PY_BUILTINS_RANGE_BINOP (0) +#define MICROPY_PY_BUILTINS_RANGE_BINOP (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Support for callling next() with second argument #ifndef MICROPY_PY_BUILTINS_NEXT2 -#define MICROPY_PY_BUILTINS_NEXT2 (0) +#define MICROPY_PY_BUILTINS_NEXT2 (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to support rounding of integers (incl bignum); eg round(123,-1)=120 @@ -1124,7 +1124,7 @@ typedef double mp_float_t; // Whether to support all inplace arithmetic operarion methods // (__imul__, etc.) #ifndef MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS -#define MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS (0) +#define MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to support reverse arithmetic operarion methods @@ -1219,7 +1219,7 @@ typedef double mp_float_t; // Whether to provide the "micropython.heap_locked" function #ifndef MICROPY_PY_MICROPYTHON_HEAP_LOCKED -#define MICROPY_PY_MICROPYTHON_HEAP_LOCKED (0) +#define MICROPY_PY_MICROPYTHON_HEAP_LOCKED (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to provide "array" module. Note that large chunk of the @@ -1258,7 +1258,7 @@ typedef double mp_float_t; // Whether to provide the _asdict function for namedtuple #ifndef MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT -#define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (0) +#define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to provide "math" module @@ -1338,7 +1338,7 @@ typedef double mp_float_t; // Whether to provide "io.BufferedWriter" class #ifndef MICROPY_PY_IO_BUFFEREDWRITER -#define MICROPY_PY_IO_BUFFEREDWRITER (0) +#define MICROPY_PY_IO_BUFFEREDWRITER (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to provide "struct" module @@ -1394,7 +1394,7 @@ typedef double mp_float_t; // Whether to provide "sys.getsizeof" function #ifndef MICROPY_PY_SYS_GETSIZEOF -#define MICROPY_PY_SYS_GETSIZEOF (0) +#define MICROPY_PY_SYS_GETSIZEOF (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif // Whether to provide sys.{stdin,stdout,stderr} objects @@ -1516,15 +1516,15 @@ typedef double mp_float_t; #endif #ifndef MICROPY_PY_URE_DEBUG -#define MICROPY_PY_URE_DEBUG (0) +#define MICROPY_PY_URE_DEBUG (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif #ifndef MICROPY_PY_URE_MATCH_GROUPS -#define MICROPY_PY_URE_MATCH_GROUPS (0) +#define MICROPY_PY_URE_MATCH_GROUPS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif #ifndef MICROPY_PY_URE_MATCH_SPAN_START_END -#define MICROPY_PY_URE_MATCH_SPAN_START_END (0) +#define MICROPY_PY_URE_MATCH_SPAN_START_END (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif #ifndef MICROPY_PY_URE_SUB From 51b054dd66fcd4f26f965910ea25de85a2ea01a3 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 16 Aug 2022 01:56:25 +1000 Subject: [PATCH 0401/1041] unix: Refactor mpconfigvariant.mk. All variants (except minimal) enable text compression and fat/lfs, so move them to the common mpconfigport.mk. Signed-off-by: Jim Mussared --- ports/unix/mpconfigport.mk | 6 ++++++ ports/unix/variants/coverage/mpconfigvariant.mk | 5 ----- ports/unix/variants/minimal/mpconfigvariant.mk | 5 ++++- ports/unix/variants/standard/mpconfigvariant.mk | 5 ----- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/ports/unix/mpconfigport.mk b/ports/unix/mpconfigport.mk index fe9eec18dc..ce6183c133 100644 --- a/ports/unix/mpconfigport.mk +++ b/ports/unix/mpconfigport.mk @@ -38,3 +38,9 @@ MICROPY_PY_JNI = 0 # Avoid using system libraries, use copies bundled with MicroPython # as submodules (currently affects only libffi). MICROPY_STANDALONE = 0 + +MICROPY_ROM_TEXT_COMPRESSION = 1 + +MICROPY_VFS_FAT = 1 +MICROPY_VFS_LFS1 = 1 +MICROPY_VFS_LFS2 = 1 diff --git a/ports/unix/variants/coverage/mpconfigvariant.mk b/ports/unix/variants/coverage/mpconfigvariant.mk index bbbb0432b5..cc37ba1582 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.mk +++ b/ports/unix/variants/coverage/mpconfigvariant.mk @@ -12,10 +12,5 @@ LDFLAGS += -fprofile-arcs -ftest-coverage FROZEN_MANIFEST ?= $(VARIANT_DIR)/manifest.py USER_C_MODULES = $(TOP)/examples/usercmodule -MICROPY_ROM_TEXT_COMPRESSION = 1 -MICROPY_VFS_FAT = 1 -MICROPY_VFS_LFS1 = 1 -MICROPY_VFS_LFS2 = 1 - SRC_C += coverage.c SRC_CXX += coveragecpp.cpp diff --git a/ports/unix/variants/minimal/mpconfigvariant.mk b/ports/unix/variants/minimal/mpconfigvariant.mk index 9d4ddab956..d5c2a52e9a 100644 --- a/ports/unix/variants/minimal/mpconfigvariant.mk +++ b/ports/unix/variants/minimal/mpconfigvariant.mk @@ -2,7 +2,6 @@ FROZEN_MANIFEST = -MICROPY_ROM_TEXT_COMPRESSION = 1 MICROPY_PY_BTREE = 0 MICROPY_PY_FFI = 0 MICROPY_PY_SOCKET = 0 @@ -10,3 +9,7 @@ MICROPY_PY_THREAD = 0 MICROPY_PY_TERMIOS = 0 MICROPY_PY_USSL = 0 MICROPY_USE_READLINE = 0 + +MICROPY_VFS_FAT = 0 +MICROPY_VFS_LFS1 = 0 +MICROPY_VFS_LFS2 = 0 diff --git a/ports/unix/variants/standard/mpconfigvariant.mk b/ports/unix/variants/standard/mpconfigvariant.mk index 929a1aec11..c91db1aa10 100644 --- a/ports/unix/variants/standard/mpconfigvariant.mk +++ b/ports/unix/variants/standard/mpconfigvariant.mk @@ -1,8 +1,3 @@ # This is the default variant when you `make` the Unix port. FROZEN_MANIFEST ?= $(VARIANT_DIR)/manifest.py - -MICROPY_ROM_TEXT_COMPRESSION = 1 -MICROPY_VFS_FAT ?= 1 -MICROPY_VFS_LFS1 ?= 1 -MICROPY_VFS_LFS2 ?= 1 From 6c376a93067230b3b9d7d4adc1b804df18b12dcd Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 13 Sep 2022 16:40:34 +1000 Subject: [PATCH 0402/1041] tests/extmod/uasyncio_heaplock.py: Force SKIP on stackless. This is a latent issue that wasn't caught by CI because there was no configuration that had both stackless+uasyncio. The previous check to skip with stackless builds only worked when the bytecode emitter was used by default. Force the check to use the bytecode emitter. Signed-off-by: Jim Mussared --- tests/extmod/uasyncio_heaplock.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/extmod/uasyncio_heaplock.py b/tests/extmod/uasyncio_heaplock.py index a6b4a0819c..9c9487357a 100644 --- a/tests/extmod/uasyncio_heaplock.py +++ b/tests/extmod/uasyncio_heaplock.py @@ -8,11 +8,19 @@ import micropython # strict stackless builds can't call functions without allocating a frame on the heap try: - f = lambda: 0 + # force bytecode (in case we're running with emit=native) and verify + # that bytecode-calling-bytecode doesn't allocate + @micropython.bytecode + def f(x): + x and f(x - 1) + micropython.heap_lock() - f() + f(1) micropython.heap_unlock() except RuntimeError: + # RuntimeError (max recursion depth) not MemoryError because effectively + # the recursion depth is at the limit while the heap is locked with + # stackless print("SKIP") raise SystemExit From 65ce7d7ade17f7f9ac2c5fbb75ad5d28078f8490 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 17 Jul 2022 08:43:02 +0200 Subject: [PATCH 0403/1041] mimxrt/machine_uart: Drop a few commented lines about TX ring buffer. --- ports/mimxrt/machine_uart.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ports/mimxrt/machine_uart.c b/ports/mimxrt/machine_uart.c index 302244f722..1b0c063334 100644 --- a/ports/mimxrt/machine_uart.c +++ b/ports/mimxrt/machine_uart.c @@ -244,12 +244,6 @@ STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args LPUART_EnableTx(self->lpuart, false); self->lpuart->STAT |= 1 << LPUART_STAT_BRK13_SHIFT; LPUART_EnableTx(self->lpuart, true); - - // Allocate the TX ring buffer. Not used yet, but maybe later. - - // ringbuf_alloc(&(self->write_buffer), txbuf_len + 1); - // MP_STATE_PORT(rp2_uart_tx_buffer[uart_id]) = self->write_buffer.buf; - } return MP_OBJ_FROM_PTR(self); From 8e542251405d780f7aa0d6c9abaa30282dd360d5 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 25 Apr 2022 13:56:45 +0200 Subject: [PATCH 0404/1041] mimxrt: Format the firmware image to match the new teensy loader. The new teensy loader keeps the file system under certain conditions: - The file size is properly set in the file header. - The header version is 4.3 These changes are implemented here, requiring a backport of fsl_flexspi_nor_boot.c. There is still a problem with the command line version of the teensy loader, which fails on the first attempt. At the second attempt it works. The GUI version of the teensy loader is fine. --- ports/mimxrt/Makefile | 2 +- ports/mimxrt/boards/common.ld | 7 +- ports/mimxrt/hal/fsl_flexspi_nor_boot.c | 53 +++++++++++ ports/mimxrt/hal/fsl_flexspi_nor_boot.h | 114 ++++++++++++++++++++++++ 4 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 ports/mimxrt/hal/fsl_flexspi_nor_boot.c create mode 100644 ports/mimxrt/hal/fsl_flexspi_nor_boot.h diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index 6312ecdd8f..6a18879ac5 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -128,7 +128,7 @@ SRC_HAL_IMX_C += \ $(MCU_DIR)/drivers/fsl_trng.c \ $(MCU_DIR)/drivers/fsl_wdog.c \ $(MCU_DIR)/system_$(MCU_SERIES).c \ - $(MCU_DIR)/xip/fsl_flexspi_nor_boot.c \ + hal/fsl_flexspi_nor_boot.c \ ifeq ($(MICROPY_HW_SDRAM_AVAIL),1) SRC_HAL_IMX_C += $(MCU_DIR)/drivers/fsl_semc.c diff --git a/ports/mimxrt/boards/common.ld b/ports/mimxrt/boards/common.ld index fbc99da3dd..3aaa14c83b 100644 --- a/ports/mimxrt/boards/common.ld +++ b/ports/mimxrt/boards/common.ld @@ -207,7 +207,7 @@ SECTIONS __ram_function_end__ = .; } > m_itcm - __NDATA_ROM = __DATA_ROM + (__ram_function_end__ - __data_start__); + __NDATA_ROM = __RAM_FUNCTIONS_ROM + (__ram_function_end__ - __ram_function_start__); .ncache.init : AT(__NDATA_ROM) { __noncachedata_start__ = .; /* create a global symbol at ncache data start */ @@ -223,7 +223,8 @@ SECTIONS __noncachedata_end__ = .; /* define a global symbol at ncache data end */ } > m_dtcm - __DATA_END = __NDATA_ROM + (__noncachedata_init_end__ - __noncachedata_start__); + __DATA_END = __NDATA_ROM + (__noncachedata_end__ - __noncachedata_start__); + __FLASH_DATA_END = __NDATA_ROM + (__noncachedata_init_end__ - __noncachedata_start__); text_end = ORIGIN(m_text) + LENGTH(m_text); ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data") @@ -262,6 +263,8 @@ SECTIONS . += STACK_SIZE; } > m_dtcm + _flashimagelen = __FLASH_DATA_END - flash_start; + /* Initializes stack on the end of block */ __StackTop = ORIGIN(m_dtcm) + LENGTH(m_dtcm); __StackLimit = __StackTop - STACK_SIZE; diff --git a/ports/mimxrt/hal/fsl_flexspi_nor_boot.c b/ports/mimxrt/hal/fsl_flexspi_nor_boot.c new file mode 100644 index 0000000000..5786f37e7a --- /dev/null +++ b/ports/mimxrt/hal/fsl_flexspi_nor_boot.c @@ -0,0 +1,53 @@ +/* + * Copyright 2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_flexspi_nor_boot.h" +extern unsigned long _flashimagelen; +extern unsigned long __etext; + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.xip_device" +#endif + +#if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1) +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) || defined(__GNUC__) +__attribute__((section(".boot_hdr.ivt"))) +#elif defined(__ICCARM__) +#pragma location=".boot_hdr.ivt" +#endif + + +/************************************* + * IVT Data + *************************************/ +const ivt image_vector_table = { + IVT_HEADER, /* IVT Header */ + IMAGE_ENTRY_ADDRESS, /* Image Entry Function */ + IVT_RSVD, /* Reserved = 0 */ + (uint32_t)DCD_ADDRESS, /* Address where DCD information is stored */ + (uint32_t)BOOT_DATA_ADDRESS, /* Address where BOOT Data Structure is stored */ + (uint32_t)&image_vector_table, /* Pointer to IVT Self (absolute address */ + (uint32_t)CSF_ADDRESS, /* Address where CSF file is stored */ + IVT_RSVD /* Reserved = 0 */ +}; + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) || defined(__GNUC__) +__attribute__((section(".boot_hdr.boot_data"))) +#elif defined(__ICCARM__) +#pragma location=".boot_hdr.boot_data" +#endif +/************************************* + * Boot Data + *************************************/ +const BOOT_DATA_T boot_data = { + FLASH_BASE, /* boot start location */ + (uint32_t)&_flashimagelen, /* Image size */ + PLUGIN_FLAG, /* Plugin flag*/ + 0xFFFFFFFF /* empty - extra data word */ +}; +#endif diff --git a/ports/mimxrt/hal/fsl_flexspi_nor_boot.h b/ports/mimxrt/hal/fsl_flexspi_nor_boot.h new file mode 100644 index 0000000000..fbb8a574f3 --- /dev/null +++ b/ports/mimxrt/hal/fsl_flexspi_nor_boot.h @@ -0,0 +1,114 @@ +/* + * Copyright 2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __FLEXSPI_NOR_BOOT_H__ +#define __FLEXSPI_NOR_BOOT_H__ + +#include +#include "board.h" + +/*! @name Driver version */ +/*@{*/ +/*! @brief XIP_DEVICE driver version 2.0.0. */ +#define FSL_XIP_DEVICE_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*@}*/ + +/************************************* + * IVT Data + *************************************/ +typedef struct _ivt_ { + /** @ref hdr with tag #HAB_TAG_IVT, length and HAB version fields + * (see @ref data) + */ + uint32_t hdr; + /** Absolute address of the first instruction to execute from the + * image + */ + uint32_t entry; + /** Reserved in this version of HAB: should be NULL. */ + uint32_t reserved1; + /** Absolute address of the image DCD: may be NULL. */ + uint32_t dcd; + /** Absolute address of the Boot Data: may be NULL, but not interpreted + * any further by HAB + */ + uint32_t boot_data; + /** Absolute address of the IVT.*/ + uint32_t self; + /** Absolute address of the image CSF.*/ + uint32_t csf; + /** Reserved in this version of HAB: should be zero. */ + uint32_t reserved2; +} ivt; + +#define IVT_MAJOR_VERSION 0x4 +#define IVT_MAJOR_VERSION_SHIFT 0x4 +#define IVT_MAJOR_VERSION_MASK 0xF +#define IVT_MINOR_VERSION 0x3 +#define IVT_MINOR_VERSION_SHIFT 0x0 +#define IVT_MINOR_VERSION_MASK 0xF + +#define IVT_VERSION(major, minor) \ + ((((major) & IVT_MAJOR_VERSION_MASK) << IVT_MAJOR_VERSION_SHIFT) | \ + (((minor) & IVT_MINOR_VERSION_MASK) << IVT_MINOR_VERSION_SHIFT)) + +/* IVT header */ +#define IVT_TAG_HEADER 0xD1 /**< Image Vector Table */ +#define IVT_SIZE 0x2000 +#define IVT_PAR IVT_VERSION(IVT_MAJOR_VERSION, IVT_MINOR_VERSION) +#define IVT_HEADER (IVT_TAG_HEADER | (IVT_SIZE << 8) | (IVT_PAR << 24)) + +/* Set resume entry */ +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +extern uint32_t __Vectors[]; +extern uint32_t Image$$RW_m_config_text$$Base[]; +#define IMAGE_ENTRY_ADDRESS ((uint32_t)__Vectors) +#define FLASH_BASE ((uint32_t)Image$$RW_m_config_text$$Base) +#elif defined(__MCUXPRESSO) +extern uint32_t __Vectors[]; +extern uint32_t __boot_hdr_start__[]; +#define IMAGE_ENTRY_ADDRESS ((uint32_t)__Vectors) +#define FLASH_BASE ((uint32_t)__boot_hdr_start__) +#elif defined(__ICCARM__) +extern uint32_t __VECTOR_TABLE[]; +extern uint32_t m_boot_hdr_conf_start[]; +#define IMAGE_ENTRY_ADDRESS ((uint32_t)__VECTOR_TABLE) +#define FLASH_BASE ((uint32_t)m_boot_hdr_conf_start) +#elif defined(__GNUC__) +extern uint32_t __VECTOR_TABLE[]; +extern uint32_t __FLASH_BASE[]; +#define IMAGE_ENTRY_ADDRESS ((uint32_t)__VECTOR_TABLE) +#define FLASH_BASE ((uint32_t)__FLASH_BASE) +#endif + +#define DCD_ADDRESS dcd_data +#define BOOT_DATA_ADDRESS &boot_data +#define CSF_ADDRESS 0 +#define IVT_RSVD (uint32_t)(0x00000000) + +/************************************* + * Boot Data + *************************************/ +typedef struct _boot_data_ { + uint32_t start; /* boot start location */ + uint32_t size; /* size */ + uint32_t plugin; /* plugin flag - 1 if downloaded application is plugin */ + uint32_t placeholder; /* placehoder to make even 0x10 size */ +}BOOT_DATA_T; + +#if defined(BOARD_FLASH_SIZE) +#define FLASH_SIZE BOARD_FLASH_SIZE +#else +#error "Please define macro BOARD_FLASH_SIZE" +#endif +#define PLUGIN_FLAG (uint32_t)0 + +/* External Variables */ +const BOOT_DATA_T boot_data; +extern const uint8_t dcd_data[]; + +#endif /* __FLEXSPI_NOR_BOOT_H__ */ From 0f048a5a2a4cb239784cd152c9cd3fa0deb86db7 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 31 Jul 2022 11:09:57 +0200 Subject: [PATCH 0405/1041] mimxrt/machine_spi: Allow a setting of -1 for cs in the constructor. In that case, no Pin will be configured for the CS signal, even if it is internally still generated. That setting allows to use any pin for CS, which then must be controlled by the Python script. Also make the default cs=-1 to match other ports (software CS). --- docs/mimxrt/pinout.rst | 3 ++- docs/mimxrt/quickref.rst | 8 +++++++- ports/mimxrt/machine_spi.c | 13 ++++++++----- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/docs/mimxrt/pinout.rst b/docs/mimxrt/pinout.rst index b82c153fc3..ef53fa63bf 100644 --- a/docs/mimxrt/pinout.rst +++ b/docs/mimxrt/pinout.rst @@ -322,7 +322,8 @@ Olimex RT1010Py - CS0/-/SDO/SDI/SCK SDCARD wi Seeed ARCH MIX J4_12/-/J4_14/J4_13/J4_15 J3_09/J3_05/J3_08_J3_11 ================= ========================= ======================= =============== -Pins denoted with (*) are by default not wired at the board. +Pins denoted with (*) are by default not wired at the board. The CS0 and CS1 signals +are enabled with the keyword option cs=0 or cs=1 of the SPI object constructor. .. _mimxrt_i2c_pinout: diff --git a/docs/mimxrt/quickref.rst b/docs/mimxrt/quickref.rst index 0a14c632aa..c75fe60c8d 100644 --- a/docs/mimxrt/quickref.rst +++ b/docs/mimxrt/quickref.rst @@ -301,13 +301,19 @@ There are up to four hardware SPI channels that allow faster transmission rates (up to 30Mhz). Hardware SPI is accessed via the :ref:`machine.SPI ` class and has the same methods as software SPI above:: - from machine import SPI + from machine import SPI, Pin spi = SPI(0, 10000000) + cs_pin = Pin(6, Pin.OUT, value=1) + cs_pin(0) spi.write('Hello World') + cs_pin(1) For the assignment of Pins to SPI signals, refer to :ref:`Hardware SPI pinout `. +The keyword option cs=n can be used to enable the cs pin 0 or 1 for an automatic cs signal. The +default is cs=-1. Using cs=-1 the automatic cs signal is not created. +In that case, cs has to be set by the script. Clearing that assignment requires a power cycle. Notes: diff --git a/ports/mimxrt/machine_spi.c b/ports/mimxrt/machine_spi.c index 805ed9a0ac..32bc77c34d 100644 --- a/ports/mimxrt/machine_spi.c +++ b/ports/mimxrt/machine_spi.c @@ -77,7 +77,7 @@ static const iomux_table_t iomux_table[] = { IOMUX_TABLE_SPI }; -bool lpspi_set_iomux(int8_t spi, uint8_t drive, uint8_t cs) { +bool lpspi_set_iomux(int8_t spi, uint8_t drive, int8_t cs) { int index = (spi - 1) * 5; if (SCK.muxRegister != 0) { @@ -93,7 +93,7 @@ bool lpspi_set_iomux(int8_t spi, uint8_t drive, uint8_t cs) { IOMUXC_SetPinMux(CS1.muxRegister, CS1.muxMode, CS1.inputRegister, CS1.inputDaisy, CS1.configRegister, 0U); IOMUXC_SetPinConfig(CS1.muxRegister, CS1.muxMode, CS1.inputRegister, CS1.inputDaisy, CS1.configRegister, pin_generate_config(PIN_PULL_UP_100K, PIN_MODE_OUT, drive, CS1.configRegister)); - } else { + } else if (cs != -1) { mp_raise_ValueError(MP_ERROR_TEXT("The chosen CS is not available")); } @@ -131,7 +131,7 @@ mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_SPI_FIRSTBIT} }, { MP_QSTR_gap_ns, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_drive, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_SPI_DRIVE} }, - { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, }; // Parse the arguments. @@ -173,8 +173,11 @@ mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n } self->master_config->lastSckToPcsDelayInNanoSec = self->master_config->betweenTransferDelayInNanoSec; self->master_config->pcsToSckDelayInNanoSec = self->master_config->betweenTransferDelayInNanoSec; - uint8_t cs = args[ARG_cs].u_int; - if (cs <= 1) { + int8_t cs = args[ARG_cs].u_int; + // In the SPI master_config for automatic CS the value cs=0 is set already, + // so only cs=1 has to be addressed here. The case cs == -1 for manual CS is handled + // in the function spi_set_iomux() and the value in the master_config can stay at 0. + if (cs == 1) { self->master_config->whichPcs = cs; } LPSPI_MasterInit(self->spi_inst, self->master_config, BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT); From 443fbcf81c05de00f35b90d8a443837d62073a63 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 18 Aug 2022 11:36:08 +0200 Subject: [PATCH 0406/1041] mimxrt/machine_uart: Set the UART ioctl write poll flag properly. It was always set to True. The change adds a check to the tx status flag which is set when all data is transferred. --- ports/mimxrt/machine_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/mimxrt/machine_uart.c b/ports/mimxrt/machine_uart.c index 1b0c063334..ab17886926 100644 --- a/ports/mimxrt/machine_uart.c +++ b/ports/mimxrt/machine_uart.c @@ -437,7 +437,7 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint ret |= MP_STREAM_POLL_RD; } } - if ((flags & MP_STREAM_POLL_WR)) { + if ((flags & MP_STREAM_POLL_WR) && (self->tx_status == kStatus_LPUART_TxIdle)) { ret |= MP_STREAM_POLL_WR; } } else if (request == MP_STREAM_FLUSH) { From 6472348c1b2559105e1b2f912a58566b9900e9c1 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 8 Sep 2022 14:24:32 +0200 Subject: [PATCH 0407/1041] mimxrt/machine_uart: Fix a bug in UART.write(). Causing an incomplete send if the data size was longer than the buffer size. --- ports/mimxrt/machine_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/mimxrt/machine_uart.c b/ports/mimxrt/machine_uart.c index ab17886926..83382a6cf2 100644 --- a/ports/mimxrt/machine_uart.c +++ b/ports/mimxrt/machine_uart.c @@ -395,7 +395,7 @@ STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uin // Wait at least the number of character times for this chunk. t = ticks_us64() + (uint64_t)xfer.dataSize * (13000000 / self->config.baudRate_Bps + 1000); - while (self->handle.txDataSize) { + while (self->tx_status != kStatus_LPUART_TxIdle) { // Wait for the first/next character to be sent. if (ticks_us64() > t) { // timed out if (self->handle.txDataSize >= size) { From 74805435f9459ceae4ea6044a767de4a5479e6c8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 13 Sep 2022 21:14:22 +1000 Subject: [PATCH 0408/1041] py/objpolyiter: Fix comment about finaliser method. Signed-off-by: Damien George --- py/objpolyiter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/objpolyiter.c b/py/objpolyiter.c index 16fd1f486c..dac6a25455 100644 --- a/py/objpolyiter.c +++ b/py/objpolyiter.c @@ -66,7 +66,7 @@ typedef struct _mp_obj_polymorph_iter_with_finaliser_t { STATIC mp_obj_t mp_obj_polymorph_iter_del(mp_obj_t self_in) { mp_obj_polymorph_with_finaliser_iter_t *self = MP_OBJ_TO_PTR(self_in); - // Redirect call to object instance's iternext method + // Redirect call to object instance's finaliser method return self->finaliser(self_in); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_obj_polymorph_iter_del_obj, mp_obj_polymorph_iter_del); From 0e8c2204da377e95b5000a3c708891d98cdeb69c Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 14 Sep 2022 14:03:37 +1000 Subject: [PATCH 0409/1041] esp32/mphalport: Fix calculation of large sleep by using 64-bit arith. Fixes issue #9304. Signed-off-by: Damien George --- ports/esp32/mphalport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/esp32/mphalport.c b/ports/esp32/mphalport.c index aab534937e..2aaeb9755f 100644 --- a/ports/esp32/mphalport.c +++ b/ports/esp32/mphalport.c @@ -130,7 +130,7 @@ uint32_t mp_hal_ticks_us(void) { } void mp_hal_delay_ms(uint32_t ms) { - uint64_t us = ms * 1000; + uint64_t us = (uint64_t)ms * 1000ULL; uint64_t dt; uint64_t t0 = esp_timer_get_time(); for (;;) { @@ -139,7 +139,7 @@ void mp_hal_delay_ms(uint32_t ms) { MP_THREAD_GIL_EXIT(); uint64_t t1 = esp_timer_get_time(); dt = t1 - t0; - if (dt + portTICK_PERIOD_MS * 1000 >= us) { + if (dt + portTICK_PERIOD_MS * 1000ULL >= us) { // doing a vTaskDelay would take us beyond requested delay time taskYIELD(); MP_THREAD_GIL_ENTER(); From 45972fa5481aeef38d074360b0f72b212968a305 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 14 Sep 2022 09:57:47 +1000 Subject: [PATCH 0410/1041] py/mkrules.mk: Add link to build troubleshooting on failure. Also update the submodules help text to match. Signed-off-by: Jim Mussared --- py/mkrules.mk | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/py/mkrules.mk b/py/mkrules.mk index 14f1b953cd..a58bd2ee0e 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -4,6 +4,9 @@ THIS_MAKEFILE = $(lastword $(MAKEFILE_LIST)) include $(dir $(THIS_MAKEFILE))mkenv.mk endif +HELP_BUILD_ERROR ?= "See \033[1;31mhttps://github.com/micropython/micropython/wiki/Build-Troubleshooting\033[0m" +HELP_MPY_LIB_SUBMODULE ?= "\033[1;31mError: micropython-lib submodule is not initialized.\033[0m Run 'make submodules'" + # Extra deps that need to happen before object compilation. OBJ_EXTRA_ORDER_DEPS = @@ -53,7 +56,7 @@ $(BUILD)/%.o: %.s define compile_c $(ECHO) "CC $<" -$(Q)$(CC) $(CFLAGS) -c -MD -o $@ $< +$(Q)$(CC) $(CFLAGS) -c -MD -o $@ $< || (echo -e $(HELP_BUILD_ERROR); false) @# The following fixes the dependency file. @# See http://make.paulandlesley.org/autodep.html for details. @# Regex adjusted from the above to play better with Windows paths, etc. @@ -65,7 +68,7 @@ endef define compile_cxx $(ECHO) "CXX $<" -$(Q)$(CXX) $(CXXFLAGS) -c -MD -o $@ $< +$(Q)$(CXX) $(CXXFLAGS) -c -MD -o $@ $< || (echo -e $(HELP_BUILD_ERROR); false) @# The following fixes the dependency file. @# See http://make.paulandlesley.org/autodep.html for details. @# Regex adjusted from the above to play better with Windows paths, etc. @@ -182,7 +185,7 @@ endif # to build frozen_content.c from a manifest $(BUILD)/frozen_content.c: FORCE $(BUILD)/genhdr/qstrdefs.generated.h $(BUILD)/genhdr/root_pointers.h | $(MICROPY_MPYCROSS_DEPENDENCY) - $(Q)test -e "$(MPY_LIB_DIR)/README.md" || (echo "Error: micropython-lib not initialized. Run 'make submodules'"; false) + $(Q)test -e "$(MPY_LIB_DIR)/README.md" || (echo -e $(HELP_MPY_LIB_SUBMODULE); false) $(Q)$(MAKE_MANIFEST) -o $@ -v "MPY_DIR=$(TOP)" -v "MPY_LIB_DIR=$(MPY_LIB_DIR)" -v "PORT_DIR=$(shell pwd)" -v "BOARD_DIR=$(BOARD_DIR)" -b "$(BUILD)" $(if $(MPY_CROSS_FLAGS),-f"$(MPY_CROSS_FLAGS)",) --mpy-tool-flags="$(MPY_TOOL_FLAGS)" $(FROZEN_MANIFEST) endif From 18d0e6d0dbdb34c6cac5aeeb9c4424821cd9f16a Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 14 Sep 2022 10:08:48 +1000 Subject: [PATCH 0411/1041] esp32/Makefile: Add link to build troubleshooting on failure. Signed-off-by: Jim Mussared --- ports/esp32/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index b7d804d073..e43cad751b 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -34,8 +34,10 @@ ifdef FROZEN_MANIFEST IDFPY_FLAGS += -D MICROPY_FROZEN_MANIFEST=$(FROZEN_MANIFEST) endif +HELP_BUILD_ERROR ?= "See \033[1;31mhttps://github.com/micropython/micropython/wiki/Build-Troubleshooting\033[0m" + all: - idf.py $(IDFPY_FLAGS) build + idf.py $(IDFPY_FLAGS) build || (echo -e $(HELP_BUILD_ERROR); false) @$(PYTHON) makeimg.py \ $(BUILD)/sdkconfig \ $(BUILD)/bootloader/bootloader.bin \ From ca51d63c37e6ca67bec0a645e2aeea71aba91058 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 14 Sep 2022 10:08:59 +1000 Subject: [PATCH 0412/1041] rp2/Makefile: Add link to build troubleshooting on failure. Signed-off-by: Jim Mussared --- ports/rp2/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ports/rp2/Makefile b/ports/rp2/Makefile index 6d2fc00964..c603f5403f 100644 --- a/ports/rp2/Makefile +++ b/ports/rp2/Makefile @@ -22,9 +22,11 @@ ifeq ($(DEBUG),1) CMAKE_ARGS += -DCMAKE_BUILD_TYPE=Debug endif +HELP_BUILD_ERROR ?= "See \033[1;31mhttps://github.com/micropython/micropython/wiki/Build-Troubleshooting\033[0m" + all: [ -e $(BUILD)/Makefile ] || cmake -S . -B $(BUILD) -DPICO_BUILD_DOCS=0 ${CMAKE_ARGS} - $(MAKE) $(MAKESILENT) -C $(BUILD) + $(MAKE) $(MAKESILENT) -C $(BUILD) || (echo -e $(HELP_BUILD_ERROR); false) clean: $(RM) -rf $(BUILD) From fb2a57800acffd811d05373dcf63e95b4048d0c6 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 15 Jul 2021 14:31:06 +1000 Subject: [PATCH 0413/1041] all: Simplify buffer protocol to just a "get buffer" callback. The buffer protocol type only has a single member, and this existing layout creates problems for the upcoming split/slot-index mp_obj_type_t layout optimisations. If we need to make the buffer protocol more sophisticated in the future either we can rely on the mp_obj_type_t optimisations to just add additional slots to mp_obj_type_t or re-visit the buffer protocol then. This change is a no-op in terms of generated code. Signed-off-by: Jim Mussared --- examples/natmod/framebuf/framebuf.c | 2 +- extmod/modbluetooth.c | 2 +- extmod/modframebuf.c | 2 +- extmod/moductypes.c | 2 +- ports/nrf/boards/microbit/modules/iters.c | 1 - ports/nrf/boards/microbit/modules/microbitdisplay.c | 1 - ports/nrf/boards/microbit/modules/microbitimage.c | 1 - ports/unix/modffi.c | 4 ++-- py/obj.c | 4 ++-- py/obj.h | 6 ++---- py/objarray.c | 6 +++--- py/objstr.c | 4 ++-- py/objstrunicode.c | 2 +- py/objtype.c | 6 +++--- 14 files changed, 19 insertions(+), 24 deletions(-) diff --git a/examples/natmod/framebuf/framebuf.c b/examples/natmod/framebuf/framebuf.c index 53fb90c625..2eff61c817 100644 --- a/examples/natmod/framebuf/framebuf.c +++ b/examples/natmod/framebuf/framebuf.c @@ -21,7 +21,7 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a mp_type_framebuf.base.type = (void*)&mp_type_type; mp_type_framebuf.name = MP_QSTR_FrameBuffer; mp_type_framebuf.make_new = framebuf_make_new; - mp_type_framebuf.buffer_p.get_buffer = framebuf_get_buffer; + mp_type_framebuf.buffer = framebuf_get_buffer; framebuf_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill), MP_OBJ_FROM_PTR(&framebuf_fill_obj) }; framebuf_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill_rect), MP_OBJ_FROM_PTR(&framebuf_fill_rect_obj) }; framebuf_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_pixel), MP_OBJ_FROM_PTR(&framebuf_pixel_obj) }; diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index bd4d9b7179..4cc57b3d55 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -248,7 +248,7 @@ const mp_obj_type_t mp_type_bluetooth_uuid = { .binary_op = bluetooth_uuid_binary_op, .locals_dict = NULL, .print = bluetooth_uuid_print, - .buffer_p = { .get_buffer = bluetooth_uuid_get_buffer }, + .buffer = bluetooth_uuid_get_buffer, }; // ---------------------------------------------------------------------------- diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index bb1f4f6310..9542d4303e 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -833,7 +833,7 @@ STATIC const mp_obj_type_t mp_type_framebuf = { { &mp_type_type }, .name = MP_QSTR_FrameBuffer, .make_new = framebuf_make_new, - .buffer_p = { .get_buffer = framebuf_get_buffer }, + .buffer = framebuf_get_buffer, .locals_dict = (mp_obj_dict_t *)&framebuf_locals_dict, }; #endif diff --git a/extmod/moductypes.c b/extmod/moductypes.c index 547453c48e..25578dd6b0 100644 --- a/extmod/moductypes.c +++ b/extmod/moductypes.c @@ -642,7 +642,7 @@ STATIC const mp_obj_type_t uctypes_struct_type = { .attr = uctypes_struct_attr, .subscr = uctypes_struct_subscr, .unary_op = uctypes_struct_unary_op, - .buffer_p = { .get_buffer = uctypes_get_buffer }, + .buffer = uctypes_get_buffer, }; STATIC const mp_rom_map_elem_t mp_module_uctypes_globals_table[] = { diff --git a/ports/nrf/boards/microbit/modules/iters.c b/ports/nrf/boards/microbit/modules/iters.c index 8ae4b698fe..e9c4ae3c72 100644 --- a/ports/nrf/boards/microbit/modules/iters.c +++ b/ports/nrf/boards/microbit/modules/iters.c @@ -55,7 +55,6 @@ const mp_obj_type_t microbit_repeat_iterator_type = { .subscr = NULL, .getiter = mp_identity_getiter, .iternext = microbit_repeat_iter_next, - .buffer_p = {NULL}, MP_OBJ_NULL }; diff --git a/ports/nrf/boards/microbit/modules/microbitdisplay.c b/ports/nrf/boards/microbit/modules/microbitdisplay.c index b35703ad6f..04b8602879 100644 --- a/ports/nrf/boards/microbit/modules/microbitdisplay.c +++ b/ports/nrf/boards/microbit/modules/microbitdisplay.c @@ -554,7 +554,6 @@ const mp_obj_type_t microbit_display_type = { .subscr = NULL, .getiter = NULL, .iternext = NULL, - .buffer_p = {NULL}, .locals_dict = (mp_obj_dict_t*)µbit_display_locals_dict, }; diff --git a/ports/nrf/boards/microbit/modules/microbitimage.c b/ports/nrf/boards/microbit/modules/microbitimage.c index a028df8282..5d2896c383 100644 --- a/ports/nrf/boards/microbit/modules/microbitimage.c +++ b/ports/nrf/boards/microbit/modules/microbitimage.c @@ -690,7 +690,6 @@ const mp_obj_type_t microbit_image_type = { .subscr = NULL, .getiter = NULL, .iternext = NULL, - .buffer_p = {NULL}, .locals_dict = (mp_obj_dict_t*)µbit_image_locals_dict, }; diff --git a/ports/unix/modffi.c b/ports/unix/modffi.c index d82d5270fa..6417b5d3b3 100644 --- a/ports/unix/modffi.c +++ b/ports/unix/modffi.c @@ -505,10 +505,10 @@ STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const } else if (mp_obj_is_str(a)) { const char *s = mp_obj_str_get_str(a); values[i].ffi = (ffi_arg)(intptr_t)s; - } else if (((mp_obj_base_t *)MP_OBJ_TO_PTR(a))->type->buffer_p.get_buffer != NULL) { + } else if (((mp_obj_base_t *)MP_OBJ_TO_PTR(a))->type->buffer != NULL) { mp_obj_base_t *o = (mp_obj_base_t *)MP_OBJ_TO_PTR(a); mp_buffer_info_t bufinfo; - int ret = o->type->buffer_p.get_buffer(MP_OBJ_FROM_PTR(o), &bufinfo, MP_BUFFER_READ); // TODO: MP_BUFFER_READ? + int ret = o->type->buffer(MP_OBJ_FROM_PTR(o), &bufinfo, MP_BUFFER_READ); // TODO: MP_BUFFER_READ? if (ret != 0) { goto error; } diff --git a/py/obj.c b/py/obj.c index b461fe50aa..eeadd3eedd 100644 --- a/py/obj.c +++ b/py/obj.c @@ -579,10 +579,10 @@ mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf) { bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) { const mp_obj_type_t *type = mp_obj_get_type(obj); - if (type->buffer_p.get_buffer == NULL) { + if (type->buffer == NULL) { return false; } - int ret = type->buffer_p.get_buffer(obj, bufinfo, flags); + int ret = type->buffer(obj, bufinfo, flags); if (ret != 0) { return false; } diff --git a/py/obj.h b/py/obj.h index 8949830282..0bf5b58f81 100644 --- a/py/obj.h +++ b/py/obj.h @@ -557,9 +557,7 @@ typedef struct _mp_buffer_info_t { #define MP_BUFFER_READ (1) #define MP_BUFFER_WRITE (2) #define MP_BUFFER_RW (MP_BUFFER_READ | MP_BUFFER_WRITE) -typedef struct _mp_buffer_p_t { - mp_int_t (*get_buffer)(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); -} mp_buffer_p_t; +typedef mp_int_t (*mp_buffer_fun_t)(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); @@ -618,7 +616,7 @@ struct _mp_obj_type_t { mp_fun_1_t iternext; // Implements the buffer protocol if supported by this type. - mp_buffer_p_t buffer_p; + mp_buffer_fun_t buffer; // One of disjoint protocols (interfaces), like mp_stream_p_t, etc. const void *protocol; diff --git a/py/objarray.c b/py/objarray.c index ecaffeb6a2..dca41c2931 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -580,7 +580,7 @@ const mp_obj_type_t mp_type_array = { .unary_op = array_unary_op, .binary_op = array_binary_op, .subscr = array_subscr, - .buffer_p = { .get_buffer = array_get_buffer }, + .buffer_p = array_get_buffer, .locals_dict = (mp_obj_dict_t *)&mp_obj_array_locals_dict, }; #endif @@ -596,7 +596,7 @@ const mp_obj_type_t mp_type_bytearray = { .unary_op = array_unary_op, .binary_op = array_binary_op, .subscr = array_subscr, - .buffer_p = { .get_buffer = array_get_buffer }, + .buffer = array_get_buffer, .locals_dict = (mp_obj_dict_t *)&mp_obj_bytearray_locals_dict, }; #endif @@ -617,7 +617,7 @@ const mp_obj_type_t mp_type_memoryview = { .locals_dict = (mp_obj_dict_t *)&mp_obj_memoryview_locals_dict, #endif .subscr = array_subscr, - .buffer_p = { .get_buffer = array_get_buffer }, + .buffer = array_get_buffer, }; #endif diff --git a/py/objstr.c b/py/objstr.c index 683d035e44..9dd7f65e66 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -2151,7 +2151,7 @@ const mp_obj_type_t mp_type_str = { .binary_op = mp_obj_str_binary_op, .subscr = bytes_subscr, .getiter = mp_obj_new_str_iterator, - .buffer_p = { .get_buffer = mp_obj_str_get_buffer }, + .buffer = mp_obj_str_get_buffer, .locals_dict = (mp_obj_dict_t *)&mp_obj_str_locals_dict, }; #endif // !MICROPY_PY_BUILTINS_STR_UNICODE @@ -2165,7 +2165,7 @@ const mp_obj_type_t mp_type_bytes = { .binary_op = mp_obj_str_binary_op, .subscr = bytes_subscr, .getiter = mp_obj_new_bytes_iterator, - .buffer_p = { .get_buffer = mp_obj_str_get_buffer }, + .buffer = mp_obj_str_get_buffer, .locals_dict = (mp_obj_dict_t *)&mp_obj_bytes_locals_dict, }; diff --git a/py/objstrunicode.c b/py/objstrunicode.c index d36dd8b137..fef0353683 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -238,7 +238,7 @@ const mp_obj_type_t mp_type_str = { .binary_op = mp_obj_str_binary_op, .subscr = str_subscr, .getiter = mp_obj_new_str_iterator, - .buffer_p = { .get_buffer = mp_obj_str_get_buffer }, + .buffer = mp_obj_str_get_buffer, .locals_dict = (mp_obj_dict_t *)&mp_obj_str_locals_dict, }; diff --git a/py/objtype.c b/py/objtype.c index fe1918bd37..c0f6857809 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -913,14 +913,14 @@ STATIC mp_int_t instance_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, struct class_lookup_data lookup = { .obj = self, .attr = MP_QSTR_, // don't actually look for a method - .meth_offset = offsetof(mp_obj_type_t, buffer_p.get_buffer), + .meth_offset = offsetof(mp_obj_type_t, buffer), .dest = member, .is_type = false, }; mp_obj_class_lookup(&lookup, self->base.type); if (member[0] == MP_OBJ_SENTINEL) { const mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]); - return type->buffer_p.get_buffer(self->subobj[0], bufinfo, flags); + return type->buffer(self->subobj[0], bufinfo, flags); } else { return 1; // object does not support buffer protocol } @@ -1160,7 +1160,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) o->subscr = instance_subscr; o->getiter = mp_obj_instance_getiter; // o->iternext = ; not implemented - o->buffer_p.get_buffer = instance_get_buffer; + o->buffer = instance_get_buffer; if (bases_len > 0) { // Inherit protocol from a base class. This allows to define an From 42587c78702e0a96ca025e66267201f27389bb17 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 14 Jul 2021 14:06:29 +1000 Subject: [PATCH 0414/1041] all: Standardise mp_obj_type_t initialisation. Remove setting unused slots. Signed-off-by: Jim Mussared --- extmod/vfs_fat.c | 1 - ports/nrf/boards/microbit/modules/iters.c | 8 ---- .../boards/microbit/modules/microbitdisplay.c | 9 ---- .../boards/microbit/modules/microbitimage.c | 42 ------------------- 4 files changed, 60 deletions(-) diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 7d8b51efeb..8d2f13be47 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -437,7 +437,6 @@ const mp_obj_type_t mp_fat_vfs_type = { .make_new = fat_vfs_make_new, .protocol = &fat_vfs_proto, .locals_dict = (mp_obj_dict_t *)&fat_vfs_locals_dict, - }; #endif // MICROPY_VFS_FAT diff --git a/ports/nrf/boards/microbit/modules/iters.c b/ports/nrf/boards/microbit/modules/iters.c index e9c4ae3c72..66f9f6c7f3 100644 --- a/ports/nrf/boards/microbit/modules/iters.c +++ b/ports/nrf/boards/microbit/modules/iters.c @@ -46,16 +46,8 @@ static mp_obj_t microbit_repeat_iter_next(mp_obj_t iter_in) { const mp_obj_type_t microbit_repeat_iterator_type = { { &mp_type_type }, .name = MP_QSTR_iterator, - .print = NULL, - .make_new = NULL, - .call = NULL, - .unary_op = NULL, - .binary_op = NULL, - .attr = NULL, - .subscr = NULL, .getiter = mp_identity_getiter, .iternext = microbit_repeat_iter_next, - MP_OBJ_NULL }; mp_obj_t microbit_repeat_iterator(mp_obj_t iterable) { diff --git a/ports/nrf/boards/microbit/modules/microbitdisplay.c b/ports/nrf/boards/microbit/modules/microbitdisplay.c index 04b8602879..93ba9772fe 100644 --- a/ports/nrf/boards/microbit/modules/microbitdisplay.c +++ b/ports/nrf/boards/microbit/modules/microbitdisplay.c @@ -545,15 +545,6 @@ STATIC MP_DEFINE_CONST_DICT(microbit_display_locals_dict, microbit_display_local const mp_obj_type_t microbit_display_type = { { &mp_type_type }, .name = MP_QSTR_MicroBitDisplay, - .print = NULL, - .make_new = NULL, - .call = NULL, - .unary_op = NULL, - .binary_op = NULL, - .attr = NULL, - .subscr = NULL, - .getiter = NULL, - .iternext = NULL, .locals_dict = (mp_obj_dict_t*)µbit_display_locals_dict, }; diff --git a/ports/nrf/boards/microbit/modules/microbitimage.c b/ports/nrf/boards/microbit/modules/microbitimage.c index 5d2896c383..eb44660b97 100644 --- a/ports/nrf/boards/microbit/modules/microbitimage.c +++ b/ports/nrf/boards/microbit/modules/microbitimage.c @@ -683,13 +683,7 @@ const mp_obj_type_t microbit_image_type = { .name = MP_QSTR_MicroBitImage, .print = microbit_image_print, .make_new = microbit_image_make_new, - .call = NULL, - .unary_op = NULL, .binary_op = image_binary_op, - .attr = NULL, - .subscr = NULL, - .getiter = NULL, - .iternext = NULL, .locals_dict = (mp_obj_dict_t*)µbit_image_locals_dict, }; @@ -829,33 +823,14 @@ STATIC mp_obj_t microbit_scrolling_string_iter_next(mp_obj_t o_in) { const mp_obj_type_t microbit_scrolling_string_type = { { &mp_type_type }, .name = MP_QSTR_ScrollingString, - .print = NULL, - .make_new = NULL, - .call = NULL, - .unary_op = NULL, - .binary_op = NULL, - .attr = NULL, - .subscr = NULL, .getiter = get_microbit_scrolling_string_iter, - .iternext = NULL, - .buffer_p = {NULL}, - .locals_dict = NULL, }; const mp_obj_type_t microbit_scrolling_string_iterator_type = { { &mp_type_type }, .name = MP_QSTR_iterator, - .print = NULL, - .make_new = NULL, - .call = NULL, - .unary_op = NULL, - .binary_op = NULL, - .attr = NULL, - .subscr = NULL, .getiter = mp_identity_getiter, .iternext = microbit_scrolling_string_iter_next, - .buffer_p = {NULL}, - .locals_dict = NULL, }; /** Facade types to present a string as a sequence of images. @@ -897,17 +872,9 @@ static mp_obj_t microbit_facade_iterator(mp_obj_t iterable_in, mp_obj_iter_buf_t const mp_obj_type_t string_image_facade_type = { { &mp_type_type }, .name = MP_QSTR_Facade, - .print = NULL, - .make_new = NULL, - .call = NULL, .unary_op = facade_unary_op, - .binary_op = NULL, - .attr = NULL, .subscr = string_image_facade_subscr, .getiter = microbit_facade_iterator, - .iternext = NULL, - .buffer_p = {NULL}, - NULL }; @@ -940,17 +907,8 @@ static mp_obj_t microbit_facade_iter_next(mp_obj_t iter_in) { const mp_obj_type_t microbit_facade_iterator_type = { { &mp_type_type }, .name = MP_QSTR_iterator, - .print = NULL, - .make_new = NULL, - .call = NULL, - .unary_op = NULL, - .binary_op = NULL, - .attr = NULL, - .subscr = NULL, .getiter = mp_identity_getiter, .iternext = microbit_facade_iter_next, - .buffer_p = {NULL}, - NULL }; mp_obj_t microbit_facade_iterator(mp_obj_t iterable_in, mp_obj_iter_buf_t *iter_buf) { From cdb880789f61ee037cc7905ad75a7a9201d12ba5 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 14 Jul 2021 13:38:27 +1000 Subject: [PATCH 0415/1041] py/obj: Add macro to declare ROM mp_obj_type_t instances. This will allow the structure of mp_obj_type_t to change while keeping the definition code the same. Signed-off-by: Jim Mussared --- py/obj.h | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/py/obj.h b/py/obj.h index 0bf5b58f81..4ab7e0dc09 100644 --- a/py/obj.h +++ b/py/obj.h @@ -513,6 +513,7 @@ typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *); // operator and not the __ne__ operator. If it's set then __ne__ may be implemented. // If MP_TYPE_FLAG_BINDS_SELF is set then the type as a method binds self as the first arg. // If MP_TYPE_FLAG_BUILTIN_FUN is set then the type is a built-in function type. +#define MP_TYPE_FLAG_NONE (0x0000) #define MP_TYPE_FLAG_IS_SUBCLASSED (0x0001) #define MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS (0x0002) #define MP_TYPE_FLAG_EQ_NOT_REFLEXIVE (0x0004) @@ -631,6 +632,40 @@ struct _mp_obj_type_t { struct _mp_obj_dict_t *locals_dict; }; +#define MP_TYPE_NULL_MAKE_NEW (NULL) + +// Implementation of MP_DEFINE_CONST_OBJ_TYPE for each number of arguments. +// Do not use these directly, instead use MP_DEFINE_CONST_OBJ_TYPE. +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_0(_struct_type, _typename, _name, _flags, _make_new) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_1(_struct_type, _typename, _name, _flags, _make_new, f1, v1) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1 } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_2(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2 } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_3(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3 } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_4(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4 } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_5(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5 } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_6(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6 } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_7(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6, .f7 = v7 } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_8(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6, .f7 = v7, .f8 = v8 } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_9(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6, .f7 = v7, .f8 = v8, .f9 = v9 } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_10(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6, .f7 = v7, .f8 = v8, .f9 = v9, .f10 = v10 } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_11(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6, .f7 = v7, .f8 = v8, .f9 = v9, .f10 = v10, .f11 = v11 } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_12(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11, f12, v12) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6, .f7 = v7, .f8 = v8, .f9 = v9, .f10 = v10, .f11 = v11, .f12 = v12 } + +// Workaround for https://docs.microsoft.com/en-us/cpp/preprocessor/preprocessor-experimental-overview?view=msvc-160#macro-arguments-are-unpacked +#define MP_DEFINE_CONST_OBJ_TYPE_EXPAND(x) x + +// This macro evaluates to MP_DEFINE_CONST_OBJ_TYPE_NARGS_##N, where N is the value +// of the 30th argument (30 is 13*2 + 4). +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, N, ...) MP_DEFINE_CONST_OBJ_TYPE_NARGS_##N + +// This macro is used to define a object type in ROM. +// Invoke as MP_DEFINE_CONST_OBJ_TYPE(_typename, _name, _flags, _make_new [, slot, func]*) +// It uses the number of arguments to select which MP_DEFINE_CONST_OBJ_TYPE_* +// macro to use based on the number of arguments. It works by shifting the +// numeric values 12, 11, ... 0 by the number of arguments, such that the +// 30th argument ends up being the number to use. The _INV values are +// placeholders because the slot arguments come in pairs. +#define MP_DEFINE_CONST_OBJ_TYPE(...) MP_DEFINE_CONST_OBJ_TYPE_EXPAND(MP_DEFINE_CONST_OBJ_TYPE_NARGS(__VA_ARGS__, _INV, 12, _INV, 11, _INV, 10, _INV, 9, _INV, 8, _INV, 7, _INV, 6, _INV, 5, _INV, 4, _INV, 3, _INV, 2, _INV, 1, _INV, 0)(mp_obj_type_t, __VA_ARGS__)) + // Constant types, globally accessible extern const mp_obj_type_t mp_type_type; extern const mp_obj_type_t mp_type_object; From 662b9761b37b054f08fe2f7c00d0fce3a418d0b0 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 14 Jul 2021 14:38:38 +1000 Subject: [PATCH 0416/1041] all: Make all mp_obj_type_t defs use MP_DEFINE_CONST_OBJ_TYPE. In preparation for upcoming rework of mp_obj_type_t layout. Signed-off-by: Jim Mussared --- extmod/machine_i2c.c | 17 +-- extmod/machine_mem.c | 14 ++- extmod/machine_pinbase.c | 13 +- extmod/machine_pwm.c | 15 +-- extmod/machine_signal.c | 17 +-- extmod/machine_spi.c | 17 +-- extmod/modbluetooth.c | 33 ++--- extmod/modbtree.c | 22 ++-- extmod/modframebuf.c | 15 +-- extmod/modlwip.c | 30 ++--- extmod/moduasyncio.c | 30 ++--- extmod/moducryptolib.c | 13 +- extmod/moductypes.c | 21 ++-- extmod/moduhashlib.c | 39 +++--- extmod/modure.c | 28 +++-- extmod/moduselect.c | 16 +-- extmod/modusocket.c | 17 +-- extmod/modussl_axtls.c | 20 ++-- extmod/modussl_mbedtls.c | 20 ++-- extmod/modutimeq.c | 15 +-- extmod/moduwebsocket.c | 15 +-- extmod/moduzlib.c | 15 +-- extmod/modwebrepl.c | 15 +-- extmod/network_cyw43.c | 15 +-- extmod/network_ninaw10.c | 15 ++- extmod/network_wiznet5k.c | 28 +++-- extmod/vfs_fat.c | 15 +-- extmod/vfs_fat_file.c | 40 ++++--- extmod/vfs_lfsx.c | 17 +-- extmod/vfs_lfsx_file.c | 40 ++++--- extmod/vfs_posix.c | 15 +-- extmod/vfs_posix_file.c | 40 ++++--- ports/cc3200/misc/mpirq.c | 14 ++- ports/cc3200/mods/modnetwork.c | 13 +- ports/cc3200/mods/moduhashlib.c | 26 ++-- ports/cc3200/mods/modusocket.c | 15 +-- ports/cc3200/mods/modussl.c | 18 +-- ports/cc3200/mods/modwlan.c | 15 ++- ports/cc3200/mods/pybadc.c | 31 ++--- ports/cc3200/mods/pybflash.c | 13 +- ports/cc3200/mods/pybi2c.c | 15 +-- ports/cc3200/mods/pybpin.c | 31 ++--- ports/cc3200/mods/pybrtc.c | 13 +- ports/cc3200/mods/pybsd.c | 13 +- ports/cc3200/mods/pybsleep.c | 10 +- ports/cc3200/mods/pybspi.c | 15 +-- ports/cc3200/mods/pybtimer.c | 29 +++-- ports/cc3200/mods/pybuart.c | 21 ++-- ports/cc3200/mods/pybwdt.c | 13 +- ports/esp32/esp32_nvs.c | 15 +-- ports/esp32/esp32_partition.c | 15 +-- ports/esp32/esp32_rmt.c | 15 +-- ports/esp32/esp32_ulp.c | 13 +- ports/esp32/machine_adc.c | 15 +-- ports/esp32/machine_adcblock.c | 15 +-- ports/esp32/machine_dac.c | 15 +-- ports/esp32/machine_hw_spi.c | 17 +-- ports/esp32/machine_i2c.c | 17 +-- ports/esp32/machine_i2s.c | 21 ++-- ports/esp32/machine_pin.c | 33 ++--- ports/esp32/machine_rtc.c | 13 +- ports/esp32/machine_sdcard.c | 13 +- ports/esp32/machine_timer.c | 15 +-- ports/esp32/machine_touchpad.c | 13 +- ports/esp32/machine_uart.c | 21 ++-- ports/esp32/machine_wdt.c | 13 +- ports/esp32/modsocket.c | 15 +-- ports/esp32/network_lan.c | 12 +- ports/esp32/network_ppp.c | 12 +- ports/esp32/network_wlan.c | 20 ++-- ports/esp8266/machine_adc.c | 15 +-- ports/esp8266/machine_hspi.c | 17 +-- ports/esp8266/machine_pin.c | 33 ++--- ports/esp8266/machine_rtc.c | 13 +- ports/esp8266/machine_uart.c | 21 ++-- ports/esp8266/machine_wdt.c | 13 +- ports/esp8266/modmachine.c | 15 +-- ports/esp8266/modnetwork.c | 12 +- ports/mimxrt/machine_adc.c | 15 +-- ports/mimxrt/machine_i2c.c | 17 +-- ports/mimxrt/machine_i2s.c | 21 ++-- ports/mimxrt/machine_led.c | 15 +-- ports/mimxrt/machine_pin.c | 59 ++++----- ports/mimxrt/machine_rtc.c | 13 +- ports/mimxrt/machine_sdcard.c | 13 +- ports/mimxrt/machine_spi.c | 17 +-- ports/mimxrt/machine_timer.c | 15 +-- ports/mimxrt/machine_uart.c | 21 ++-- ports/mimxrt/machine_wdt.c | 13 +- ports/mimxrt/mimxrt_flash.c | 13 +- ports/mimxrt/network_lan.c | 16 +-- ports/nrf/boards/microbit/modules/iters.c | 14 ++- .../boards/microbit/modules/microbitdisplay.c | 12 +- .../boards/microbit/modules/microbitimage.c | 73 ++++++----- ports/nrf/modules/board/led.c | 15 +-- ports/nrf/modules/machine/adc.c | 15 +-- ports/nrf/modules/machine/i2c.c | 17 +-- ports/nrf/modules/machine/pin.c | 31 ++--- ports/nrf/modules/machine/pwm.c | 15 +-- ports/nrf/modules/machine/rtcounter.c | 15 +-- ports/nrf/modules/machine/spi.c | 17 +-- ports/nrf/modules/machine/temp.c | 15 +-- ports/nrf/modules/machine/timer.c | 15 +-- ports/nrf/modules/machine/uart.c | 21 ++-- ports/nrf/modules/nrf/flashbdev.c | 15 +-- .../modules/ubluepy/ubluepy_characteristic.c | 15 +-- ports/nrf/modules/ubluepy/ubluepy_constants.c | 24 ++-- ports/nrf/modules/ubluepy/ubluepy_delegate.c | 15 +-- .../nrf/modules/ubluepy/ubluepy_descriptor.c | 15 +-- .../nrf/modules/ubluepy/ubluepy_peripheral.c | 15 +-- .../nrf/modules/ubluepy/ubluepy_scan_entry.c | 14 ++- ports/nrf/modules/ubluepy/ubluepy_scanner.c | 15 +-- ports/nrf/modules/ubluepy/ubluepy_service.c | 15 +-- ports/nrf/modules/ubluepy/ubluepy_uuid.c | 15 +-- ports/nrf/modules/uos/microbitfs.c | 28 +++-- ports/nrf/pin_named_pins.c | 28 +++-- ports/pic16bit/modpybled.c | 15 +-- ports/pic16bit/modpybswitch.c | 17 +-- ports/renesas-ra/extint.c | 15 +-- ports/renesas-ra/led.c | 15 +-- ports/renesas-ra/machine_adc.c | 15 +-- ports/renesas-ra/machine_i2c.c | 17 +-- ports/renesas-ra/machine_pin.c | 43 ++++--- ports/renesas-ra/machine_rtc.c | 13 +- ports/renesas-ra/machine_spi.c | 17 +-- ports/renesas-ra/machine_timer.c | 15 +-- ports/renesas-ra/machine_uart.c | 21 ++-- ports/renesas-ra/storage.c | 15 +-- ports/renesas-ra/timer.c | 29 +++-- ports/renesas-ra/usrsw.c | 17 +-- ports/rp2/machine_adc.c | 15 +-- ports/rp2/machine_i2c.c | 17 +-- ports/rp2/machine_i2s.c | 21 ++-- ports/rp2/machine_pin.c | 19 +-- ports/rp2/machine_rtc.c | 13 +- ports/rp2/machine_spi.c | 17 +-- ports/rp2/machine_timer.c | 15 +-- ports/rp2/machine_uart.c | 21 ++-- ports/rp2/machine_wdt.c | 13 +- ports/rp2/rp2_flash.c | 13 +- ports/rp2/rp2_pio.c | 30 ++--- ports/samd/machine_led.c | 17 +-- ports/samd/machine_pin.c | 19 +-- ports/samd/samd_flash.c | 13 +- ports/stm32/accel.c | 13 +- ports/stm32/adc.c | 28 +++-- ports/stm32/dac.c | 15 +-- ports/stm32/extint.c | 15 +-- ports/stm32/lcd.c | 13 +- ports/stm32/led.c | 15 +-- ports/stm32/machine_adc.c | 15 +-- ports/stm32/machine_i2c.c | 17 +-- ports/stm32/machine_i2s.c | 21 ++-- ports/stm32/machine_spi.c | 17 +-- ports/stm32/machine_timer.c | 15 +-- ports/stm32/machine_uart.c | 21 ++-- ports/stm32/network_lan.c | 15 +-- ports/stm32/pin.c | 33 ++--- ports/stm32/pin_named_pins.c | 24 ++-- ports/stm32/pyb_can.c | 17 +-- ports/stm32/pyb_i2c.c | 15 +-- ports/stm32/pyb_spi.c | 17 +-- ports/stm32/rtc.c | 13 +- ports/stm32/sdcard.c | 26 ++-- ports/stm32/servo.c | 15 +-- ports/stm32/storage.c | 15 +-- ports/stm32/timer.c | 29 +++-- ports/stm32/usb.c | 36 +++--- ports/stm32/usrsw.c | 17 +-- ports/stm32/wdt.c | 13 +- ports/teensy/led.c | 15 +-- ports/teensy/timer.c | 29 +++-- ports/teensy/uart.c | 15 +-- ports/unix/coverage.c | 26 ++-- ports/unix/modffi.c | 69 ++++++----- ports/unix/modjni.c | 58 +++++---- ports/unix/moduselect.c | 16 +-- ports/unix/modusocket.c | 21 ++-- ports/zephyr/machine_i2c.c | 17 +-- ports/zephyr/machine_pin.c | 19 +-- ports/zephyr/machine_spi.c | 17 +-- ports/zephyr/machine_uart.c | 21 ++-- ports/zephyr/modusocket.c | 17 +-- ports/zephyr/modzsensor.c | 13 +- ports/zephyr/zephyr_storage.c | 30 ++--- py/builtinevex.c | 10 +- py/modio.c | 28 +++-- py/modthread.c | 12 +- py/objarray.c | 87 +++++++------- py/objattrtuple.c | 23 ++-- py/objbool.c | 19 +-- py/objboundmeth.c | 16 +-- py/objcell.c | 10 +- py/objclosure.c | 17 +-- py/objcomplex.c | 17 ++- py/objdeque.c | 15 +-- py/objdict.c | 78 ++++++------ py/objenumerate.c | 15 +-- py/objexcept.c | 15 +-- py/objfilter.c | 15 +-- py/objfloat.c | 15 +-- py/objfun.c | 113 ++++++++---------- py/objgenerator.c | 54 +++++---- py/objgetitemiter.c | 14 ++- py/objint.c | 19 +-- py/objlist.c | 24 ++-- py/objmap.c | 15 +-- py/objmodule.c | 14 ++- py/objnone.c | 14 ++- py/objobject.c | 13 +- py/objpolyiter.c | 31 ++--- py/objproperty.c | 13 +- py/objrange.c | 37 +++--- py/objreversed.c | 15 +-- py/objset.c | 43 +++---- py/objsingleton.c | 11 +- py/objslice.c | 16 +-- py/objstr.c | 48 ++++---- py/objstringio.c | 42 +++---- py/objstrunicode.c | 25 ++-- py/objtuple.c | 23 ++-- py/objtype.c | 56 +++++---- py/objzip.c | 15 +-- py/profile.c | 32 ++--- py/runtime.c | 13 +- shared/runtime/mpirq.c | 14 ++- shared/runtime/sys_stdio_mphal.c | 40 ++++--- 227 files changed, 2543 insertions(+), 2184 deletions(-) diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c index ff597b58c5..7e597b7910 100644 --- a/extmod/machine_i2c.c +++ b/extmod/machine_i2c.c @@ -730,13 +730,14 @@ STATIC const mp_machine_i2c_p_t mp_machine_soft_i2c_p = { .transfer = mp_machine_soft_i2c_transfer, }; -const mp_obj_type_t mp_machine_soft_i2c_type = { - { &mp_type_type }, - .name = MP_QSTR_SoftI2C, - .print = mp_machine_soft_i2c_print, - .make_new = mp_machine_soft_i2c_make_new, - .protocol = &mp_machine_soft_i2c_p, - .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_machine_soft_i2c_type, + MP_QSTR_SoftI2C, + MP_TYPE_FLAG_NONE, + mp_machine_soft_i2c_make_new, + print, mp_machine_soft_i2c_print, + protocol, &mp_machine_soft_i2c_p, + locals_dict, (mp_obj_dict_t *)&mp_machine_i2c_locals_dict + ); #endif // MICROPY_PY_MACHINE_SOFTI2C diff --git a/extmod/machine_mem.c b/extmod/machine_mem.c index 73e2f7fd1f..422e99d3ce 100644 --- a/extmod/machine_mem.c +++ b/extmod/machine_mem.c @@ -101,12 +101,14 @@ STATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t va } } -const mp_obj_type_t machine_mem_type = { - { &mp_type_type }, - .name = MP_QSTR_mem, - .print = machine_mem_print, - .subscr = machine_mem_subscr, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_mem_type, + MP_QSTR_mem, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, machine_mem_print, + subscr, machine_mem_subscr + ); const machine_mem_obj_t machine_mem8_obj = {{&machine_mem_type}, 1}; const machine_mem_obj_t machine_mem16_obj = {{&machine_mem_type}, 2}; diff --git a/extmod/machine_pinbase.c b/extmod/machine_pinbase.c index 070c5cde9d..617dd1280c 100644 --- a/extmod/machine_pinbase.c +++ b/extmod/machine_pinbase.c @@ -77,11 +77,12 @@ STATIC const mp_pin_p_t pinbase_pin_p = { .ioctl = pinbase_ioctl, }; -const mp_obj_type_t machine_pinbase_type = { - { &mp_type_type }, - .name = MP_QSTR_PinBase, - .make_new = pinbase_make_new, - .protocol = &pinbase_pin_p, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_pinbase_type, + MP_QSTR_PinBase, + MP_TYPE_FLAG_NONE, + pinbase_make_new, + protocol, &pinbase_pin_p + ); #endif // MICROPY_PY_MACHINE diff --git a/extmod/machine_pwm.c b/extmod/machine_pwm.c index ddf49c1358..f12f70a2d1 100644 --- a/extmod/machine_pwm.c +++ b/extmod/machine_pwm.c @@ -132,12 +132,13 @@ STATIC const mp_rom_map_elem_t machine_pwm_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_pwm_locals_dict, machine_pwm_locals_dict_table); -const mp_obj_type_t machine_pwm_type = { - { &mp_type_type }, - .name = MP_QSTR_PWM, - .print = mp_machine_pwm_print, - .make_new = mp_machine_pwm_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_pwm_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_pwm_type, + MP_QSTR_PWM, + MP_TYPE_FLAG_NONE, + mp_machine_pwm_make_new, + print, mp_machine_pwm_print, + locals_dict, &machine_pwm_locals_dict + ); #endif // MICROPY_PY_MACHINE_PWM diff --git a/extmod/machine_signal.c b/extmod/machine_signal.c index cf7550a2e0..818bc01c27 100644 --- a/extmod/machine_signal.c +++ b/extmod/machine_signal.c @@ -172,13 +172,14 @@ STATIC const mp_pin_p_t signal_pin_p = { .ioctl = signal_ioctl, }; -const mp_obj_type_t machine_signal_type = { - { &mp_type_type }, - .name = MP_QSTR_Signal, - .make_new = signal_make_new, - .call = signal_call, - .protocol = &signal_pin_p, - .locals_dict = (void *)&signal_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_signal_type, + MP_QSTR_Signal, + MP_TYPE_FLAG_NONE, + signal_make_new, + call, signal_call, + protocol, &signal_pin_p, + locals_dict, (void *)&signal_locals_dict + ); #endif // MICROPY_PY_MACHINE diff --git a/extmod/machine_spi.c b/extmod/machine_spi.c index ba533b2a65..43148c9c8d 100644 --- a/extmod/machine_spi.c +++ b/extmod/machine_spi.c @@ -251,13 +251,14 @@ const mp_machine_spi_p_t mp_machine_soft_spi_p = { .transfer = mp_machine_soft_spi_transfer, }; -const mp_obj_type_t mp_machine_soft_spi_type = { - { &mp_type_type }, - .name = MP_QSTR_SoftSPI, - .print = mp_machine_soft_spi_print, - .make_new = mp_machine_soft_spi_make_new, - .protocol = &mp_machine_soft_spi_p, - .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_machine_soft_spi_type, + MP_QSTR_SoftSPI, + MP_TYPE_FLAG_NONE, + mp_machine_soft_spi_make_new, + print, mp_machine_soft_spi_print, + protocol, &mp_machine_soft_spi_p, + locals_dict, (mp_obj_dict_t *)&mp_machine_spi_locals_dict + ); #endif // MICROPY_PY_MACHINE_SOFTSPI diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 4cc57b3d55..2b7497e1b6 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -240,16 +240,16 @@ STATIC void ringbuf_get_uuid(ringbuf_t *ringbuf, mp_obj_bluetooth_uuid_t *uuid) #endif // !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS -const mp_obj_type_t mp_type_bluetooth_uuid = { - { &mp_type_type }, - .name = MP_QSTR_UUID, - .make_new = bluetooth_uuid_make_new, - .unary_op = bluetooth_uuid_unary_op, - .binary_op = bluetooth_uuid_binary_op, - .locals_dict = NULL, - .print = bluetooth_uuid_print, - .buffer = bluetooth_uuid_get_buffer, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_bluetooth_uuid, + MP_QSTR_UUID, + MP_TYPE_FLAG_NONE, + bluetooth_uuid_make_new, + unary_op, bluetooth_uuid_unary_op, + binary_op, bluetooth_uuid_binary_op, + print, bluetooth_uuid_print, + buffer, bluetooth_uuid_get_buffer + ); // ---------------------------------------------------------------------------- // Bluetooth object: General @@ -976,12 +976,13 @@ STATIC const mp_rom_map_elem_t bluetooth_ble_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(bluetooth_ble_locals_dict, bluetooth_ble_locals_dict_table); -STATIC const mp_obj_type_t mp_type_bluetooth_ble = { - { &mp_type_type }, - .name = MP_QSTR_BLE, - .make_new = bluetooth_ble_make_new, - .locals_dict = (void *)&bluetooth_ble_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_bluetooth_ble, + MP_QSTR_BLE, + MP_TYPE_FLAG_NONE, + bluetooth_ble_make_new, + locals_dict, (void *)&bluetooth_ble_locals_dict + ); STATIC const mp_rom_map_elem_t mp_module_bluetooth_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubluetooth) }, diff --git a/extmod/modbtree.c b/extmod/modbtree.c index 7a1daacb41..f115be44fe 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -319,17 +319,19 @@ STATIC const mp_rom_map_elem_t btree_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(btree_locals_dict, btree_locals_dict_table); -STATIC const mp_obj_type_t btree_type = { - { &mp_type_type }, +STATIC MP_DEFINE_CONST_OBJ_TYPE( + btree_type, + MP_QSTR_btree, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, // Save on qstr's, reuse same as for module - .name = MP_QSTR_btree, - .print = btree_print, - .getiter = btree_getiter, - .iternext = btree_iternext, - .binary_op = btree_binary_op, - .subscr = btree_subscr, - .locals_dict = (void *)&btree_locals_dict, -}; + print, btree_print, + getiter, btree_getiter, + iternext, btree_iternext, + binary_op, btree_binary_op, + subscr, btree_subscr, + locals_dict, (void *)&btree_locals_dict + ); #endif STATIC const FILEVTABLE btree_stream_fvtable = { diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index 9542d4303e..1d44312cf3 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -829,13 +829,14 @@ STATIC const mp_rom_map_elem_t framebuf_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table); -STATIC const mp_obj_type_t mp_type_framebuf = { - { &mp_type_type }, - .name = MP_QSTR_FrameBuffer, - .make_new = framebuf_make_new, - .buffer = framebuf_get_buffer, - .locals_dict = (mp_obj_dict_t *)&framebuf_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_framebuf, + MP_QSTR_FrameBuffer, + MP_TYPE_FLAG_NONE, + framebuf_make_new, + buffer, framebuf_get_buffer, + locals_dict, (mp_obj_dict_t *)&framebuf_locals_dict + ); #endif // this factory function is provided for backwards compatibility with old FrameBuffer1 class diff --git a/extmod/modlwip.c b/extmod/modlwip.c index f9451a0ce4..f9d5b76b2c 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -177,12 +177,13 @@ STATIC const mp_rom_map_elem_t lwip_slip_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(lwip_slip_locals_dict, lwip_slip_locals_dict_table); -STATIC const mp_obj_type_t lwip_slip_type = { - { &mp_type_type }, - .name = MP_QSTR_slip, - .make_new = lwip_slip_make_new, - .locals_dict = (mp_obj_dict_t *)&lwip_slip_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + lwip_slip_type, + MP_QSTR_slip, + MP_TYPE_FLAG_NONE, + lwip_slip_make_new, + locals_dict, (mp_obj_dict_t *)&lwip_slip_locals_dict + ); #endif // MICROPY_PY_LWIP_SLIP @@ -1594,14 +1595,15 @@ STATIC const mp_stream_p_t lwip_socket_stream_p = { .ioctl = lwip_socket_ioctl, }; -STATIC const mp_obj_type_t lwip_socket_type = { - { &mp_type_type }, - .name = MP_QSTR_socket, - .print = lwip_socket_print, - .make_new = lwip_socket_make_new, - .protocol = &lwip_socket_stream_p, - .locals_dict = (mp_obj_dict_t *)&lwip_socket_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + lwip_socket_type, + MP_QSTR_socket, + MP_TYPE_FLAG_NONE, + lwip_socket_make_new, + print, lwip_socket_print, + protocol, &lwip_socket_stream_p, + locals_dict, (mp_obj_dict_t *)&lwip_socket_locals_dict + ); /******************************************************************************/ // Support functions for memory protection. lwIP has its own memory management diff --git a/extmod/moduasyncio.c b/extmod/moduasyncio.c index 6e3603fa18..500d13c5b8 100644 --- a/extmod/moduasyncio.c +++ b/extmod/moduasyncio.c @@ -144,12 +144,13 @@ STATIC const mp_rom_map_elem_t task_queue_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(task_queue_locals_dict, task_queue_locals_dict_table); -STATIC const mp_obj_type_t task_queue_type = { - { &mp_type_type }, - .name = MP_QSTR_TaskQueue, - .make_new = task_queue_make_new, - .locals_dict = (mp_obj_dict_t *)&task_queue_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + task_queue_type, + MP_QSTR_TaskQueue, + MP_TYPE_FLAG_NONE, + task_queue_make_new, + locals_dict, (mp_obj_dict_t *)&task_queue_locals_dict + ); /******************************************************************************/ // Task class @@ -286,14 +287,15 @@ STATIC mp_obj_t task_iternext(mp_obj_t self_in) { return mp_const_none; } -STATIC const mp_obj_type_t task_type = { - { &mp_type_type }, - .name = MP_QSTR_Task, - .make_new = task_make_new, - .attr = task_attr, - .getiter = task_getiter, - .iternext = task_iternext, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + task_type, + MP_QSTR_Task, + MP_TYPE_FLAG_NONE, + task_make_new, + attr, task_attr, + getiter, task_getiter, + iternext, task_iternext + ); /******************************************************************************/ // C-level uasyncio module diff --git a/extmod/moducryptolib.c b/extmod/moducryptolib.c index dc0ecb9b20..236b7edfd7 100644 --- a/extmod/moducryptolib.c +++ b/extmod/moducryptolib.c @@ -348,12 +348,13 @@ STATIC const mp_rom_map_elem_t ucryptolib_aes_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(ucryptolib_aes_locals_dict, ucryptolib_aes_locals_dict_table); -STATIC const mp_obj_type_t ucryptolib_aes_type = { - { &mp_type_type }, - .name = MP_QSTR_aes, - .make_new = ucryptolib_aes_make_new, - .locals_dict = (void *)&ucryptolib_aes_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + ucryptolib_aes_type, + MP_QSTR_aes, + MP_TYPE_FLAG_NONE, + ucryptolib_aes_make_new, + locals_dict, (void *)&ucryptolib_aes_locals_dict + ); STATIC const mp_rom_map_elem_t mp_module_ucryptolib_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ucryptolib) }, diff --git a/extmod/moductypes.c b/extmod/moductypes.c index 25578dd6b0..a9ad500c2d 100644 --- a/extmod/moductypes.c +++ b/extmod/moductypes.c @@ -634,16 +634,17 @@ STATIC mp_obj_t uctypes_struct_bytes_at(mp_obj_t ptr, mp_obj_t size) { } MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytes_at_obj, uctypes_struct_bytes_at); -STATIC const mp_obj_type_t uctypes_struct_type = { - { &mp_type_type }, - .name = MP_QSTR_struct, - .print = uctypes_struct_print, - .make_new = uctypes_struct_make_new, - .attr = uctypes_struct_attr, - .subscr = uctypes_struct_subscr, - .unary_op = uctypes_struct_unary_op, - .buffer = uctypes_get_buffer, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + uctypes_struct_type, + MP_QSTR_struct, + MP_TYPE_FLAG_NONE, + uctypes_struct_make_new, + print, uctypes_struct_print, + attr, uctypes_struct_attr, + subscr, uctypes_struct_subscr, + unary_op, uctypes_struct_unary_op, + buffer, uctypes_get_buffer + ); STATIC const mp_rom_map_elem_t mp_module_uctypes_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uctypes) }, diff --git a/extmod/moduhashlib.c b/extmod/moduhashlib.c index 7eae06b77d..44625ed6da 100644 --- a/extmod/moduhashlib.c +++ b/extmod/moduhashlib.c @@ -157,12 +157,13 @@ STATIC const mp_rom_map_elem_t uhashlib_sha256_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(uhashlib_sha256_locals_dict, uhashlib_sha256_locals_dict_table); -STATIC const mp_obj_type_t uhashlib_sha256_type = { - { &mp_type_type }, - .name = MP_QSTR_sha256, - .make_new = uhashlib_sha256_make_new, - .locals_dict = (void *)&uhashlib_sha256_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + uhashlib_sha256_type, + MP_QSTR_sha256, + MP_TYPE_FLAG_NONE, + uhashlib_sha256_make_new, + locals_dict, (void *)&uhashlib_sha256_locals_dict + ); #endif #if MICROPY_PY_UHASHLIB_SHA1 @@ -250,12 +251,13 @@ STATIC const mp_rom_map_elem_t uhashlib_sha1_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(uhashlib_sha1_locals_dict, uhashlib_sha1_locals_dict_table); -STATIC const mp_obj_type_t uhashlib_sha1_type = { - { &mp_type_type }, - .name = MP_QSTR_sha1, - .make_new = uhashlib_sha1_make_new, - .locals_dict = (void *)&uhashlib_sha1_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + uhashlib_sha1_type, + MP_QSTR_sha1, + MP_TYPE_FLAG_NONE, + uhashlib_sha1_make_new, + locals_dict, (void *)&uhashlib_sha1_locals_dict + ); #endif #if MICROPY_PY_UHASHLIB_MD5 @@ -343,12 +345,13 @@ STATIC const mp_rom_map_elem_t uhashlib_md5_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(uhashlib_md5_locals_dict, uhashlib_md5_locals_dict_table); -STATIC const mp_obj_type_t uhashlib_md5_type = { - { &mp_type_type }, - .name = MP_QSTR_md5, - .make_new = uhashlib_md5_make_new, - .locals_dict = (void *)&uhashlib_md5_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + uhashlib_md5_type, + MP_QSTR_md5, + MP_TYPE_FLAG_NONE, + uhashlib_md5_make_new, + locals_dict, (void *)&uhashlib_md5_locals_dict + ); #endif // MICROPY_PY_UHASHLIB_MD5 STATIC const mp_rom_map_elem_t mp_module_uhashlib_globals_table[] = { diff --git a/extmod/modure.c b/extmod/modure.c index a674d66499..a27c7ff9fd 100644 --- a/extmod/modure.c +++ b/extmod/modure.c @@ -179,12 +179,14 @@ STATIC const mp_rom_map_elem_t match_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table); -STATIC const mp_obj_type_t match_type = { - { &mp_type_type }, - .name = MP_QSTR_match, - .print = match_print, - .locals_dict = (void *)&match_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + match_type, + MP_QSTR_match, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, match_print, + locals_dict, (void *)&match_locals_dict + ); #endif STATIC void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -411,12 +413,14 @@ STATIC const mp_rom_map_elem_t re_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table); -STATIC const mp_obj_type_t re_type = { - { &mp_type_type }, - .name = MP_QSTR_ure, - .print = re_print, - .locals_dict = (void *)&re_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + re_type, + MP_QSTR_ure, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, re_print, + locals_dict, (void *)&re_locals_dict + ); #endif STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) { diff --git a/extmod/moduselect.c b/extmod/moduselect.c index 70a1de2e40..1a11ee0eab 100644 --- a/extmod/moduselect.c +++ b/extmod/moduselect.c @@ -336,13 +336,15 @@ STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table); -STATIC const mp_obj_type_t mp_type_poll = { - { &mp_type_type }, - .name = MP_QSTR_poll, - .getiter = mp_identity_getiter, - .iternext = poll_iternext, - .locals_dict = (void *)&poll_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_poll, + MP_QSTR_poll, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + getiter, mp_identity_getiter, + iternext, poll_iternext, + locals_dict, (void *)&poll_locals_dict + ); // poll() STATIC mp_obj_t select_poll(void) { diff --git a/extmod/modusocket.c b/extmod/modusocket.c index 4d72531160..6008edb11c 100644 --- a/extmod/modusocket.c +++ b/extmod/modusocket.c @@ -528,14 +528,15 @@ STATIC const mp_stream_p_t socket_stream_p = { .is_text = false, }; -STATIC const mp_obj_type_t socket_type = { - { &mp_type_type }, - .name = MP_QSTR_socket, - .print = socket_print, - .make_new = socket_make_new, - .protocol = &socket_stream_p, - .locals_dict = (mp_obj_dict_t *)&socket_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + socket_type, + MP_QSTR_socket, + MP_TYPE_FLAG_NONE, + socket_make_new, + protocol, &socket_stream_p, + locals_dict, (mp_obj_dict_t *)&socket_locals_dict, + print, socket_print + ); /******************************************************************************/ // usocket module diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c index 9ba613a3e8..72eb0e214f 100644 --- a/extmod/modussl_axtls.c +++ b/extmod/modussl_axtls.c @@ -314,16 +314,18 @@ STATIC const mp_stream_p_t ussl_socket_stream_p = { .ioctl = ussl_socket_ioctl, }; -STATIC const mp_obj_type_t ussl_socket_type = { - { &mp_type_type }, +STATIC MP_DEFINE_CONST_OBJ_TYPE( + ussl_socket_type, + MP_QSTR_ussl, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, // Save on qstr's, reuse same as for module - .name = MP_QSTR_ussl, - .print = ussl_socket_print, - .getiter = NULL, - .iternext = NULL, - .protocol = &ussl_socket_stream_p, - .locals_dict = (void *)&ussl_socket_locals_dict, -}; + print, ussl_socket_print, + getiter, NULL, + iternext, NULL, + protocol, &ussl_socket_stream_p, + locals_dict, (void *)&ussl_socket_locals_dict + ); STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // TODO: Implement more args diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c index b14ed9ad0e..0fab915f3f 100644 --- a/extmod/modussl_mbedtls.c +++ b/extmod/modussl_mbedtls.c @@ -392,16 +392,18 @@ STATIC const mp_stream_p_t ussl_socket_stream_p = { .ioctl = socket_ioctl, }; -STATIC const mp_obj_type_t ussl_socket_type = { - { &mp_type_type }, +STATIC MP_DEFINE_CONST_OBJ_TYPE( + ussl_socket_type, + MP_QSTR_ussl, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, // Save on qstr's, reuse same as for module - .name = MP_QSTR_ussl, - .print = socket_print, - .getiter = NULL, - .iternext = NULL, - .protocol = &ussl_socket_stream_p, - .locals_dict = (void *)&ussl_socket_locals_dict, -}; + print, socket_print, + getiter, NULL, + iternext, NULL, + protocol, &ussl_socket_stream_p, + locals_dict, (void *)&ussl_socket_locals_dict + ); STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // TODO: Implement more args diff --git a/extmod/modutimeq.c b/extmod/modutimeq.c index 1dde90bd1b..bf4e031895 100644 --- a/extmod/modutimeq.c +++ b/extmod/modutimeq.c @@ -209,13 +209,14 @@ STATIC const mp_rom_map_elem_t utimeq_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(utimeq_locals_dict, utimeq_locals_dict_table); -STATIC const mp_obj_type_t utimeq_type = { - { &mp_type_type }, - .name = MP_QSTR_utimeq, - .make_new = utimeq_make_new, - .unary_op = utimeq_unary_op, - .locals_dict = (void *)&utimeq_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + utimeq_type, + MP_QSTR_utimeq, + MP_TYPE_FLAG_NONE, + utimeq_make_new, + unary_op, utimeq_unary_op, + locals_dict, (void *)&utimeq_locals_dict + ); STATIC const mp_rom_map_elem_t mp_module_utimeq_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utimeq) }, diff --git a/extmod/moduwebsocket.c b/extmod/moduwebsocket.c index a9ad0c22e3..2895978f3d 100644 --- a/extmod/moduwebsocket.c +++ b/extmod/moduwebsocket.c @@ -290,13 +290,14 @@ STATIC const mp_stream_p_t websocket_stream_p = { .ioctl = websocket_ioctl, }; -STATIC const mp_obj_type_t websocket_type = { - { &mp_type_type }, - .name = MP_QSTR_websocket, - .make_new = websocket_make_new, - .protocol = &websocket_stream_p, - .locals_dict = (void *)&websocket_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + websocket_type, + MP_QSTR_websocket, + MP_TYPE_FLAG_NONE, + websocket_make_new, + protocol, &websocket_stream_p, + locals_dict, (void *)&websocket_locals_dict + ); STATIC const mp_rom_map_elem_t uwebsocket_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uwebsocket) }, diff --git a/extmod/moduzlib.c b/extmod/moduzlib.c index 0161b9f49c..93c939129e 100644 --- a/extmod/moduzlib.c +++ b/extmod/moduzlib.c @@ -140,13 +140,14 @@ STATIC const mp_stream_p_t decompio_stream_p = { }; #if !MICROPY_ENABLE_DYNRUNTIME -STATIC const mp_obj_type_t decompio_type = { - { &mp_type_type }, - .name = MP_QSTR_DecompIO, - .make_new = decompio_make_new, - .protocol = &decompio_stream_p, - .locals_dict = (void *)&decompio_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + decompio_type, + MP_QSTR_DecompIO, + MP_TYPE_FLAG_NONE, + decompio_make_new, + protocol, &decompio_stream_p, + locals_dict, (void *)&decompio_locals_dict + ); #endif STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) { diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c index 1a2a718acf..cb893b38dc 100644 --- a/extmod/modwebrepl.c +++ b/extmod/modwebrepl.c @@ -342,13 +342,14 @@ STATIC const mp_stream_p_t webrepl_stream_p = { .ioctl = webrepl_ioctl, }; -STATIC const mp_obj_type_t webrepl_type = { - { &mp_type_type }, - .name = MP_QSTR__webrepl, - .make_new = webrepl_make_new, - .protocol = &webrepl_stream_p, - .locals_dict = (mp_obj_dict_t *)&webrepl_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + webrepl_type, + MP_QSTR__webrepl, + MP_TYPE_FLAG_NONE, + webrepl_make_new, + protocol, &webrepl_stream_p, + locals_dict, (mp_obj_dict_t *)&webrepl_locals_dict + ); STATIC const mp_rom_map_elem_t webrepl_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__webrepl) }, diff --git a/extmod/network_cyw43.c b/extmod/network_cyw43.c index 9df799119f..fbd0a750b8 100644 --- a/extmod/network_cyw43.c +++ b/extmod/network_cyw43.c @@ -496,12 +496,13 @@ STATIC const mp_rom_map_elem_t network_cyw43_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(network_cyw43_locals_dict, network_cyw43_locals_dict_table); -const mp_obj_type_t mp_network_cyw43_type = { - { &mp_type_type }, - .name = MP_QSTR_CYW43, - .print = network_cyw43_print, - .make_new = network_cyw43_make_new, - .locals_dict = (mp_obj_dict_t *)&network_cyw43_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_network_cyw43_type, + MP_QSTR_CYW43, + MP_TYPE_FLAG_NONE, + network_cyw43_make_new, + print, network_cyw43_print, + locals_dict, (mp_obj_dict_t *)&network_cyw43_locals_dict + ); #endif // MICROPY_PY_NETWORK_CYW43 diff --git a/extmod/network_ninaw10.c b/extmod/network_ninaw10.c index 4014a71c1a..0906176d20 100644 --- a/extmod/network_ninaw10.c +++ b/extmod/network_ninaw10.c @@ -774,13 +774,16 @@ static const mp_rom_map_elem_t nina_locals_dict_table[] = { static MP_DEFINE_CONST_DICT(nina_locals_dict, nina_locals_dict_table); +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mod_network_nic_type_nina_base, + MP_QSTR_nina, + MP_TYPE_FLAG_NONE, + network_ninaw10_make_new, + locals_dict, &nina_locals_dict + ); + const mod_network_nic_type_t mod_network_nic_type_nina = { - .base = { - { &mp_type_type }, - .name = MP_QSTR_nina, - .make_new = network_ninaw10_make_new, - .locals_dict = (mp_obj_t)&nina_locals_dict, - }, + .base = mod_network_nic_type_nina_base, .gethostbyname = network_ninaw10_gethostbyname, .socket = network_ninaw10_socket_socket, .close = network_ninaw10_socket_close, diff --git a/extmod/network_wiznet5k.c b/extmod/network_wiznet5k.c index 95c852d7f7..951a2966c9 100644 --- a/extmod/network_wiznet5k.c +++ b/extmod/network_wiznet5k.c @@ -1016,20 +1016,24 @@ STATIC const mp_rom_map_elem_t wiznet5k_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(wiznet5k_locals_dict, wiznet5k_locals_dict_table); #if WIZNET5K_WITH_LWIP_STACK -const mp_obj_type_t mod_network_nic_type_wiznet5k = { - { &mp_type_type }, - .name = MP_QSTR_WIZNET5K, - .make_new = wiznet5k_make_new, - .locals_dict = (mp_obj_dict_t *)&wiznet5k_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mod_network_nic_type_wiznet5k, + MP_QSTR_WIZNET5K, + MP_TYPE_FLAG_NONE, + wiznet5k_make_new, + locals_dict, &wiznet5k_locals_dict + ); #else // WIZNET5K_PROVIDED_STACK +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mod_network_nic_type_wiznet5k_base, + MP_QSTR_WIZNET5K, + MP_TYPE_FLAG_NONE, + wiznet5k_make_new, + locals_dict, &wiznet5k_locals_dict + ); + const mod_network_nic_type_t mod_network_nic_type_wiznet5k = { - .base = { - { &mp_type_type }, - .name = MP_QSTR_WIZNET5K, - .make_new = wiznet5k_make_new, - .locals_dict = (mp_obj_dict_t *)&wiznet5k_locals_dict, - }, + .base = mod_network_nic_type_wiznet5k_base, .gethostbyname = wiznet5k_gethostbyname, .socket = wiznet5k_socket_socket, .close = wiznet5k_socket_close, diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 8d2f13be47..4a2ef883c2 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -431,12 +431,13 @@ STATIC const mp_vfs_proto_t fat_vfs_proto = { .import_stat = fat_vfs_import_stat, }; -const mp_obj_type_t mp_fat_vfs_type = { - { &mp_type_type }, - .name = MP_QSTR_VfsFat, - .make_new = fat_vfs_make_new, - .protocol = &fat_vfs_proto, - .locals_dict = (mp_obj_dict_t *)&fat_vfs_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_fat_vfs_type, + MP_QSTR_VfsFat, + MP_TYPE_FLAG_NONE, + fat_vfs_make_new, + protocol, &fat_vfs_proto, + locals_dict, (mp_obj_dict_t *)&fat_vfs_locals_dict + ); #endif // MICROPY_VFS_FAT diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index 874f10c500..0d4af09b45 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -176,15 +176,17 @@ STATIC const mp_stream_p_t vfs_fat_fileio_stream_p = { .ioctl = file_obj_ioctl, }; -const mp_obj_type_t mp_type_vfs_fat_fileio = { - { &mp_type_type }, - .name = MP_QSTR_FileIO, - .print = file_obj_print, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &vfs_fat_fileio_stream_p, - .locals_dict = (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_vfs_fat_fileio, + MP_QSTR_FileIO, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, file_obj_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &vfs_fat_fileio_stream_p, + locals_dict, (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict + ); STATIC const mp_stream_p_t vfs_fat_textio_stream_p = { .read = file_obj_read, @@ -193,15 +195,17 @@ STATIC const mp_stream_p_t vfs_fat_textio_stream_p = { .is_text = true, }; -const mp_obj_type_t mp_type_vfs_fat_textio = { - { &mp_type_type }, - .name = MP_QSTR_TextIOWrapper, - .print = file_obj_print, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &vfs_fat_textio_stream_p, - .locals_dict = (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_vfs_fat_textio, + MP_QSTR_TextIOWrapper, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, file_obj_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &vfs_fat_textio_stream_p, + locals_dict, (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict + ); // Factory function for I/O stream classes STATIC mp_obj_t fat_vfs_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) { diff --git a/extmod/vfs_lfsx.c b/extmod/vfs_lfsx.c index fbfeaa5ccf..72c6696105 100644 --- a/extmod/vfs_lfsx.c +++ b/extmod/vfs_lfsx.c @@ -502,14 +502,15 @@ STATIC const mp_vfs_proto_t MP_VFS_LFSx(proto) = { .import_stat = MP_VFS_LFSx(import_stat), }; -const mp_obj_type_t MP_TYPE_VFS_LFSx = { - { &mp_type_type }, +MP_DEFINE_CONST_OBJ_TYPE( + MP_TYPE_VFS_LFSx, #if LFS_BUILD_VERSION == 1 - .name = MP_QSTR_VfsLfs1, + MP_QSTR_VfsLfs1, #else - .name = MP_QSTR_VfsLfs2, + MP_QSTR_VfsLfs2, #endif - .make_new = MP_VFS_LFSx(make_new), - .protocol = &MP_VFS_LFSx(proto), - .locals_dict = (mp_obj_dict_t *)&MP_VFS_LFSx(locals_dict), -}; + MP_TYPE_FLAG_NONE, + MP_VFS_LFSx(make_new), + protocol, &MP_VFS_LFSx(proto), + locals_dict, (mp_obj_dict_t *)&MP_VFS_LFSx(locals_dict) + ); diff --git a/extmod/vfs_lfsx_file.c b/extmod/vfs_lfsx_file.c index 124361feb9..ba90cc6084 100644 --- a/extmod/vfs_lfsx_file.c +++ b/extmod/vfs_lfsx_file.c @@ -220,15 +220,17 @@ STATIC const mp_stream_p_t MP_VFS_LFSx(fileio_stream_p) = { .ioctl = MP_VFS_LFSx(file_ioctl), }; -const mp_obj_type_t MP_TYPE_VFS_LFSx_(_fileio) = { - { &mp_type_type }, - .name = MP_QSTR_FileIO, - .print = MP_VFS_LFSx(file_print), - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &MP_VFS_LFSx(fileio_stream_p), - .locals_dict = (mp_obj_dict_t *)&MP_VFS_LFSx(file_locals_dict), -}; +MP_DEFINE_CONST_OBJ_TYPE( + MP_TYPE_VFS_LFSx_(_fileio), + MP_QSTR_FileIO, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, MP_VFS_LFSx(file_print), + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &MP_VFS_LFSx(fileio_stream_p), + locals_dict, (mp_obj_dict_t *)&MP_VFS_LFSx(file_locals_dict) + ); STATIC const mp_stream_p_t MP_VFS_LFSx(textio_stream_p) = { .read = MP_VFS_LFSx(file_read), @@ -237,12 +239,14 @@ STATIC const mp_stream_p_t MP_VFS_LFSx(textio_stream_p) = { .is_text = true, }; -const mp_obj_type_t MP_TYPE_VFS_LFSx_(_textio) = { - { &mp_type_type }, - .name = MP_QSTR_TextIOWrapper, - .print = MP_VFS_LFSx(file_print), - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &MP_VFS_LFSx(textio_stream_p), - .locals_dict = (mp_obj_dict_t *)&MP_VFS_LFSx(file_locals_dict), -}; +MP_DEFINE_CONST_OBJ_TYPE( + MP_TYPE_VFS_LFSx_(_textio), + MP_QSTR_TextIOWrapper, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, MP_VFS_LFSx(file_print), + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &MP_VFS_LFSx(textio_stream_p), + locals_dict, (mp_obj_dict_t *)&MP_VFS_LFSx(file_locals_dict) + ); diff --git a/extmod/vfs_posix.c b/extmod/vfs_posix.c index 36b211b84d..79126c0070 100644 --- a/extmod/vfs_posix.c +++ b/extmod/vfs_posix.c @@ -398,12 +398,13 @@ STATIC const mp_vfs_proto_t vfs_posix_proto = { .import_stat = mp_vfs_posix_import_stat, }; -const mp_obj_type_t mp_type_vfs_posix = { - { &mp_type_type }, - .name = MP_QSTR_VfsPosix, - .make_new = vfs_posix_make_new, - .protocol = &vfs_posix_proto, - .locals_dict = (mp_obj_dict_t *)&vfs_posix_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_vfs_posix, + MP_QSTR_VfsPosix, + MP_TYPE_FLAG_NONE, + vfs_posix_make_new, + protocol, &vfs_posix_proto, + locals_dict, (mp_obj_dict_t *)&vfs_posix_locals_dict + ); #endif // MICROPY_VFS_POSIX diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index c550842cd4..85aef1617b 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -249,15 +249,17 @@ STATIC const mp_stream_p_t vfs_posix_fileio_stream_p = { .ioctl = vfs_posix_file_ioctl, }; -const mp_obj_type_t mp_type_vfs_posix_fileio = { - { &mp_type_type }, - .name = MP_QSTR_FileIO, - .print = vfs_posix_file_print, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &vfs_posix_fileio_stream_p, - .locals_dict = (mp_obj_dict_t *)&vfs_posix_rawfile_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_vfs_posix_fileio, + MP_QSTR_FileIO, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, vfs_posix_file_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &vfs_posix_fileio_stream_p, + locals_dict, (mp_obj_dict_t *)&vfs_posix_rawfile_locals_dict + ); STATIC const mp_stream_p_t vfs_posix_textio_stream_p = { .read = vfs_posix_file_read, @@ -266,15 +268,17 @@ STATIC const mp_stream_p_t vfs_posix_textio_stream_p = { .is_text = true, }; -const mp_obj_type_t mp_type_vfs_posix_textio = { - { &mp_type_type }, - .name = MP_QSTR_TextIOWrapper, - .print = vfs_posix_file_print, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &vfs_posix_textio_stream_p, - .locals_dict = (mp_obj_dict_t *)&vfs_posix_rawfile_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_vfs_posix_textio, + MP_QSTR_TextIOWrapper, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, vfs_posix_file_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &vfs_posix_textio_stream_p, + locals_dict, (mp_obj_dict_t *)&vfs_posix_rawfile_locals_dict + ); const mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_vfs_posix_textio}, STDIN_FILENO}; const mp_obj_vfs_posix_file_t mp_sys_stdout_obj = {{&mp_type_vfs_posix_textio}, STDOUT_FILENO}; diff --git a/ports/cc3200/misc/mpirq.c b/ports/cc3200/misc/mpirq.c index eb93e5eef0..e9cae92a32 100644 --- a/ports/cc3200/misc/mpirq.c +++ b/ports/cc3200/misc/mpirq.c @@ -190,11 +190,13 @@ STATIC const mp_rom_map_elem_t mp_irq_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(mp_irq_locals_dict, mp_irq_locals_dict_table); -const mp_obj_type_t mp_irq_type = { - { &mp_type_type }, - .name = MP_QSTR_irq, - .call = mp_irq_call, - .locals_dict = (mp_obj_t)&mp_irq_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_irq_type, + MP_QSTR_irq, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + call, mp_irq_call, + locals_dict, (mp_obj_t)&mp_irq_locals_dict + ); MP_REGISTER_ROOT_POINTER(mp_obj_list_t mp_irq_obj_list); diff --git a/ports/cc3200/mods/modnetwork.c b/ports/cc3200/mods/modnetwork.c index d6ccc7c6a0..a741893007 100644 --- a/ports/cc3200/mods/modnetwork.c +++ b/ports/cc3200/mods/modnetwork.c @@ -171,10 +171,11 @@ STATIC const mp_rom_map_elem_t network_server_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(network_server_locals_dict, network_server_locals_dict_table); -STATIC const mp_obj_type_t network_server_type = { - { &mp_type_type }, - .name = MP_QSTR_Server, - .make_new = network_server_make_new, - .locals_dict = (mp_obj_t)&network_server_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + network_server_type, + MP_QSTR_Server, + MP_TYPE_FLAG_NONE, + network_server_make_new, + locals_dict, (mp_obj_t)&network_server_locals_dict + ); #endif diff --git a/ports/cc3200/mods/moduhashlib.c b/ports/cc3200/mods/moduhashlib.c index fc11569b7f..5437cfb264 100644 --- a/ports/cc3200/mods/moduhashlib.c +++ b/ports/cc3200/mods/moduhashlib.c @@ -177,19 +177,21 @@ STATIC MP_DEFINE_CONST_DICT(hash_locals_dict, hash_locals_dict_table); // .locals_dict = (mp_obj_t)&hash_locals_dict, //}; -STATIC const mp_obj_type_t sha1_type = { - { &mp_type_type }, - .name = MP_QSTR_sha1, - .make_new = hash_make_new, - .locals_dict = (mp_obj_t)&hash_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + sha1_type, + MP_QSTR_sha1, + MP_TYPE_FLAG_NONE, + hash_make_new, + locals_dict, (mp_obj_t)&hash_locals_dict + ); -STATIC const mp_obj_type_t sha256_type = { - { &mp_type_type }, - .name = MP_QSTR_sha256, - .make_new = hash_make_new, - .locals_dict = (mp_obj_t)&hash_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + sha256_type, + MP_QSTR_sha256, + MP_TYPE_FLAG_NONE, + hash_make_new, + locals_dict, (mp_obj_t)&hash_locals_dict + ); STATIC const mp_rom_map_elem_t mp_module_hashlib_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uhashlib) }, diff --git a/ports/cc3200/mods/modusocket.c b/ports/cc3200/mods/modusocket.c index 23982eb966..11199de146 100644 --- a/ports/cc3200/mods/modusocket.c +++ b/ports/cc3200/mods/modusocket.c @@ -759,13 +759,14 @@ const mp_stream_p_t socket_stream_p = { .is_text = false, }; -STATIC const mp_obj_type_t socket_type = { - { &mp_type_type }, - .name = MP_QSTR_socket, - .make_new = socket_make_new, - .protocol = &socket_stream_p, - .locals_dict = (mp_obj_t)&socket_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + socket_type, + MP_QSTR_socket, + MP_TYPE_FLAG_NONE, + socket_make_new, + protocol, &socket_stream_p, + locals_dict, (mp_obj_t)&socket_locals_dict + ); /******************************************************************************/ // usocket module diff --git a/ports/cc3200/mods/modussl.c b/ports/cc3200/mods/modussl.c index cd2c62dcb8..d0909e7c29 100644 --- a/ports/cc3200/mods/modussl.c +++ b/ports/cc3200/mods/modussl.c @@ -60,14 +60,16 @@ STATIC const mp_obj_type_t ssl_socket_type; // ssl sockets inherit from normal socket, so we take its // locals and stream methods -STATIC const mp_obj_type_t ssl_socket_type = { - { &mp_type_type }, - .name = MP_QSTR_ussl, - .getiter = NULL, - .iternext = NULL, - .protocol = &socket_stream_p, - .locals_dict = (mp_obj_t)&socket_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + ssl_socket_type, + MP_QSTR_ussl, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + getiter, NULL, + iternext, NULL, + protocol, &socket_stream_p, + locals_dict, (mp_obj_t)&socket_locals_dict + ); STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC const mp_arg_t allowed_args[] = { diff --git a/ports/cc3200/mods/modwlan.c b/ports/cc3200/mods/modwlan.c index 3b686932e8..24f5d196d2 100644 --- a/ports/cc3200/mods/modwlan.c +++ b/ports/cc3200/mods/modwlan.c @@ -1285,13 +1285,16 @@ STATIC const mp_rom_map_elem_t wlan_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(wlan_locals_dict, wlan_locals_dict_table); +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mod_network_nic_type_wlan_base, + MP_QSTR_WLAN, + MP_TYPE_FLAG_NONE, + wlan_make_new, + locals_dict, (mp_obj_t)&wlan_locals_dict + ); + const mod_network_nic_type_t mod_network_nic_type_wlan = { - .base = { - { &mp_type_type }, - .name = MP_QSTR_WLAN, - .make_new = wlan_make_new, - .locals_dict = (mp_obj_t)&wlan_locals_dict, - }, + .base = mod_network_nic_type_wlan_base, }; STATIC const mp_irq_methods_t wlan_irq_methods = { diff --git a/ports/cc3200/mods/pybadc.c b/ports/cc3200/mods/pybadc.c index fbdd393cd2..a114eeda16 100644 --- a/ports/cc3200/mods/pybadc.c +++ b/ports/cc3200/mods/pybadc.c @@ -233,13 +233,14 @@ STATIC const mp_rom_map_elem_t adc_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table); -const mp_obj_type_t pyb_adc_type = { - { &mp_type_type }, - .name = MP_QSTR_ADC, - .print = adc_print, - .make_new = adc_make_new, - .locals_dict = (mp_obj_t)&adc_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_adc_type, + MP_QSTR_ADC, + MP_TYPE_FLAG_NONE, + adc_make_new, + print, adc_print, + locals_dict, (mp_obj_t)&adc_locals_dict + ); STATIC void adc_channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_adc_channel_obj_t *self = self_in; @@ -300,10 +301,12 @@ STATIC const mp_rom_map_elem_t adc_channel_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(adc_channel_locals_dict, adc_channel_locals_dict_table); -STATIC const mp_obj_type_t pyb_adc_channel_type = { - { &mp_type_type }, - .name = MP_QSTR_ADCChannel, - .print = adc_channel_print, - .call = adc_channel_call, - .locals_dict = (mp_obj_t)&adc_channel_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + pyb_adc_channel_type, + MP_QSTR_ADCChannel, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, adc_channel_print, + call, adc_channel_call, + locals_dict, (mp_obj_t)&adc_channel_locals_dict + ); diff --git a/ports/cc3200/mods/pybflash.c b/ports/cc3200/mods/pybflash.c index 9d534608be..4cfafb7abf 100644 --- a/ports/cc3200/mods/pybflash.c +++ b/ports/cc3200/mods/pybflash.c @@ -84,12 +84,13 @@ STATIC const mp_rom_map_elem_t pyb_flash_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_flash_locals_dict, pyb_flash_locals_dict_table); -const mp_obj_type_t pyb_flash_type = { - { &mp_type_type }, - .name = MP_QSTR_Flash, - .make_new = pyb_flash_make_new, - .locals_dict = (mp_obj_t)&pyb_flash_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_flash_type, + MP_QSTR_Flash, + MP_TYPE_FLAG_NONE, + pyb_flash_make_new, + locals_dict, (mp_obj_t)&pyb_flash_locals_dict + ); void pyb_flash_init_vfs(fs_user_mount_t *vfs) { vfs->base.type = &mp_fat_vfs_type; diff --git a/ports/cc3200/mods/pybi2c.c b/ports/cc3200/mods/pybi2c.c index 40b3e2a207..91a0b9b9f9 100644 --- a/ports/cc3200/mods/pybi2c.c +++ b/ports/cc3200/mods/pybi2c.c @@ -521,10 +521,11 @@ STATIC const mp_rom_map_elem_t pyb_i2c_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table); -const mp_obj_type_t pyb_i2c_type = { - { &mp_type_type }, - .name = MP_QSTR_I2C, - .print = pyb_i2c_print, - .make_new = pyb_i2c_make_new, - .locals_dict = (mp_obj_t)&pyb_i2c_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_i2c_type, + MP_QSTR_I2C, + MP_TYPE_FLAG_NONE, + pyb_i2c_make_new, + print, pyb_i2c_print, + locals_dict, (mp_obj_t)&pyb_i2c_locals_dict + ); diff --git a/ports/cc3200/mods/pybpin.c b/ports/cc3200/mods/pybpin.c index fd2f032e8d..948cda70d4 100644 --- a/ports/cc3200/mods/pybpin.c +++ b/ports/cc3200/mods/pybpin.c @@ -931,14 +931,15 @@ STATIC const mp_rom_map_elem_t pin_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pin_locals_dict, pin_locals_dict_table); -const mp_obj_type_t pin_type = { - { &mp_type_type }, - .name = MP_QSTR_Pin, - .print = pin_print, - .make_new = pin_make_new, - .call = pin_call, - .locals_dict = (mp_obj_t)&pin_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pin_type, + MP_QSTR_Pin, + MP_TYPE_FLAG_NONE, + pin_make_new, + print, pin_print, + call, pin_call, + locals_dict, (mp_obj_t)&pin_locals_dict + ); STATIC const mp_irq_methods_t pin_irq_methods = { .init = pin_irq, @@ -952,10 +953,12 @@ STATIC void pin_named_pins_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_printf(print, "", self->name); } -const mp_obj_type_t pin_board_pins_obj_type = { - { &mp_type_type }, - .name = MP_QSTR_board, - .print = pin_named_pins_obj_print, - .locals_dict = (mp_obj_t)&pin_board_pins_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pin_board_pins_obj_type, + MP_QSTR_board, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, pin_named_pins_obj_print, + locals_dict, (mp_obj_t)&pin_board_pins_locals_dict + ); diff --git a/ports/cc3200/mods/pybrtc.c b/ports/cc3200/mods/pybrtc.c index 6c1918831c..2761cb3c64 100644 --- a/ports/cc3200/mods/pybrtc.c +++ b/ports/cc3200/mods/pybrtc.c @@ -469,12 +469,13 @@ STATIC const mp_rom_map_elem_t pyb_rtc_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table); -const mp_obj_type_t pyb_rtc_type = { - { &mp_type_type }, - .name = MP_QSTR_RTC, - .make_new = pyb_rtc_make_new, - .locals_dict = (mp_obj_t)&pyb_rtc_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_rtc_type, + MP_QSTR_RTC, + MP_TYPE_FLAG_NONE, + pyb_rtc_make_new, + locals_dict, (mp_obj_t)&pyb_rtc_locals_dict + ); STATIC const mp_irq_methods_t pyb_rtc_irq_methods = { .init = pyb_rtc_irq, diff --git a/ports/cc3200/mods/pybsd.c b/ports/cc3200/mods/pybsd.c index 817127634d..d8834e36f7 100644 --- a/ports/cc3200/mods/pybsd.c +++ b/ports/cc3200/mods/pybsd.c @@ -212,9 +212,10 @@ STATIC const mp_rom_map_elem_t pyb_sd_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_sd_locals_dict, pyb_sd_locals_dict_table); -const mp_obj_type_t pyb_sd_type = { - { &mp_type_type }, - .name = MP_QSTR_SD, - .make_new = pyb_sd_make_new, - .locals_dict = (mp_obj_t)&pyb_sd_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_sd_type, + MP_QSTR_SD, + MP_TYPE_FLAG_NONE, + pyb_sd_make_new, + locals_dict, (mp_obj_t)&pyb_sd_locals_dict + ); diff --git a/ports/cc3200/mods/pybsleep.c b/ports/cc3200/mods/pybsleep.c index 76fe0849a4..423099991f 100644 --- a/ports/cc3200/mods/pybsleep.c +++ b/ports/cc3200/mods/pybsleep.c @@ -125,10 +125,12 @@ STATIC pybsleep_data_t pybsleep_data = {NULL, NULL, NULL}; volatile arm_cm4_core_regs_t vault_arm_registers; STATIC pybsleep_reset_cause_t pybsleep_reset_cause = PYB_SLP_PWRON_RESET; STATIC pybsleep_wake_reason_t pybsleep_wake_reason = PYB_SLP_WAKED_PWRON; -STATIC const mp_obj_type_t pyb_sleep_type = { - { &mp_type_type }, - .name = MP_QSTR_sleep, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + pyb_sleep_type, + MP_QSTR_sleep, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW + ); /****************************************************************************** DECLARE PRIVATE FUNCTIONS diff --git a/ports/cc3200/mods/pybspi.c b/ports/cc3200/mods/pybspi.c index ed03b09060..50d897633e 100644 --- a/ports/cc3200/mods/pybspi.c +++ b/ports/cc3200/mods/pybspi.c @@ -377,10 +377,11 @@ STATIC const mp_rom_map_elem_t pyb_spi_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table); -const mp_obj_type_t pyb_spi_type = { - { &mp_type_type }, - .name = MP_QSTR_SPI, - .print = pyb_spi_print, - .make_new = pyb_spi_make_new, - .locals_dict = (mp_obj_t)&pyb_spi_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_spi_type, + MP_QSTR_SPI, + MP_TYPE_FLAG_NONE, + pyb_spi_make_new, + print, pyb_spi_print, + locals_dict, (mp_obj_t)&pyb_spi_locals_dict + ); diff --git a/ports/cc3200/mods/pybtimer.c b/ports/cc3200/mods/pybtimer.c index b2725ae166..a8bc7821e0 100644 --- a/ports/cc3200/mods/pybtimer.c +++ b/ports/cc3200/mods/pybtimer.c @@ -459,13 +459,14 @@ STATIC const mp_rom_map_elem_t pyb_timer_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table); -const mp_obj_type_t pyb_timer_type = { - { &mp_type_type }, - .name = MP_QSTR_Timer, - .print = pyb_timer_print, - .make_new = pyb_timer_make_new, - .locals_dict = (mp_obj_t)&pyb_timer_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_timer_type, + MP_QSTR_Timer, + MP_TYPE_FLAG_NONE, + pyb_timer_make_new, + print, pyb_timer_print, + locals_dict, (mp_obj_t)&pyb_timer_locals_dict + ); STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods = { .init = pyb_timer_channel_irq, @@ -721,11 +722,13 @@ STATIC const mp_rom_map_elem_t pyb_timer_channel_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table); -STATIC const mp_obj_type_t pyb_timer_channel_type = { - { &mp_type_type }, - .name = MP_QSTR_TimerChannel, - .print = pyb_timer_channel_print, - .locals_dict = (mp_obj_t)&pyb_timer_channel_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + pyb_timer_channel_type, + MP_QSTR_TimerChannel, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, pyb_timer_channel_print, + locals_dict, (mp_obj_t)&pyb_timer_channel_locals_dict + ); MP_REGISTER_ROOT_POINTER(mp_obj_list_t pyb_timer_channel_obj_list); diff --git a/ports/cc3200/mods/pybuart.c b/ports/cc3200/mods/pybuart.c index a81954abb8..059101f4f2 100644 --- a/ports/cc3200/mods/pybuart.c +++ b/ports/cc3200/mods/pybuart.c @@ -685,15 +685,16 @@ STATIC const mp_irq_methods_t uart_irq_methods = { .flags = uart_irq_flags }; -const mp_obj_type_t pyb_uart_type = { - { &mp_type_type }, - .name = MP_QSTR_UART, - .print = pyb_uart_print, - .make_new = pyb_uart_make_new, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &uart_stream_p, - .locals_dict = (mp_obj_t)&pyb_uart_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_uart_type, + MP_QSTR_UART, + MP_TYPE_FLAG_NONE, + pyb_uart_make_new, + print, pyb_uart_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &uart_stream_p, + locals_dict, (mp_obj_t)&pyb_uart_locals_dict + ); MP_REGISTER_ROOT_POINTER(struct _pyb_uart_obj_t *pyb_uart_objs[2]); diff --git a/ports/cc3200/mods/pybwdt.c b/ports/cc3200/mods/pybwdt.c index 8db096d6b5..cde1abe59d 100644 --- a/ports/cc3200/mods/pybwdt.c +++ b/ports/cc3200/mods/pybwdt.c @@ -150,10 +150,11 @@ STATIC const mp_rom_map_elem_t pybwdt_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pybwdt_locals_dict, pybwdt_locals_dict_table); -const mp_obj_type_t pyb_wdt_type = { - { &mp_type_type }, - .name = MP_QSTR_WDT, - .make_new = pyb_wdt_make_new, - .locals_dict = (mp_obj_t)&pybwdt_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_wdt_type, + MP_QSTR_WDT, + MP_TYPE_FLAG_NONE, + pyb_wdt_make_new, + locals_dict, (mp_obj_t)&pybwdt_locals_dict + ); diff --git a/ports/esp32/esp32_nvs.c b/ports/esp32/esp32_nvs.c index 42d65be4a6..1f96ad129d 100644 --- a/ports/esp32/esp32_nvs.c +++ b/ports/esp32/esp32_nvs.c @@ -141,10 +141,11 @@ STATIC const mp_rom_map_elem_t esp32_nvs_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(esp32_nvs_locals_dict, esp32_nvs_locals_dict_table); -const mp_obj_type_t esp32_nvs_type = { - { &mp_type_type }, - .name = MP_QSTR_NVS, - .print = esp32_nvs_print, - .make_new = esp32_nvs_make_new, - .locals_dict = (mp_obj_dict_t *)&esp32_nvs_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + esp32_nvs_type, + MP_QSTR_NVS, + MP_TYPE_FLAG_NONE, + esp32_nvs_make_new, + print, esp32_nvs_print, + locals_dict, (mp_obj_dict_t *)&esp32_nvs_locals_dict + ); diff --git a/ports/esp32/esp32_partition.c b/ports/esp32/esp32_partition.c index 47e769486c..2e42e7a819 100644 --- a/ports/esp32/esp32_partition.c +++ b/ports/esp32/esp32_partition.c @@ -284,10 +284,11 @@ STATIC const mp_rom_map_elem_t esp32_partition_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(esp32_partition_locals_dict, esp32_partition_locals_dict_table); -const mp_obj_type_t esp32_partition_type = { - { &mp_type_type }, - .name = MP_QSTR_Partition, - .print = esp32_partition_print, - .make_new = esp32_partition_make_new, - .locals_dict = (mp_obj_dict_t *)&esp32_partition_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + esp32_partition_type, + MP_QSTR_Partition, + MP_TYPE_FLAG_NONE, + esp32_partition_make_new, + print, esp32_partition_print, + locals_dict, (mp_obj_dict_t *)&esp32_partition_locals_dict + ); diff --git a/ports/esp32/esp32_rmt.c b/ports/esp32/esp32_rmt.c index ac897e3336..36f33df3f5 100644 --- a/ports/esp32/esp32_rmt.c +++ b/ports/esp32/esp32_rmt.c @@ -372,10 +372,11 @@ STATIC const mp_rom_map_elem_t esp32_rmt_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(esp32_rmt_locals_dict, esp32_rmt_locals_dict_table); -const mp_obj_type_t esp32_rmt_type = { - { &mp_type_type }, - .name = MP_QSTR_RMT, - .print = esp32_rmt_print, - .make_new = esp32_rmt_make_new, - .locals_dict = (mp_obj_dict_t *)&esp32_rmt_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + esp32_rmt_type, + MP_QSTR_RMT, + MP_TYPE_FLAG_NONE, + esp32_rmt_make_new, + print, esp32_rmt_print, + locals_dict, (mp_obj_dict_t *)&esp32_rmt_locals_dict + ); diff --git a/ports/esp32/esp32_ulp.c b/ports/esp32/esp32_ulp.c index 8e4ce9c5a4..5eb0e5591e 100644 --- a/ports/esp32/esp32_ulp.c +++ b/ports/esp32/esp32_ulp.c @@ -91,11 +91,12 @@ STATIC const mp_rom_map_elem_t esp32_ulp_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(esp32_ulp_locals_dict, esp32_ulp_locals_dict_table); -const mp_obj_type_t esp32_ulp_type = { - { &mp_type_type }, - .name = MP_QSTR_ULP, - .make_new = esp32_ulp_make_new, - .locals_dict = (mp_obj_t)&esp32_ulp_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + esp32_ulp_type, + MP_QSTR_ULP, + MP_TYPE_FLAG_NONE, + esp32_ulp_make_new, + locals_dict, (mp_obj_t)&esp32_ulp_locals_dict + ); #endif // CONFIG_IDF_TARGET_ESP32 diff --git a/ports/esp32/machine_adc.c b/ports/esp32/machine_adc.c index cb45aab339..5cc2d80384 100644 --- a/ports/esp32/machine_adc.c +++ b/ports/esp32/machine_adc.c @@ -256,10 +256,11 @@ STATIC const mp_rom_map_elem_t madc_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(madc_locals_dict, madc_locals_dict_table); -const mp_obj_type_t machine_adc_type = { - { &mp_type_type }, - .name = MP_QSTR_ADC, - .print = madc_print, - .make_new = madc_make_new, - .locals_dict = (mp_obj_t)&madc_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_adc_type, + MP_QSTR_ADC, + MP_TYPE_FLAG_NONE, + madc_make_new, + print, madc_print, + locals_dict, (mp_obj_t)&madc_locals_dict + ); diff --git a/ports/esp32/machine_adcblock.c b/ports/esp32/machine_adcblock.c index 06c215f8ae..770839e93e 100644 --- a/ports/esp32/machine_adcblock.c +++ b/ports/esp32/machine_adcblock.c @@ -194,10 +194,11 @@ STATIC const mp_rom_map_elem_t madcblock_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(madcblock_locals_dict, madcblock_locals_dict_table); -const mp_obj_type_t machine_adcblock_type = { - { &mp_type_type }, - .name = MP_QSTR_ADCBlock, - .print = madcblock_print, - .make_new = madcblock_make_new, - .locals_dict = (mp_obj_t)&madcblock_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_adcblock_type, + MP_QSTR_ADCBlock, + MP_TYPE_FLAG_NONE, + madcblock_make_new, + print, madcblock_print, + locals_dict, (mp_obj_dict_t *)&madcblock_locals_dict + ); diff --git a/ports/esp32/machine_dac.c b/ports/esp32/machine_dac.c index 35826d4a99..c9b9c14e01 100644 --- a/ports/esp32/machine_dac.c +++ b/ports/esp32/machine_dac.c @@ -104,12 +104,13 @@ STATIC const mp_rom_map_elem_t mdac_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(mdac_locals_dict, mdac_locals_dict_table); -const mp_obj_type_t machine_dac_type = { - { &mp_type_type }, - .name = MP_QSTR_DAC, - .print = mdac_print, - .make_new = mdac_make_new, - .locals_dict = (mp_obj_t)&mdac_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_dac_type, + MP_QSTR_DAC, + MP_TYPE_FLAG_NONE, + mdac_make_new, + print, mdac_print, + locals_dict, (mp_obj_t)&mdac_locals_dict + ); #endif // MICROPY_PY_MACHINE_DAC diff --git a/ports/esp32/machine_hw_spi.c b/ports/esp32/machine_hw_spi.c index 3e720adb1a..71583ef60e 100644 --- a/ports/esp32/machine_hw_spi.c +++ b/ports/esp32/machine_hw_spi.c @@ -545,11 +545,12 @@ STATIC const mp_machine_spi_p_t machine_hw_spi_p = { .transfer = machine_hw_spi_transfer, }; -const mp_obj_type_t machine_hw_spi_type = { - { &mp_type_type }, - .name = MP_QSTR_SPI, - .print = machine_hw_spi_print, - .make_new = machine_hw_spi_make_new, - .protocol = &machine_hw_spi_p, - .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_hw_spi_type, + MP_QSTR_SPI, + MP_TYPE_FLAG_NONE, + machine_hw_spi_make_new, + print, machine_hw_spi_print, + protocol, &machine_hw_spi_p, + locals_dict, (mp_obj_dict_t *)&mp_machine_spi_locals_dict + ); diff --git a/ports/esp32/machine_i2c.c b/ports/esp32/machine_i2c.c index e25cad0b60..9e5be606db 100644 --- a/ports/esp32/machine_i2c.c +++ b/ports/esp32/machine_i2c.c @@ -192,11 +192,12 @@ STATIC const mp_machine_i2c_p_t machine_hw_i2c_p = { .transfer = machine_hw_i2c_transfer, }; -const mp_obj_type_t machine_hw_i2c_type = { - { &mp_type_type }, - .name = MP_QSTR_I2C, - .print = machine_hw_i2c_print, - .make_new = machine_hw_i2c_make_new, - .protocol = &machine_hw_i2c_p, - .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_hw_i2c_type, + MP_QSTR_I2C, + MP_TYPE_FLAG_NONE, + machine_hw_i2c_make_new, + print, machine_hw_i2c_print, + protocol, &machine_hw_i2c_p, + locals_dict, (mp_obj_dict_t *)&mp_machine_i2c_locals_dict + ); diff --git a/ports/esp32/machine_i2s.c b/ports/esp32/machine_i2s.c index 933e68684b..d30fb5d836 100644 --- a/ports/esp32/machine_i2s.c +++ b/ports/esp32/machine_i2s.c @@ -829,16 +829,17 @@ STATIC const mp_stream_p_t i2s_stream_p = { .is_text = false, }; -const mp_obj_type_t machine_i2s_type = { - { &mp_type_type }, - .name = MP_QSTR_I2S, - .print = machine_i2s_print, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &i2s_stream_p, - .make_new = machine_i2s_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_i2s_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_i2s_type, + MP_QSTR_I2S, + MP_TYPE_FLAG_NONE, + machine_i2s_make_new, + print, machine_i2s_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &i2s_stream_p, + locals_dict, (mp_obj_dict_t *)&machine_i2s_locals_dict + ); MP_REGISTER_ROOT_POINTER(struct _machine_i2s_obj_t *machine_i2s_obj[I2S_NUM_MAX]); diff --git a/ports/esp32/machine_pin.c b/ports/esp32/machine_pin.c index b575626338..1a1a3a0f8d 100644 --- a/ports/esp32/machine_pin.c +++ b/ports/esp32/machine_pin.c @@ -529,15 +529,16 @@ STATIC const mp_pin_p_t pin_pin_p = { .ioctl = pin_ioctl, }; -const mp_obj_type_t machine_pin_type = { - { &mp_type_type }, - .name = MP_QSTR_Pin, - .print = machine_pin_print, - .make_new = mp_pin_make_new, - .call = machine_pin_call, - .protocol = &pin_pin_p, - .locals_dict = (mp_obj_t)&machine_pin_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_type, + MP_QSTR_Pin, + MP_TYPE_FLAG_NONE, + mp_pin_make_new, + print, machine_pin_print, + call, machine_pin_call, + protocol, &pin_pin_p, + locals_dict, (mp_obj_t)&machine_pin_locals_dict + ); /******************************************************************************/ // Pin IRQ object @@ -723,11 +724,13 @@ STATIC const mp_rom_map_elem_t machine_pin_irq_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_pin_irq_locals_dict, machine_pin_irq_locals_dict_table); -STATIC const mp_obj_type_t machine_pin_irq_type = { - { &mp_type_type }, - .name = MP_QSTR_IRQ, - .call = machine_pin_irq_call, - .locals_dict = (mp_obj_dict_t *)&machine_pin_irq_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_irq_type, + MP_QSTR_IRQ, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + call, machine_pin_irq_call, + locals_dict, (mp_obj_dict_t *)&machine_pin_irq_locals_dict + ); MP_REGISTER_ROOT_POINTER(mp_obj_t machine_pin_irq_handler[40]); diff --git a/ports/esp32/machine_rtc.c b/ports/esp32/machine_rtc.c index 72d7b5c828..6634bf5b03 100644 --- a/ports/esp32/machine_rtc.c +++ b/ports/esp32/machine_rtc.c @@ -173,9 +173,10 @@ STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table); -const mp_obj_type_t machine_rtc_type = { - { &mp_type_type }, - .name = MP_QSTR_RTC, - .make_new = machine_rtc_make_new, - .locals_dict = (mp_obj_t)&machine_rtc_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_rtc_type, + MP_QSTR_RTC, + MP_TYPE_FLAG_NONE, + machine_rtc_make_new, + locals_dict, (mp_obj_t)&machine_rtc_locals_dict + ); diff --git a/ports/esp32/machine_sdcard.c b/ports/esp32/machine_sdcard.c index 3f94356adb..2d5663d476 100644 --- a/ports/esp32/machine_sdcard.c +++ b/ports/esp32/machine_sdcard.c @@ -399,11 +399,12 @@ STATIC const mp_rom_map_elem_t machine_sdcard_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(machine_sdcard_locals_dict, machine_sdcard_locals_dict_table); -const mp_obj_type_t machine_sdcard_type = { - { &mp_type_type }, - .name = MP_QSTR_SDCard, - .make_new = machine_sdcard_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_sdcard_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_sdcard_type, + MP_QSTR_SDCard, + MP_TYPE_FLAG_NONE, + machine_sdcard_make_new, + locals_dict, (mp_obj_dict_t *)&machine_sdcard_locals_dict + ); #endif // MICROPY_HW_ENABLE_SDCARD diff --git a/ports/esp32/machine_timer.c b/ports/esp32/machine_timer.c index 66969b3a95..3b12950955 100644 --- a/ports/esp32/machine_timer.c +++ b/ports/esp32/machine_timer.c @@ -277,12 +277,13 @@ STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table); -const mp_obj_type_t machine_timer_type = { - { &mp_type_type }, - .name = MP_QSTR_Timer, - .print = machine_timer_print, - .make_new = machine_timer_make_new, - .locals_dict = (mp_obj_t)&machine_timer_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_timer_type, + MP_QSTR_Timer, + MP_TYPE_FLAG_NONE, + machine_timer_make_new, + print, machine_timer_print, + locals_dict, (mp_obj_t)&machine_timer_locals_dict + ); MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *machine_timer_obj_head); diff --git a/ports/esp32/machine_touchpad.c b/ports/esp32/machine_touchpad.c index 168ac16d0e..c5e3483b74 100644 --- a/ports/esp32/machine_touchpad.c +++ b/ports/esp32/machine_touchpad.c @@ -134,11 +134,12 @@ STATIC const mp_rom_map_elem_t mtp_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(mtp_locals_dict, mtp_locals_dict_table); -const mp_obj_type_t machine_touchpad_type = { - { &mp_type_type }, - .name = MP_QSTR_TouchPad, - .make_new = mtp_make_new, - .locals_dict = (mp_obj_t)&mtp_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_touchpad_type, + MP_QSTR_TouchPad, + MP_TYPE_FLAG_NONE, + mtp_make_new, + locals_dict, (mp_obj_t)&mtp_locals_dict + ); #endif // CONFIG_IDF_TARGET_ESP32 diff --git a/ports/esp32/machine_uart.c b/ports/esp32/machine_uart.c index 7244591289..9df16ae419 100644 --- a/ports/esp32/machine_uart.c +++ b/ports/esp32/machine_uart.c @@ -530,13 +530,14 @@ STATIC const mp_stream_p_t uart_stream_p = { .is_text = false, }; -const mp_obj_type_t machine_uart_type = { - { &mp_type_type }, - .name = MP_QSTR_UART, - .print = machine_uart_print, - .make_new = machine_uart_make_new, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &uart_stream_p, - .locals_dict = (mp_obj_dict_t *)&machine_uart_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_uart_type, + MP_QSTR_UART, + MP_TYPE_FLAG_NONE, + machine_uart_make_new, + print, machine_uart_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &uart_stream_p, + locals_dict, (mp_obj_dict_t *)&machine_uart_locals_dict + ); diff --git a/ports/esp32/machine_wdt.c b/ports/esp32/machine_wdt.c index f0ec6928e0..c2898c7fe1 100644 --- a/ports/esp32/machine_wdt.c +++ b/ports/esp32/machine_wdt.c @@ -83,9 +83,10 @@ STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table); -const mp_obj_type_t machine_wdt_type = { - { &mp_type_type }, - .name = MP_QSTR_WDT, - .make_new = machine_wdt_make_new, - .locals_dict = (mp_obj_t)&machine_wdt_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_wdt_type, + MP_QSTR_WDT, + MP_TYPE_FLAG_NONE, + machine_wdt_make_new, + locals_dict, (mp_obj_t)&machine_wdt_locals_dict + ); diff --git a/ports/esp32/modsocket.c b/ports/esp32/modsocket.c index a281558241..a2dcb3946c 100644 --- a/ports/esp32/modsocket.c +++ b/ports/esp32/modsocket.c @@ -785,13 +785,14 @@ STATIC const mp_stream_p_t socket_stream_p = { .ioctl = socket_stream_ioctl }; -STATIC const mp_obj_type_t socket_type = { - { &mp_type_type }, - .name = MP_QSTR_socket, - .make_new = socket_make_new, - .protocol = &socket_stream_p, - .locals_dict = (mp_obj_t)&socket_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + socket_type, + MP_QSTR_socket, + MP_TYPE_FLAG_NONE, + socket_make_new, + protocol, &socket_stream_p, + locals_dict, (mp_obj_t)&socket_locals_dict + ); STATIC mp_obj_t esp_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { // TODO support additional args beyond the first two diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c index f302d70fec..fc50e13c48 100644 --- a/ports/esp32/network_lan.c +++ b/ports/esp32/network_lan.c @@ -302,10 +302,12 @@ STATIC const mp_rom_map_elem_t lan_if_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(lan_if_locals_dict, lan_if_locals_dict_table); -const mp_obj_type_t lan_if_type = { - { &mp_type_type }, - .name = MP_QSTR_LAN, - .locals_dict = (mp_obj_dict_t *)&lan_if_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + lan_if_type, + MP_QSTR_LAN, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + locals_dict, (mp_obj_dict_t *)&lan_if_locals_dict + ); #endif diff --git a/ports/esp32/network_ppp.c b/ports/esp32/network_ppp.c index d74283c19c..d6368d9f20 100644 --- a/ports/esp32/network_ppp.c +++ b/ports/esp32/network_ppp.c @@ -278,8 +278,10 @@ STATIC const mp_rom_map_elem_t ppp_if_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(ppp_if_locals_dict, ppp_if_locals_dict_table); -const mp_obj_type_t ppp_if_type = { - { &mp_type_type }, - .name = MP_QSTR_PPP, - .locals_dict = (mp_obj_dict_t *)&ppp_if_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + ppp_if_type, + MP_QSTR_PPP, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + locals_dict, (mp_obj_dict_t *)&ppp_if_locals_dict + ); diff --git a/ports/esp32/network_wlan.c b/ports/esp32/network_wlan.c index 4f74262afc..6ca5f9a9ba 100644 --- a/ports/esp32/network_wlan.c +++ b/ports/esp32/network_wlan.c @@ -47,9 +47,8 @@ #error WIFI_MODE_STA and WIFI_MODE_AP are supposed to be bitfields! #endif -STATIC const mp_obj_type_t wlan_if_type; -STATIC const wlan_if_obj_t wlan_sta_obj = {{&wlan_if_type}, WIFI_IF_STA}; -STATIC const wlan_if_obj_t wlan_ap_obj = {{&wlan_if_type}, WIFI_IF_AP}; +STATIC const wlan_if_obj_t wlan_sta_obj; +STATIC const wlan_if_obj_t wlan_ap_obj; // Set to "true" if esp_wifi_start() was called static bool wifi_started = false; @@ -616,10 +615,15 @@ STATIC const mp_rom_map_elem_t wlan_if_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table); -STATIC const mp_obj_type_t wlan_if_type = { - { &mp_type_type }, - .name = MP_QSTR_WLAN, - .locals_dict = (mp_obj_t)&wlan_if_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + wlan_if_type, + MP_QSTR_WLAN, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + locals_dict, (mp_obj_dict_t *)&wlan_if_locals_dict + ); + +STATIC const wlan_if_obj_t wlan_sta_obj = {{&wlan_if_type}, WIFI_IF_STA}; +STATIC const wlan_if_obj_t wlan_ap_obj = {{&wlan_if_type}, WIFI_IF_AP}; #endif // MICROPY_PY_NETWORK_WLAN diff --git a/ports/esp8266/machine_adc.c b/ports/esp8266/machine_adc.c index 471e14d8df..bface7f7e1 100644 --- a/ports/esp8266/machine_adc.c +++ b/ports/esp8266/machine_adc.c @@ -89,10 +89,11 @@ STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table); -const mp_obj_type_t machine_adc_type = { - { &mp_type_type }, - .name = MP_QSTR_ADC, - .print = machine_adc_print, - .make_new = machine_adc_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_adc_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_adc_type, + MP_QSTR_ADC, + MP_TYPE_FLAG_NONE, + machine_adc_make_new, + print, machine_adc_print, + locals_dict, (mp_obj_dict_t *)&machine_adc_locals_dict + ); diff --git a/ports/esp8266/machine_hspi.c b/ports/esp8266/machine_hspi.c index 3ff76f5a02..c0d4a677e3 100644 --- a/ports/esp8266/machine_hspi.c +++ b/ports/esp8266/machine_hspi.c @@ -175,13 +175,14 @@ STATIC const mp_machine_spi_p_t machine_hspi_p = { .transfer = machine_hspi_transfer, }; -const mp_obj_type_t machine_hspi_type = { - { &mp_type_type }, - .name = MP_QSTR_HSPI, - .print = machine_hspi_print, - .make_new = machine_hspi_make_new, - .protocol = &machine_hspi_p, - .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_hspi_type, + MP_QSTR_HSPI, + MP_TYPE_FLAG_NONE, + machine_hspi_make_new, + print, machine_hspi_print, + protocol, &machine_hspi_p, + locals_dict, (mp_obj_dict_t *)&mp_machine_spi_locals_dict + ); #endif // MICROPY_PY_MACHINE_SPI diff --git a/ports/esp8266/machine_pin.c b/ports/esp8266/machine_pin.c index 8171b8a8a3..8b759766cd 100644 --- a/ports/esp8266/machine_pin.c +++ b/ports/esp8266/machine_pin.c @@ -450,15 +450,16 @@ STATIC const mp_pin_p_t pin_pin_p = { .ioctl = pin_ioctl, }; -const mp_obj_type_t pyb_pin_type = { - { &mp_type_type }, - .name = MP_QSTR_Pin, - .print = pyb_pin_print, - .make_new = mp_pin_make_new, - .call = pyb_pin_call, - .protocol = &pin_pin_p, - .locals_dict = (mp_obj_dict_t *)&pyb_pin_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_pin_type, + MP_QSTR_Pin, + MP_TYPE_FLAG_NONE, + mp_pin_make_new, + print, pyb_pin_print, + call, pyb_pin_call, + protocol, &pin_pin_p, + locals_dict, (mp_obj_dict_t *)&pyb_pin_locals_dict + ); /******************************************************************************/ // Pin IRQ object @@ -509,11 +510,13 @@ STATIC const mp_rom_map_elem_t pin_irq_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pin_irq_locals_dict, pin_irq_locals_dict_table); -STATIC const mp_obj_type_t pin_irq_type = { - { &mp_type_type }, - .name = MP_QSTR_IRQ, - .call = pin_irq_call, - .locals_dict = (mp_obj_dict_t *)&pin_irq_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + pin_irq_type, + MP_QSTR_IRQ, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + call, pin_irq_call, + locals_dict, (mp_obj_dict_t *)&pin_irq_locals_dict + ); MP_REGISTER_ROOT_POINTER(mp_obj_t pin_irq_handler[16]); diff --git a/ports/esp8266/machine_rtc.c b/ports/esp8266/machine_rtc.c index 38049ce724..4235b325ef 100644 --- a/ports/esp8266/machine_rtc.c +++ b/ports/esp8266/machine_rtc.c @@ -262,9 +262,10 @@ STATIC const mp_rom_map_elem_t pyb_rtc_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table); -const mp_obj_type_t pyb_rtc_type = { - { &mp_type_type }, - .name = MP_QSTR_RTC, - .make_new = pyb_rtc_make_new, - .locals_dict = (mp_obj_dict_t *)&pyb_rtc_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_rtc_type, + MP_QSTR_RTC, + MP_TYPE_FLAG_NONE, + pyb_rtc_make_new, + locals_dict, (mp_obj_dict_t *)&pyb_rtc_locals_dict + ); diff --git a/ports/esp8266/machine_uart.c b/ports/esp8266/machine_uart.c index 2fe6516dc7..82f5189388 100644 --- a/ports/esp8266/machine_uart.c +++ b/ports/esp8266/machine_uart.c @@ -343,15 +343,16 @@ STATIC const mp_stream_p_t uart_stream_p = { .is_text = false, }; -const mp_obj_type_t pyb_uart_type = { - { &mp_type_type }, - .name = MP_QSTR_UART, - .print = pyb_uart_print, - .make_new = pyb_uart_make_new, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &uart_stream_p, - .locals_dict = (mp_obj_dict_t *)&pyb_uart_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_uart_type, + MP_QSTR_UART, + MP_TYPE_FLAG_NONE, + pyb_uart_make_new, + print, pyb_uart_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &uart_stream_p, + locals_dict, (mp_obj_dict_t *)&pyb_uart_locals_dict + ); MP_REGISTER_ROOT_POINTER(byte * uart0_rxbuf); diff --git a/ports/esp8266/machine_wdt.c b/ports/esp8266/machine_wdt.c index b06e752277..d8c32ddd1a 100644 --- a/ports/esp8266/machine_wdt.c +++ b/ports/esp8266/machine_wdt.c @@ -69,9 +69,10 @@ STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table); -const mp_obj_type_t esp_wdt_type = { - { &mp_type_type }, - .name = MP_QSTR_WDT, - .make_new = machine_wdt_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_wdt_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + esp_wdt_type, + MP_QSTR_WDT, + MP_TYPE_FLAG_NONE, + machine_wdt_make_new, + locals_dict, (mp_obj_dict_t *)&machine_wdt_locals_dict + ); diff --git a/ports/esp8266/modmachine.c b/ports/esp8266/modmachine.c index 1dd87b9af8..2bb2c7bd76 100644 --- a/ports/esp8266/modmachine.c +++ b/ports/esp8266/modmachine.c @@ -337,13 +337,14 @@ STATIC const mp_rom_map_elem_t esp_timer_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(esp_timer_locals_dict, esp_timer_locals_dict_table); -const mp_obj_type_t esp_timer_type = { - { &mp_type_type }, - .name = MP_QSTR_Timer, - .print = esp_timer_print, - .make_new = esp_timer_make_new, - .locals_dict = (mp_obj_dict_t *)&esp_timer_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + esp_timer_type, + MP_QSTR_Timer, + MP_TYPE_FLAG_NONE, + esp_timer_make_new, + print, esp_timer_print, + locals_dict, (mp_obj_dict_t *)&esp_timer_locals_dict + ); // this bit is unused in the Xtensa PS register #define ETS_LOOP_ITER_BIT (12) diff --git a/ports/esp8266/modnetwork.c b/ports/esp8266/modnetwork.c index 5240d3b320..f78bf5da52 100644 --- a/ports/esp8266/modnetwork.c +++ b/ports/esp8266/modnetwork.c @@ -510,11 +510,13 @@ STATIC const mp_rom_map_elem_t wlan_if_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table); -const mp_obj_type_t wlan_if_type = { - { &mp_type_type }, - .name = MP_QSTR_WLAN, - .locals_dict = (mp_obj_dict_t *)&wlan_if_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + wlan_if_type, + MP_QSTR_WLAN, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + locals_dict, (mp_obj_dict_t *)&wlan_if_locals_dict + ); STATIC mp_obj_t esp_phy_mode(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { diff --git a/ports/mimxrt/machine_adc.c b/ports/mimxrt/machine_adc.c index aa4cc831e5..cbac6b5734 100644 --- a/ports/mimxrt/machine_adc.c +++ b/ports/mimxrt/machine_adc.c @@ -117,13 +117,14 @@ STATIC const mp_rom_map_elem_t adc_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table); -const mp_obj_type_t machine_adc_type = { - {&mp_type_type}, - .name = MP_QSTR_ADC, - .print = adc_obj_print, - .make_new = adc_obj_make_new, - .locals_dict = (mp_obj_dict_t *)&adc_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_adc_type, + MP_QSTR_ADC, + MP_TYPE_FLAG_NONE, + adc_obj_make_new, + print, adc_obj_print, + locals_dict, (mp_obj_dict_t *)&adc_locals_dict + ); void machine_adc_init(void) { for (int i = 1; i < sizeof(adc_bases) / sizeof(ADC_Type *); ++i) { diff --git a/ports/mimxrt/machine_i2c.c b/ports/mimxrt/machine_i2c.c index c10fcaddbe..b8b6b7bc63 100644 --- a/ports/mimxrt/machine_i2c.c +++ b/ports/mimxrt/machine_i2c.c @@ -197,11 +197,12 @@ STATIC const mp_machine_i2c_p_t machine_i2c_p = { .transfer_single = machine_i2c_transfer_single, }; -const mp_obj_type_t machine_i2c_type = { - { &mp_type_type }, - .name = MP_QSTR_I2C, - .print = machine_i2c_print, - .make_new = machine_i2c_make_new, - .protocol = &machine_i2c_p, - .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_i2c_type, + MP_QSTR_I2C, + MP_TYPE_FLAG_NONE, + machine_i2c_make_new, + print, machine_i2c_print, + protocol, &machine_i2c_p, + locals_dict, (mp_obj_dict_t *)&mp_machine_i2c_locals_dict + ); diff --git a/ports/mimxrt/machine_i2s.c b/ports/mimxrt/machine_i2s.c index a5446c7ac3..68bf3a820f 100644 --- a/ports/mimxrt/machine_i2s.c +++ b/ports/mimxrt/machine_i2s.c @@ -1213,16 +1213,17 @@ STATIC const mp_stream_p_t i2s_stream_p = { .is_text = false, }; -const mp_obj_type_t machine_i2s_type = { - { &mp_type_type }, - .name = MP_QSTR_I2S, - .print = machine_i2s_print, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &i2s_stream_p, - .make_new = machine_i2s_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_i2s_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_i2s_type, + MP_QSTR_I2S, + MP_TYPE_FLAG_NONE, + machine_i2s_make_new, + print, machine_i2s_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &i2s_stream_p, + locals_dict, (mp_obj_dict_t *)&machine_i2s_locals_dict + ); MP_REGISTER_ROOT_POINTER(struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM]); diff --git a/ports/mimxrt/machine_led.c b/ports/mimxrt/machine_led.c index 4082eb34bb..d766c8f323 100644 --- a/ports/mimxrt/machine_led.c +++ b/ports/mimxrt/machine_led.c @@ -80,12 +80,13 @@ STATIC const mp_rom_map_elem_t led_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(led_locals_dict, led_locals_dict_table); -const mp_obj_type_t machine_led_type = { - {&mp_type_type}, - .name = MP_QSTR_LED, - .print = led_obj_print, - .make_new = led_obj_make_new, - .locals_dict = (mp_obj_dict_t *)&led_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_led_type, + MP_QSTR_LED, + MP_TYPE_FLAG_NONE, + led_obj_make_new, + print, led_obj_print, + locals_dict, (mp_obj_dict_t *)&led_locals_dict + ); #endif diff --git a/ports/mimxrt/machine_pin.c b/ports/mimxrt/machine_pin.c index 64066af0e1..7ec66d0eac 100644 --- a/ports/mimxrt/machine_pin.c +++ b/ports/mimxrt/machine_pin.c @@ -58,17 +58,21 @@ enum { }; // Pin mapping dictionaries -const mp_obj_type_t machine_pin_cpu_pins_obj_type = { - { &mp_type_type }, - .name = MP_QSTR_cpu, - .locals_dict = (mp_obj_t)&machine_pin_cpu_pins_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_cpu_pins_obj_type, + MP_QSTR_cpu, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + locals_dict, (mp_obj_t)&machine_pin_cpu_pins_locals_dict + ); -const mp_obj_type_t machine_pin_board_pins_obj_type = { - { &mp_type_type }, - .name = MP_QSTR_board, - .locals_dict = (mp_obj_t)&machine_pin_board_pins_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_board_pins_obj_type, + MP_QSTR_board, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + locals_dict, (mp_obj_t)&machine_pin_board_pins_locals_dict + ); STATIC const mp_irq_methods_t machine_pin_irq_methods; @@ -396,7 +400,6 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table); - STATIC mp_uint_t machine_pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { (void)errcode; machine_pin_obj_t *self = self_in; @@ -417,24 +420,26 @@ STATIC const mp_pin_p_t machine_pin_obj_protocol = { .ioctl = machine_pin_ioctl, }; -const mp_obj_type_t machine_pin_type = { - {&mp_type_type}, - .name = MP_QSTR_Pin, - .print = machine_pin_obj_print, - .call = machine_pin_obj_call, - .make_new = mp_pin_make_new, - .protocol = &machine_pin_obj_protocol, - .locals_dict = (mp_obj_dict_t *)&machine_pin_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_type, + MP_QSTR_Pin, + MP_TYPE_FLAG_NONE, + mp_pin_make_new, + print, machine_pin_obj_print, + call, machine_pin_obj_call, + protocol, &machine_pin_obj_protocol, + locals_dict, (mp_obj_dict_t *)&machine_pin_locals_dict + ); // FIXME: Create actual pin_af type!!! -const mp_obj_type_t machine_pin_af_type = { - {&mp_type_type}, - .name = MP_QSTR_PinAF, - .print = machine_pin_obj_print, - .make_new = mp_pin_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_pin_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_af_type, + MP_QSTR_PinAF, + MP_TYPE_FLAG_NONE, + mp_pin_make_new, + print, machine_pin_obj_print, + locals_dict, (mp_obj_dict_t *)&machine_pin_locals_dict + ); STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/ports/mimxrt/machine_rtc.c b/ports/mimxrt/machine_rtc.c index e0d33554b5..5211027bdf 100644 --- a/ports/mimxrt/machine_rtc.c +++ b/ports/mimxrt/machine_rtc.c @@ -166,9 +166,10 @@ STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table); -const mp_obj_type_t machine_rtc_type = { - { &mp_type_type }, - .name = MP_QSTR_RTC, - .make_new = machine_rtc_make_new, - .locals_dict = (mp_obj_t)&machine_rtc_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_rtc_type, + MP_QSTR_RTC, + MP_TYPE_FLAG_NONE, + machine_rtc_make_new, + locals_dict, (mp_obj_t)&machine_rtc_locals_dict + ); diff --git a/ports/mimxrt/machine_sdcard.c b/ports/mimxrt/machine_sdcard.c index 4a92aae00c..b7bdceef47 100644 --- a/ports/mimxrt/machine_sdcard.c +++ b/ports/mimxrt/machine_sdcard.c @@ -208,12 +208,13 @@ STATIC const mp_rom_map_elem_t sdcard_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(sdcard_locals_dict, sdcard_locals_dict_table); -const mp_obj_type_t machine_sdcard_type = { - { &mp_type_type }, - .name = MP_QSTR_SDCard, - .make_new = sdcard_obj_make_new, - .locals_dict = (mp_obj_dict_t *)&sdcard_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_sdcard_type, + MP_QSTR_SDCard, + MP_TYPE_FLAG_NONE, + sdcard_obj_make_new, + locals_dict, (mp_obj_dict_t *)&sdcard_locals_dict + ); void machine_sdcard_init0(void) { return; diff --git a/ports/mimxrt/machine_spi.c b/ports/mimxrt/machine_spi.c index 32bc77c34d..ff3cf4fb25 100644 --- a/ports/mimxrt/machine_spi.c +++ b/ports/mimxrt/machine_spi.c @@ -251,11 +251,12 @@ STATIC const mp_machine_spi_p_t machine_spi_p = { .transfer = machine_spi_transfer, }; -const mp_obj_type_t machine_spi_type = { - { &mp_type_type }, - .name = MP_QSTR_SPI, - .print = machine_spi_print, - .make_new = machine_spi_make_new, - .protocol = &machine_spi_p, - .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_spi_type, + MP_QSTR_SPI, + MP_TYPE_FLAG_NONE, + machine_spi_make_new, + print, machine_spi_print, + protocol, &machine_spi_p, + locals_dict, (mp_obj_dict_t *)&mp_machine_spi_locals_dict + ); diff --git a/ports/mimxrt/machine_timer.c b/ports/mimxrt/machine_timer.c index 62a560ebbf..9612388486 100644 --- a/ports/mimxrt/machine_timer.c +++ b/ports/mimxrt/machine_timer.c @@ -211,12 +211,13 @@ STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table); -const mp_obj_type_t machine_timer_type = { - { &mp_type_type }, - .name = MP_QSTR_Timer, - .print = machine_timer_print, - .make_new = machine_timer_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_timer_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_timer_type, + MP_QSTR_Timer, + MP_TYPE_FLAG_NONE, + machine_timer_make_new, + print, machine_timer_print, + locals_dict, (mp_obj_dict_t *)&machine_timer_locals_dict + ); MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *timer_table[MICROPY_HW_PIT_NUM_CHANNELS]); diff --git a/ports/mimxrt/machine_uart.c b/ports/mimxrt/machine_uart.c index 83382a6cf2..4bb518eab2 100644 --- a/ports/mimxrt/machine_uart.c +++ b/ports/mimxrt/machine_uart.c @@ -469,13 +469,14 @@ STATIC const mp_stream_p_t uart_stream_p = { .is_text = false, }; -const mp_obj_type_t machine_uart_type = { - { &mp_type_type }, - .name = MP_QSTR_UART, - .print = machine_uart_print, - .make_new = machine_uart_make_new, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &uart_stream_p, - .locals_dict = (mp_obj_dict_t *)&machine_uart_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_uart_type, + MP_QSTR_UART, + MP_TYPE_FLAG_NONE, + machine_uart_make_new, + print, machine_uart_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &uart_stream_p, + locals_dict, (mp_obj_dict_t *)&machine_uart_locals_dict + ); diff --git a/ports/mimxrt/machine_wdt.c b/ports/mimxrt/machine_wdt.c index d09c464f69..cde80f085b 100644 --- a/ports/mimxrt/machine_wdt.c +++ b/ports/mimxrt/machine_wdt.c @@ -99,9 +99,10 @@ STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table); -const mp_obj_type_t machine_wdt_type = { - { &mp_type_type }, - .name = MP_QSTR_WDT, - .make_new = machine_wdt_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_wdt_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_wdt_type, + MP_QSTR_WDT, + MP_TYPE_FLAG_NONE, + machine_wdt_make_new, + locals_dict, (mp_obj_dict_t *)&machine_wdt_locals_dict + ); diff --git a/ports/mimxrt/mimxrt_flash.c b/ports/mimxrt/mimxrt_flash.c index 27ab987ed1..1a7d6cca8d 100644 --- a/ports/mimxrt/mimxrt_flash.c +++ b/ports/mimxrt/mimxrt_flash.c @@ -215,9 +215,10 @@ STATIC const mp_rom_map_elem_t mimxrt_flash_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(mimxrt_flash_locals_dict, mimxrt_flash_locals_dict_table); -const mp_obj_type_t mimxrt_flash_type = { - { &mp_type_type }, - .name = MP_QSTR_Flash, - .make_new = mimxrt_flash_make_new, - .locals_dict = (mp_obj_dict_t *)&mimxrt_flash_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mimxrt_flash_type, + MP_QSTR_Flash, + MP_TYPE_FLAG_NONE, + mimxrt_flash_make_new, + locals_dict, (mp_obj_dict_t *)&mimxrt_flash_locals_dict + ); diff --git a/ports/mimxrt/network_lan.c b/ports/mimxrt/network_lan.c index 5517b54bd0..08c3c9e729 100644 --- a/ports/mimxrt/network_lan.c +++ b/ports/mimxrt/network_lan.c @@ -220,12 +220,14 @@ STATIC const mp_rom_map_elem_t network_lan_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(network_lan_locals_dict, network_lan_locals_dict_table); -const mp_obj_type_t network_lan_type = { - { &mp_type_type }, - .name = MP_QSTR_LAN, - .print = network_lan_print, - .make_new = network_lan_make_new, - .locals_dict = (mp_obj_dict_t *)&network_lan_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + network_lan_type, + MP_QSTR_LAN, + MP_TYPE_FLAG_NONE, + network_lan_make_new, + print, network_lan_print, + locals_dict, (mp_obj_dict_t *)&network_lan_locals_dict + ); + #endif // defined(MICROPY_HW_ETH_MDC) diff --git a/ports/nrf/boards/microbit/modules/iters.c b/ports/nrf/boards/microbit/modules/iters.c index 66f9f6c7f3..296fc1f51c 100644 --- a/ports/nrf/boards/microbit/modules/iters.c +++ b/ports/nrf/boards/microbit/modules/iters.c @@ -43,12 +43,14 @@ static mp_obj_t microbit_repeat_iter_next(mp_obj_t iter_in) { return mp_obj_subscr(iter->iterable, MP_OBJ_NEW_SMALL_INT(iter->index), MP_OBJ_SENTINEL); } -const mp_obj_type_t microbit_repeat_iterator_type = { - { &mp_type_type }, - .name = MP_QSTR_iterator, - .getiter = mp_identity_getiter, - .iternext = microbit_repeat_iter_next, -}; +MP_DEFINE_CONST_OBJ_TYPE( + microbit_repeat_iterator_type, + MP_QSTR_iterator, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + getiter, mp_identity_getiter, + iternext, microbit_repeat_iter_next + ); mp_obj_t microbit_repeat_iterator(mp_obj_t iterable) { repeat_iterator_t *result = mp_obj_malloc(repeat_iterator_t, µbit_repeat_iterator_type); diff --git a/ports/nrf/boards/microbit/modules/microbitdisplay.c b/ports/nrf/boards/microbit/modules/microbitdisplay.c index 93ba9772fe..084cb09524 100644 --- a/ports/nrf/boards/microbit/modules/microbitdisplay.c +++ b/ports/nrf/boards/microbit/modules/microbitdisplay.c @@ -542,11 +542,13 @@ STATIC const mp_rom_map_elem_t microbit_display_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(microbit_display_locals_dict, microbit_display_locals_dict_table); -const mp_obj_type_t microbit_display_type = { - { &mp_type_type }, - .name = MP_QSTR_MicroBitDisplay, - .locals_dict = (mp_obj_dict_t*)µbit_display_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + microbit_display_type, + MP_QSTR_MicroBitDisplay, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + locals_dict, (mp_obj_dict_t*)µbit_display_locals_dict + ); microbit_display_obj_t microbit_display_obj = { {µbit_display_type}, diff --git a/ports/nrf/boards/microbit/modules/microbitimage.c b/ports/nrf/boards/microbit/modules/microbitimage.c index eb44660b97..95b17bb6d3 100644 --- a/ports/nrf/boards/microbit/modules/microbitimage.c +++ b/ports/nrf/boards/microbit/modules/microbitimage.c @@ -678,14 +678,15 @@ STATIC mp_obj_t image_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs } -const mp_obj_type_t microbit_image_type = { - { &mp_type_type }, - .name = MP_QSTR_MicroBitImage, - .print = microbit_image_print, - .make_new = microbit_image_make_new, - .binary_op = image_binary_op, - .locals_dict = (mp_obj_dict_t*)µbit_image_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + microbit_image_type, + MP_QSTR_MicroBitImage, + MP_TYPE_FLAG_NONE, + microbit_image_make_new, + print, microbit_image_print, + binary_op, image_binary_op, + locals_dict, (mp_obj_dict_t*)µbit_image_locals_dict + ); typedef struct _scrolling_string_t { mp_obj_base_t base; @@ -820,18 +821,22 @@ STATIC mp_obj_t microbit_scrolling_string_iter_next(mp_obj_t o_in) { return iter->img; } -const mp_obj_type_t microbit_scrolling_string_type = { - { &mp_type_type }, - .name = MP_QSTR_ScrollingString, - .getiter = get_microbit_scrolling_string_iter, -}; +MP_DEFINE_CONST_OBJ_TYPE( + microbit_scrolling_string_type, + MP_QSTR_ScrollingString, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + getiter, get_microbit_scrolling_string_iter + ); -const mp_obj_type_t microbit_scrolling_string_iterator_type = { - { &mp_type_type }, - .name = MP_QSTR_iterator, - .getiter = mp_identity_getiter, - .iternext = microbit_scrolling_string_iter_next, -}; +MP_DEFINE_CONST_OBJ_TYPE( + microbit_scrolling_string_iterator_type, + MP_QSTR_iterator, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + getiter, mp_identity_getiter, + iternext, microbit_scrolling_string_iter_next + ); /** Facade types to present a string as a sequence of images. * These are necessary to avoid allocation during iteration, @@ -869,13 +874,15 @@ static mp_obj_t facade_unary_op(mp_unary_op_t op, mp_obj_t self_in) { static mp_obj_t microbit_facade_iterator(mp_obj_t iterable_in, mp_obj_iter_buf_t *iter_buf); -const mp_obj_type_t string_image_facade_type = { - { &mp_type_type }, - .name = MP_QSTR_Facade, - .unary_op = facade_unary_op, - .subscr = string_image_facade_subscr, - .getiter = microbit_facade_iterator, -}; +MP_DEFINE_CONST_OBJ_TYPE( + string_image_facade_type, + MP_QSTR_Facade, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + unary_op, facade_unary_op, + subscr, string_image_facade_subscr, + getiter, microbit_facade_iterator + ); typedef struct _facade_iterator_t { @@ -904,12 +911,14 @@ static mp_obj_t microbit_facade_iter_next(mp_obj_t iter_in) { return iter->image; } -const mp_obj_type_t microbit_facade_iterator_type = { - { &mp_type_type }, - .name = MP_QSTR_iterator, - .getiter = mp_identity_getiter, - .iternext = microbit_facade_iter_next, -}; +MP_DEFINE_CONST_OBJ_TYPE( + microbit_facade_iterator_type, + MP_QSTR_iterator, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + getiter, mp_identity_getiter, + iternext, microbit_facade_iter_next + ); mp_obj_t microbit_facade_iterator(mp_obj_t iterable_in, mp_obj_iter_buf_t *iter_buf) { (void)iter_buf; diff --git a/ports/nrf/modules/board/led.c b/ports/nrf/modules/board/led.c index cbfc330d63..5eef8f0464 100644 --- a/ports/nrf/modules/board/led.c +++ b/ports/nrf/modules/board/led.c @@ -194,13 +194,14 @@ STATIC const mp_rom_map_elem_t led_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(led_locals_dict, led_locals_dict_table); -const mp_obj_type_t board_led_type = { - { &mp_type_type }, - .name = MP_QSTR_LED, - .print = led_obj_print, - .make_new = led_obj_make_new, - .locals_dict = (mp_obj_dict_t*)&led_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + board_led_type, + MP_QSTR_LED, + MP_TYPE_FLAG_NONE, + led_obj_make_new, + print, led_obj_print, + locals_dict, (mp_obj_dict_t*)&led_locals_dict + ); #else // For boards with no LEDs, we leave an empty function here so that we don't diff --git a/ports/nrf/modules/machine/adc.c b/ports/nrf/modules/machine/adc.c index 54870d2c18..5814dcaa39 100644 --- a/ports/nrf/modules/machine/adc.c +++ b/ports/nrf/modules/machine/adc.c @@ -294,12 +294,13 @@ STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table); -const mp_obj_type_t machine_adc_type = { - { &mp_type_type }, - .name = MP_QSTR_ADC, - .make_new = machine_adc_make_new, - .locals_dict = (mp_obj_dict_t*)&machine_adc_locals_dict, - .print = machine_adc_print, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_adc_type, + MP_QSTR_ADC, + MP_TYPE_FLAG_NONE, + machine_adc_make_new, + locals_dict, (mp_obj_dict_t*)&machine_adc_locals_dict, + print, machine_adc_print + ); #endif // MICROPY_PY_MACHINE_ADC diff --git a/ports/nrf/modules/machine/i2c.c b/ports/nrf/modules/machine/i2c.c index aac9320873..8468684428 100644 --- a/ports/nrf/modules/machine/i2c.c +++ b/ports/nrf/modules/machine/i2c.c @@ -161,13 +161,14 @@ STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = { .transfer_single = machine_hard_i2c_transfer_single, }; -const mp_obj_type_t machine_hard_i2c_type = { - { &mp_type_type }, - .name = MP_QSTR_I2C, - .print = machine_hard_i2c_print, - .make_new = machine_hard_i2c_make_new, - .protocol = &machine_hard_i2c_p, - .locals_dict = (mp_obj_dict_t*)&mp_machine_i2c_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_hard_i2c_type, + MP_QSTR_I2C, + MP_TYPE_FLAG_NONE, + machine_hard_i2c_make_new, + print, machine_hard_i2c_print, + protocol, &machine_hard_i2c_p, + locals_dict, (mp_obj_dict_t*)&mp_machine_i2c_locals_dict + ); #endif // MICROPY_PY_MACHINE_I2C diff --git a/ports/nrf/modules/machine/pin.c b/ports/nrf/modules/machine/pin.c index 3a45c22d18..835f6cf2bd 100644 --- a/ports/nrf/modules/machine/pin.c +++ b/ports/nrf/modules/machine/pin.c @@ -596,14 +596,15 @@ STATIC const mp_rom_map_elem_t pin_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pin_locals_dict, pin_locals_dict_table); -const mp_obj_type_t pin_type = { - { &mp_type_type }, - .name = MP_QSTR_Pin, - .print = pin_print, - .make_new = pin_make_new, - .call = pin_call, - .locals_dict = (mp_obj_dict_t*)&pin_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pin_type, + MP_QSTR_Pin, + MP_TYPE_FLAG_NONE, + pin_make_new, + print, pin_print, + call, pin_call, + locals_dict, (mp_obj_dict_t*)&pin_locals_dict + ); /// \moduleref machine /// \class PinAF - Pin Alternate Functions @@ -671,12 +672,14 @@ STATIC const mp_rom_map_elem_t pin_af_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pin_af_locals_dict, pin_af_locals_dict_table); -const mp_obj_type_t pin_af_type = { - { &mp_type_type }, - .name = MP_QSTR_PinAF, - .print = pin_af_obj_print, - .locals_dict = (mp_obj_dict_t*)&pin_af_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pin_af_type, + MP_QSTR_PinAF, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, pin_af_obj_print, + locals_dict, (mp_obj_dict_t*)&pin_af_locals_dict + ); MP_REGISTER_ROOT_POINTER(mp_obj_t pin_class_mapper); MP_REGISTER_ROOT_POINTER(mp_obj_t pin_class_map_dict); diff --git a/ports/nrf/modules/machine/pwm.c b/ports/nrf/modules/machine/pwm.c index a750285841..d0ac0e9450 100644 --- a/ports/nrf/modules/machine/pwm.c +++ b/ports/nrf/modules/machine/pwm.c @@ -339,12 +339,13 @@ STATIC mp_obj_t machine_hard_pwm_freq(mp_obj_t self_in, mp_arg_val_t *args) { return mp_const_none; } -const mp_obj_type_t machine_hard_pwm_type = { - { &mp_type_type }, - .name = MP_QSTR_PWM, - .print = machine_pwm_print, - .make_new = machine_pwm_make_new, - .locals_dict = (mp_obj_dict_t*)&machine_pwm_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_hard_pwm_type, + MP_QSTR_PWM, + MP_TYPE_FLAG_NONE, + machine_pwm_make_new, + print, machine_pwm_print, + locals_dict, (mp_obj_dict_t*)&machine_pwm_locals_dict + ); #endif // MICROPY_PY_MACHINE_HW_PWM diff --git a/ports/nrf/modules/machine/rtcounter.c b/ports/nrf/modules/machine/rtcounter.c index c9f907774e..3c48c4bb1f 100644 --- a/ports/nrf/modules/machine/rtcounter.c +++ b/ports/nrf/modules/machine/rtcounter.c @@ -262,12 +262,13 @@ STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table); -const mp_obj_type_t machine_rtcounter_type = { - { &mp_type_type }, - .name = MP_QSTR_RTCounter, - .print = rtc_print, - .make_new = machine_rtc_make_new, - .locals_dict = (mp_obj_dict_t*)&machine_rtc_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_rtcounter_type, + MP_QSTR_RTCounter, + MP_TYPE_FLAG_NONE, + machine_rtc_make_new, + print, rtc_print, + locals_dict, (mp_obj_dict_t*)&machine_rtc_locals_dict + ); #endif // MICROPY_PY_MACHINE_RTCOUNTER diff --git a/ports/nrf/modules/machine/spi.c b/ports/nrf/modules/machine/spi.c index 81bc151beb..22b0ff56e5 100644 --- a/ports/nrf/modules/machine/spi.c +++ b/ports/nrf/modules/machine/spi.c @@ -427,13 +427,14 @@ STATIC const mp_machine_spi_p_t machine_hard_spi_p = { .transfer = machine_hard_spi_transfer, }; -const mp_obj_type_t machine_hard_spi_type = { - { &mp_type_type }, - .name = MP_QSTR_SPI, - .print = machine_hard_spi_print, - .make_new = machine_spi_make_new, - .protocol = &machine_hard_spi_p, - .locals_dict = (mp_obj_dict_t*)&machine_spi_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_hard_spi_type, + MP_QSTR_SPI, + MP_TYPE_FLAG_NONE, + machine_spi_make_new, + print, machine_hard_spi_print, + protocol, &machine_hard_spi_p, + locals_dict, (mp_obj_dict_t*)&machine_spi_locals_dict + ); #endif // MICROPY_PY_MACHINE_HW_SPI diff --git a/ports/nrf/modules/machine/temp.c b/ports/nrf/modules/machine/temp.c index 1eb38c08d0..1e21f11253 100644 --- a/ports/nrf/modules/machine/temp.c +++ b/ports/nrf/modules/machine/temp.c @@ -112,12 +112,13 @@ STATIC const mp_rom_map_elem_t machine_temp_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(machine_temp_locals_dict, machine_temp_locals_dict_table); -const mp_obj_type_t machine_temp_type = { - { &mp_type_type }, - .name = MP_QSTR_Temp, - .make_new = machine_temp_make_new, - .locals_dict = (mp_obj_dict_t*)&machine_temp_locals_dict, - .print = machine_temp_print, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_temp_type, + MP_QSTR_Temp, + MP_TYPE_FLAG_NONE, + machine_temp_make_new, + locals_dict, (mp_obj_dict_t*)&machine_temp_locals_dict, + print, machine_temp_print + ); #endif // MICROPY_PY_MACHINE_TEMP diff --git a/ports/nrf/modules/machine/timer.c b/ports/nrf/modules/machine/timer.c index c99713ef52..3724881aa8 100644 --- a/ports/nrf/modules/machine/timer.c +++ b/ports/nrf/modules/machine/timer.c @@ -234,12 +234,13 @@ STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table); -const mp_obj_type_t machine_timer_type = { - { &mp_type_type }, - .name = MP_QSTR_Timer, - .print = timer_print, - .make_new = machine_timer_make_new, - .locals_dict = (mp_obj_dict_t*)&machine_timer_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_timer_type, + MP_QSTR_Timer, + MP_TYPE_FLAG_NONE, + machine_timer_make_new, + print, timer_print, + locals_dict, (mp_obj_dict_t*)&machine_timer_locals_dict + ); #endif // MICROPY_PY_MACHINE_TIMER diff --git a/ports/nrf/modules/machine/uart.c b/ports/nrf/modules/machine/uart.c index 1fd2ccc06c..5c9ba83ab6 100644 --- a/ports/nrf/modules/machine/uart.c +++ b/ports/nrf/modules/machine/uart.c @@ -370,15 +370,16 @@ STATIC const mp_stream_p_t uart_stream_p = { .is_text = false, }; -const mp_obj_type_t machine_hard_uart_type = { - { &mp_type_type }, - .name = MP_QSTR_UART, - .print = machine_hard_uart_print, - .make_new = machine_hard_uart_make_new, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &uart_stream_p, - .locals_dict = (mp_obj_dict_t*)&machine_hard_uart_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_hard_uart_type, + MP_QSTR_UART, + MP_TYPE_FLAG_NONE, + machine_hard_uart_make_new, + print, machine_hard_uart_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &uart_stream_p, + locals_dict, (mp_obj_dict_t*)&machine_hard_uart_locals_dict + ); #endif // MICROPY_PY_MACHINE_UART diff --git a/ports/nrf/modules/nrf/flashbdev.c b/ports/nrf/modules/nrf/flashbdev.c index f63a9b46b2..b67e86d0d0 100644 --- a/ports/nrf/modules/nrf/flashbdev.c +++ b/ports/nrf/modules/nrf/flashbdev.c @@ -183,13 +183,14 @@ STATIC mp_obj_t nrf_flashbdev_make_new(const mp_obj_type_t *type, size_t n_args, return MP_OBJ_FROM_PTR(self); } -const mp_obj_type_t nrf_flashbdev_type = { - { &mp_type_type }, - .name = MP_QSTR_Flash, - .print = nrf_flashbdev_print, - .make_new = nrf_flashbdev_make_new, - .locals_dict = (mp_obj_dict_t *)&nrf_flashbdev_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + nrf_flashbdev_type, + MP_QSTR_Flash, + MP_TYPE_FLAG_NONE, + nrf_flashbdev_make_new, + print, nrf_flashbdev_print, + locals_dict, (mp_obj_dict_t *)&nrf_flashbdev_locals_dict + ); void flashbdev_init(void) { // Set start to first aligned page from _fs_start. diff --git a/ports/nrf/modules/ubluepy/ubluepy_characteristic.c b/ports/nrf/modules/ubluepy/ubluepy_characteristic.c index a66483f60d..5544ac6aef 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_characteristic.c +++ b/ports/nrf/modules/ubluepy/ubluepy_characteristic.c @@ -209,12 +209,13 @@ STATIC const mp_rom_map_elem_t ubluepy_characteristic_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ubluepy_characteristic_locals_dict, ubluepy_characteristic_locals_dict_table); -const mp_obj_type_t ubluepy_characteristic_type = { - { &mp_type_type }, - .name = MP_QSTR_Characteristic, - .print = ubluepy_characteristic_print, - .make_new = ubluepy_characteristic_make_new, - .locals_dict = (mp_obj_dict_t*)&ubluepy_characteristic_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + ubluepy_characteristic_type, + MP_QSTR_Characteristic, + MP_TYPE_FLAG_NONE, + ubluepy_characteristic_make_new, + print, ubluepy_characteristic_print, + locals_dict, (mp_obj_dict_t*)&ubluepy_characteristic_locals_dict + ); #endif // MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL diff --git a/ports/nrf/modules/ubluepy/ubluepy_constants.c b/ports/nrf/modules/ubluepy/ubluepy_constants.c index 14e433e6eb..e4637c8cbc 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_constants.c +++ b/ports/nrf/modules/ubluepy/ubluepy_constants.c @@ -69,11 +69,13 @@ STATIC const mp_rom_map_elem_t ubluepy_constants_ad_types_locals_dict_table[] = STATIC MP_DEFINE_CONST_DICT(ubluepy_constants_ad_types_locals_dict, ubluepy_constants_ad_types_locals_dict_table); -const mp_obj_type_t ubluepy_constants_ad_types_type = { - { &mp_type_type }, - .name = MP_QSTR_ad_types, - .locals_dict = (mp_obj_dict_t*)&ubluepy_constants_ad_types_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + ubluepy_constants_ad_types_type, + MP_QSTR_ad_types, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + locals_dict, (mp_obj_dict_t*)&ubluepy_constants_ad_types_locals_dict + ); STATIC const mp_rom_map_elem_t ubluepy_constants_locals_dict_table[] = { // GAP events @@ -90,10 +92,12 @@ STATIC const mp_rom_map_elem_t ubluepy_constants_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ubluepy_constants_locals_dict, ubluepy_constants_locals_dict_table); -const mp_obj_type_t ubluepy_constants_type = { - { &mp_type_type }, - .name = MP_QSTR_constants, - .locals_dict = (mp_obj_dict_t*)&ubluepy_constants_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + ubluepy_constants_type, + MP_QSTR_constants, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + locals_dict, (mp_obj_dict_t*)&ubluepy_constants_locals_dict + ); #endif // MICROPY_PY_UBLUEPY diff --git a/ports/nrf/modules/ubluepy/ubluepy_delegate.c b/ports/nrf/modules/ubluepy/ubluepy_delegate.c index 736bfbc9dd..71648767e6 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_delegate.c +++ b/ports/nrf/modules/ubluepy/ubluepy_delegate.c @@ -77,12 +77,13 @@ STATIC const mp_rom_map_elem_t ubluepy_delegate_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ubluepy_delegate_locals_dict, ubluepy_delegate_locals_dict_table); -const mp_obj_type_t ubluepy_delegate_type = { - { &mp_type_type }, - .name = MP_QSTR_DefaultDelegate, - .print = ubluepy_delegate_print, - .make_new = ubluepy_delegate_make_new, - .locals_dict = (mp_obj_dict_t*)&ubluepy_delegate_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + ubluepy_delegate_type, + MP_QSTR_DefaultDelegate, + MP_TYPE_FLAG_NONE, + ubluepy_delegate_make_new, + print, ubluepy_delegate_print, + locals_dict, (mp_obj_dict_t*)&ubluepy_delegate_locals_dict + ); #endif // MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL diff --git a/ports/nrf/modules/ubluepy/ubluepy_descriptor.c b/ports/nrf/modules/ubluepy/ubluepy_descriptor.c index 370188f7fc..07035460ae 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_descriptor.c +++ b/ports/nrf/modules/ubluepy/ubluepy_descriptor.c @@ -70,12 +70,13 @@ STATIC const mp_rom_map_elem_t ubluepy_descriptor_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ubluepy_descriptor_locals_dict, ubluepy_descriptor_locals_dict_table); -const mp_obj_type_t ubluepy_descriptor_type = { - { &mp_type_type }, - .name = MP_QSTR_Descriptor, - .print = ubluepy_descriptor_print, - .make_new = ubluepy_descriptor_make_new, - .locals_dict = (mp_obj_dict_t*)&ubluepy_descriptor_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + ubluepy_descriptor_type, + MP_QSTR_Descriptor, + MP_TYPE_FLAG_NONE, + ubluepy_descriptor_make_new, + print, ubluepy_descriptor_print, + locals_dict, (mp_obj_dict_t*)&ubluepy_descriptor_locals_dict + ); #endif // MICROPY_PY_UBLUEPY diff --git a/ports/nrf/modules/ubluepy/ubluepy_peripheral.c b/ports/nrf/modules/ubluepy/ubluepy_peripheral.c index acfe316c0c..9c346a885b 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_peripheral.c +++ b/ports/nrf/modules/ubluepy/ubluepy_peripheral.c @@ -482,12 +482,13 @@ STATIC const mp_rom_map_elem_t ubluepy_peripheral_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ubluepy_peripheral_locals_dict, ubluepy_peripheral_locals_dict_table); -const mp_obj_type_t ubluepy_peripheral_type = { - { &mp_type_type }, - .name = MP_QSTR_Peripheral, - .print = ubluepy_peripheral_print, - .make_new = ubluepy_peripheral_make_new, - .locals_dict = (mp_obj_dict_t*)&ubluepy_peripheral_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + ubluepy_peripheral_type, + MP_QSTR_Peripheral, + MP_TYPE_FLAG_NONE, + ubluepy_peripheral_make_new, + print, ubluepy_peripheral_print, + locals_dict, (mp_obj_dict_t*)&ubluepy_peripheral_locals_dict + ); #endif // MICROPY_PY_UBLUEPY diff --git a/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c b/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c index 773070b089..64a81d215d 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c +++ b/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c @@ -136,11 +136,13 @@ STATIC const mp_rom_map_elem_t ubluepy_scan_entry_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ubluepy_scan_entry_locals_dict, ubluepy_scan_entry_locals_dict_table); -const mp_obj_type_t ubluepy_scan_entry_type = { - { &mp_type_type }, - .name = MP_QSTR_ScanEntry, - .print = ubluepy_scan_entry_print, - .locals_dict = (mp_obj_dict_t*)&ubluepy_scan_entry_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + ubluepy_scan_entry_type, + MP_QSTR_ScanEntry, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, ubluepy_scan_entry_print, + locals_dict, (mp_obj_dict_t*)&ubluepy_scan_entry_locals_dict + ); #endif // MICROPY_PY_UBLUEPY_CENTRAL diff --git a/ports/nrf/modules/ubluepy/ubluepy_scanner.c b/ports/nrf/modules/ubluepy/ubluepy_scanner.c index 60895a3da9..c47044cf0c 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_scanner.c +++ b/ports/nrf/modules/ubluepy/ubluepy_scanner.c @@ -114,12 +114,13 @@ STATIC const mp_rom_map_elem_t ubluepy_scanner_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ubluepy_scanner_locals_dict, ubluepy_scanner_locals_dict_table); -const mp_obj_type_t ubluepy_scanner_type = { - { &mp_type_type }, - .name = MP_QSTR_Scanner, - .print = ubluepy_scanner_print, - .make_new = ubluepy_scanner_make_new, - .locals_dict = (mp_obj_dict_t*)&ubluepy_scanner_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + ubluepy_scanner_type, + MP_QSTR_Scanner, + MP_TYPE_FLAG_NONE, + ubluepy_scanner_make_new, + print, ubluepy_scanner_print, + locals_dict, (mp_obj_dict_t*)&ubluepy_scanner_locals_dict + ); #endif // MICROPY_PY_UBLUEPY_CENTRAL diff --git a/ports/nrf/modules/ubluepy/ubluepy_service.c b/ports/nrf/modules/ubluepy/ubluepy_service.c index 6dac231779..9d0d6e5b95 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_service.c +++ b/ports/nrf/modules/ubluepy/ubluepy_service.c @@ -171,12 +171,13 @@ STATIC const mp_rom_map_elem_t ubluepy_service_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ubluepy_service_locals_dict, ubluepy_service_locals_dict_table); -const mp_obj_type_t ubluepy_service_type = { - { &mp_type_type }, - .name = MP_QSTR_Service, - .print = ubluepy_service_print, - .make_new = ubluepy_service_make_new, - .locals_dict = (mp_obj_dict_t*)&ubluepy_service_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + ubluepy_service_type, + MP_QSTR_Service, + MP_TYPE_FLAG_NONE, + ubluepy_service_make_new, + print, ubluepy_service_print, + locals_dict, (mp_obj_dict_t*)&ubluepy_service_locals_dict + ); #endif // MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL diff --git a/ports/nrf/modules/ubluepy/ubluepy_uuid.c b/ports/nrf/modules/ubluepy/ubluepy_uuid.c index aee7b9a1a8..0414a2a286 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_uuid.c +++ b/ports/nrf/modules/ubluepy/ubluepy_uuid.c @@ -160,12 +160,13 @@ STATIC const mp_rom_map_elem_t ubluepy_uuid_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ubluepy_uuid_locals_dict, ubluepy_uuid_locals_dict_table); -const mp_obj_type_t ubluepy_uuid_type = { - { &mp_type_type }, - .name = MP_QSTR_UUID, - .print = ubluepy_uuid_print, - .make_new = ubluepy_uuid_make_new, - .locals_dict = (mp_obj_dict_t*)&ubluepy_uuid_locals_dict -}; +MP_DEFINE_CONST_OBJ_TYPE( + ubluepy_uuid_type, + MP_QSTR_UUID, + MP_TYPE_FLAG_NONE, + ubluepy_uuid_make_new, + print, ubluepy_uuid_print, + locals_dict, (mp_obj_dict_t*)&ubluepy_uuid_locals_dict + ); #endif // MICROPY_PY_UBLUEPY diff --git a/ports/nrf/modules/uos/microbitfs.c b/ports/nrf/modules/uos/microbitfs.c index 6c8ffb0925..63ac8c9321 100644 --- a/ports/nrf/modules/uos/microbitfs.c +++ b/ports/nrf/modules/uos/microbitfs.c @@ -626,12 +626,14 @@ STATIC const mp_stream_p_t textio_stream_p = { .is_text = true, }; -const mp_obj_type_t uos_mbfs_textio_type = { - { &mp_type_type }, - .name = MP_QSTR_TextIO, - .protocol = &textio_stream_p, - .locals_dict = (mp_obj_dict_t*)&uos_mbfs_file_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + uos_mbfs_textio_type, + MP_QSTR_TextIO, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + protocol, &textio_stream_p, + locals_dict, (mp_obj_dict_t*)&uos_mbfs_file_locals_dict + ); STATIC const mp_stream_p_t fileio_stream_p = { @@ -639,12 +641,14 @@ STATIC const mp_stream_p_t fileio_stream_p = { .write = microbit_file_write, }; -const mp_obj_type_t uos_mbfs_fileio_type = { - { &mp_type_type }, - .name = MP_QSTR_FileIO, - .protocol = &fileio_stream_p, - .locals_dict = (mp_obj_dict_t*)&uos_mbfs_file_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + uos_mbfs_fileio_type, + MP_QSTR_FileIO, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + protocol, &fileio_stream_p, + locals_dict, (mp_obj_dict_t*)&uos_mbfs_file_locals_dict + ); // From micro:bit fileobj.c mp_obj_t uos_mbfs_open(size_t n_args, const mp_obj_t *args) { diff --git a/ports/nrf/pin_named_pins.c b/ports/nrf/pin_named_pins.c index e1d8736b9c..87fed746e6 100644 --- a/ports/nrf/pin_named_pins.c +++ b/ports/nrf/pin_named_pins.c @@ -36,19 +36,23 @@ STATIC void pin_named_pins_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_printf(print, "", self->name); } -const mp_obj_type_t pin_cpu_pins_obj_type = { - { &mp_type_type }, - .name = MP_QSTR_cpu, - .print = pin_named_pins_obj_print, - .locals_dict = (mp_obj_t)&pin_cpu_pins_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pin_cpu_pins_obj_type, + MP_QSTR_cpu, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, pin_named_pins_obj_print, + locals_dict, (mp_obj_t)&pin_cpu_pins_locals_dict + ); -const mp_obj_type_t pin_board_pins_obj_type = { - { &mp_type_type }, - .name = MP_QSTR_board, - .print = pin_named_pins_obj_print, - .locals_dict = (mp_obj_t)&pin_board_pins_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pin_board_pins_obj_type, + MP_QSTR_board, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, pin_named_pins_obj_print, + locals_dict, (mp_obj_t)&pin_board_pins_locals_dict + ); const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) { mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)named_pins); diff --git a/ports/pic16bit/modpybled.c b/ports/pic16bit/modpybled.c index 6adb2fda31..fd4e8cce9c 100644 --- a/ports/pic16bit/modpybled.c +++ b/ports/pic16bit/modpybled.c @@ -84,10 +84,11 @@ STATIC const mp_rom_map_elem_t pyb_led_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_led_locals_dict, pyb_led_locals_dict_table); -const mp_obj_type_t pyb_led_type = { - { &mp_type_type }, - .name = MP_QSTR_LED, - .print = pyb_led_print, - .make_new = pyb_led_make_new, - .locals_dict = (mp_obj_t)&pyb_led_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_led_type, + MP_QSTR_LED, + MP_TYPE_FLAG_NONE, + pyb_led_make_new, + print, pyb_led_print, + locals_dict, (mp_obj_t)&pyb_led_locals_dict + ); diff --git a/ports/pic16bit/modpybswitch.c b/ports/pic16bit/modpybswitch.c index 7b3d0f5f52..e1096b1daa 100644 --- a/ports/pic16bit/modpybswitch.c +++ b/ports/pic16bit/modpybswitch.c @@ -71,11 +71,12 @@ STATIC const mp_rom_map_elem_t pyb_switch_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_switch_locals_dict, pyb_switch_locals_dict_table); -const mp_obj_type_t pyb_switch_type = { - { &mp_type_type }, - .name = MP_QSTR_Switch, - .print = pyb_switch_print, - .make_new = pyb_switch_make_new, - .call = pyb_switch_call, - .locals_dict = (mp_obj_t)&pyb_switch_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_switch_type, + MP_QSTR_Switch, + MP_TYPE_FLAG_NONE, + pyb_switch_make_new, + print, pyb_switch_print, + call, pyb_switch_call, + locals_dict, (mp_obj_t)&pyb_switch_locals_dict + ); diff --git a/ports/renesas-ra/extint.c b/ports/renesas-ra/extint.c index 59f9ecfa37..496a50c3e8 100644 --- a/ports/renesas-ra/extint.c +++ b/ports/renesas-ra/extint.c @@ -374,13 +374,14 @@ STATIC const mp_rom_map_elem_t extint_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(extint_locals_dict, extint_locals_dict_table); -const mp_obj_type_t extint_type = { - { &mp_type_type }, - .name = MP_QSTR_ExtInt, - .print = extint_obj_print, - .make_new = extint_make_new, - .locals_dict = (mp_obj_dict_t *)&extint_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + extint_type, + MP_QSTR_ExtInt, + MP_TYPE_FLAG_NONE, + extint_make_new, + locals_dict, &extint_locals_dict, + print, extint_obj_print + ); void extint_init0(void) { ra_icu_init(); diff --git a/ports/renesas-ra/led.c b/ports/renesas-ra/led.c index efc09d9de1..9a3f1d40e9 100644 --- a/ports/renesas-ra/led.c +++ b/ports/renesas-ra/led.c @@ -170,13 +170,14 @@ STATIC const mp_rom_map_elem_t led_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(led_locals_dict, led_locals_dict_table); -const mp_obj_type_t ra_led_type = { - { &mp_type_type }, - .name = MP_QSTR_LED, - .print = led_obj_print, - .make_new = led_obj_make_new, - .locals_dict = (mp_obj_dict_t *)&led_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + ra_led_type, + MP_QSTR_LED, + MP_TYPE_FLAG_NONE, + led_obj_make_new, + locals_dict, &led_locals_dict, + print, led_obj_print + ); #else // For boards with no LEDs, we leave an empty function here so that we don't diff --git a/ports/renesas-ra/machine_adc.c b/ports/renesas-ra/machine_adc.c index adeebeb4c4..99e35f48d9 100644 --- a/ports/renesas-ra/machine_adc.c +++ b/ports/renesas-ra/machine_adc.c @@ -126,10 +126,11 @@ STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table); -const mp_obj_type_t machine_adc_type = { - { &mp_type_type }, - .name = MP_QSTR_ADC, - .print = machine_adc_print, - .make_new = machine_adc_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_adc_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_adc_type, + MP_QSTR_ADC, + MP_TYPE_FLAG_NONE, + machine_adc_make_new, + locals_dict, &machine_adc_locals_dict, + print, machine_adc_print + ); diff --git a/ports/renesas-ra/machine_i2c.c b/ports/renesas-ra/machine_i2c.c index bc1cea0cd9..eaca5ff4a8 100644 --- a/ports/renesas-ra/machine_i2c.c +++ b/ports/renesas-ra/machine_i2c.c @@ -156,13 +156,14 @@ STATIC const mp_machine_i2c_p_t machine_i2c_p = { .transfer_single = machine_i2c_transfer_single, }; -const mp_obj_type_t machine_i2c_type = { - { &mp_type_type }, - .name = MP_QSTR_I2C, - .print = machine_i2c_print, - .make_new = machine_i2c_make_new, - .protocol = &machine_i2c_p, - .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_i2c_type, + MP_QSTR_I2C, + MP_TYPE_FLAG_NONE, + machine_i2c_make_new, + locals_dict, (void *)&mp_machine_i2c_locals_dict, + print, machine_i2c_print, + protocol, &machine_i2c_p + ); #endif // MICROPY_HW_ENABLE_HW_I2C diff --git a/ports/renesas-ra/machine_pin.c b/ports/renesas-ra/machine_pin.c index f940b55547..17ef1e19a4 100644 --- a/ports/renesas-ra/machine_pin.c +++ b/ports/renesas-ra/machine_pin.c @@ -349,15 +349,16 @@ STATIC const mp_pin_p_t machine_pin_pin_p = { .ioctl = machine_pin_ioctl, }; -const mp_obj_type_t machine_pin_type = { - { &mp_type_type }, - .name = MP_QSTR_Pin, - .print = machine_pin_print, - .make_new = mp_pin_make_new, - .call = machine_pin_call, - .protocol = &machine_pin_pin_p, - .locals_dict = (mp_obj_t)&machine_pin_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_type, + MP_QSTR_Pin, + MP_TYPE_FLAG_NONE, + mp_pin_make_new, + locals_dict, &machine_pin_locals_dict, + print, machine_pin_print, + call, machine_pin_call, + protocol, &machine_pin_pin_p + ); // Returns the pin mode. This value returned by this macro should be one of: // GPIO_MODE_INPUT, GPIO_MODE_OUTPUT_PP, GPIO_MODE_OUTPUT_OD, @@ -388,17 +389,21 @@ uint32_t pin_get_af(const machine_pin_obj_t *pin) { return (uint32_t)ra_gpio_get_af(pin->pin); } -const mp_obj_type_t pin_cpu_pins_obj_type = { - { &mp_type_type }, - .name = MP_QSTR_cpu, - .locals_dict = (mp_obj_dict_t *)&pin_cpu_pins_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pin_cpu_pins_obj_type, + MP_QSTR_cpu, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + locals_dict, &pin_cpu_pins_locals_dict + ); -const mp_obj_type_t pin_board_pins_obj_type = { - { &mp_type_type }, - .name = MP_QSTR_board, - .locals_dict = (mp_obj_dict_t *)&pin_board_pins_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pin_board_pins_obj_type, + MP_QSTR_board, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + locals_dict, &pin_board_pins_locals_dict + ); const machine_pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) { const mp_map_t *named_map = &named_pins->map; diff --git a/ports/renesas-ra/machine_rtc.c b/ports/renesas-ra/machine_rtc.c index 9ddc902137..c3f64c6971 100644 --- a/ports/renesas-ra/machine_rtc.c +++ b/ports/renesas-ra/machine_rtc.c @@ -341,9 +341,10 @@ STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table); -const mp_obj_type_t machine_rtc_type = { - { &mp_type_type }, - .name = MP_QSTR_RTC, - .make_new = machine_rtc_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_rtc_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_rtc_type, + MP_QSTR_RTC, + MP_TYPE_FLAG_NONE, + machine_rtc_make_new, + locals_dict, &machine_rtc_locals_dict + ); diff --git a/ports/renesas-ra/machine_spi.c b/ports/renesas-ra/machine_spi.c index 01972ad457..d0e8b03bd1 100644 --- a/ports/renesas-ra/machine_spi.c +++ b/ports/renesas-ra/machine_spi.c @@ -297,14 +297,15 @@ STATIC const mp_machine_spi_p_t machine_hard_spi_p = { .transfer = machine_hard_spi_transfer, }; -const mp_obj_type_t machine_hard_spi_type = { - { &mp_type_type }, - .name = MP_QSTR_SPI, - .print = machine_hard_spi_print, - .make_new = machine_hard_spi_make_new, - .protocol = &machine_hard_spi_p, - .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_hard_spi_type, + MP_QSTR_SPI, + MP_TYPE_FLAG_NONE, + machine_hard_spi_make_new, + locals_dict, &mp_machine_spi_locals_dict, + print, machine_hard_spi_print, + protocol, &machine_hard_spi_p + ); void spi_init0(void) { } diff --git a/ports/renesas-ra/machine_timer.c b/ports/renesas-ra/machine_timer.c index c387d35117..f3e5aafb7c 100644 --- a/ports/renesas-ra/machine_timer.c +++ b/ports/renesas-ra/machine_timer.c @@ -136,10 +136,11 @@ STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table); -const mp_obj_type_t machine_timer_type = { - { &mp_type_type }, - .name = MP_QSTR_Timer, - .print = machine_timer_print, - .make_new = machine_timer_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_timer_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_timer_type, + MP_QSTR_Timer, + MP_TYPE_FLAG_NONE, + machine_timer_make_new, + locals_dict, &machine_timer_locals_dict, + print, machine_timer_print + ); diff --git a/ports/renesas-ra/machine_uart.c b/ports/renesas-ra/machine_uart.c index 4b4aa3396b..11f5d6825e 100644 --- a/ports/renesas-ra/machine_uart.c +++ b/ports/renesas-ra/machine_uart.c @@ -571,15 +571,16 @@ STATIC const mp_stream_p_t uart_stream_p = { .is_text = false, }; -const mp_obj_type_t machine_uart_type = { - { &mp_type_type }, - .name = MP_QSTR_UART, - .print = machine_uart_print, - .make_new = machine_uart_make_new, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &uart_stream_p, - .locals_dict = (mp_obj_dict_t *)&machine_uart_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_uart_type, + MP_QSTR_UART, + MP_TYPE_FLAG_NONE, + machine_uart_make_new, + locals_dict, &machine_uart_locals_dict, + print, machine_uart_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + 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/storage.c b/ports/renesas-ra/storage.c index 8d94f6fb9c..f573894a50 100644 --- a/ports/renesas-ra/storage.c +++ b/ports/renesas-ra/storage.c @@ -400,13 +400,14 @@ STATIC const mp_rom_map_elem_t pyb_flash_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_flash_locals_dict, pyb_flash_locals_dict_table); -const mp_obj_type_t pyb_flash_type = { - { &mp_type_type }, - .name = MP_QSTR_Flash, - .print = pyb_flash_print, - .make_new = pyb_flash_make_new, - .locals_dict = (mp_obj_dict_t *)&pyb_flash_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_flash_type, + MP_QSTR_Flash, + MP_TYPE_FLAG_NONE, + pyb_flash_make_new, + locals_dict, &pyb_flash_locals_dict, + print, pyb_flash_print + ); void pyb_flash_init_vfs(fs_user_mount_t *vfs) { vfs->base.type = &mp_fat_vfs_type; diff --git a/ports/renesas-ra/timer.c b/ports/renesas-ra/timer.c index 1ae936525e..8f7acbcdaa 100644 --- a/ports/renesas-ra/timer.c +++ b/ports/renesas-ra/timer.c @@ -410,13 +410,14 @@ STATIC const mp_rom_map_elem_t pyb_timer_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table); -const mp_obj_type_t pyb_timer_type = { - { &mp_type_type }, - .name = MP_QSTR_Timer, - .print = pyb_timer_print, - .make_new = pyb_timer_make_new, - .locals_dict = (mp_obj_dict_t *)&pyb_timer_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_timer_type, + MP_QSTR_Timer, + MP_TYPE_FLAG_NONE, + pyb_timer_make_new, + locals_dict, &pyb_timer_locals_dict, + print, pyb_timer_print + ); #if defined(TIMER_CHANNEL) /* @@ -502,12 +503,14 @@ STATIC const mp_rom_map_elem_t pyb_timer_channel_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table); -STATIC const mp_obj_type_t pyb_timer_channel_type = { - { &mp_type_type }, - .name = MP_QSTR_TimerChannel, - .print = pyb_timer_channel_print, - .locals_dict = (mp_obj_dict_t *)&pyb_timer_channel_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + pyb_timer_channel_type, + MP_QSTR_TimerChannel, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + locals_dict, &pyb_timer_channel_locals_dict, + print, pyb_timer_channel_print + ); #endif STATIC void timer_handle_irq_channel(pyb_timer_obj_t *tim, uint8_t channel, mp_obj_t callback) { diff --git a/ports/renesas-ra/usrsw.c b/ports/renesas-ra/usrsw.c index 572510816b..4107d7850d 100644 --- a/ports/renesas-ra/usrsw.c +++ b/ports/renesas-ra/usrsw.c @@ -135,14 +135,15 @@ STATIC const mp_rom_map_elem_t pyb_switch_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_switch_locals_dict, pyb_switch_locals_dict_table); -const mp_obj_type_t pyb_switch_type = { - { &mp_type_type }, - .name = MP_QSTR_Switch, - .print = pyb_switch_print, - .make_new = pyb_switch_make_new, - .call = pyb_switch_call, - .locals_dict = (mp_obj_dict_t *)&pyb_switch_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_switch_type, + MP_QSTR_Switch, + MP_TYPE_FLAG_NONE, + pyb_switch_make_new, + locals_dict, &pyb_switch_locals_dict, + print, pyb_switch_print, + call, pyb_switch_call + ); MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_switch_callback); diff --git a/ports/rp2/machine_adc.c b/ports/rp2/machine_adc.c index 5f91392e14..549f8d5ecd 100644 --- a/ports/rp2/machine_adc.c +++ b/ports/rp2/machine_adc.c @@ -113,10 +113,11 @@ STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table); -const mp_obj_type_t machine_adc_type = { - { &mp_type_type }, - .name = MP_QSTR_ADC, - .print = machine_adc_print, - .make_new = machine_adc_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_adc_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_adc_type, + MP_QSTR_ADC, + MP_TYPE_FLAG_NONE, + machine_adc_make_new, + print, machine_adc_print, + locals_dict, (mp_obj_dict_t *)&machine_adc_locals_dict + ); diff --git a/ports/rp2/machine_i2c.c b/ports/rp2/machine_i2c.c index 3390cc4210..91d8bb59b7 100644 --- a/ports/rp2/machine_i2c.c +++ b/ports/rp2/machine_i2c.c @@ -176,11 +176,12 @@ STATIC const mp_machine_i2c_p_t machine_i2c_p = { .transfer_single = machine_i2c_transfer_single, }; -const mp_obj_type_t machine_hw_i2c_type = { - { &mp_type_type }, - .name = MP_QSTR_I2C, - .print = machine_i2c_print, - .make_new = machine_i2c_make_new, - .protocol = &machine_i2c_p, - .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_hw_i2c_type, + MP_QSTR_I2C, + MP_TYPE_FLAG_NONE, + machine_i2c_make_new, + print, machine_i2c_print, + protocol, &machine_i2c_p, + locals_dict, (mp_obj_dict_t *)&mp_machine_i2c_locals_dict + ); diff --git a/ports/rp2/machine_i2s.c b/ports/rp2/machine_i2s.c index 1015ba1017..8446a59781 100644 --- a/ports/rp2/machine_i2s.c +++ b/ports/rp2/machine_i2s.c @@ -1137,15 +1137,16 @@ STATIC const mp_stream_p_t i2s_stream_p = { .is_text = false, }; -const mp_obj_type_t machine_i2s_type = { - { &mp_type_type }, - .name = MP_QSTR_I2S, - .print = machine_i2s_print, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &i2s_stream_p, - .make_new = machine_i2s_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_i2s_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_i2s_type, + MP_QSTR_I2S, + MP_TYPE_FLAG_NONE, + machine_i2s_make_new, + print, machine_i2s_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &i2s_stream_p, + locals_dict, (mp_obj_dict_t *)&machine_i2s_locals_dict + ); MP_REGISTER_ROOT_POINTER(void *machine_i2s_obj[2]); diff --git a/ports/rp2/machine_pin.c b/ports/rp2/machine_pin.c index 705f61242c..38670f09ab 100644 --- a/ports/rp2/machine_pin.c +++ b/ports/rp2/machine_pin.c @@ -641,15 +641,16 @@ STATIC const mp_pin_p_t pin_pin_p = { .ioctl = pin_ioctl, }; -const mp_obj_type_t machine_pin_type = { - { &mp_type_type }, - .name = MP_QSTR_Pin, - .print = machine_pin_print, - .make_new = mp_pin_make_new, - .call = machine_pin_call, - .protocol = &pin_pin_p, - .locals_dict = (mp_obj_t)&machine_pin_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_type, + MP_QSTR_Pin, + MP_TYPE_FLAG_NONE, + mp_pin_make_new, + print, machine_pin_print, + call, machine_pin_call, + protocol, &pin_pin_p, + locals_dict, (mp_obj_t)&machine_pin_locals_dict + ); STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/ports/rp2/machine_rtc.c b/ports/rp2/machine_rtc.c index 9d59124a66..73bdaee6c7 100644 --- a/ports/rp2/machine_rtc.c +++ b/ports/rp2/machine_rtc.c @@ -115,9 +115,10 @@ STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table); -const mp_obj_type_t machine_rtc_type = { - { &mp_type_type }, - .name = MP_QSTR_RTC, - .make_new = machine_rtc_make_new, - .locals_dict = (mp_obj_t)&machine_rtc_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_rtc_type, + MP_QSTR_RTC, + MP_TYPE_FLAG_NONE, + machine_rtc_make_new, + locals_dict, (mp_obj_t)&machine_rtc_locals_dict + ); diff --git a/ports/rp2/machine_spi.c b/ports/rp2/machine_spi.c index 104bd1fd53..f3ac8d7cf8 100644 --- a/ports/rp2/machine_spi.c +++ b/ports/rp2/machine_spi.c @@ -290,14 +290,15 @@ STATIC const mp_machine_spi_p_t machine_spi_p = { .transfer = machine_spi_transfer, }; -const mp_obj_type_t machine_spi_type = { - { &mp_type_type }, - .name = MP_QSTR_SPI, - .print = machine_spi_print, - .make_new = machine_spi_make_new, - .protocol = &machine_spi_p, - .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_spi_type, + MP_QSTR_SPI, + MP_TYPE_FLAG_NONE, + machine_spi_make_new, + print, machine_spi_print, + protocol, &machine_spi_p, + locals_dict, (mp_obj_dict_t *)&mp_machine_spi_locals_dict + ); mp_obj_base_t *mp_hal_get_spi_obj(mp_obj_t o) { if (mp_obj_is_type(o, &machine_spi_type)) { diff --git a/ports/rp2/machine_timer.c b/ports/rp2/machine_timer.c index e7e8f02d55..d3b6015529 100644 --- a/ports/rp2/machine_timer.c +++ b/ports/rp2/machine_timer.c @@ -156,10 +156,11 @@ STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table); -const mp_obj_type_t machine_timer_type = { - { &mp_type_type }, - .name = MP_QSTR_Timer, - .print = machine_timer_print, - .make_new = machine_timer_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_timer_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_timer_type, + MP_QSTR_Timer, + MP_TYPE_FLAG_NONE, + machine_timer_make_new, + print, machine_timer_print, + locals_dict, (mp_obj_dict_t *)&machine_timer_locals_dict + ); diff --git a/ports/rp2/machine_uart.c b/ports/rp2/machine_uart.c index f7e44b6b25..df6228058b 100644 --- a/ports/rp2/machine_uart.c +++ b/ports/rp2/machine_uart.c @@ -579,16 +579,17 @@ STATIC const mp_stream_p_t uart_stream_p = { .is_text = false, }; -const mp_obj_type_t machine_uart_type = { - { &mp_type_type }, - .name = MP_QSTR_UART, - .print = machine_uart_print, - .make_new = machine_uart_make_new, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &uart_stream_p, - .locals_dict = (mp_obj_dict_t *)&machine_uart_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_uart_type, + MP_QSTR_UART, + MP_TYPE_FLAG_NONE, + machine_uart_make_new, + print, machine_uart_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &uart_stream_p, + locals_dict, (mp_obj_dict_t *)&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/machine_wdt.c b/ports/rp2/machine_wdt.c index d6914a4f26..e8c4333069 100644 --- a/ports/rp2/machine_wdt.c +++ b/ports/rp2/machine_wdt.c @@ -77,9 +77,10 @@ STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table); -const mp_obj_type_t machine_wdt_type = { - { &mp_type_type }, - .name = MP_QSTR_WDT, - .make_new = machine_wdt_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_wdt_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_wdt_type, + MP_QSTR_WDT, + MP_TYPE_FLAG_NONE, + machine_wdt_make_new, + locals_dict, (mp_obj_dict_t *)&machine_wdt_locals_dict + ); diff --git a/ports/rp2/rp2_flash.c b/ports/rp2/rp2_flash.c index 47c95ea5c8..37a3412db5 100644 --- a/ports/rp2/rp2_flash.c +++ b/ports/rp2/rp2_flash.c @@ -185,9 +185,10 @@ STATIC const mp_rom_map_elem_t rp2_flash_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(rp2_flash_locals_dict, rp2_flash_locals_dict_table); -const mp_obj_type_t rp2_flash_type = { - { &mp_type_type }, - .name = MP_QSTR_Flash, - .make_new = rp2_flash_make_new, - .locals_dict = (mp_obj_dict_t *)&rp2_flash_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + rp2_flash_type, + MP_QSTR_Flash, + MP_TYPE_FLAG_NONE, + rp2_flash_make_new, + locals_dict, (mp_obj_dict_t *)&rp2_flash_locals_dict + ); diff --git a/ports/rp2/rp2_pio.c b/ports/rp2/rp2_pio.c index eb85eb2248..9a195bdd8a 100644 --- a/ports/rp2/rp2_pio.c +++ b/ports/rp2/rp2_pio.c @@ -376,13 +376,14 @@ STATIC const mp_rom_map_elem_t rp2_pio_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(rp2_pio_locals_dict, rp2_pio_locals_dict_table); -const mp_obj_type_t rp2_pio_type = { - { &mp_type_type }, - .name = MP_QSTR_PIO, - .print = rp2_pio_print, - .make_new = rp2_pio_make_new, - .locals_dict = (mp_obj_dict_t *)&rp2_pio_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + rp2_pio_type, + MP_QSTR_PIO, + MP_TYPE_FLAG_NONE, + rp2_pio_make_new, + print, rp2_pio_print, + locals_dict, (mp_obj_dict_t *)&rp2_pio_locals_dict + ); STATIC mp_uint_t rp2_pio_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { rp2_pio_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -806,13 +807,14 @@ STATIC const mp_rom_map_elem_t rp2_state_machine_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(rp2_state_machine_locals_dict, rp2_state_machine_locals_dict_table); -const mp_obj_type_t rp2_state_machine_type = { - { &mp_type_type }, - .name = MP_QSTR_StateMachine, - .print = rp2_state_machine_print, - .make_new = rp2_state_machine_make_new, - .locals_dict = (mp_obj_dict_t *)&rp2_state_machine_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + rp2_state_machine_type, + MP_QSTR_StateMachine, + MP_TYPE_FLAG_NONE, + rp2_state_machine_make_new, + print, rp2_state_machine_print, + locals_dict, (mp_obj_dict_t *)&rp2_state_machine_locals_dict + ); STATIC mp_uint_t rp2_state_machine_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { rp2_state_machine_obj_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/ports/samd/machine_led.c b/ports/samd/machine_led.c index f4dd1aeb3c..76aae8ffc5 100644 --- a/ports/samd/machine_led.c +++ b/ports/samd/machine_led.c @@ -162,11 +162,12 @@ STATIC const mp_rom_map_elem_t machine_led_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_led_locals_dict, machine_led_locals_dict_table); -const mp_obj_type_t machine_led_type = { - { &mp_type_type }, - .name = MP_QSTR_LED, - .print = machine_led_print, - .make_new = mp_led_make_new, - .call = machine_led_call, - .locals_dict = (mp_obj_t)&machine_led_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_led_type, + MP_QSTR_LED, + MP_TYPE_FLAG_NONE, + mp_led_make_new, + print, machine_led_print, + call, machine_led_call, + locals_dict, (mp_obj_t)&machine_led_locals_dict + ); diff --git a/ports/samd/machine_pin.c b/ports/samd/machine_pin.c index 161a3ccddd..d47982e0e1 100644 --- a/ports/samd/machine_pin.c +++ b/ports/samd/machine_pin.c @@ -287,15 +287,16 @@ STATIC const mp_pin_p_t pin_pin_p = { .ioctl = pin_ioctl, }; -const mp_obj_type_t machine_pin_type = { - { &mp_type_type }, - .name = MP_QSTR_Pin, - .print = machine_pin_print, - .make_new = mp_pin_make_new, - .call = machine_pin_call, - .protocol = &pin_pin_p, - .locals_dict = (mp_obj_t)&machine_pin_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_type, + MP_QSTR_Pin, + MP_TYPE_FLAG_NONE, + mp_pin_make_new, + print, machine_pin_print, + call, machine_pin_call, + protocol, &pin_pin_p, + locals_dict, (mp_obj_t)&machine_pin_locals_dict + ); /* STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { diff --git a/ports/samd/samd_flash.c b/ports/samd/samd_flash.c index 530e3d9c8e..6c74b59a26 100644 --- a/ports/samd/samd_flash.c +++ b/ports/samd/samd_flash.c @@ -181,9 +181,10 @@ STATIC const mp_rom_map_elem_t samd_flash_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(samd_flash_locals_dict, samd_flash_locals_dict_table); -const mp_obj_type_t samd_flash_type = { - { &mp_type_type }, - .name = MP_QSTR_Flash, - .make_new = samd_flash_make_new, - .locals_dict = (mp_obj_dict_t *)&samd_flash_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + samd_flash_type, + MP_QSTR_Flash, + MP_TYPE_FLAG_NONE, + samd_flash_make_new, + locals_dict, (mp_obj_dict_t *)&samd_flash_locals_dict + ); diff --git a/ports/stm32/accel.c b/ports/stm32/accel.c index b07791a9a0..276ce37d3a 100644 --- a/ports/stm32/accel.c +++ b/ports/stm32/accel.c @@ -281,11 +281,12 @@ STATIC const mp_rom_map_elem_t pyb_accel_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_accel_locals_dict, pyb_accel_locals_dict_table); -const mp_obj_type_t pyb_accel_type = { - { &mp_type_type }, - .name = MP_QSTR_Accel, - .make_new = pyb_accel_make_new, - .locals_dict = (mp_obj_dict_t *)&pyb_accel_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_accel_type, + MP_QSTR_Accel, + MP_TYPE_FLAG_NONE, + pyb_accel_make_new, + locals_dict, (mp_obj_dict_t *)&pyb_accel_locals_dict + ); #endif // MICROPY_HW_HAS_MMA7660 || MICROPY_HW_HAS_KXTJ3 diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index 9d58cf2e7c..7e627d088f 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -703,13 +703,14 @@ STATIC const mp_rom_map_elem_t adc_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table); -const mp_obj_type_t pyb_adc_type = { - { &mp_type_type }, - .name = MP_QSTR_ADC, - .print = adc_print, - .make_new = adc_make_new, - .locals_dict = (mp_obj_dict_t *)&adc_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_adc_type, + MP_QSTR_ADC, + MP_TYPE_FLAG_NONE, + adc_make_new, + print, adc_print, + locals_dict, (mp_obj_dict_t *)&adc_locals_dict + ); /******************************************************************************/ /* adc all object */ @@ -911,11 +912,12 @@ STATIC const mp_rom_map_elem_t adc_all_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(adc_all_locals_dict, adc_all_locals_dict_table); -const mp_obj_type_t pyb_adc_all_type = { - { &mp_type_type }, - .name = MP_QSTR_ADCAll, - .make_new = adc_all_make_new, - .locals_dict = (mp_obj_dict_t *)&adc_all_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_adc_all_type, + MP_QSTR_ADCAll, + MP_TYPE_FLAG_NONE, + adc_all_make_new, + locals_dict, (mp_obj_dict_t *)&adc_all_locals_dict + ); #endif // MICROPY_HW_ENABLE_ADC diff --git a/ports/stm32/dac.c b/ports/stm32/dac.c index c41bf858a7..da50b30fef 100644 --- a/ports/stm32/dac.c +++ b/ports/stm32/dac.c @@ -502,12 +502,13 @@ STATIC const mp_rom_map_elem_t pyb_dac_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_dac_locals_dict, pyb_dac_locals_dict_table); -const mp_obj_type_t pyb_dac_type = { - { &mp_type_type }, - .name = MP_QSTR_DAC, - .print = pyb_dac_print, - .make_new = pyb_dac_make_new, - .locals_dict = (mp_obj_dict_t *)&pyb_dac_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_dac_type, + MP_QSTR_DAC, + MP_TYPE_FLAG_NONE, + pyb_dac_make_new, + print, pyb_dac_print, + locals_dict, (mp_obj_dict_t *)&pyb_dac_locals_dict + ); #endif // MICROPY_HW_ENABLE_DAC diff --git a/ports/stm32/extint.c b/ports/stm32/extint.c index d68275bf19..4d2dc5d23b 100644 --- a/ports/stm32/extint.c +++ b/ports/stm32/extint.c @@ -659,13 +659,14 @@ STATIC const mp_rom_map_elem_t extint_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(extint_locals_dict, extint_locals_dict_table); -const mp_obj_type_t extint_type = { - { &mp_type_type }, - .name = MP_QSTR_ExtInt, - .print = extint_obj_print, - .make_new = extint_make_new, - .locals_dict = (mp_obj_dict_t *)&extint_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + extint_type, + MP_QSTR_ExtInt, + MP_TYPE_FLAG_NONE, + extint_make_new, + print, extint_obj_print, + locals_dict, (mp_obj_dict_t *)&extint_locals_dict + ); void extint_init0(void) { for (int i = 0; i < PYB_EXTI_NUM_VECTORS; i++) { diff --git a/ports/stm32/lcd.c b/ports/stm32/lcd.c index a0e001d1fd..a951ea7668 100644 --- a/ports/stm32/lcd.c +++ b/ports/stm32/lcd.c @@ -525,11 +525,12 @@ STATIC const mp_rom_map_elem_t pyb_lcd_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_lcd_locals_dict, pyb_lcd_locals_dict_table); -const mp_obj_type_t pyb_lcd_type = { - { &mp_type_type }, - .name = MP_QSTR_LCD, - .make_new = pyb_lcd_make_new, - .locals_dict = (mp_obj_dict_t *)&pyb_lcd_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_lcd_type, + MP_QSTR_LCD, + MP_TYPE_FLAG_NONE, + pyb_lcd_make_new, + locals_dict, (mp_obj_dict_t *)&pyb_lcd_locals_dict + ); #endif // MICROPY_HW_HAS_LCD diff --git a/ports/stm32/led.c b/ports/stm32/led.c index 078327462a..6745ef60b8 100644 --- a/ports/stm32/led.c +++ b/ports/stm32/led.c @@ -381,13 +381,14 @@ STATIC const mp_rom_map_elem_t led_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(led_locals_dict, led_locals_dict_table); -const mp_obj_type_t pyb_led_type = { - { &mp_type_type }, - .name = MP_QSTR_LED, - .print = led_obj_print, - .make_new = led_obj_make_new, - .locals_dict = (mp_obj_dict_t *)&led_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_led_type, + MP_QSTR_LED, + MP_TYPE_FLAG_NONE, + led_obj_make_new, + print, led_obj_print, + locals_dict, (mp_obj_dict_t *)&led_locals_dict + ); #else // For boards with no LEDs, we leave an empty function here so that we don't diff --git a/ports/stm32/machine_adc.c b/ports/stm32/machine_adc.c index ad7c994ba1..682bae3a6d 100644 --- a/ports/stm32/machine_adc.c +++ b/ports/stm32/machine_adc.c @@ -492,12 +492,13 @@ STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table); -const mp_obj_type_t machine_adc_type = { - { &mp_type_type }, - .name = MP_QSTR_ADC, - .print = machine_adc_print, - .make_new = machine_adc_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_adc_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_adc_type, + MP_QSTR_ADC, + MP_TYPE_FLAG_NONE, + machine_adc_make_new, + print, machine_adc_print, + locals_dict, (mp_obj_dict_t *)&machine_adc_locals_dict + ); #endif diff --git a/ports/stm32/machine_i2c.c b/ports/stm32/machine_i2c.c index 262944585a..89970f234d 100644 --- a/ports/stm32/machine_i2c.c +++ b/ports/stm32/machine_i2c.c @@ -236,13 +236,14 @@ STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = { .transfer = machine_hard_i2c_transfer, }; -const mp_obj_type_t machine_hard_i2c_type = { - { &mp_type_type }, - .name = MP_QSTR_I2C, - .print = machine_hard_i2c_print, - .make_new = machine_hard_i2c_make_new, - .protocol = &machine_hard_i2c_p, - .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_hard_i2c_type, + MP_QSTR_I2C, + MP_TYPE_FLAG_NONE, + machine_hard_i2c_make_new, + print, machine_hard_i2c_print, + protocol, &machine_hard_i2c_p, + locals_dict, (mp_obj_dict_t *)&mp_machine_i2c_locals_dict + ); #endif // MICROPY_HW_ENABLE_HW_I2C diff --git a/ports/stm32/machine_i2s.c b/ports/stm32/machine_i2s.c index 4f583a53e8..7dc6439f25 100644 --- a/ports/stm32/machine_i2s.c +++ b/ports/stm32/machine_i2s.c @@ -1114,16 +1114,17 @@ STATIC const mp_stream_p_t i2s_stream_p = { .is_text = false, }; -const mp_obj_type_t machine_i2s_type = { - { &mp_type_type }, - .name = MP_QSTR_I2S, - .print = machine_i2s_print, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &i2s_stream_p, - .make_new = machine_i2s_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_i2s_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_i2s_type, + MP_QSTR_I2S, + MP_TYPE_FLAG_NONE, + machine_i2s_make_new, + print, machine_i2s_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &i2s_stream_p, + locals_dict, (mp_obj_dict_t *)&machine_i2s_locals_dict + ); MP_REGISTER_ROOT_POINTER(struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_MAX_I2S]); diff --git a/ports/stm32/machine_spi.c b/ports/stm32/machine_spi.c index 37c026cefc..87561c2b7b 100644 --- a/ports/stm32/machine_spi.c +++ b/ports/stm32/machine_spi.c @@ -135,11 +135,12 @@ STATIC const mp_machine_spi_p_t machine_hard_spi_p = { .transfer = machine_hard_spi_transfer, }; -const mp_obj_type_t machine_hard_spi_type = { - { &mp_type_type }, - .name = MP_QSTR_SPI, - .print = machine_hard_spi_print, - .make_new = machine_hard_spi_make_new, - .protocol = &machine_hard_spi_p, - .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_hard_spi_type, + MP_QSTR_SPI, + MP_TYPE_FLAG_NONE, + machine_hard_spi_make_new, + print, machine_hard_spi_print, + protocol, &machine_hard_spi_p, + locals_dict, (mp_obj_dict_t *)&mp_machine_spi_locals_dict + ); diff --git a/ports/stm32/machine_timer.c b/ports/stm32/machine_timer.c index c387d35117..bd9dbe6098 100644 --- a/ports/stm32/machine_timer.c +++ b/ports/stm32/machine_timer.c @@ -136,10 +136,11 @@ STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table); -const mp_obj_type_t machine_timer_type = { - { &mp_type_type }, - .name = MP_QSTR_Timer, - .print = machine_timer_print, - .make_new = machine_timer_make_new, - .locals_dict = (mp_obj_dict_t *)&machine_timer_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_timer_type, + MP_QSTR_Timer, + MP_TYPE_FLAG_NONE, + machine_timer_make_new, + print, machine_timer_print, + locals_dict, (mp_obj_dict_t *)&machine_timer_locals_dict + ); diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index 1bb1d2a1a7..4d25a0274c 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -660,13 +660,14 @@ STATIC const mp_stream_p_t uart_stream_p = { .is_text = false, }; -const mp_obj_type_t pyb_uart_type = { - { &mp_type_type }, - .name = MP_QSTR_UART, - .print = pyb_uart_print, - .make_new = pyb_uart_make_new, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &uart_stream_p, - .locals_dict = (mp_obj_dict_t *)&pyb_uart_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_uart_type, + MP_QSTR_UART, + MP_TYPE_FLAG_NONE, + pyb_uart_make_new, + print, pyb_uart_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &uart_stream_p, + locals_dict, (mp_obj_dict_t *)&pyb_uart_locals_dict + ); diff --git a/ports/stm32/network_lan.c b/ports/stm32/network_lan.c index f19916a1df..f9c7d80b78 100644 --- a/ports/stm32/network_lan.c +++ b/ports/stm32/network_lan.c @@ -158,12 +158,13 @@ STATIC const mp_rom_map_elem_t network_lan_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(network_lan_locals_dict, network_lan_locals_dict_table); -const mp_obj_type_t network_lan_type = { - { &mp_type_type }, - .name = MP_QSTR_LAN, - .print = network_lan_print, - .make_new = network_lan_make_new, - .locals_dict = (mp_obj_dict_t *)&network_lan_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + network_lan_type, + MP_QSTR_LAN, + MP_TYPE_FLAG_NONE, + network_lan_make_new, + print, network_lan_print, + locals_dict, (mp_obj_dict_t *)&network_lan_locals_dict + ); #endif // defined(MICROPY_HW_ETH_MDC) diff --git a/ports/stm32/pin.c b/ports/stm32/pin.c index af6bafc43f..992046cd17 100644 --- a/ports/stm32/pin.c +++ b/ports/stm32/pin.c @@ -592,15 +592,16 @@ STATIC const mp_pin_p_t pin_pin_p = { .ioctl = pin_ioctl, }; -const mp_obj_type_t pin_type = { - { &mp_type_type }, - .name = MP_QSTR_Pin, - .print = pin_print, - .make_new = mp_pin_make_new, - .call = pin_call, - .protocol = &pin_pin_p, - .locals_dict = (mp_obj_dict_t *)&pin_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pin_type, + MP_QSTR_Pin, + MP_TYPE_FLAG_NONE, + mp_pin_make_new, + print, pin_print, + call, pin_call, + protocol, &pin_pin_p, + locals_dict, (mp_obj_dict_t *)&pin_locals_dict + ); /// \moduleref pyb /// \class PinAF - Pin Alternate Functions @@ -669,12 +670,14 @@ STATIC const mp_rom_map_elem_t pin_af_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pin_af_locals_dict, pin_af_locals_dict_table); -const mp_obj_type_t pin_af_type = { - { &mp_type_type }, - .name = MP_QSTR_PinAF, - .print = pin_af_obj_print, - .locals_dict = (mp_obj_dict_t *)&pin_af_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pin_af_type, + MP_QSTR_PinAF, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, pin_af_obj_print, + locals_dict, (mp_obj_dict_t *)&pin_af_locals_dict + ); MP_REGISTER_ROOT_POINTER(mp_obj_t pin_class_mapper); MP_REGISTER_ROOT_POINTER(mp_obj_t pin_class_map_dict); diff --git a/ports/stm32/pin_named_pins.c b/ports/stm32/pin_named_pins.c index 3a8e0f9fce..620888878c 100644 --- a/ports/stm32/pin_named_pins.c +++ b/ports/stm32/pin_named_pins.c @@ -31,17 +31,21 @@ #include "py/mphal.h" #include "pin.h" -const mp_obj_type_t pin_cpu_pins_obj_type = { - { &mp_type_type }, - .name = MP_QSTR_cpu, - .locals_dict = (mp_obj_dict_t *)&pin_cpu_pins_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pin_cpu_pins_obj_type, + MP_QSTR_cpu, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + locals_dict, (mp_obj_dict_t *)&pin_cpu_pins_locals_dict + ); -const mp_obj_type_t pin_board_pins_obj_type = { - { &mp_type_type }, - .name = MP_QSTR_board, - .locals_dict = (mp_obj_dict_t *)&pin_board_pins_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pin_board_pins_obj_type, + MP_QSTR_board, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + locals_dict, (mp_obj_dict_t *)&pin_board_pins_locals_dict + ); const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) { const mp_map_t *named_map = &named_pins->map; diff --git a/ports/stm32/pyb_can.c b/ports/stm32/pyb_can.c index ff41de3186..6fdfd2c854 100644 --- a/ports/stm32/pyb_can.c +++ b/ports/stm32/pyb_can.c @@ -1072,14 +1072,15 @@ STATIC const mp_stream_p_t can_stream_p = { .is_text = false, }; -const mp_obj_type_t pyb_can_type = { - { &mp_type_type }, - .name = MP_QSTR_CAN, - .print = pyb_can_print, - .make_new = pyb_can_make_new, - .protocol = &can_stream_p, - .locals_dict = (mp_obj_dict_t *)&pyb_can_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_can_type, + MP_QSTR_CAN, + MP_TYPE_FLAG_NONE, + pyb_can_make_new, + print, pyb_can_print, + protocol, &can_stream_p, + locals_dict, (mp_obj_dict_t *)&pyb_can_locals_dict + ); MP_REGISTER_ROOT_POINTER(struct _pyb_can_obj_t *pyb_can_obj_all[MICROPY_HW_MAX_CAN]); diff --git a/ports/stm32/pyb_i2c.c b/ports/stm32/pyb_i2c.c index e9877422ca..ee6983a143 100644 --- a/ports/stm32/pyb_i2c.c +++ b/ports/stm32/pyb_i2c.c @@ -1104,12 +1104,13 @@ STATIC const mp_rom_map_elem_t pyb_i2c_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table); -const mp_obj_type_t pyb_i2c_type = { - { &mp_type_type }, - .name = MP_QSTR_I2C, - .print = pyb_i2c_print, - .make_new = pyb_i2c_make_new, - .locals_dict = (mp_obj_dict_t *)&pyb_i2c_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_i2c_type, + MP_QSTR_I2C, + MP_TYPE_FLAG_NONE, + pyb_i2c_make_new, + print, pyb_i2c_print, + locals_dict, (mp_obj_dict_t *)&pyb_i2c_locals_dict + ); #endif // MICROPY_PY_PYB_LEGACY && MICROPY_HW_ENABLE_HW_I2C diff --git a/ports/stm32/pyb_spi.c b/ports/stm32/pyb_spi.c index f2cdcebf2a..b1425272fe 100644 --- a/ports/stm32/pyb_spi.c +++ b/ports/stm32/pyb_spi.c @@ -350,11 +350,12 @@ STATIC const mp_machine_spi_p_t pyb_spi_p = { .transfer = spi_transfer_machine, }; -const mp_obj_type_t pyb_spi_type = { - { &mp_type_type }, - .name = MP_QSTR_SPI, - .print = pyb_spi_print, - .make_new = pyb_spi_make_new, - .protocol = &pyb_spi_p, - .locals_dict = (mp_obj_dict_t *)&pyb_spi_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_spi_type, + MP_QSTR_SPI, + MP_TYPE_FLAG_NONE, + pyb_spi_make_new, + print, pyb_spi_print, + protocol, &pyb_spi_p, + locals_dict, (mp_obj_dict_t *)&pyb_spi_locals_dict + ); diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index 55977791b8..c7698db143 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -837,9 +837,10 @@ STATIC const mp_rom_map_elem_t pyb_rtc_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table); -const mp_obj_type_t pyb_rtc_type = { - { &mp_type_type }, - .name = MP_QSTR_RTC, - .make_new = pyb_rtc_make_new, - .locals_dict = (mp_obj_dict_t *)&pyb_rtc_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_rtc_type, + MP_QSTR_RTC, + MP_TYPE_FLAG_NONE, + pyb_rtc_make_new, + locals_dict, (mp_obj_dict_t *)&pyb_rtc_locals_dict + ); diff --git a/ports/stm32/sdcard.c b/ports/stm32/sdcard.c index 6f5892570b..b9cc051e7f 100644 --- a/ports/stm32/sdcard.c +++ b/ports/stm32/sdcard.c @@ -872,21 +872,23 @@ STATIC const mp_rom_map_elem_t pyb_sdcard_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_sdcard_locals_dict, pyb_sdcard_locals_dict_table); #if MICROPY_HW_ENABLE_SDCARD -const mp_obj_type_t pyb_sdcard_type = { - { &mp_type_type }, - .name = MP_QSTR_SDCard, - .make_new = pyb_sdcard_make_new, - .locals_dict = (mp_obj_dict_t *)&pyb_sdcard_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_sdcard_type, + MP_QSTR_SDCard, + MP_TYPE_FLAG_NONE, + pyb_sdcard_make_new, + locals_dict, (mp_obj_dict_t *)&pyb_sdcard_locals_dict + ); #endif #if MICROPY_HW_ENABLE_MMCARD -const mp_obj_type_t pyb_mmcard_type = { - { &mp_type_type }, - .name = MP_QSTR_MMCard, - .make_new = pyb_mmcard_make_new, - .locals_dict = (mp_obj_dict_t *)&pyb_sdcard_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_mmcard_type, + MP_QSTR_MMCard, + MP_TYPE_FLAG_NONE, + pyb_mmcard_make_new, + locals_dict, (mp_obj_dict_t *)&pyb_sdcard_locals_dict + ); #endif void sdcard_init_vfs(fs_user_mount_t *vfs, int part) { diff --git a/ports/stm32/servo.c b/ports/stm32/servo.c index 1708422463..d552f5e6b5 100644 --- a/ports/stm32/servo.c +++ b/ports/stm32/servo.c @@ -336,12 +336,13 @@ STATIC const mp_rom_map_elem_t pyb_servo_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_servo_locals_dict, pyb_servo_locals_dict_table); -const mp_obj_type_t pyb_servo_type = { - { &mp_type_type }, - .name = MP_QSTR_Servo, - .print = pyb_servo_print, - .make_new = pyb_servo_make_new, - .locals_dict = (mp_obj_dict_t *)&pyb_servo_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_servo_type, + MP_QSTR_Servo, + MP_TYPE_FLAG_NONE, + pyb_servo_make_new, + print, pyb_servo_print, + locals_dict, (mp_obj_dict_t *)&pyb_servo_locals_dict + ); #endif // MICROPY_HW_ENABLE_SERVO diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c index c33a75f671..92f7059493 100644 --- a/ports/stm32/storage.c +++ b/ports/stm32/storage.c @@ -453,13 +453,14 @@ STATIC const mp_rom_map_elem_t pyb_flash_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_flash_locals_dict, pyb_flash_locals_dict_table); -const mp_obj_type_t pyb_flash_type = { - { &mp_type_type }, - .name = MP_QSTR_Flash, - .print = pyb_flash_print, - .make_new = pyb_flash_make_new, - .locals_dict = (mp_obj_dict_t *)&pyb_flash_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_flash_type, + MP_QSTR_Flash, + MP_TYPE_FLAG_NONE, + pyb_flash_make_new, + print, pyb_flash_print, + locals_dict, (mp_obj_dict_t *)&pyb_flash_locals_dict + ); void pyb_flash_init_vfs(fs_user_mount_t *vfs) { vfs->base.type = &mp_fat_vfs_type; diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index 518a2e23b4..abf4c1f3fc 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -1471,13 +1471,14 @@ STATIC const mp_rom_map_elem_t pyb_timer_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table); -const mp_obj_type_t pyb_timer_type = { - { &mp_type_type }, - .name = MP_QSTR_Timer, - .print = pyb_timer_print, - .make_new = pyb_timer_make_new, - .locals_dict = (mp_obj_dict_t *)&pyb_timer_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_timer_type, + MP_QSTR_Timer, + MP_TYPE_FLAG_NONE, + pyb_timer_make_new, + print, pyb_timer_print, + locals_dict, (mp_obj_dict_t *)&pyb_timer_locals_dict + ); /// \moduleref pyb /// \class TimerChannel - setup a channel for a timer. @@ -1610,12 +1611,14 @@ STATIC const mp_rom_map_elem_t pyb_timer_channel_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table); -STATIC const mp_obj_type_t pyb_timer_channel_type = { - { &mp_type_type }, - .name = MP_QSTR_TimerChannel, - .print = pyb_timer_channel_print, - .locals_dict = (mp_obj_dict_t *)&pyb_timer_channel_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + pyb_timer_channel_type, + MP_QSTR_TimerChannel, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, pyb_timer_channel_print, + locals_dict, (mp_obj_dict_t *)&pyb_timer_channel_locals_dict + ); STATIC void timer_handle_irq_channel(pyb_timer_obj_t *tim, uint8_t channel, mp_obj_t callback) { uint32_t irq_mask = TIMER_IRQ_MASK(channel); diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index c5fdd88acf..7c36765c28 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -936,16 +936,17 @@ STATIC const mp_stream_p_t pyb_usb_vcp_stream_p = { .ioctl = pyb_usb_vcp_ioctl, }; -const mp_obj_type_t pyb_usb_vcp_type = { - { &mp_type_type }, - .name = MP_QSTR_USB_VCP, - .print = pyb_usb_vcp_print, - .make_new = pyb_usb_vcp_make_new, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &pyb_usb_vcp_stream_p, - .locals_dict = (mp_obj_dict_t *)&pyb_usb_vcp_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_usb_vcp_type, + MP_QSTR_USB_VCP, + MP_TYPE_FLAG_NONE, + pyb_usb_vcp_make_new, + print, pyb_usb_vcp_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &pyb_usb_vcp_stream_p, + locals_dict, (mp_obj_dict_t *)&pyb_usb_vcp_locals_dict + ); /******************************************************************************/ // MicroPython bindings for USB HID @@ -1077,13 +1078,14 @@ STATIC const mp_stream_p_t pyb_usb_hid_stream_p = { .ioctl = pyb_usb_hid_ioctl, }; -const mp_obj_type_t pyb_usb_hid_type = { - { &mp_type_type }, - .name = MP_QSTR_USB_HID, - .make_new = pyb_usb_hid_make_new, - .protocol = &pyb_usb_hid_stream_p, - .locals_dict = (mp_obj_dict_t *)&pyb_usb_hid_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_usb_hid_type, + MP_QSTR_USB_HID, + MP_TYPE_FLAG_NONE, + pyb_usb_hid_make_new, + protocol, &pyb_usb_hid_stream_p, + locals_dict, (mp_obj_dict_t *)&pyb_usb_hid_locals_dict + ); #endif // MICROPY_HW_USB_HID diff --git a/ports/stm32/usrsw.c b/ports/stm32/usrsw.c index 60aae1c883..137f4dabfa 100644 --- a/ports/stm32/usrsw.c +++ b/ports/stm32/usrsw.c @@ -134,14 +134,15 @@ STATIC const mp_rom_map_elem_t pyb_switch_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_switch_locals_dict, pyb_switch_locals_dict_table); -const mp_obj_type_t pyb_switch_type = { - { &mp_type_type }, - .name = MP_QSTR_Switch, - .print = pyb_switch_print, - .make_new = pyb_switch_make_new, - .call = pyb_switch_call, - .locals_dict = (mp_obj_dict_t *)&pyb_switch_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_switch_type, + MP_QSTR_Switch, + MP_TYPE_FLAG_NONE, + pyb_switch_make_new, + print, pyb_switch_print, + call, pyb_switch_call, + locals_dict, (mp_obj_dict_t *)&pyb_switch_locals_dict + ); MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_switch_callback); diff --git a/ports/stm32/wdt.c b/ports/stm32/wdt.c index d794607bc0..e3b8e2e0ae 100644 --- a/ports/stm32/wdt.c +++ b/ports/stm32/wdt.c @@ -102,9 +102,10 @@ STATIC const mp_rom_map_elem_t pyb_wdt_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_wdt_locals_dict, pyb_wdt_locals_dict_table); -const mp_obj_type_t pyb_wdt_type = { - { &mp_type_type }, - .name = MP_QSTR_WDT, - .make_new = pyb_wdt_make_new, - .locals_dict = (mp_obj_dict_t *)&pyb_wdt_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_wdt_type, + MP_QSTR_WDT, + MP_TYPE_FLAG_NONE, + pyb_wdt_make_new, + locals_dict, (mp_obj_dict_t *)&pyb_wdt_locals_dict + ); diff --git a/ports/teensy/led.c b/ports/teensy/led.c index d79e63cf71..ca548431fe 100644 --- a/ports/teensy/led.c +++ b/ports/teensy/led.c @@ -134,10 +134,11 @@ STATIC const mp_rom_map_elem_t led_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(led_locals_dict, led_locals_dict_table); -const mp_obj_type_t pyb_led_type = { - { &mp_type_type }, - .name = MP_QSTR_LED, - .print = led_obj_print, - .make_new = led_obj_make_new, - .locals_dict = (mp_obj_t)&led_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_led_type, + MP_QSTR_LED, + MP_TYPE_FLAG_NONE, + led_obj_make_new, + print, led_obj_print, + locals_dict, (mp_obj_t)&led_locals_dict + ); diff --git a/ports/teensy/timer.c b/ports/teensy/timer.c index 68dc965eb8..4df2474335 100644 --- a/ports/teensy/timer.c +++ b/ports/teensy/timer.c @@ -746,13 +746,14 @@ STATIC const mp_rom_map_elem_t pyb_timer_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table); -const mp_obj_type_t pyb_timer_type = { - { &mp_type_type }, - .name = MP_QSTR_Timer, - .print = pyb_timer_print, - .make_new = pyb_timer_make_new, - .locals_dict = (mp_obj_t)&pyb_timer_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_timer_type, + MP_QSTR_Timer, + MP_TYPE_FLAG_NONE, + pyb_timer_make_new, + print, pyb_timer_print, + locals_dict, (mp_obj_t)&pyb_timer_locals_dict + ); /// \moduleref pyb /// \class TimerChannel - setup a channel for a timer. @@ -889,12 +890,14 @@ STATIC const mp_rom_map_elem_t pyb_timer_channel_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table); -STATIC const mp_obj_type_t pyb_timer_channel_type = { - { &mp_type_type }, - .name = MP_QSTR_TimerChannel, - .print = pyb_timer_channel_print, - .locals_dict = (mp_obj_t)&pyb_timer_channel_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + pyb_timer_channel_type, + MP_QSTR_TimerChannel, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, pyb_timer_channel_print, + locals_dict, (mp_obj_t)&pyb_timer_channel_locals_dict + ); STATIC bool ftm_handle_irq_callback(pyb_timer_obj_t *self, mp_uint_t channel, mp_obj_t callback) { // execute callback if it's set diff --git a/ports/teensy/uart.c b/ports/teensy/uart.c index 5b63fcb3cd..8957d92709 100644 --- a/ports/teensy/uart.c +++ b/ports/teensy/uart.c @@ -483,10 +483,11 @@ STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table); -const mp_obj_type_t pyb_uart_type = { - { &mp_type_type }, - .name = MP_QSTR_UART, - .print = pyb_uart_print, - .make_new = pyb_uart_make_new, - .locals_dict = (mp_obj_t)&pyb_uart_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + pyb_uart_type, + MP_QSTR_UART, + MP_TYPE_FLAG_NONE, + pyb_uart_make_new, + print, pyb_uart_print, + locals_dict, (mp_obj_t)&pyb_uart_locals_dict + ); diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index cf425ac433..b4567417a2 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -106,11 +106,14 @@ STATIC const mp_stream_p_t fileio_stream_p = { .ioctl = stest_ioctl, }; -STATIC const mp_obj_type_t mp_type_stest_fileio = { - { &mp_type_type }, - .protocol = &fileio_stream_p, - .locals_dict = (mp_obj_dict_t *)&rawfile_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_stest_fileio, + MP_QSTR_stest_fileio, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + protocol, &fileio_stream_p, + locals_dict, (mp_obj_dict_t *)&rawfile_locals_dict + ); // stream read returns non-blocking error STATIC mp_uint_t stest_read2(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { @@ -133,11 +136,14 @@ STATIC const mp_stream_p_t textio_stream_p2 = { .is_text = true, }; -STATIC const mp_obj_type_t mp_type_stest_textio2 = { - { &mp_type_type }, - .protocol = &textio_stream_p2, - .locals_dict = (mp_obj_dict_t *)&rawfile_locals_dict2, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_stest_textio2, + MP_QSTR_stest_textio2, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + protocol, &textio_stream_p2, + locals_dict, (mp_obj_dict_t *)&rawfile_locals_dict2 + ); // str/bytes objects without a valid hash STATIC const mp_obj_str_t str_no_hash_obj = {{&mp_type_str}, 0, 10, (const byte *)"0123456789"}; diff --git a/ports/unix/modffi.c b/ports/unix/modffi.c index 6417b5d3b3..98f0a1aa0f 100644 --- a/ports/unix/modffi.c +++ b/ports/unix/modffi.c @@ -421,13 +421,14 @@ STATIC const mp_rom_map_elem_t ffimod_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ffimod_locals_dict, ffimod_locals_dict_table); -STATIC const mp_obj_type_t ffimod_type = { - { &mp_type_type }, - .name = MP_QSTR_ffimod, - .print = ffimod_print, - .make_new = ffimod_make_new, - .locals_dict = (mp_obj_dict_t *)&ffimod_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + ffimod_type, + MP_QSTR_ffimod, + MP_TYPE_FLAG_NONE, + ffimod_make_new, + print, ffimod_print, + locals_dict, (mp_obj_dict_t *)&ffimod_locals_dict + ); // FFI function @@ -530,12 +531,14 @@ error: mp_raise_TypeError(MP_ERROR_TEXT("don't know how to pass object to native function")); } -STATIC const mp_obj_type_t ffifunc_type = { - { &mp_type_type }, - .name = MP_QSTR_ffifunc, - .print = ffifunc_print, - .call = ffifunc_call, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + ffifunc_type, + MP_QSTR_ffifunc, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, ffifunc_print, + call, ffifunc_call + ); // FFI callback for Python function @@ -556,12 +559,14 @@ STATIC const mp_rom_map_elem_t fficallback_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(fficallback_locals_dict, fficallback_locals_dict_table); -STATIC const mp_obj_type_t fficallback_type = { - { &mp_type_type }, - .name = MP_QSTR_fficallback, - .print = fficallback_print, - .locals_dict = (mp_obj_dict_t *)&fficallback_locals_dict -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + fficallback_type, + MP_QSTR_fficallback, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, fficallback_print, + locals_dict, (mp_obj_dict_t *)&fficallback_locals_dict + ); // FFI variable @@ -592,21 +597,25 @@ STATIC const mp_rom_map_elem_t ffivar_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ffivar_locals_dict, ffivar_locals_dict_table); -STATIC const mp_obj_type_t ffivar_type = { - { &mp_type_type }, - .name = MP_QSTR_ffivar, - .print = ffivar_print, - .locals_dict = (mp_obj_dict_t *)&ffivar_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + ffivar_type, + MP_QSTR_ffivar, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, ffivar_print, + locals_dict, (mp_obj_dict_t *)&ffivar_locals_dict + ); // Generic opaque storage object (unused) /* -STATIC const mp_obj_type_t opaque_type = { - { &mp_type_type }, - .name = MP_QSTR_opaqueval, -// .print = opaque_print, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + opaque_type, + MP_QSTR_opaqueval, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + // .print = opaque_print, + ); */ STATIC mp_obj_t mod_ffi_open(size_t n_args, const mp_obj_t *args) { diff --git a/ports/unix/modjni.c b/ports/unix/modjni.c index 6fa00731fb..72f95b645b 100644 --- a/ports/unix/modjni.c +++ b/ports/unix/modjni.c @@ -174,14 +174,16 @@ STATIC const mp_rom_map_elem_t jclass_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(jclass_locals_dict, jclass_locals_dict_table); -STATIC const mp_obj_type_t jclass_type = { - { &mp_type_type }, - .name = MP_QSTR_jclass, - .print = jclass_print, - .attr = jclass_attr, - .call = jclass_call, - .locals_dict = (mp_obj_dict_t *)&jclass_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + jclass_type, + MP_QSTR_jclass, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, jclass_print, + attr, jclass_attr, + call, jclass_call, + locals_dict, (mp_obj_dict_t *)&jclass_locals_dict + ); STATIC mp_obj_t new_jclass(jclass jc) { mp_obj_jclass_t *o = mp_obj_malloc(mp_obj_jclass_t, &jclass_type); @@ -320,16 +322,18 @@ STATIC mp_obj_t subscr_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { return mp_obj_new_getitem_iter(dest, iter_buf); } -STATIC const mp_obj_type_t jobject_type = { - { &mp_type_type }, - .name = MP_QSTR_jobject, - .print = jobject_print, - .unary_op = jobject_unary_op, - .attr = jobject_attr, - .subscr = jobject_subscr, - .getiter = subscr_getiter, -// .locals_dict = (mp_obj_dict_t*)&jobject_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + jobject_type, + MP_QSTR_jobject, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, jobject_print, + unary_op, jobject_unary_op, + attr, jobject_attr, + subscr, jobject_subscr, + getiter, subscr_getiter, + // .locals_dict = (mp_obj_dict_t*)&jobject_locals_dict, + ); STATIC mp_obj_t new_jobject(jobject jo) { if (jo == NULL) { @@ -567,14 +571,16 @@ STATIC mp_obj_t jmethod_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const return call_method(self->obj, name, methods, false, n_args, args); } -STATIC const mp_obj_type_t jmethod_type = { - { &mp_type_type }, - .name = MP_QSTR_jmethod, - .print = jmethod_print, - .call = jmethod_call, -// .attr = jobject_attr, -// .locals_dict = (mp_obj_dict_t*)&jobject_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + jmethod_type, + MP_QSTR_jmethod, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, jmethod_print, + call, jmethod_call, + // .attr = jobject_attr, + // .locals_dict = (mp_obj_dict_t*)&jobject_locals_dict, + ); #ifdef __ANDROID__ #define LIBJVM_SO "libdvm.so" diff --git a/ports/unix/moduselect.c b/ports/unix/moduselect.c index 2de4a316ed..d8a8d1d8c3 100644 --- a/ports/unix/moduselect.c +++ b/ports/unix/moduselect.c @@ -311,13 +311,15 @@ STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table); -STATIC const mp_obj_type_t mp_type_poll = { - { &mp_type_type }, - .name = MP_QSTR_poll, - .getiter = mp_identity_getiter, - .iternext = poll_iternext, - .locals_dict = (void *)&poll_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_poll, + MP_QSTR_poll, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + getiter, mp_identity_getiter, + iternext, poll_iternext, + locals_dict, (void *)&poll_locals_dict + ); STATIC mp_obj_t select_poll(size_t n_args, const mp_obj_t *args) { int alloc = 4; diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c index 72c70d1750..7e4476cbd0 100644 --- a/ports/unix/modusocket.c +++ b/ports/unix/modusocket.c @@ -516,16 +516,17 @@ STATIC const mp_stream_p_t usocket_stream_p = { .ioctl = socket_ioctl, }; -const mp_obj_type_t mp_type_socket = { - { &mp_type_type }, - .name = MP_QSTR_socket, - .print = socket_print, - .make_new = socket_make_new, - .getiter = NULL, - .iternext = NULL, - .protocol = &usocket_stream_p, - .locals_dict = (mp_obj_dict_t *)&usocket_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_socket, + MP_QSTR_socket, + MP_TYPE_FLAG_NONE, + socket_make_new, + print, socket_print, + getiter, NULL, + iternext, NULL, + protocol, &usocket_stream_p, + locals_dict, (mp_obj_dict_t *)&usocket_locals_dict + ); #define BINADDR_MAX_LEN sizeof(struct in6_addr) STATIC mp_obj_t mod_socket_inet_pton(mp_obj_t family_in, mp_obj_t addr_in) { diff --git a/ports/zephyr/machine_i2c.c b/ports/zephyr/machine_i2c.c index 9bb63229dd..60a1924d80 100644 --- a/ports/zephyr/machine_i2c.c +++ b/ports/zephyr/machine_i2c.c @@ -126,13 +126,14 @@ STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = { .transfer_single = machine_hard_i2c_transfer_single, }; -const mp_obj_type_t machine_hard_i2c_type = { - { &mp_type_type }, - .name = MP_QSTR_I2C, - .print = machine_hard_i2c_print, - .make_new = machine_hard_i2c_make_new, - .protocol = &machine_hard_i2c_p, - .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_hard_i2c_type, + MP_QSTR_I2C, + MP_TYPE_FLAG_NONE, + machine_hard_i2c_make_new, + print, machine_hard_i2c_print, + protocol, &machine_hard_i2c_p, + locals_dict, (mp_obj_dict_t *)&mp_machine_i2c_locals_dict + ); #endif // MICROPY_PY_MACHINE_I2C diff --git a/ports/zephyr/machine_pin.c b/ports/zephyr/machine_pin.c index aa55c04104..48303edd81 100644 --- a/ports/zephyr/machine_pin.c +++ b/ports/zephyr/machine_pin.c @@ -285,15 +285,16 @@ STATIC const mp_pin_p_t machine_pin_pin_p = { .ioctl = machine_pin_ioctl, }; -const mp_obj_type_t machine_pin_type = { - { &mp_type_type }, - .name = MP_QSTR_Pin, - .print = machine_pin_print, - .make_new = mp_pin_make_new, - .call = machine_pin_call, - .protocol = &machine_pin_pin_p, - .locals_dict = (mp_obj_t)&machine_pin_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_type, + MP_QSTR_Pin, + MP_TYPE_FLAG_NONE, + mp_pin_make_new, + print, machine_pin_print, + call, machine_pin_call, + protocol, &machine_pin_pin_p, + locals_dict, (mp_obj_t)&machine_pin_locals_dict + ); STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/ports/zephyr/machine_spi.c b/ports/zephyr/machine_spi.c index 2b0911c591..6d9bf896b0 100644 --- a/ports/zephyr/machine_spi.c +++ b/ports/zephyr/machine_spi.c @@ -197,13 +197,14 @@ STATIC const mp_machine_spi_p_t machine_hard_spi_p = { .transfer = machine_hard_spi_transfer, }; -const mp_obj_type_t machine_hard_spi_type = { - { &mp_type_type }, - .name = MP_QSTR_SPI, - .print = machine_hard_spi_print, - .make_new = machine_hard_spi_make_new, - .protocol = &machine_hard_spi_p, - .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_hard_spi_type, + MP_QSTR_SPI, + MP_TYPE_FLAG_NONE, + machine_hard_spi_make_new, + print, machine_hard_spi_print, + protocol, &machine_hard_spi_p, + locals_dict, (mp_obj_dict_t *)&mp_machine_spi_locals_dict + ); #endif // MICROPY_PY_MACHINE_SPI diff --git a/ports/zephyr/machine_uart.c b/ports/zephyr/machine_uart.c index 3520795c5a..3f5df74657 100644 --- a/ports/zephyr/machine_uart.c +++ b/ports/zephyr/machine_uart.c @@ -154,13 +154,14 @@ STATIC const mp_stream_p_t uart_stream_p = { .is_text = false, }; -const mp_obj_type_t machine_uart_type = { - { &mp_type_type }, - .name = MP_QSTR_UART, - .print = machine_uart_print, - .make_new = machine_uart_make_new, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &uart_stream_p, - .locals_dict = (mp_obj_dict_t *)&machine_uart_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + machine_uart_type, + MP_QSTR_UART, + MP_TYPE_FLAG_NONE, + machine_uart_make_new, + print, machine_uart_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &uart_stream_p, + locals_dict, (mp_obj_dict_t *)&machine_uart_locals_dict + ); diff --git a/ports/zephyr/modusocket.c b/ports/zephyr/modusocket.c index 17cf9babd3..a7bef74ca6 100644 --- a/ports/zephyr/modusocket.c +++ b/ports/zephyr/modusocket.c @@ -353,14 +353,15 @@ STATIC const mp_stream_p_t socket_stream_p = { .ioctl = sock_ioctl, }; -STATIC const mp_obj_type_t socket_type = { - { &mp_type_type }, - .name = MP_QSTR_socket, - .print = socket_print, - .make_new = socket_make_new, - .protocol = &socket_stream_p, - .locals_dict = (mp_obj_t)&socket_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + socket_type, + MP_QSTR_socket, + MP_TYPE_FLAG_NONE, + socket_make_new, + print, socket_print, + protocol, &socket_stream_p, + locals_dict, (mp_obj_t)&socket_locals_dict + ); // // getaddrinfo() implementation diff --git a/ports/zephyr/modzsensor.c b/ports/zephyr/modzsensor.c index ba6717046f..7c0b0193d3 100644 --- a/ports/zephyr/modzsensor.c +++ b/ports/zephyr/modzsensor.c @@ -105,12 +105,13 @@ STATIC const mp_rom_map_elem_t sensor_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(sensor_locals_dict, sensor_locals_dict_table); -STATIC const mp_obj_type_t sensor_type = { - { &mp_type_type }, - .name = MP_QSTR_Sensor, - .make_new = sensor_make_new, - .locals_dict = (void *)&sensor_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + sensor_type, + MP_QSTR_Sensor, + MP_TYPE_FLAG_NONE, + sensor_make_new, + locals_dict, (void *)&sensor_locals_dict + ); STATIC const mp_rom_map_elem_t mp_module_zsensor_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_zsensor) }, diff --git a/ports/zephyr/zephyr_storage.c b/ports/zephyr/zephyr_storage.c index 1179c3fda8..ded7caa657 100644 --- a/ports/zephyr/zephyr_storage.c +++ b/ports/zephyr/zephyr_storage.c @@ -128,13 +128,14 @@ STATIC const mp_rom_map_elem_t zephyr_disk_access_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(zephyr_disk_access_locals_dict, zephyr_disk_access_locals_dict_table); -const mp_obj_type_t zephyr_disk_access_type = { - { &mp_type_type }, - .name = MP_QSTR_DiskAccess, - .print = zephyr_disk_access_print, - .make_new = zephyr_disk_access_make_new, - .locals_dict = (mp_obj_dict_t *)&zephyr_disk_access_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + zephyr_disk_access_type, + MP_QSTR_DiskAccess, + MP_TYPE_FLAG_NONE, + zephyr_disk_access_make_new, + print, zephyr_disk_access_print, + locals_dict, (mp_obj_dict_t *)&zephyr_disk_access_locals_dict + ); #endif // CONFIG_DISK_ACCESS #ifdef CONFIG_FLASH_MAP @@ -249,11 +250,12 @@ STATIC const mp_rom_map_elem_t zephyr_flash_area_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(zephyr_flash_area_locals_dict, zephyr_flash_area_locals_dict_table); -const mp_obj_type_t zephyr_flash_area_type = { - { &mp_type_type }, - .name = MP_QSTR_FlashArea, - .print = zephyr_flash_area_print, - .make_new = zephyr_flash_area_make_new, - .locals_dict = (mp_obj_dict_t *)&zephyr_flash_area_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + zephyr_flash_area_type, + MP_QSTR_FlashArea, + MP_TYPE_FLAG_NONE, + zephyr_flash_area_make_new, + print, zephyr_flash_area_print, + locals_dict, (mp_obj_dict_t *)&zephyr_flash_area_locals_dict + ); #endif // CONFIG_FLASH_MAP diff --git a/py/builtinevex.c b/py/builtinevex.c index 73b77b40b7..403cd95a9d 100644 --- a/py/builtinevex.c +++ b/py/builtinevex.c @@ -38,10 +38,12 @@ typedef struct _mp_obj_code_t { mp_obj_t module_fun; } mp_obj_code_t; -STATIC const mp_obj_type_t mp_type_code = { - { &mp_type_type }, - .name = MP_QSTR_code, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_code, + MP_QSTR_code, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW + ); STATIC mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_dict_t *globals, mp_obj_dict_t *locals) { // save context and set new context diff --git a/py/modio.c b/py/modio.c index d44c1948ab..093cb1f7e7 100644 --- a/py/modio.c +++ b/py/modio.c @@ -97,12 +97,13 @@ STATIC const mp_stream_p_t iobase_p = { .ioctl = iobase_ioctl, }; -STATIC const mp_obj_type_t mp_type_iobase = { - { &mp_type_type }, - .name = MP_QSTR_IOBase, - .make_new = iobase_make_new, - .protocol = &iobase_p, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_iobase, + MP_QSTR_IOBase, + MP_TYPE_FLAG_NONE, + iobase_make_new, + protocol, &iobase_p + ); #endif // MICROPY_PY_IO_IOBASE @@ -191,13 +192,14 @@ STATIC const mp_stream_p_t bufwriter_stream_p = { .write = bufwriter_write, }; -STATIC const mp_obj_type_t mp_type_bufwriter = { - { &mp_type_type }, - .name = MP_QSTR_BufferedWriter, - .make_new = bufwriter_make_new, - .protocol = &bufwriter_stream_p, - .locals_dict = (mp_obj_dict_t *)&bufwriter_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_bufwriter, + MP_QSTR_BufferedWriter, + MP_TYPE_FLAG_NONE, + bufwriter_make_new, + protocol, &bufwriter_stream_p, + locals_dict, (mp_obj_dict_t *)&bufwriter_locals_dict + ); #endif // MICROPY_PY_IO_BUFFEREDWRITER STATIC const mp_rom_map_elem_t mp_module_io_globals_table[] = { diff --git a/py/modthread.c b/py/modthread.c index bad94fbf2f..0a15447425 100644 --- a/py/modthread.c +++ b/py/modthread.c @@ -116,11 +116,13 @@ STATIC const mp_rom_map_elem_t thread_lock_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(thread_lock_locals_dict, thread_lock_locals_dict_table); -STATIC const mp_obj_type_t mp_type_thread_lock = { - { &mp_type_type }, - .name = MP_QSTR_lock, - .locals_dict = (mp_obj_dict_t *)&thread_lock_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_thread_lock, + MP_QSTR_lock, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + locals_dict, (mp_obj_dict_t *)&thread_lock_locals_dict + ); /****************************************************************/ // _thread module diff --git a/py/objarray.c b/py/objarray.c index dca41c2931..d93cce29ee 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -571,54 +571,55 @@ STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_ui } #if MICROPY_PY_ARRAY -const mp_obj_type_t mp_type_array = { - { &mp_type_type }, - .name = MP_QSTR_array, - .print = array_print, - .make_new = array_make_new, - .getiter = array_iterator_new, - .unary_op = array_unary_op, - .binary_op = array_binary_op, - .subscr = array_subscr, - .buffer_p = array_get_buffer, - .locals_dict = (mp_obj_dict_t *)&mp_obj_array_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_array, + MP_QSTR_array, + MP_TYPE_FLAG_NONE, + array_make_new, + print, array_print, + getiter, array_iterator_new, + unary_op, array_unary_op, + binary_op, array_binary_op, + subscr, array_subscr, + buffer, array_get_buffer, + locals_dict, (mp_obj_dict_t *)&mp_obj_array_locals_dict + ); #endif #if MICROPY_PY_BUILTINS_BYTEARRAY -const mp_obj_type_t mp_type_bytearray = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, - .name = MP_QSTR_bytearray, - .print = array_print, - .make_new = bytearray_make_new, - .getiter = array_iterator_new, - .unary_op = array_unary_op, - .binary_op = array_binary_op, - .subscr = array_subscr, - .buffer = array_get_buffer, - .locals_dict = (mp_obj_dict_t *)&mp_obj_bytearray_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_bytearray, + MP_QSTR_bytearray, + MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, + bytearray_make_new, + print, array_print, + getiter, array_iterator_new, + unary_op, array_unary_op, + binary_op, array_binary_op, + subscr, array_subscr, + buffer, array_get_buffer, + locals_dict, (mp_obj_dict_t *)&mp_obj_bytearray_locals_dict + ); #endif #if MICROPY_PY_BUILTINS_MEMORYVIEW -const mp_obj_type_t mp_type_memoryview = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, - .name = MP_QSTR_memoryview, - .make_new = memoryview_make_new, - .getiter = array_iterator_new, - .unary_op = array_unary_op, - .binary_op = array_binary_op, +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_memoryview, + MP_QSTR_memoryview, + MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, + memoryview_make_new, + getiter, array_iterator_new, + unary_op, array_unary_op, + binary_op, array_binary_op, #if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE - .attr = memoryview_attr, + attr, memoryview_attr, #endif #if MICROPY_PY_BUILTINS_BYTES_HEX - .locals_dict = (mp_obj_dict_t *)&mp_obj_memoryview_locals_dict, + locals_dict, (mp_obj_dict_t *)&mp_obj_memoryview_locals_dict, #endif .subscr = array_subscr, .buffer = array_get_buffer, -}; + ); #endif /* unused @@ -664,12 +665,14 @@ STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) { } } -STATIC const mp_obj_type_t mp_type_array_it = { - { &mp_type_type }, - .name = MP_QSTR_iterator, - .getiter = mp_identity_getiter, - .iternext = array_it_iternext, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_array_it, + MP_QSTR_iterator, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + getiter, mp_identity_getiter, + iternext, array_it_iternext + ); STATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_array_t) <= sizeof(mp_obj_iter_buf_t)); diff --git a/py/objattrtuple.c b/py/objattrtuple.c index 13c281aa1c..0d41ee5235 100644 --- a/py/objattrtuple.c +++ b/py/objattrtuple.c @@ -80,15 +80,18 @@ mp_obj_t mp_obj_new_attrtuple(const qstr *fields, size_t n, const mp_obj_t *item return MP_OBJ_FROM_PTR(o); } -const mp_obj_type_t mp_type_attrtuple = { - { &mp_type_type }, - .name = MP_QSTR_tuple, // reuse tuple to save on a qstr - .print = mp_obj_attrtuple_print, - .unary_op = mp_obj_tuple_unary_op, - .binary_op = mp_obj_tuple_binary_op, - .attr = mp_obj_attrtuple_attr, - .subscr = mp_obj_tuple_subscr, - .getiter = mp_obj_tuple_getiter, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_attrtuple, + MP_QSTR_tuple, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + // reuse tuple to save on a qstr + print, mp_obj_attrtuple_print, + unary_op, mp_obj_tuple_unary_op, + binary_op, mp_obj_tuple_binary_op, + attr, mp_obj_attrtuple_attr, + subscr, mp_obj_tuple_subscr, + getiter, mp_obj_tuple_getiter + ); #endif // MICROPY_PY_ATTRTUPLE diff --git a/py/objbool.c b/py/objbool.c index 23e023d8cb..5d014bbb8e 100644 --- a/py/objbool.c +++ b/py/objbool.c @@ -84,15 +84,16 @@ STATIC mp_obj_t bool_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_ return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT(value), rhs_in); } -const mp_obj_type_t mp_type_bool = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, // can match all numeric types - .name = MP_QSTR_bool, - .print = bool_print, - .make_new = bool_make_new, - .unary_op = bool_unary_op, - .binary_op = bool_binary_op, -}; +MP_DEFINE_CONST_OBJ_TYPE( + // can match all numeric types + mp_type_bool, + MP_QSTR_bool, + MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, + bool_make_new, + print, bool_print, + unary_op, bool_unary_op, + binary_op, bool_binary_op + ); #if !MICROPY_OBJ_IMMEDIATE_OBJS const mp_obj_bool_t mp_const_false_obj = {{&mp_type_bool}, false}; diff --git a/py/objboundmeth.c b/py/objboundmeth.c index 9936c06e49..353364cdc7 100644 --- a/py/objboundmeth.c +++ b/py/objboundmeth.c @@ -95,17 +95,19 @@ STATIC void bound_meth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } #endif -STATIC const mp_obj_type_t mp_type_bound_meth = { - { &mp_type_type }, - .name = MP_QSTR_bound_method, +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_bound_meth, + MP_QSTR_bound_method, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED - .print = bound_meth_print, + print, bound_meth_print, #endif - .call = bound_meth_call, + call, bound_meth_call #if MICROPY_PY_FUNCTION_ATTRS - .attr = bound_meth_attr, + , attr, bound_meth_attr #endif -}; + ); mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self) { mp_obj_bound_meth_t *o = mp_obj_malloc(mp_obj_bound_meth_t, &mp_type_bound_meth); diff --git a/py/objcell.c b/py/objcell.c index cab0d0b030..a17a94b9b7 100644 --- a/py/objcell.c +++ b/py/objcell.c @@ -40,13 +40,13 @@ STATIC void cell_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t k } #endif -STATIC const mp_obj_type_t mp_type_cell = { - { &mp_type_type }, - .name = MP_QSTR_, // cell representation is just value in < > +STATIC MP_DEFINE_CONST_OBJ_TYPE( + // cell representation is just value in < > + mp_type_cell, MP_QSTR_, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED - .print = cell_print, + , print, cell_print #endif -}; + ); mp_obj_t mp_obj_new_cell(mp_obj_t obj) { mp_obj_cell_t *o = mp_obj_malloc(mp_obj_cell_t, &mp_type_cell); diff --git a/py/objclosure.c b/py/objclosure.c index 5b9923a44b..15ed994d37 100644 --- a/py/objclosure.c +++ b/py/objclosure.c @@ -86,18 +86,19 @@ STATIC void mp_obj_closure_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } #endif -const mp_obj_type_t mp_type_closure = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF, - .name = MP_QSTR_closure, +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_closure, + MP_QSTR_closure, + MP_TYPE_FLAG_BINDS_SELF, + MP_TYPE_NULL_MAKE_NEW, #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED - .print = closure_print, + print, closure_print, #endif - .call = closure_call, #if MICROPY_PY_FUNCTION_ATTRS - .attr = mp_obj_closure_attr, + attr, mp_obj_closure_attr, #endif -}; + call, closure_call + ); mp_obj_t mp_obj_new_closure(mp_obj_t fun, size_t n_closed_over, const mp_obj_t *closed) { mp_obj_closure_t *o = mp_obj_malloc_var(mp_obj_closure_t, mp_obj_t, n_closed_over, &mp_type_closure); diff --git a/py/objcomplex.c b/py/objcomplex.c index 4aa598a0bc..cf213d718a 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -151,16 +151,13 @@ STATIC void complex_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -const mp_obj_type_t mp_type_complex = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, - .name = MP_QSTR_complex, - .print = complex_print, - .make_new = complex_make_new, - .unary_op = complex_unary_op, - .binary_op = complex_binary_op, - .attr = complex_attr, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_complex, MP_QSTR_complex, MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, complex_make_new, + print, complex_print, + unary_op, complex_unary_op, + binary_op, complex_binary_op, + attr, complex_attr + ); mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag) { mp_obj_complex_t *o = mp_obj_malloc(mp_obj_complex_t, &mp_type_complex); diff --git a/py/objdeque.c b/py/objdeque.c index b1c59a81e9..22770317ab 100644 --- a/py/objdeque.c +++ b/py/objdeque.c @@ -155,12 +155,13 @@ STATIC const mp_rom_map_elem_t deque_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(deque_locals_dict, deque_locals_dict_table); -const mp_obj_type_t mp_type_deque = { - { &mp_type_type }, - .name = MP_QSTR_deque, - .make_new = deque_make_new, - .unary_op = deque_unary_op, - .locals_dict = (mp_obj_dict_t *)&deque_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_deque, + MP_QSTR_deque, + MP_TYPE_FLAG_NONE, + deque_make_new, + unary_op, deque_unary_op, + locals_dict, (mp_obj_dict_t *)&deque_locals_dict + ); #endif // MICROPY_PY_COLLECTIONS_DEQUE diff --git a/py/objdict.c b/py/objdict.c index 1d8e9059a1..6e217d5c9a 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -461,12 +461,14 @@ STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) { } } -STATIC const mp_obj_type_t mp_type_dict_view_it = { - { &mp_type_type }, - .name = MP_QSTR_iterator, - .getiter = mp_identity_getiter, - .iternext = dict_view_it_iternext, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_dict_view_it, + MP_QSTR_iterator, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + getiter, mp_identity_getiter, + iternext, dict_view_it_iternext + ); STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_dict_view_it_t) <= sizeof(mp_obj_iter_buf_t)); @@ -512,13 +514,15 @@ STATIC mp_obj_t dict_view_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t return dict_binary_op(op, o->dict, rhs_in); } -STATIC const mp_obj_type_t mp_type_dict_view = { - { &mp_type_type }, - .name = MP_QSTR_dict_view, - .print = dict_view_print, - .binary_op = dict_view_binary_op, - .getiter = dict_view_getiter, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_dict_view, + MP_QSTR_dict_view, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, dict_view_print, + binary_op, dict_view_binary_op, + getiter, dict_view_getiter + ); STATIC mp_obj_t mp_obj_new_dict_view(mp_obj_t dict, mp_dict_view_kind_t kind) { mp_obj_dict_view_t *o = mp_obj_malloc(mp_obj_dict_view_t, &mp_type_dict_view); @@ -585,31 +589,33 @@ STATIC const mp_rom_map_elem_t dict_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(dict_locals_dict, dict_locals_dict_table); -const mp_obj_type_t mp_type_dict = { - { &mp_type_type }, - .name = MP_QSTR_dict, - .print = dict_print, - .make_new = mp_obj_dict_make_new, - .unary_op = dict_unary_op, - .binary_op = dict_binary_op, - .subscr = dict_subscr, - .getiter = dict_getiter, - .locals_dict = (mp_obj_dict_t *)&dict_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_dict, + MP_QSTR_dict, + MP_TYPE_FLAG_NONE, + mp_obj_dict_make_new, + print, dict_print, + unary_op, dict_unary_op, + binary_op, dict_binary_op, + subscr, dict_subscr, + getiter, dict_getiter, + locals_dict, (mp_obj_dict_t *)&dict_locals_dict + ); #if MICROPY_PY_COLLECTIONS_ORDEREDDICT -const mp_obj_type_t mp_type_ordereddict = { - { &mp_type_type }, - .name = MP_QSTR_OrderedDict, - .print = dict_print, - .make_new = mp_obj_dict_make_new, - .unary_op = dict_unary_op, - .binary_op = dict_binary_op, - .subscr = dict_subscr, - .getiter = dict_getiter, - .parent = &mp_type_dict, - .locals_dict = (mp_obj_dict_t *)&dict_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_ordereddict, + MP_QSTR_OrderedDict, + MP_TYPE_FLAG_NONE, + mp_obj_dict_make_new, + print, dict_print, + unary_op, dict_unary_op, + binary_op, dict_binary_op, + subscr, dict_subscr, + getiter, dict_getiter, + parent, &mp_type_dict, + locals_dict, (mp_obj_dict_t *)&dict_locals_dict + ); #endif void mp_obj_dict_init(mp_obj_dict_t *dict, size_t n_args) { diff --git a/py/objenumerate.c b/py/objenumerate.c index 241aef3023..f4f4ff6ae1 100644 --- a/py/objenumerate.c +++ b/py/objenumerate.c @@ -67,13 +67,14 @@ STATIC mp_obj_t enumerate_make_new(const mp_obj_type_t *type, size_t n_args, siz return MP_OBJ_FROM_PTR(o); } -const mp_obj_type_t mp_type_enumerate = { - { &mp_type_type }, - .name = MP_QSTR_enumerate, - .make_new = enumerate_make_new, - .iternext = enumerate_iternext, - .getiter = mp_identity_getiter, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_enumerate, + MP_QSTR_enumerate, + MP_TYPE_FLAG_NONE, + enumerate_make_new, + iternext, enumerate_iternext, + getiter, mp_identity_getiter + ); STATIC mp_obj_t enumerate_iternext(mp_obj_t self_in) { assert(mp_obj_is_type(self_in, &mp_type_enumerate)); diff --git a/py/objexcept.c b/py/objexcept.c index 028b73fd8b..190213e12f 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -284,13 +284,14 @@ void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -const mp_obj_type_t mp_type_BaseException = { - { &mp_type_type }, - .name = MP_QSTR_BaseException, - .print = mp_obj_exception_print, - .make_new = mp_obj_exception_make_new, - .attr = mp_obj_exception_attr, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_BaseException, + MP_QSTR_BaseException, + MP_TYPE_FLAG_NONE, + mp_obj_exception_make_new, + print, mp_obj_exception_print, + attr, mp_obj_exception_attr + ); // *FORMAT-OFF* diff --git a/py/objfilter.c b/py/objfilter.c index a402d8c648..2b57300af3 100644 --- a/py/objfilter.c +++ b/py/objfilter.c @@ -60,12 +60,13 @@ STATIC mp_obj_t filter_iternext(mp_obj_t self_in) { return MP_OBJ_STOP_ITERATION; } -const mp_obj_type_t mp_type_filter = { - { &mp_type_type }, - .name = MP_QSTR_filter, - .make_new = filter_make_new, - .getiter = mp_identity_getiter, - .iternext = filter_iternext, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_filter, + MP_QSTR_filter, + MP_TYPE_FLAG_NONE, + filter_make_new, + getiter, mp_identity_getiter, + iternext, filter_iternext + ); #endif // MICROPY_PY_BUILTINS_FILTER diff --git a/py/objfloat.c b/py/objfloat.c index 8e89b3da37..9ecbab7a4d 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -182,15 +182,12 @@ STATIC mp_obj_t float_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs return mp_obj_float_binary_op(op, lhs_val, rhs_in); } -const mp_obj_type_t mp_type_float = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, - .name = MP_QSTR_float, - .print = float_print, - .make_new = float_make_new, - .unary_op = float_unary_op, - .binary_op = float_binary_op, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_float, MP_QSTR_float, MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, float_make_new, + print, float_print, + unary_op, float_unary_op, + binary_op, float_binary_op + ); #if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C && MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D diff --git a/py/objfun.c b/py/objfun.c index 5fa9d71dda..30de8670a1 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -56,13 +56,11 @@ STATIC mp_obj_t fun_builtin_0_call(mp_obj_t self_in, size_t n_args, size_t n_kw, return self->fun._0(); } -const mp_obj_type_t mp_type_fun_builtin_0 = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, - .name = MP_QSTR_function, - .call = fun_builtin_0_call, - .unary_op = mp_generic_unary_op, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_builtin_0, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, MP_TYPE_NULL_MAKE_NEW, + call, fun_builtin_0_call, + unary_op, mp_generic_unary_op + ); STATIC mp_obj_t fun_builtin_1_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_1)); @@ -71,13 +69,11 @@ STATIC mp_obj_t fun_builtin_1_call(mp_obj_t self_in, size_t n_args, size_t n_kw, return self->fun._1(args[0]); } -const mp_obj_type_t mp_type_fun_builtin_1 = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, - .name = MP_QSTR_function, - .call = fun_builtin_1_call, - .unary_op = mp_generic_unary_op, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_builtin_1, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, MP_TYPE_NULL_MAKE_NEW, + call, fun_builtin_1_call, + unary_op, mp_generic_unary_op + ); STATIC mp_obj_t fun_builtin_2_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_2)); @@ -86,13 +82,11 @@ STATIC mp_obj_t fun_builtin_2_call(mp_obj_t self_in, size_t n_args, size_t n_kw, return self->fun._2(args[0], args[1]); } -const mp_obj_type_t mp_type_fun_builtin_2 = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, - .name = MP_QSTR_function, - .call = fun_builtin_2_call, - .unary_op = mp_generic_unary_op, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_builtin_2, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, MP_TYPE_NULL_MAKE_NEW, + call, fun_builtin_2_call, + unary_op, mp_generic_unary_op + ); STATIC mp_obj_t fun_builtin_3_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_3)); @@ -101,13 +95,11 @@ STATIC mp_obj_t fun_builtin_3_call(mp_obj_t self_in, size_t n_args, size_t n_kw, return self->fun._3(args[0], args[1], args[2]); } -const mp_obj_type_t mp_type_fun_builtin_3 = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, - .name = MP_QSTR_function, - .call = fun_builtin_3_call, - .unary_op = mp_generic_unary_op, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_builtin_3, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, MP_TYPE_NULL_MAKE_NEW, + call, fun_builtin_3_call, + unary_op, mp_generic_unary_op + ); STATIC mp_obj_t fun_builtin_var_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_var)); @@ -132,13 +124,11 @@ STATIC mp_obj_t fun_builtin_var_call(mp_obj_t self_in, size_t n_args, size_t n_k } } -const mp_obj_type_t mp_type_fun_builtin_var = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, - .name = MP_QSTR_function, - .call = fun_builtin_var_call, - .unary_op = mp_generic_unary_op, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_builtin_var, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, MP_TYPE_NULL_MAKE_NEW, + call, fun_builtin_var_call, + unary_op, mp_generic_unary_op + ); /******************************************************************************/ /* byte code functions */ @@ -362,19 +352,20 @@ void mp_obj_fun_bc_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } #endif -const mp_obj_type_t mp_type_fun_bc = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF, - .name = MP_QSTR_function, +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_bc, + MP_QSTR_function, + MP_TYPE_FLAG_BINDS_SELF, + MP_TYPE_NULL_MAKE_NEW, #if MICROPY_CPYTHON_COMPAT - .print = fun_bc_print, + print, fun_bc_print, #endif - .call = fun_bc_call, - .unary_op = mp_generic_unary_op, + call, fun_bc_call, + unary_op, mp_generic_unary_op #if MICROPY_PY_FUNCTION_ATTRS - .attr = mp_obj_fun_bc_attr, + , attr, mp_obj_fun_bc_attr #endif -}; + ); mp_obj_t mp_obj_new_fun_bc(const mp_obj_t *def_args, const byte *code, const mp_module_context_t *context, struct _mp_raw_code_t *const *child_table) { size_t n_def_args = 0; @@ -417,19 +408,20 @@ STATIC mp_obj_t fun_native_call(mp_obj_t self_in, size_t n_args, size_t n_kw, co return fun(self_in, n_args, n_kw, args); } -STATIC const mp_obj_type_t mp_type_fun_native = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF, - .name = MP_QSTR_function, +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_native, + MP_QSTR_function, + MP_TYPE_FLAG_BINDS_SELF, + MP_TYPE_NULL_MAKE_NEW, #if MICROPY_CPYTHON_COMPAT - .print = fun_bc_print, + print, fun_bc_print, #endif - .call = fun_native_call, - .unary_op = mp_generic_unary_op, #if MICROPY_PY_FUNCTION_ATTRS - .attr = mp_obj_fun_bc_attr, + attr, mp_obj_fun_bc_attr, #endif -}; + call, fun_native_call, + unary_op, mp_generic_unary_op + ); mp_obj_t mp_obj_new_fun_native(const mp_obj_t *def_args, const void *fun_data, const mp_module_context_t *mc, struct _mp_raw_code_t *const *child_table) { mp_obj_fun_bc_t *o = MP_OBJ_TO_PTR(mp_obj_new_fun_bc(def_args, (const byte *)fun_data, mc, child_table)); @@ -531,13 +523,14 @@ STATIC mp_obj_t fun_asm_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const return mp_native_to_obj(ret, self->type_sig); } -STATIC const mp_obj_type_t mp_type_fun_asm = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF, - .name = MP_QSTR_function, - .call = fun_asm_call, - .unary_op = mp_generic_unary_op, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_asm, + MP_QSTR_function, + MP_TYPE_FLAG_BINDS_SELF, + MP_TYPE_NULL_MAKE_NEW, + call, fun_asm_call, + unary_op, mp_generic_unary_op + ); mp_obj_t mp_obj_new_fun_asm(size_t n_args, const void *fun_data, mp_uint_t type_sig) { mp_obj_fun_asm_t *o = mp_obj_malloc(mp_obj_fun_asm_t, &mp_type_fun_asm); diff --git a/py/objgenerator.c b/py/objgenerator.c index 802fd45bbd..0ab80ca118 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -70,16 +70,17 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons return MP_OBJ_FROM_PTR(o); } -const mp_obj_type_t mp_type_gen_wrap = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF, - .name = MP_QSTR_generator, - .call = gen_wrap_call, - .unary_op = mp_generic_unary_op, +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_gen_wrap, + MP_QSTR_generator, + MP_TYPE_FLAG_BINDS_SELF, + MP_TYPE_NULL_MAKE_NEW, + call, gen_wrap_call, + unary_op, mp_generic_unary_op #if MICROPY_PY_FUNCTION_ATTRS - .attr = mp_obj_fun_bc_attr, + , attr, mp_obj_fun_bc_attr #endif -}; + ); /******************************************************************************/ // native generator wrapper @@ -131,16 +132,17 @@ STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_k return MP_OBJ_FROM_PTR(o); } -const mp_obj_type_t mp_type_native_gen_wrap = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF, - .name = MP_QSTR_generator, - .call = native_gen_wrap_call, - .unary_op = mp_generic_unary_op, +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_native_gen_wrap, + MP_QSTR_generator, + MP_TYPE_FLAG_BINDS_SELF, + MP_TYPE_NULL_MAKE_NEW, + call, native_gen_wrap_call, + unary_op, mp_generic_unary_op #if MICROPY_PY_FUNCTION_ATTRS - .attr = mp_obj_fun_bc_attr, + , attr, mp_obj_fun_bc_attr #endif -}; + ); #endif // MICROPY_EMIT_NATIVE @@ -357,12 +359,14 @@ STATIC const mp_rom_map_elem_t gen_instance_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(gen_instance_locals_dict, gen_instance_locals_dict_table); -const mp_obj_type_t mp_type_gen_instance = { - { &mp_type_type }, - .name = MP_QSTR_generator, - .print = gen_instance_print, - .unary_op = mp_generic_unary_op, - .getiter = mp_identity_getiter, - .iternext = gen_instance_iternext, - .locals_dict = (mp_obj_dict_t *)&gen_instance_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_gen_instance, + MP_QSTR_generator, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, gen_instance_print, + unary_op, mp_generic_unary_op, + getiter, mp_identity_getiter, + iternext, gen_instance_iternext, + locals_dict, (mp_obj_dict_t *)&gen_instance_locals_dict + ); diff --git a/py/objgetitemiter.c b/py/objgetitemiter.c index 31ed4a9228..ed2dfbbe1f 100644 --- a/py/objgetitemiter.c +++ b/py/objgetitemiter.c @@ -56,12 +56,14 @@ STATIC mp_obj_t it_iternext(mp_obj_t self_in) { } } -STATIC const mp_obj_type_t mp_type_it = { - { &mp_type_type }, - .name = MP_QSTR_iterator, - .getiter = mp_identity_getiter, - .iternext = it_iternext, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_it, + MP_QSTR_iterator, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + getiter, mp_identity_getiter, + iternext, it_iternext + ); // args are those returned from mp_load_method_maybe (ie either an attribute or a method) mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args, mp_obj_iter_buf_t *iter_buf) { diff --git a/py/objint.c b/py/objint.c index 645b269966..d7a3f9eb9d 100644 --- a/py/objint.c +++ b/py/objint.c @@ -457,12 +457,13 @@ STATIC const mp_rom_map_elem_t int_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(int_locals_dict, int_locals_dict_table); -const mp_obj_type_t mp_type_int = { - { &mp_type_type }, - .name = MP_QSTR_int, - .print = mp_obj_int_print, - .make_new = mp_obj_int_make_new, - .unary_op = mp_obj_int_unary_op, - .binary_op = mp_obj_int_binary_op, - .locals_dict = (mp_obj_dict_t *)&int_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_int, + MP_QSTR_int, + MP_TYPE_FLAG_NONE, + mp_obj_int_make_new, + print, mp_obj_int_print, + unary_op, mp_obj_int_unary_op, + binary_op, mp_obj_int_binary_op, + locals_dict, (mp_obj_dict_t *)&int_locals_dict + ); diff --git a/py/objlist.c b/py/objlist.c index f431e273df..8c7921b989 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -452,17 +452,19 @@ STATIC const mp_rom_map_elem_t list_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(list_locals_dict, list_locals_dict_table); -const mp_obj_type_t mp_type_list = { - { &mp_type_type }, - .name = MP_QSTR_list, - .print = list_print, - .make_new = list_make_new, - .unary_op = list_unary_op, - .binary_op = list_binary_op, - .subscr = list_subscr, - .getiter = list_getiter, - .locals_dict = (mp_obj_dict_t *)&list_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_list, + MP_QSTR_list, + MP_TYPE_FLAG_NONE, + list_make_new, + print, list_print, + unary_op, list_unary_op, + binary_op, list_binary_op, + subscr, list_subscr, + getiter, list_getiter, + locals_dict, (mp_obj_dict_t *)&list_locals_dict + ); + void mp_obj_list_init(mp_obj_list_t *o, size_t n) { o->base.type = &mp_type_list; diff --git a/py/objmap.c b/py/objmap.c index 1f9275854f..dc305e21b5 100644 --- a/py/objmap.c +++ b/py/objmap.c @@ -63,10 +63,11 @@ STATIC mp_obj_t map_iternext(mp_obj_t self_in) { return mp_call_function_n_kw(self->fun, self->n_iters, 0, nextses); } -const mp_obj_type_t mp_type_map = { - { &mp_type_type }, - .name = MP_QSTR_map, - .make_new = map_make_new, - .getiter = mp_identity_getiter, - .iternext = map_iternext, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_map, + MP_QSTR_map, + MP_TYPE_FLAG_NONE, + map_make_new, + getiter, mp_identity_getiter, + iternext, map_iternext + ); diff --git a/py/objmodule.c b/py/objmodule.c index 783d6b0508..6fc3653e6a 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -130,12 +130,14 @@ STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -const mp_obj_type_t mp_type_module = { - { &mp_type_type }, - .name = MP_QSTR_module, - .print = module_print, - .attr = module_attr, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_module, + MP_QSTR_module, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, module_print, + attr, module_attr + ); mp_obj_t mp_obj_new_module(qstr module_name) { mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map; diff --git a/py/objnone.c b/py/objnone.c index 271a8543f9..4fffbc997e 100644 --- a/py/objnone.c +++ b/py/objnone.c @@ -43,12 +43,14 @@ STATIC void none_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ } } -const mp_obj_type_t mp_type_NoneType = { - { &mp_type_type }, - .name = MP_QSTR_NoneType, - .print = none_print, - .unary_op = mp_generic_unary_op, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_NoneType, + MP_QSTR_NoneType, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, none_print, + unary_op, mp_generic_unary_op + ); #if !MICROPY_OBJ_IMMEDIATE_OBJS const mp_obj_none_t mp_const_none_obj = {{&mp_type_NoneType}}; diff --git a/py/objobject.c b/py/objobject.c index 1652802805..617b40fbbf 100644 --- a/py/objobject.c +++ b/py/objobject.c @@ -111,11 +111,12 @@ STATIC const mp_rom_map_elem_t object_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(object_locals_dict, object_locals_dict_table); #endif -const mp_obj_type_t mp_type_object = { - { &mp_type_type }, - .name = MP_QSTR_object, - .make_new = object_make_new, +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_object, + MP_QSTR_object, + MP_TYPE_FLAG_NONE, + object_make_new #if MICROPY_CPYTHON_COMPAT - .locals_dict = (mp_obj_dict_t *)&object_locals_dict, + , locals_dict, (mp_obj_dict_t *)&object_locals_dict #endif -}; + ); diff --git a/py/objpolyiter.c b/py/objpolyiter.c index dac6a25455..326153182b 100644 --- a/py/objpolyiter.c +++ b/py/objpolyiter.c @@ -45,12 +45,14 @@ STATIC mp_obj_t polymorph_it_iternext(mp_obj_t self_in) { return self->iternext(self_in); } -const mp_obj_type_t mp_type_polymorph_iter = { - { &mp_type_type }, - .name = MP_QSTR_iterator, - .getiter = mp_identity_getiter, - .iternext = polymorph_it_iternext, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_polymorph_iter, + MP_QSTR_iterator, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + getiter, mp_identity_getiter, + iternext, polymorph_it_iternext + ); #if MICROPY_ENABLE_FINALISER // mp_type_polymorph_iter_with_finaliser is a variant of the universal iterator @@ -76,12 +78,13 @@ STATIC const mp_rom_map_elem_t mp_obj_polymorph_iter_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(mp_obj_polymorph_iter_locals_dict, mp_obj_polymorph_iter_locals_dict_table); -const mp_obj_type_t mp_type_polymorph_iter_with_finaliser = { - { &mp_type_type }, - .name = MP_QSTR_iterator, - .getiter = mp_identity_getiter, - .iternext = polymorph_it_iternext, - .locals_dict = (mp_obj_dict_t *)&mp_obj_polymorph_iter_locals_dict, -}; - +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_polymorph_iter_with_finaliser, + MP_QSTR_iterator, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + getiter, mp_identity_getiter, + iternext, polymorph_it_iternext, + locals_dict, (mp_obj_dict_t *)&mp_obj_polymorph_iter_locals_dict + ); #endif diff --git a/py/objproperty.c b/py/objproperty.c index 49327c981e..42c357f330 100644 --- a/py/objproperty.c +++ b/py/objproperty.c @@ -90,12 +90,13 @@ STATIC const mp_rom_map_elem_t property_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(property_locals_dict, property_locals_dict_table); -const mp_obj_type_t mp_type_property = { - { &mp_type_type }, - .name = MP_QSTR_property, - .make_new = property_make_new, - .locals_dict = (mp_obj_dict_t *)&property_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_property, + MP_QSTR_property, + MP_TYPE_FLAG_NONE, + property_make_new, + locals_dict, (mp_obj_dict_t *)&property_locals_dict + ); const mp_obj_t *mp_obj_property_get(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_property)); diff --git a/py/objrange.c b/py/objrange.c index 5496021892..adf4b17466 100644 --- a/py/objrange.c +++ b/py/objrange.c @@ -50,12 +50,14 @@ STATIC mp_obj_t range_it_iternext(mp_obj_t o_in) { } } -STATIC const mp_obj_type_t mp_type_range_it = { - { &mp_type_type }, - .name = MP_QSTR_iterator, - .getiter = mp_identity_getiter, - .iternext = range_it_iternext, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_range_it, + MP_QSTR_iterator, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + getiter, mp_identity_getiter, + iternext, range_it_iternext + ); STATIC mp_obj_t mp_obj_new_range_iterator(mp_int_t cur, mp_int_t stop, mp_int_t step, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_range_it_t) <= sizeof(mp_obj_iter_buf_t)); @@ -208,18 +210,19 @@ STATIC void range_attr(mp_obj_t o_in, qstr attr, mp_obj_t *dest) { } #endif -const mp_obj_type_t mp_type_range = { - { &mp_type_type }, - .name = MP_QSTR_range, - .print = range_print, - .make_new = range_make_new, - .unary_op = range_unary_op, +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_range, + MP_QSTR_range, + MP_TYPE_FLAG_NONE, + range_make_new, + print, range_print, + unary_op, range_unary_op, #if MICROPY_PY_BUILTINS_RANGE_BINOP - .binary_op = range_binary_op, + binary_op, range_binary_op, #endif - .subscr = range_subscr, - .getiter = range_getiter, + subscr, range_subscr, + getiter, range_getiter #if MICROPY_PY_BUILTINS_RANGE_ATTRS - .attr = range_attr, + , attr, range_attr #endif -}; + ); diff --git a/py/objreversed.c b/py/objreversed.c index 08961c0d2d..bc1f07ddec 100644 --- a/py/objreversed.c +++ b/py/objreversed.c @@ -68,12 +68,13 @@ STATIC mp_obj_t reversed_iternext(mp_obj_t self_in) { return mp_obj_subscr(self->seq, MP_OBJ_NEW_SMALL_INT(self->cur_index), MP_OBJ_SENTINEL); } -const mp_obj_type_t mp_type_reversed = { - { &mp_type_type }, - .name = MP_QSTR_reversed, - .make_new = reversed_make_new, - .getiter = mp_identity_getiter, - .iternext = reversed_iternext, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_reversed, + MP_QSTR_reversed, + MP_TYPE_FLAG_NONE, + reversed_make_new, + getiter, mp_identity_getiter, + iternext, reversed_iternext + ); #endif // MICROPY_PY_BUILTINS_REVERSED diff --git a/py/objset.c b/py/objset.c index 26fd74398b..8fc744a140 100644 --- a/py/objset.c +++ b/py/objset.c @@ -539,16 +539,17 @@ STATIC const mp_rom_map_elem_t set_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(set_locals_dict, set_locals_dict_table); -const mp_obj_type_t mp_type_set = { - { &mp_type_type }, - .name = MP_QSTR_set, - .print = set_print, - .make_new = set_make_new, - .unary_op = set_unary_op, - .binary_op = set_binary_op, - .getiter = set_getiter, - .locals_dict = (mp_obj_dict_t *)&set_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_set, + MP_QSTR_set, + MP_TYPE_FLAG_NONE, + set_make_new, + print, set_print, + unary_op, set_unary_op, + binary_op, set_binary_op, + getiter, set_getiter, + locals_dict, (mp_obj_dict_t *)&set_locals_dict + ); #if MICROPY_PY_BUILTINS_FROZENSET STATIC const mp_rom_map_elem_t frozenset_locals_dict_table[] = { @@ -564,17 +565,17 @@ STATIC const mp_rom_map_elem_t frozenset_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(frozenset_locals_dict, frozenset_locals_dict_table); -const mp_obj_type_t mp_type_frozenset = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, - .name = MP_QSTR_frozenset, - .print = set_print, - .make_new = set_make_new, - .unary_op = set_unary_op, - .binary_op = set_binary_op, - .getiter = set_getiter, - .locals_dict = (mp_obj_dict_t *)&frozenset_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_frozenset, + MP_QSTR_frozenset, + MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, + set_make_new, + print, set_print, + unary_op, set_unary_op, + binary_op, set_binary_op, + getiter, set_getiter, + locals_dict, (mp_obj_dict_t *)&frozenset_locals_dict + ); #endif mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items) { diff --git a/py/objsingleton.c b/py/objsingleton.c index 2b896305cf..4a099657d4 100644 --- a/py/objsingleton.c +++ b/py/objsingleton.c @@ -43,12 +43,11 @@ STATIC void singleton_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ mp_printf(print, "%q", self->name); } -const mp_obj_type_t mp_type_singleton = { - { &mp_type_type }, - .name = MP_QSTR_, - .print = singleton_print, - .unary_op = mp_generic_unary_op, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_singleton, MP_QSTR_, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, + print, singleton_print, + unary_op, mp_generic_unary_op + ); const mp_obj_singleton_t mp_const_ellipsis_obj = {{&mp_type_singleton}, MP_QSTR_Ellipsis}; #if MICROPY_PY_BUILTINS_NOTIMPLEMENTED diff --git a/py/objslice.c b/py/objslice.c index 0b34516c18..98c03485ff 100644 --- a/py/objslice.c +++ b/py/objslice.c @@ -92,16 +92,18 @@ STATIC const mp_rom_map_elem_t slice_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(slice_locals_dict, slice_locals_dict_table); #endif -const mp_obj_type_t mp_type_slice = { - { &mp_type_type }, - .name = MP_QSTR_slice, - .print = slice_print, +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_slice, + MP_QSTR_slice, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, slice_print #if MICROPY_PY_BUILTINS_SLICE_ATTRS - .attr = slice_attr, + , attr, slice_attr #elif MICROPY_PY_BUILTINS_SLICE_INDICES - .locals_dict = (mp_obj_dict_t *)&slice_locals_dict, + , locals_dict, (mp_obj_dict_t *)&slice_locals_dict #endif -}; + ); mp_obj_t mp_obj_new_slice(mp_obj_t ostart, mp_obj_t ostop, mp_obj_t ostep) { mp_obj_slice_t *o = mp_obj_malloc(mp_obj_slice_t, &mp_type_slice); diff --git a/py/objstr.c b/py/objstr.c index 9dd7f65e66..77ca269d42 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -2143,31 +2143,33 @@ MP_DEFINE_CONST_DICT_WITH_SIZE(mp_obj_memoryview_locals_dict, #if !MICROPY_PY_BUILTINS_STR_UNICODE STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); -const mp_obj_type_t mp_type_str = { - { &mp_type_type }, - .name = MP_QSTR_str, - .print = str_print, - .make_new = mp_obj_str_make_new, - .binary_op = mp_obj_str_binary_op, - .subscr = bytes_subscr, - .getiter = mp_obj_new_str_iterator, - .buffer = mp_obj_str_get_buffer, - .locals_dict = (mp_obj_dict_t *)&mp_obj_str_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_str, + MP_QSTR_str, + MP_TYPE_FLAG_NONE, + mp_obj_str_make_new, + print, str_print, + binary_op, mp_obj_str_binary_op, + subscr, bytes_subscr, + getiter, mp_obj_new_str_iterator, + buffer, mp_obj_str_get_buffer, + locals_dict, (mp_obj_dict_t *)&mp_obj_str_locals_dict + ); #endif // !MICROPY_PY_BUILTINS_STR_UNICODE -// Reuses most of methods from str -const mp_obj_type_t mp_type_bytes = { - { &mp_type_type }, - .name = MP_QSTR_bytes, - .print = str_print, - .make_new = bytes_make_new, - .binary_op = mp_obj_str_binary_op, - .subscr = bytes_subscr, - .getiter = mp_obj_new_bytes_iterator, - .buffer = mp_obj_str_get_buffer, - .locals_dict = (mp_obj_dict_t *)&mp_obj_bytes_locals_dict, -}; +// Reuses most methods from str +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_bytes, + MP_QSTR_bytes, + MP_TYPE_FLAG_NONE, + bytes_make_new, + print, str_print, + binary_op, mp_obj_str_binary_op, + subscr, bytes_subscr, + getiter, mp_obj_new_bytes_iterator, + buffer, mp_obj_str_get_buffer, + locals_dict, (mp_obj_dict_t *)&mp_obj_bytes_locals_dict + ); // The zero-length bytes object, with data that includes a null-terminating byte const mp_obj_str_t mp_const_empty_bytes_obj = {{&mp_type_bytes}, 0, 0, (const byte *)""}; diff --git a/py/objstringio.c b/py/objstringio.c index 8b6c7531d7..d781ccc789 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -244,16 +244,17 @@ STATIC const mp_stream_p_t stringio_stream_p = { .is_text = true, }; -const mp_obj_type_t mp_type_stringio = { - { &mp_type_type }, - .name = MP_QSTR_StringIO, - .print = stringio_print, - .make_new = stringio_make_new, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &stringio_stream_p, - .locals_dict = (mp_obj_dict_t *)&stringio_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_stringio, + MP_QSTR_StringIO, + MP_TYPE_FLAG_NONE, + stringio_make_new, + print, stringio_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &stringio_stream_p, + locals_dict, (mp_obj_dict_t *)&stringio_locals_dict + ); #if MICROPY_PY_IO_BYTESIO STATIC const mp_stream_p_t bytesio_stream_p = { @@ -262,16 +263,17 @@ STATIC const mp_stream_p_t bytesio_stream_p = { .ioctl = stringio_ioctl, }; -const mp_obj_type_t mp_type_bytesio = { - { &mp_type_type }, - .name = MP_QSTR_BytesIO, - .print = stringio_print, - .make_new = stringio_make_new, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &bytesio_stream_p, - .locals_dict = (mp_obj_dict_t *)&stringio_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_bytesio, + MP_QSTR_BytesIO, + MP_TYPE_FLAG_NONE, + stringio_make_new, + print, stringio_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &bytesio_stream_p, + locals_dict, (mp_obj_dict_t *)&stringio_locals_dict + ); #endif #endif diff --git a/py/objstrunicode.c b/py/objstrunicode.c index fef0353683..afef1498e9 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -229,18 +229,19 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } } -const mp_obj_type_t mp_type_str = { - { &mp_type_type }, - .name = MP_QSTR_str, - .print = uni_print, - .make_new = mp_obj_str_make_new, - .unary_op = uni_unary_op, - .binary_op = mp_obj_str_binary_op, - .subscr = str_subscr, - .getiter = mp_obj_new_str_iterator, - .buffer = mp_obj_str_get_buffer, - .locals_dict = (mp_obj_dict_t *)&mp_obj_str_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_str, + MP_QSTR_str, + MP_TYPE_FLAG_NONE, + mp_obj_str_make_new, + print, uni_print, + unary_op, uni_unary_op, + binary_op, mp_obj_str_binary_op, + subscr, str_subscr, + getiter, mp_obj_new_str_iterator, + buffer, mp_obj_str_get_buffer, + locals_dict, (mp_obj_dict_t *)&mp_obj_str_locals_dict + ); /******************************************************************************/ /* str iterator */ diff --git a/py/objtuple.c b/py/objtuple.c index e0cec84473..b2ea6e380e 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -224,17 +224,18 @@ STATIC const mp_rom_map_elem_t tuple_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(tuple_locals_dict, tuple_locals_dict_table); -const mp_obj_type_t mp_type_tuple = { - { &mp_type_type }, - .name = MP_QSTR_tuple, - .print = mp_obj_tuple_print, - .make_new = mp_obj_tuple_make_new, - .unary_op = mp_obj_tuple_unary_op, - .binary_op = mp_obj_tuple_binary_op, - .subscr = mp_obj_tuple_subscr, - .getiter = mp_obj_tuple_getiter, - .locals_dict = (mp_obj_dict_t *)&tuple_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_tuple, + MP_QSTR_tuple, + MP_TYPE_FLAG_NONE, + mp_obj_tuple_make_new, + print, mp_obj_tuple_print, + unary_op, mp_obj_tuple_unary_op, + binary_op, mp_obj_tuple_binary_op, + subscr, mp_obj_tuple_subscr, + getiter, mp_obj_tuple_getiter, + locals_dict, (mp_obj_dict_t *)&tuple_locals_dict + ); // the zero-length tuple const mp_obj_tuple_t mp_const_empty_tuple_obj = {{&mp_type_tuple}, 0}; diff --git a/py/objtype.c b/py/objtype.c index c0f6857809..77fe8e22e3 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -1098,15 +1098,16 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -const mp_obj_type_t mp_type_type = { - { &mp_type_type }, - .name = MP_QSTR_type, - .print = type_print, - .make_new = type_make_new, - .call = type_call, - .unary_op = mp_generic_unary_op, - .attr = type_attr, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_type, + MP_QSTR_type, + MP_TYPE_FLAG_NONE, + type_make_new, + print, type_print, + call, type_call, + unary_op, mp_generic_unary_op, + attr, type_attr + ); mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) { // Verify input objects have expected type @@ -1314,13 +1315,14 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_class_lookup(&lookup, &mp_type_object); } -const mp_obj_type_t mp_type_super = { - { &mp_type_type }, - .name = MP_QSTR_super, - .print = super_print, - .make_new = super_make_new, - .attr = super_attr, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_super, + MP_QSTR_super, + MP_TYPE_FLAG_NONE, + super_make_new, + print, super_print, + attr, super_attr + ); void mp_load_super_method(qstr attr, mp_obj_t *dest) { mp_obj_super_t super = {{&mp_type_super}, dest[1], dest[2]}; @@ -1436,14 +1438,16 @@ STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self, size_t n return MP_OBJ_FROM_PTR(o); } -const mp_obj_type_t mp_type_staticmethod = { - { &mp_type_type }, - .name = MP_QSTR_staticmethod, - .make_new = static_class_method_make_new, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_staticmethod, + MP_QSTR_staticmethod, + MP_TYPE_FLAG_NONE, + static_class_method_make_new + ); -const mp_obj_type_t mp_type_classmethod = { - { &mp_type_type }, - .name = MP_QSTR_classmethod, - .make_new = static_class_method_make_new, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_classmethod, + MP_QSTR_classmethod, + MP_TYPE_FLAG_NONE, + static_class_method_make_new + ); diff --git a/py/objzip.c b/py/objzip.c index 81fa1d587e..0ceafd97f2 100644 --- a/py/objzip.c +++ b/py/objzip.c @@ -66,10 +66,11 @@ STATIC mp_obj_t zip_iternext(mp_obj_t self_in) { return MP_OBJ_FROM_PTR(tuple); } -const mp_obj_type_t mp_type_zip = { - { &mp_type_type }, - .name = MP_QSTR_zip, - .make_new = zip_make_new, - .getiter = mp_identity_getiter, - .iternext = zip_iternext, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_zip, + MP_QSTR_zip, + MP_TYPE_FLAG_NONE, + zip_make_new, + getiter, mp_identity_getiter, + iternext, zip_iternext + ); diff --git a/py/profile.c b/py/profile.c index 4e23e9eac4..2b9531e245 100644 --- a/py/profile.c +++ b/py/profile.c @@ -172,13 +172,15 @@ STATIC void code_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -const mp_obj_type_t mp_type_settrace_codeobj = { - { &mp_type_type }, - .name = MP_QSTR_code, - .print = code_print, - .unary_op = mp_generic_unary_op, - .attr = code_attr, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_settrace_codeobj, + MP_QSTR_code, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, code_print, + unary_op, mp_generic_unary_op, + attr, code_attr + ); mp_obj_t mp_obj_new_code(const mp_module_context_t *context, const mp_raw_code_t *rc) { mp_obj_code_t *o = m_new_obj_maybe(mp_obj_code_t); @@ -241,13 +243,15 @@ STATIC void frame_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -const mp_obj_type_t mp_type_frame = { - { &mp_type_type }, - .name = MP_QSTR_frame, - .print = frame_print, - .unary_op = mp_generic_unary_op, - .attr = frame_attr, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_frame, + MP_QSTR_frame, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, frame_print, + unary_op, mp_generic_unary_op, + attr, frame_attr + ); mp_obj_t mp_obj_new_frame(const mp_code_state_t *code_state) { if (gc_is_locked()) { diff --git a/py/runtime.c b/py/runtime.c index ea3553db72..27b4f05f04 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1070,12 +1070,13 @@ STATIC mp_obj_t checked_fun_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c return mp_call_function_n_kw(self->fun, n_args, n_kw, args); } -STATIC const mp_obj_type_t mp_type_checked_fun = { - { &mp_type_type }, - .flags = MP_TYPE_FLAG_BINDS_SELF, - .name = MP_QSTR_function, - .call = checked_fun_call, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + mp_type_checked_fun, + MP_QSTR_function, + MP_TYPE_FLAG_BINDS_SELF, + MP_TYPE_NULL_MAKE_NEW, + call, checked_fun_call + ); STATIC mp_obj_t mp_obj_new_checked_fun(const mp_obj_type_t *type, mp_obj_t fun) { mp_obj_checked_fun_t *o = mp_obj_malloc(mp_obj_checked_fun_t, &mp_type_checked_fun); diff --git a/shared/runtime/mpirq.c b/shared/runtime/mpirq.c index 8e474bf5a2..763da6e0e4 100644 --- a/shared/runtime/mpirq.c +++ b/shared/runtime/mpirq.c @@ -125,11 +125,13 @@ STATIC const mp_rom_map_elem_t mp_irq_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(mp_irq_locals_dict, mp_irq_locals_dict_table); -const mp_obj_type_t mp_irq_type = { - { &mp_type_type }, - .name = MP_QSTR_irq, - .call = mp_irq_call, - .locals_dict = (mp_obj_dict_t *)&mp_irq_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + mp_irq_type, + MP_QSTR_irq, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + call, mp_irq_call, + locals_dict, (mp_obj_dict_t *)&mp_irq_locals_dict + ); #endif // MICROPY_ENABLE_SCHEDULER diff --git a/shared/runtime/sys_stdio_mphal.c b/shared/runtime/sys_stdio_mphal.c index 24f528b0c4..f1290853da 100644 --- a/shared/runtime/sys_stdio_mphal.c +++ b/shared/runtime/sys_stdio_mphal.c @@ -123,15 +123,17 @@ STATIC const mp_stream_p_t stdio_obj_stream_p = { .is_text = true, }; -STATIC const mp_obj_type_t stdio_obj_type = { - { &mp_type_type }, - .name = MP_QSTR_FileIO, - .print = stdio_obj_print, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &stdio_obj_stream_p, - .locals_dict = (mp_obj_dict_t *)&stdio_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + stdio_obj_type, + MP_QSTR_FileIO, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, stdio_obj_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &stdio_obj_stream_p, + locals_dict, (mp_obj_dict_t *)&stdio_locals_dict + ); const sys_stdio_obj_t mp_sys_stdin_obj = {{&stdio_obj_type}, .fd = STDIO_FD_IN}; const sys_stdio_obj_t mp_sys_stdout_obj = {{&stdio_obj_type}, .fd = STDIO_FD_OUT}; @@ -157,15 +159,17 @@ STATIC const mp_stream_p_t stdio_buffer_obj_stream_p = { .is_text = false, }; -STATIC const mp_obj_type_t stdio_buffer_obj_type = { - { &mp_type_type }, - .name = MP_QSTR_FileIO, - .print = stdio_obj_print, - .getiter = mp_identity_getiter, - .iternext = mp_stream_unbuffered_iter, - .protocol = &stdio_buffer_obj_stream_p, - .locals_dict = (mp_obj_dict_t *)&stdio_locals_dict, -}; +STATIC MP_DEFINE_CONST_OBJ_TYPE( + stdio_buffer_obj_type, + MP_QSTR_FileIO, + MP_TYPE_FLAG_NONE, + MP_TYPE_NULL_MAKE_NEW, + print, stdio_obj_print, + getiter, mp_identity_getiter, + iternext, mp_stream_unbuffered_iter, + protocol, &stdio_buffer_obj_stream_p, + locals_dict, (mp_obj_dict_t *)&stdio_locals_dict + ); STATIC const sys_stdio_obj_t stdio_buffer_obj = {{&stdio_buffer_obj_type}, .fd = 0}; // fd unused #endif From b7d6ee9b75650bd0ac36e89077d5d08a3eed9e3f Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 24 Jun 2022 16:22:38 +1000 Subject: [PATCH 0417/1041] all: Fix #if inside MP_DEFINE_CONST_OBJ_TYPE for msvc. Changes: MP_DEFINE_CONST_OBJ_TYPE( ... #if FOO ... #endif ... ); to: MP_DEFINE_CONST_OBJ_TYPE( ... FOO_TYPE_ATTR ... ); Signed-off-by: Jim Mussared --- extmod/vfs_lfsx.c | 14 +++++++++----- py/objarray.c | 26 +++++++++++++++++--------- py/objboundmeth.c | 20 ++++++++++++++------ py/objcell.c | 10 +++++++--- py/objclosure.c | 17 +++++++++++------ py/objfun.c | 39 +++++++++++++++++++++++++++------------ py/objgenerator.c | 20 ++++++++++++++------ py/objobject.c | 10 +++++++--- py/objrange.c | 20 ++++++++++++++------ py/objslice.c | 14 +++++++++----- 10 files changed, 129 insertions(+), 61 deletions(-) diff --git a/extmod/vfs_lfsx.c b/extmod/vfs_lfsx.c index 72c6696105..3f8d262a48 100644 --- a/extmod/vfs_lfsx.c +++ b/extmod/vfs_lfsx.c @@ -502,15 +502,19 @@ STATIC const mp_vfs_proto_t MP_VFS_LFSx(proto) = { .import_stat = MP_VFS_LFSx(import_stat), }; +#if LFS_BUILD_VERSION == 1 +#define VFS_LFSx_QSTR MP_QSTR_VfsLfs1 +#else +#define VFS_LFSx_QSTR MP_QSTR_VfsLfs2 +#endif + MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_VFS_LFSx, - #if LFS_BUILD_VERSION == 1 - MP_QSTR_VfsLfs1, - #else - MP_QSTR_VfsLfs2, - #endif + VFS_LFSx_QSTR, MP_TYPE_FLAG_NONE, MP_VFS_LFSx(make_new), protocol, &MP_VFS_LFSx(proto), locals_dict, (mp_obj_dict_t *)&MP_VFS_LFSx(locals_dict) ); + +#undef VFS_LFSx_QSTR diff --git a/py/objarray.c b/py/objarray.c index d93cce29ee..8d0fe7f585 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -603,6 +603,18 @@ MP_DEFINE_CONST_OBJ_TYPE( #endif #if MICROPY_PY_BUILTINS_MEMORYVIEW +#if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE +#define MEMORYVIEW_TYPE_ATTR attr, memoryview_attr, +#else +#define MEMORYVIEW_TYPE_ATTR +#endif + +#if MICROPY_PY_BUILTINS_BYTES_HEX +#define MEMORYVIEW_TYPE_LOCALS_DICT locals_dict, (mp_obj_dict_t *)&mp_obj_memoryview_locals_dict, +#else +#define MEMORYVIEW_TYPE_LOCALS_DICT +#endif + MP_DEFINE_CONST_OBJ_TYPE( mp_type_memoryview, MP_QSTR_memoryview, @@ -611,16 +623,12 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, array_iterator_new, unary_op, array_unary_op, binary_op, array_binary_op, - #if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE - attr, memoryview_attr, - #endif - #if MICROPY_PY_BUILTINS_BYTES_HEX - locals_dict, (mp_obj_dict_t *)&mp_obj_memoryview_locals_dict, - #endif - .subscr = array_subscr, - .buffer = array_get_buffer, + MEMORYVIEW_TYPE_LOCALS_DICT + MEMORYVIEW_TYPE_ATTR + subscr, array_subscr, + buffer, array_get_buffer ); -#endif +#endif // MICROPY_PY_BUILTINS_MEMORYVIEW /* unused size_t mp_obj_array_len(mp_obj_t self_in) { diff --git a/py/objboundmeth.c b/py/objboundmeth.c index 353364cdc7..f4b3b9b7df 100644 --- a/py/objboundmeth.c +++ b/py/objboundmeth.c @@ -95,18 +95,26 @@ STATIC void bound_meth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } #endif +#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED +#define BOUND_METH_TYPE_PRINT print, bound_meth_print, +#else +#define BOUND_METH_TYPE_PRINT +#endif + +#if MICROPY_PY_FUNCTION_ATTRS +#define BOUND_METH_TYPE_ATTR attr, bound_meth_attr, +#else +#define BOUND_METH_TYPE_ATTR +#endif + STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_bound_meth, MP_QSTR_bound_method, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, - #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED - print, bound_meth_print, - #endif + BOUND_METH_TYPE_PRINT + BOUND_METH_TYPE_ATTR call, bound_meth_call - #if MICROPY_PY_FUNCTION_ATTRS - , attr, bound_meth_attr - #endif ); mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self) { diff --git a/py/objcell.c b/py/objcell.c index a17a94b9b7..b100fae4fe 100644 --- a/py/objcell.c +++ b/py/objcell.c @@ -40,12 +40,16 @@ STATIC void cell_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t k } #endif +#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED +#define CELL_TYPE_PRINT , print, cell_print +#else +#define CELL_TYPE_PRINT +#endif + STATIC MP_DEFINE_CONST_OBJ_TYPE( // cell representation is just value in < > mp_type_cell, MP_QSTR_, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW - #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED - , print, cell_print - #endif + CELL_TYPE_PRINT ); mp_obj_t mp_obj_new_cell(mp_obj_t obj) { diff --git a/py/objclosure.c b/py/objclosure.c index 15ed994d37..45a3e83c46 100644 --- a/py/objclosure.c +++ b/py/objclosure.c @@ -84,6 +84,15 @@ STATIC void mp_obj_closure_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_closure_t *o = MP_OBJ_TO_PTR(self_in); mp_load_method_maybe(o->fun, attr, dest); } +#define CLOSURE_TYPE_ATTR attr, mp_obj_closure_attr, +#else +#define CLOSURE_TYPE_ATTR +#endif + +#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED +#define CLOSURE_TYPE_PRINT print, closure_print, +#else +#define CLOSURE_TYPE_PRINT #endif MP_DEFINE_CONST_OBJ_TYPE( @@ -91,12 +100,8 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_closure, MP_TYPE_FLAG_BINDS_SELF, MP_TYPE_NULL_MAKE_NEW, - #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED - print, closure_print, - #endif - #if MICROPY_PY_FUNCTION_ATTRS - attr, mp_obj_closure_attr, - #endif + CLOSURE_TYPE_ATTR + CLOSURE_TYPE_PRINT call, closure_call ); diff --git a/py/objfun.c b/py/objfun.c index 30de8670a1..d6ff354575 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -352,19 +352,27 @@ void mp_obj_fun_bc_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } #endif +#if MICROPY_CPYTHON_COMPAT +#define FUN_BC_TYPE_PRINT print, fun_bc_print, +#else +#define FUN_BC_TYPE_PRINT +#endif + +#if MICROPY_PY_FUNCTION_ATTRS +#define FUN_BC_TYPE_ATTR attr, mp_obj_fun_bc_attr, +#else +#define FUN_BC_TYPE_ATTR +#endif + MP_DEFINE_CONST_OBJ_TYPE( mp_type_fun_bc, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF, MP_TYPE_NULL_MAKE_NEW, - #if MICROPY_CPYTHON_COMPAT - print, fun_bc_print, - #endif + FUN_BC_TYPE_PRINT + FUN_BC_TYPE_ATTR call, fun_bc_call, unary_op, mp_generic_unary_op - #if MICROPY_PY_FUNCTION_ATTRS - , attr, mp_obj_fun_bc_attr - #endif ); mp_obj_t mp_obj_new_fun_bc(const mp_obj_t *def_args, const byte *code, const mp_module_context_t *context, struct _mp_raw_code_t *const *child_table) { @@ -408,17 +416,24 @@ STATIC mp_obj_t fun_native_call(mp_obj_t self_in, size_t n_args, size_t n_kw, co return fun(self_in, n_args, n_kw, args); } +#if MICROPY_CPYTHON_COMPAT +#define FUN_BC_TYPE_PRINT print, fun_bc_print, +#else +#define FUN_BC_TYPE_PRINT +#endif +#if MICROPY_PY_FUNCTION_ATTRS +#define FUN_BC_TYPE_ATTR attr, mp_obj_fun_bc_attr, +#else +#define FUN_BC_TYPE_ATTR +#endif + STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_fun_native, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF, MP_TYPE_NULL_MAKE_NEW, - #if MICROPY_CPYTHON_COMPAT - print, fun_bc_print, - #endif - #if MICROPY_PY_FUNCTION_ATTRS - attr, mp_obj_fun_bc_attr, - #endif + FUN_BC_TYPE_PRINT + FUN_BC_TYPE_ATTR call, fun_native_call, unary_op, mp_generic_unary_op ); diff --git a/py/objgenerator.c b/py/objgenerator.c index 0ab80ca118..299f25e7bb 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -70,16 +70,20 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons return MP_OBJ_FROM_PTR(o); } +#if MICROPY_PY_FUNCTION_ATTRS +#define GEN_WRAP_TYPE_ATTR attr, mp_obj_fun_bc_attr, +#else +#define GEN_WRAP_TYPE_ATTR +#endif + MP_DEFINE_CONST_OBJ_TYPE( mp_type_gen_wrap, MP_QSTR_generator, MP_TYPE_FLAG_BINDS_SELF, MP_TYPE_NULL_MAKE_NEW, + GEN_WRAP_TYPE_ATTR call, gen_wrap_call, unary_op, mp_generic_unary_op - #if MICROPY_PY_FUNCTION_ATTRS - , attr, mp_obj_fun_bc_attr - #endif ); /******************************************************************************/ @@ -132,16 +136,20 @@ STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_k return MP_OBJ_FROM_PTR(o); } +#if MICROPY_PY_FUNCTION_ATTRS +#define NATIVE_GEN_WRAP_TYPE_ATTR attr, mp_obj_fun_bc_attr, +#else +#define NATIVE_GEN_WRAP_TYPE_ATTR +#endif + MP_DEFINE_CONST_OBJ_TYPE( mp_type_native_gen_wrap, MP_QSTR_generator, MP_TYPE_FLAG_BINDS_SELF, MP_TYPE_NULL_MAKE_NEW, call, native_gen_wrap_call, + NATIVE_GEN_WRAP_TYPE_ATTR unary_op, mp_generic_unary_op - #if MICROPY_PY_FUNCTION_ATTRS - , attr, mp_obj_fun_bc_attr - #endif ); #endif // MICROPY_EMIT_NATIVE diff --git a/py/objobject.c b/py/objobject.c index 617b40fbbf..868a85b32a 100644 --- a/py/objobject.c +++ b/py/objobject.c @@ -111,12 +111,16 @@ STATIC const mp_rom_map_elem_t object_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(object_locals_dict, object_locals_dict_table); #endif +#if MICROPY_CPYTHON_COMPAT +#define OBJECT_TYPE_LOCALS_DICT , locals_dict, (mp_obj_dict_t *)&object_locals_dict +#else +#define OBJECT_TYPE_LOCALS_DICT +#endif + MP_DEFINE_CONST_OBJ_TYPE( mp_type_object, MP_QSTR_object, MP_TYPE_FLAG_NONE, object_make_new - #if MICROPY_CPYTHON_COMPAT - , locals_dict, (mp_obj_dict_t *)&object_locals_dict - #endif + OBJECT_TYPE_LOCALS_DICT ); diff --git a/py/objrange.c b/py/objrange.c index adf4b17466..3140504b2b 100644 --- a/py/objrange.c +++ b/py/objrange.c @@ -210,19 +210,27 @@ STATIC void range_attr(mp_obj_t o_in, qstr attr, mp_obj_t *dest) { } #endif +#if MICROPY_PY_BUILTINS_RANGE_BINOP +#define RANGE_TYPE_BINOP binary_op, range_binary_op, +#else +#define RANGE_TYPE_BINOP +#endif + +#if MICROPY_PY_BUILTINS_RANGE_ATTRS +#define RANGE_TYPE_ATTR attr, range_attr, +#else +#define RANGE_TYPE_ATTR +#endif + MP_DEFINE_CONST_OBJ_TYPE( mp_type_range, MP_QSTR_range, MP_TYPE_FLAG_NONE, range_make_new, + RANGE_TYPE_BINOP + RANGE_TYPE_ATTR print, range_print, unary_op, range_unary_op, - #if MICROPY_PY_BUILTINS_RANGE_BINOP - binary_op, range_binary_op, - #endif subscr, range_subscr, getiter, range_getiter - #if MICROPY_PY_BUILTINS_RANGE_ATTRS - , attr, range_attr - #endif ); diff --git a/py/objslice.c b/py/objslice.c index 98c03485ff..7baca1fbe6 100644 --- a/py/objslice.c +++ b/py/objslice.c @@ -92,17 +92,21 @@ STATIC const mp_rom_map_elem_t slice_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(slice_locals_dict, slice_locals_dict_table); #endif +#if MICROPY_PY_BUILTINS_SLICE_ATTRS +#define SLICE_TYPE_ATTR_OR_LOCALS_DICT attr, slice_attr, +#elif MICROPY_PY_BUILTINS_SLICE_INDICES +#define SLICE_TYPE_ATTR_OR_LOCALS_DICT locals_dict, (mp_obj_dict_t *)&slice_locals_dict, +#else +#define SLICE_TYPE_ATTR_OR_LOCALS_DICT +#endif + MP_DEFINE_CONST_OBJ_TYPE( mp_type_slice, MP_QSTR_slice, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, + SLICE_TYPE_ATTR_OR_LOCALS_DICT print, slice_print - #if MICROPY_PY_BUILTINS_SLICE_ATTRS - , attr, slice_attr - #elif MICROPY_PY_BUILTINS_SLICE_INDICES - , locals_dict, (mp_obj_dict_t *)&slice_locals_dict - #endif ); mp_obj_t mp_obj_new_slice(mp_obj_t ostart, mp_obj_t ostop, mp_obj_t ostep) { From 9dce82776db104750283b213095a7aedfb95a1d9 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 24 Jun 2022 16:27:46 +1000 Subject: [PATCH 0418/1041] all: Remove unnecessary locals_dict cast. Signed-off-by: Jim Mussared --- extmod/machine_i2c.c | 2 +- extmod/machine_signal.c | 2 +- extmod/machine_spi.c | 2 +- extmod/modbluetooth.c | 2 +- extmod/modbtree.c | 2 +- extmod/modframebuf.c | 2 +- extmod/modlwip.c | 4 ++-- extmod/moduasyncio.c | 2 +- extmod/moducryptolib.c | 2 +- extmod/moduhashlib.c | 6 +++--- extmod/modure.c | 4 ++-- extmod/moduselect.c | 2 +- extmod/modusocket.c | 2 +- extmod/modussl_axtls.c | 2 +- extmod/modussl_mbedtls.c | 2 +- extmod/modutimeq.c | 2 +- extmod/moduwebsocket.c | 2 +- extmod/moduzlib.c | 2 +- extmod/modwebrepl.c | 2 +- extmod/network_cyw43.c | 2 +- extmod/vfs_fat.c | 2 +- extmod/vfs_fat_file.c | 4 ++-- extmod/vfs_lfsx.c | 2 +- extmod/vfs_lfsx_file.c | 4 ++-- extmod/vfs_posix.c | 2 +- extmod/vfs_posix_file.c | 4 ++-- ports/cc3200/misc/mpirq.c | 2 +- ports/cc3200/mods/modnetwork.c | 2 +- ports/cc3200/mods/moduhashlib.c | 4 ++-- ports/cc3200/mods/modusocket.c | 2 +- ports/cc3200/mods/modussl.c | 2 +- ports/cc3200/mods/modwlan.c | 2 +- ports/cc3200/mods/pybadc.c | 4 ++-- ports/cc3200/mods/pybflash.c | 2 +- ports/cc3200/mods/pybi2c.c | 2 +- ports/cc3200/mods/pybpin.c | 4 ++-- ports/cc3200/mods/pybrtc.c | 2 +- ports/cc3200/mods/pybsd.c | 2 +- ports/cc3200/mods/pybspi.c | 2 +- ports/cc3200/mods/pybtimer.c | 4 ++-- ports/cc3200/mods/pybuart.c | 2 +- ports/cc3200/mods/pybwdt.c | 2 +- ports/esp32/esp32_nvs.c | 2 +- ports/esp32/esp32_partition.c | 2 +- ports/esp32/esp32_rmt.c | 2 +- ports/esp32/esp32_ulp.c | 2 +- ports/esp32/machine_adc.c | 2 +- ports/esp32/machine_adcblock.c | 2 +- ports/esp32/machine_dac.c | 2 +- ports/esp32/machine_hw_spi.c | 2 +- ports/esp32/machine_i2c.c | 2 +- ports/esp32/machine_i2s.c | 2 +- ports/esp32/machine_pin.c | 4 ++-- ports/esp32/machine_rtc.c | 2 +- ports/esp32/machine_sdcard.c | 2 +- ports/esp32/machine_timer.c | 2 +- ports/esp32/machine_touchpad.c | 2 +- ports/esp32/machine_uart.c | 2 +- ports/esp32/machine_wdt.c | 2 +- ports/esp32/modsocket.c | 2 +- ports/esp32/network_lan.c | 2 +- ports/esp32/network_ppp.c | 2 +- ports/esp32/network_wlan.c | 2 +- ports/esp8266/machine_adc.c | 2 +- ports/esp8266/machine_hspi.c | 2 +- ports/esp8266/machine_pin.c | 4 ++-- ports/esp8266/machine_rtc.c | 2 +- ports/esp8266/machine_uart.c | 2 +- ports/esp8266/machine_wdt.c | 2 +- ports/esp8266/modmachine.c | 2 +- ports/esp8266/modnetwork.c | 2 +- ports/mimxrt/machine_adc.c | 2 +- ports/mimxrt/machine_i2c.c | 2 +- ports/mimxrt/machine_i2s.c | 2 +- ports/mimxrt/machine_led.c | 2 +- ports/mimxrt/machine_pin.c | 8 ++++---- ports/mimxrt/machine_rtc.c | 2 +- ports/mimxrt/machine_sdcard.c | 2 +- ports/mimxrt/machine_spi.c | 2 +- ports/mimxrt/machine_timer.c | 2 +- ports/mimxrt/machine_uart.c | 2 +- ports/mimxrt/machine_wdt.c | 2 +- ports/mimxrt/mimxrt_flash.c | 2 +- ports/mimxrt/network_lan.c | 2 +- ports/nrf/boards/microbit/modules/microbitdisplay.c | 2 +- ports/nrf/boards/microbit/modules/microbitimage.c | 2 +- ports/nrf/modules/board/led.c | 2 +- ports/nrf/modules/machine/adc.c | 2 +- ports/nrf/modules/machine/i2c.c | 2 +- ports/nrf/modules/machine/pin.c | 4 ++-- ports/nrf/modules/machine/pwm.c | 2 +- ports/nrf/modules/machine/rtcounter.c | 2 +- ports/nrf/modules/machine/spi.c | 2 +- ports/nrf/modules/machine/temp.c | 2 +- ports/nrf/modules/machine/timer.c | 2 +- ports/nrf/modules/machine/uart.c | 2 +- ports/nrf/modules/nrf/flashbdev.c | 2 +- ports/nrf/modules/ubluepy/ubluepy_characteristic.c | 2 +- ports/nrf/modules/ubluepy/ubluepy_constants.c | 4 ++-- ports/nrf/modules/ubluepy/ubluepy_delegate.c | 2 +- ports/nrf/modules/ubluepy/ubluepy_descriptor.c | 2 +- ports/nrf/modules/ubluepy/ubluepy_peripheral.c | 2 +- ports/nrf/modules/ubluepy/ubluepy_scan_entry.c | 2 +- ports/nrf/modules/ubluepy/ubluepy_scanner.c | 2 +- ports/nrf/modules/ubluepy/ubluepy_service.c | 2 +- ports/nrf/modules/ubluepy/ubluepy_uuid.c | 2 +- ports/nrf/modules/uos/microbitfs.c | 4 ++-- ports/nrf/pin_named_pins.c | 4 ++-- ports/pic16bit/modpybled.c | 2 +- ports/pic16bit/modpybswitch.c | 2 +- ports/renesas-ra/machine_i2c.c | 2 +- ports/rp2/machine_adc.c | 2 +- ports/rp2/machine_i2c.c | 2 +- ports/rp2/machine_i2s.c | 2 +- ports/rp2/machine_pin.c | 2 +- ports/rp2/machine_rtc.c | 2 +- ports/rp2/machine_spi.c | 2 +- ports/rp2/machine_timer.c | 2 +- ports/rp2/machine_uart.c | 2 +- ports/rp2/machine_wdt.c | 2 +- ports/rp2/rp2_flash.c | 2 +- ports/rp2/rp2_pio.c | 4 ++-- ports/samd/machine_led.c | 2 +- ports/samd/machine_pin.c | 2 +- ports/samd/samd_flash.c | 2 +- ports/stm32/accel.c | 2 +- ports/stm32/adc.c | 4 ++-- ports/stm32/dac.c | 2 +- ports/stm32/extint.c | 2 +- ports/stm32/lcd.c | 2 +- ports/stm32/led.c | 2 +- ports/stm32/machine_adc.c | 2 +- ports/stm32/machine_i2c.c | 2 +- ports/stm32/machine_i2s.c | 2 +- ports/stm32/machine_spi.c | 2 +- ports/stm32/machine_timer.c | 2 +- ports/stm32/machine_uart.c | 2 +- ports/stm32/network_lan.c | 2 +- ports/stm32/pin.c | 4 ++-- ports/stm32/pin_named_pins.c | 4 ++-- ports/stm32/pyb_can.c | 2 +- ports/stm32/pyb_i2c.c | 2 +- ports/stm32/pyb_spi.c | 2 +- ports/stm32/rtc.c | 2 +- ports/stm32/sdcard.c | 4 ++-- ports/stm32/servo.c | 2 +- ports/stm32/storage.c | 2 +- ports/stm32/timer.c | 4 ++-- ports/stm32/usb.c | 4 ++-- ports/stm32/usrsw.c | 2 +- ports/stm32/wdt.c | 2 +- ports/teensy/led.c | 2 +- ports/teensy/timer.c | 4 ++-- ports/teensy/uart.c | 2 +- ports/unix/coverage.c | 4 ++-- ports/unix/modffi.c | 6 +++--- ports/unix/modjni.c | 6 +++--- ports/unix/moduselect.c | 2 +- ports/unix/modusocket.c | 2 +- ports/zephyr/machine_i2c.c | 2 +- ports/zephyr/machine_pin.c | 2 +- ports/zephyr/machine_spi.c | 2 +- ports/zephyr/machine_uart.c | 2 +- ports/zephyr/modusocket.c | 2 +- ports/zephyr/modzsensor.c | 2 +- ports/zephyr/zephyr_storage.c | 4 ++-- py/modio.c | 2 +- py/modthread.c | 2 +- py/objarray.c | 6 +++--- py/objdeque.c | 2 +- py/objdict.c | 4 ++-- py/objgenerator.c | 2 +- py/objint.c | 2 +- py/objlist.c | 2 +- py/objobject.c | 2 +- py/objpolyiter.c | 2 +- py/objproperty.c | 2 +- py/objset.c | 4 ++-- py/objslice.c | 2 +- py/objstr.c | 4 ++-- py/objstringio.c | 4 ++-- py/objstrunicode.c | 2 +- py/objtuple.c | 2 +- shared/runtime/mpirq.c | 2 +- shared/runtime/sys_stdio_mphal.c | 4 ++-- 185 files changed, 226 insertions(+), 226 deletions(-) diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c index 7e597b7910..378bf8fc91 100644 --- a/extmod/machine_i2c.c +++ b/extmod/machine_i2c.c @@ -737,7 +737,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_machine_soft_i2c_make_new, print, mp_machine_soft_i2c_print, protocol, &mp_machine_soft_i2c_p, - locals_dict, (mp_obj_dict_t *)&mp_machine_i2c_locals_dict + locals_dict, &mp_machine_i2c_locals_dict ); #endif // MICROPY_PY_MACHINE_SOFTI2C diff --git a/extmod/machine_signal.c b/extmod/machine_signal.c index 818bc01c27..f665ffaa49 100644 --- a/extmod/machine_signal.c +++ b/extmod/machine_signal.c @@ -179,7 +179,7 @@ MP_DEFINE_CONST_OBJ_TYPE( signal_make_new, call, signal_call, protocol, &signal_pin_p, - locals_dict, (void *)&signal_locals_dict + locals_dict, &signal_locals_dict ); #endif // MICROPY_PY_MACHINE diff --git a/extmod/machine_spi.c b/extmod/machine_spi.c index 43148c9c8d..c7fc5877b1 100644 --- a/extmod/machine_spi.c +++ b/extmod/machine_spi.c @@ -258,7 +258,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_machine_soft_spi_make_new, print, mp_machine_soft_spi_print, protocol, &mp_machine_soft_spi_p, - locals_dict, (mp_obj_dict_t *)&mp_machine_spi_locals_dict + locals_dict, &mp_machine_spi_locals_dict ); #endif // MICROPY_PY_MACHINE_SOFTSPI diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 2b7497e1b6..2e058fc7de 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -981,7 +981,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_BLE, MP_TYPE_FLAG_NONE, bluetooth_ble_make_new, - locals_dict, (void *)&bluetooth_ble_locals_dict + locals_dict, &bluetooth_ble_locals_dict ); STATIC const mp_rom_map_elem_t mp_module_bluetooth_globals_table[] = { diff --git a/extmod/modbtree.c b/extmod/modbtree.c index f115be44fe..15cb634163 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -330,7 +330,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( iternext, btree_iternext, binary_op, btree_binary_op, subscr, btree_subscr, - locals_dict, (void *)&btree_locals_dict + locals_dict, &btree_locals_dict ); #endif diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index 1d44312cf3..f29eab272f 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -835,7 +835,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, framebuf_make_new, buffer, framebuf_get_buffer, - locals_dict, (mp_obj_dict_t *)&framebuf_locals_dict + locals_dict, &framebuf_locals_dict ); #endif diff --git a/extmod/modlwip.c b/extmod/modlwip.c index f9d5b76b2c..2f5da36f40 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -182,7 +182,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_slip, MP_TYPE_FLAG_NONE, lwip_slip_make_new, - locals_dict, (mp_obj_dict_t *)&lwip_slip_locals_dict + locals_dict, &lwip_slip_locals_dict ); #endif // MICROPY_PY_LWIP_SLIP @@ -1602,7 +1602,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( lwip_socket_make_new, print, lwip_socket_print, protocol, &lwip_socket_stream_p, - locals_dict, (mp_obj_dict_t *)&lwip_socket_locals_dict + locals_dict, &lwip_socket_locals_dict ); /******************************************************************************/ diff --git a/extmod/moduasyncio.c b/extmod/moduasyncio.c index 500d13c5b8..5467642096 100644 --- a/extmod/moduasyncio.c +++ b/extmod/moduasyncio.c @@ -149,7 +149,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_TaskQueue, MP_TYPE_FLAG_NONE, task_queue_make_new, - locals_dict, (mp_obj_dict_t *)&task_queue_locals_dict + locals_dict, &task_queue_locals_dict ); /******************************************************************************/ diff --git a/extmod/moducryptolib.c b/extmod/moducryptolib.c index 236b7edfd7..e4625c21a8 100644 --- a/extmod/moducryptolib.c +++ b/extmod/moducryptolib.c @@ -353,7 +353,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_aes, MP_TYPE_FLAG_NONE, ucryptolib_aes_make_new, - locals_dict, (void *)&ucryptolib_aes_locals_dict + locals_dict, &ucryptolib_aes_locals_dict ); STATIC const mp_rom_map_elem_t mp_module_ucryptolib_globals_table[] = { diff --git a/extmod/moduhashlib.c b/extmod/moduhashlib.c index 44625ed6da..9535e00b40 100644 --- a/extmod/moduhashlib.c +++ b/extmod/moduhashlib.c @@ -162,7 +162,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_sha256, MP_TYPE_FLAG_NONE, uhashlib_sha256_make_new, - locals_dict, (void *)&uhashlib_sha256_locals_dict + locals_dict, &uhashlib_sha256_locals_dict ); #endif @@ -256,7 +256,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_sha1, MP_TYPE_FLAG_NONE, uhashlib_sha1_make_new, - locals_dict, (void *)&uhashlib_sha1_locals_dict + locals_dict, &uhashlib_sha1_locals_dict ); #endif @@ -350,7 +350,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_md5, MP_TYPE_FLAG_NONE, uhashlib_md5_make_new, - locals_dict, (void *)&uhashlib_md5_locals_dict + locals_dict, &uhashlib_md5_locals_dict ); #endif // MICROPY_PY_UHASHLIB_MD5 diff --git a/extmod/modure.c b/extmod/modure.c index a27c7ff9fd..4395992405 100644 --- a/extmod/modure.c +++ b/extmod/modure.c @@ -185,7 +185,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, print, match_print, - locals_dict, (void *)&match_locals_dict + locals_dict, &match_locals_dict ); #endif @@ -419,7 +419,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, print, re_print, - locals_dict, (void *)&re_locals_dict + locals_dict, &re_locals_dict ); #endif diff --git a/extmod/moduselect.c b/extmod/moduselect.c index 1a11ee0eab..352b15d983 100644 --- a/extmod/moduselect.c +++ b/extmod/moduselect.c @@ -343,7 +343,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_NULL_MAKE_NEW, getiter, mp_identity_getiter, iternext, poll_iternext, - locals_dict, (void *)&poll_locals_dict + locals_dict, &poll_locals_dict ); // poll() diff --git a/extmod/modusocket.c b/extmod/modusocket.c index 6008edb11c..fc16d7e270 100644 --- a/extmod/modusocket.c +++ b/extmod/modusocket.c @@ -534,7 +534,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, socket_make_new, protocol, &socket_stream_p, - locals_dict, (mp_obj_dict_t *)&socket_locals_dict, + locals_dict, &socket_locals_dict, print, socket_print ); diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c index 72eb0e214f..78470ea6df 100644 --- a/extmod/modussl_axtls.c +++ b/extmod/modussl_axtls.c @@ -324,7 +324,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( getiter, NULL, iternext, NULL, protocol, &ussl_socket_stream_p, - locals_dict, (void *)&ussl_socket_locals_dict + locals_dict, &ussl_socket_locals_dict ); STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c index 0fab915f3f..76ca3ac719 100644 --- a/extmod/modussl_mbedtls.c +++ b/extmod/modussl_mbedtls.c @@ -402,7 +402,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( getiter, NULL, iternext, NULL, protocol, &ussl_socket_stream_p, - locals_dict, (void *)&ussl_socket_locals_dict + locals_dict, &ussl_socket_locals_dict ); STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { diff --git a/extmod/modutimeq.c b/extmod/modutimeq.c index bf4e031895..1a7575adc9 100644 --- a/extmod/modutimeq.c +++ b/extmod/modutimeq.c @@ -215,7 +215,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, utimeq_make_new, unary_op, utimeq_unary_op, - locals_dict, (void *)&utimeq_locals_dict + locals_dict, &utimeq_locals_dict ); STATIC const mp_rom_map_elem_t mp_module_utimeq_globals_table[] = { diff --git a/extmod/moduwebsocket.c b/extmod/moduwebsocket.c index 2895978f3d..c6be50d0e1 100644 --- a/extmod/moduwebsocket.c +++ b/extmod/moduwebsocket.c @@ -296,7 +296,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, websocket_make_new, protocol, &websocket_stream_p, - locals_dict, (void *)&websocket_locals_dict + locals_dict, &websocket_locals_dict ); STATIC const mp_rom_map_elem_t uwebsocket_module_globals_table[] = { diff --git a/extmod/moduzlib.c b/extmod/moduzlib.c index 93c939129e..533168d0b0 100644 --- a/extmod/moduzlib.c +++ b/extmod/moduzlib.c @@ -146,7 +146,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, decompio_make_new, protocol, &decompio_stream_p, - locals_dict, (void *)&decompio_locals_dict + locals_dict, &decompio_locals_dict ); #endif diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c index cb893b38dc..fc5ca35ea0 100644 --- a/extmod/modwebrepl.c +++ b/extmod/modwebrepl.c @@ -348,7 +348,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, webrepl_make_new, protocol, &webrepl_stream_p, - locals_dict, (mp_obj_dict_t *)&webrepl_locals_dict + locals_dict, &webrepl_locals_dict ); STATIC const mp_rom_map_elem_t webrepl_module_globals_table[] = { diff --git a/extmod/network_cyw43.c b/extmod/network_cyw43.c index fbd0a750b8..329ba53ef5 100644 --- a/extmod/network_cyw43.c +++ b/extmod/network_cyw43.c @@ -502,7 +502,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, network_cyw43_make_new, print, network_cyw43_print, - locals_dict, (mp_obj_dict_t *)&network_cyw43_locals_dict + locals_dict, &network_cyw43_locals_dict ); #endif // MICROPY_PY_NETWORK_CYW43 diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 4a2ef883c2..7c18a51633 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -437,7 +437,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, fat_vfs_make_new, protocol, &fat_vfs_proto, - locals_dict, (mp_obj_dict_t *)&fat_vfs_locals_dict + locals_dict, &fat_vfs_locals_dict ); #endif // MICROPY_VFS_FAT diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index 0d4af09b45..00980459db 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -185,7 +185,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &vfs_fat_fileio_stream_p, - locals_dict, (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict + locals_dict, &vfs_fat_rawfile_locals_dict ); STATIC const mp_stream_p_t vfs_fat_textio_stream_p = { @@ -204,7 +204,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &vfs_fat_textio_stream_p, - locals_dict, (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict + locals_dict, &vfs_fat_rawfile_locals_dict ); // Factory function for I/O stream classes diff --git a/extmod/vfs_lfsx.c b/extmod/vfs_lfsx.c index 3f8d262a48..33e2ef5519 100644 --- a/extmod/vfs_lfsx.c +++ b/extmod/vfs_lfsx.c @@ -514,7 +514,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_VFS_LFSx(make_new), protocol, &MP_VFS_LFSx(proto), - locals_dict, (mp_obj_dict_t *)&MP_VFS_LFSx(locals_dict) + locals_dict, &MP_VFS_LFSx(locals_dict) ); #undef VFS_LFSx_QSTR diff --git a/extmod/vfs_lfsx_file.c b/extmod/vfs_lfsx_file.c index ba90cc6084..fda1b97b2a 100644 --- a/extmod/vfs_lfsx_file.c +++ b/extmod/vfs_lfsx_file.c @@ -229,7 +229,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &MP_VFS_LFSx(fileio_stream_p), - locals_dict, (mp_obj_dict_t *)&MP_VFS_LFSx(file_locals_dict) + locals_dict, &MP_VFS_LFSx(file_locals_dict) ); STATIC const mp_stream_p_t MP_VFS_LFSx(textio_stream_p) = { @@ -248,5 +248,5 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &MP_VFS_LFSx(textio_stream_p), - locals_dict, (mp_obj_dict_t *)&MP_VFS_LFSx(file_locals_dict) + locals_dict, &MP_VFS_LFSx(file_locals_dict) ); diff --git a/extmod/vfs_posix.c b/extmod/vfs_posix.c index 79126c0070..b02827e864 100644 --- a/extmod/vfs_posix.c +++ b/extmod/vfs_posix.c @@ -404,7 +404,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, vfs_posix_make_new, protocol, &vfs_posix_proto, - locals_dict, (mp_obj_dict_t *)&vfs_posix_locals_dict + locals_dict, &vfs_posix_locals_dict ); #endif // MICROPY_VFS_POSIX diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index 85aef1617b..f0b5436fe1 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -258,7 +258,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &vfs_posix_fileio_stream_p, - locals_dict, (mp_obj_dict_t *)&vfs_posix_rawfile_locals_dict + locals_dict, &vfs_posix_rawfile_locals_dict ); STATIC const mp_stream_p_t vfs_posix_textio_stream_p = { @@ -277,7 +277,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &vfs_posix_textio_stream_p, - locals_dict, (mp_obj_dict_t *)&vfs_posix_rawfile_locals_dict + locals_dict, &vfs_posix_rawfile_locals_dict ); const mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_vfs_posix_textio}, STDIN_FILENO}; diff --git a/ports/cc3200/misc/mpirq.c b/ports/cc3200/misc/mpirq.c index e9cae92a32..9c3c2f7196 100644 --- a/ports/cc3200/misc/mpirq.c +++ b/ports/cc3200/misc/mpirq.c @@ -196,7 +196,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, call, mp_irq_call, - locals_dict, (mp_obj_t)&mp_irq_locals_dict + locals_dict, &mp_irq_locals_dict ); MP_REGISTER_ROOT_POINTER(mp_obj_list_t mp_irq_obj_list); diff --git a/ports/cc3200/mods/modnetwork.c b/ports/cc3200/mods/modnetwork.c index a741893007..0a72a1ab32 100644 --- a/ports/cc3200/mods/modnetwork.c +++ b/ports/cc3200/mods/modnetwork.c @@ -176,6 +176,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_Server, MP_TYPE_FLAG_NONE, network_server_make_new, - locals_dict, (mp_obj_t)&network_server_locals_dict + locals_dict, &network_server_locals_dict ); #endif diff --git a/ports/cc3200/mods/moduhashlib.c b/ports/cc3200/mods/moduhashlib.c index 5437cfb264..4a759d8ea5 100644 --- a/ports/cc3200/mods/moduhashlib.c +++ b/ports/cc3200/mods/moduhashlib.c @@ -182,7 +182,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_sha1, MP_TYPE_FLAG_NONE, hash_make_new, - locals_dict, (mp_obj_t)&hash_locals_dict + locals_dict, &hash_locals_dict ); STATIC MP_DEFINE_CONST_OBJ_TYPE( @@ -190,7 +190,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_sha256, MP_TYPE_FLAG_NONE, hash_make_new, - locals_dict, (mp_obj_t)&hash_locals_dict + locals_dict, &hash_locals_dict ); STATIC const mp_rom_map_elem_t mp_module_hashlib_globals_table[] = { diff --git a/ports/cc3200/mods/modusocket.c b/ports/cc3200/mods/modusocket.c index 11199de146..55d504a709 100644 --- a/ports/cc3200/mods/modusocket.c +++ b/ports/cc3200/mods/modusocket.c @@ -765,7 +765,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, socket_make_new, protocol, &socket_stream_p, - locals_dict, (mp_obj_t)&socket_locals_dict + locals_dict, &socket_locals_dict ); /******************************************************************************/ diff --git a/ports/cc3200/mods/modussl.c b/ports/cc3200/mods/modussl.c index d0909e7c29..abc9917c81 100644 --- a/ports/cc3200/mods/modussl.c +++ b/ports/cc3200/mods/modussl.c @@ -68,7 +68,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( getiter, NULL, iternext, NULL, protocol, &socket_stream_p, - locals_dict, (mp_obj_t)&socket_locals_dict + locals_dict, &socket_locals_dict ); STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { diff --git a/ports/cc3200/mods/modwlan.c b/ports/cc3200/mods/modwlan.c index 24f5d196d2..1c99f075e9 100644 --- a/ports/cc3200/mods/modwlan.c +++ b/ports/cc3200/mods/modwlan.c @@ -1290,7 +1290,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_WLAN, MP_TYPE_FLAG_NONE, wlan_make_new, - locals_dict, (mp_obj_t)&wlan_locals_dict + locals_dict, &wlan_locals_dict ); const mod_network_nic_type_t mod_network_nic_type_wlan = { diff --git a/ports/cc3200/mods/pybadc.c b/ports/cc3200/mods/pybadc.c index a114eeda16..a14f9aced2 100644 --- a/ports/cc3200/mods/pybadc.c +++ b/ports/cc3200/mods/pybadc.c @@ -239,7 +239,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, adc_make_new, print, adc_print, - locals_dict, (mp_obj_t)&adc_locals_dict + locals_dict, &adc_locals_dict ); STATIC void adc_channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -308,5 +308,5 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_NULL_MAKE_NEW, print, adc_channel_print, call, adc_channel_call, - locals_dict, (mp_obj_t)&adc_channel_locals_dict + locals_dict, &adc_channel_locals_dict ); diff --git a/ports/cc3200/mods/pybflash.c b/ports/cc3200/mods/pybflash.c index 4cfafb7abf..a6d1e23fbf 100644 --- a/ports/cc3200/mods/pybflash.c +++ b/ports/cc3200/mods/pybflash.c @@ -89,7 +89,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_Flash, MP_TYPE_FLAG_NONE, pyb_flash_make_new, - locals_dict, (mp_obj_t)&pyb_flash_locals_dict + locals_dict, &pyb_flash_locals_dict ); void pyb_flash_init_vfs(fs_user_mount_t *vfs) { diff --git a/ports/cc3200/mods/pybi2c.c b/ports/cc3200/mods/pybi2c.c index 91a0b9b9f9..de92cc7c32 100644 --- a/ports/cc3200/mods/pybi2c.c +++ b/ports/cc3200/mods/pybi2c.c @@ -527,5 +527,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, pyb_i2c_make_new, print, pyb_i2c_print, - locals_dict, (mp_obj_t)&pyb_i2c_locals_dict + locals_dict, &pyb_i2c_locals_dict ); diff --git a/ports/cc3200/mods/pybpin.c b/ports/cc3200/mods/pybpin.c index 948cda70d4..374d09ddfb 100644 --- a/ports/cc3200/mods/pybpin.c +++ b/ports/cc3200/mods/pybpin.c @@ -938,7 +938,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pin_make_new, print, pin_print, call, pin_call, - locals_dict, (mp_obj_t)&pin_locals_dict + locals_dict, &pin_locals_dict ); STATIC const mp_irq_methods_t pin_irq_methods = { @@ -959,6 +959,6 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, print, pin_named_pins_obj_print, - locals_dict, (mp_obj_t)&pin_board_pins_locals_dict + locals_dict, &pin_board_pins_locals_dict ); diff --git a/ports/cc3200/mods/pybrtc.c b/ports/cc3200/mods/pybrtc.c index 2761cb3c64..ed7a20fecb 100644 --- a/ports/cc3200/mods/pybrtc.c +++ b/ports/cc3200/mods/pybrtc.c @@ -474,7 +474,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_RTC, MP_TYPE_FLAG_NONE, pyb_rtc_make_new, - locals_dict, (mp_obj_t)&pyb_rtc_locals_dict + locals_dict, &pyb_rtc_locals_dict ); STATIC const mp_irq_methods_t pyb_rtc_irq_methods = { diff --git a/ports/cc3200/mods/pybsd.c b/ports/cc3200/mods/pybsd.c index d8834e36f7..968a6a87ec 100644 --- a/ports/cc3200/mods/pybsd.c +++ b/ports/cc3200/mods/pybsd.c @@ -217,5 +217,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_SD, MP_TYPE_FLAG_NONE, pyb_sd_make_new, - locals_dict, (mp_obj_t)&pyb_sd_locals_dict + locals_dict, &pyb_sd_locals_dict ); diff --git a/ports/cc3200/mods/pybspi.c b/ports/cc3200/mods/pybspi.c index 50d897633e..7d83fabfde 100644 --- a/ports/cc3200/mods/pybspi.c +++ b/ports/cc3200/mods/pybspi.c @@ -383,5 +383,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, pyb_spi_make_new, print, pyb_spi_print, - locals_dict, (mp_obj_t)&pyb_spi_locals_dict + locals_dict, &pyb_spi_locals_dict ); diff --git a/ports/cc3200/mods/pybtimer.c b/ports/cc3200/mods/pybtimer.c index a8bc7821e0..14e1deb083 100644 --- a/ports/cc3200/mods/pybtimer.c +++ b/ports/cc3200/mods/pybtimer.c @@ -465,7 +465,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, pyb_timer_make_new, print, pyb_timer_print, - locals_dict, (mp_obj_t)&pyb_timer_locals_dict + locals_dict, &pyb_timer_locals_dict ); STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods = { @@ -728,7 +728,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, print, pyb_timer_channel_print, - locals_dict, (mp_obj_t)&pyb_timer_channel_locals_dict + locals_dict, &pyb_timer_channel_locals_dict ); MP_REGISTER_ROOT_POINTER(mp_obj_list_t pyb_timer_channel_obj_list); diff --git a/ports/cc3200/mods/pybuart.c b/ports/cc3200/mods/pybuart.c index 059101f4f2..e7896c4ca5 100644 --- a/ports/cc3200/mods/pybuart.c +++ b/ports/cc3200/mods/pybuart.c @@ -694,7 +694,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p, - locals_dict, (mp_obj_t)&pyb_uart_locals_dict + locals_dict, &pyb_uart_locals_dict ); MP_REGISTER_ROOT_POINTER(struct _pyb_uart_obj_t *pyb_uart_objs[2]); diff --git a/ports/cc3200/mods/pybwdt.c b/ports/cc3200/mods/pybwdt.c index cde1abe59d..3c1f9eb195 100644 --- a/ports/cc3200/mods/pybwdt.c +++ b/ports/cc3200/mods/pybwdt.c @@ -155,6 +155,6 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_WDT, MP_TYPE_FLAG_NONE, pyb_wdt_make_new, - locals_dict, (mp_obj_t)&pybwdt_locals_dict + locals_dict, &pybwdt_locals_dict ); diff --git a/ports/esp32/esp32_nvs.c b/ports/esp32/esp32_nvs.c index 1f96ad129d..d935a13d6f 100644 --- a/ports/esp32/esp32_nvs.c +++ b/ports/esp32/esp32_nvs.c @@ -147,5 +147,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, esp32_nvs_make_new, print, esp32_nvs_print, - locals_dict, (mp_obj_dict_t *)&esp32_nvs_locals_dict + locals_dict, &esp32_nvs_locals_dict ); diff --git a/ports/esp32/esp32_partition.c b/ports/esp32/esp32_partition.c index 2e42e7a819..6ce1e90b4c 100644 --- a/ports/esp32/esp32_partition.c +++ b/ports/esp32/esp32_partition.c @@ -290,5 +290,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, esp32_partition_make_new, print, esp32_partition_print, - locals_dict, (mp_obj_dict_t *)&esp32_partition_locals_dict + locals_dict, &esp32_partition_locals_dict ); diff --git a/ports/esp32/esp32_rmt.c b/ports/esp32/esp32_rmt.c index 36f33df3f5..ee09ac5200 100644 --- a/ports/esp32/esp32_rmt.c +++ b/ports/esp32/esp32_rmt.c @@ -378,5 +378,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, esp32_rmt_make_new, print, esp32_rmt_print, - locals_dict, (mp_obj_dict_t *)&esp32_rmt_locals_dict + locals_dict, &esp32_rmt_locals_dict ); diff --git a/ports/esp32/esp32_ulp.c b/ports/esp32/esp32_ulp.c index 5eb0e5591e..5030f98067 100644 --- a/ports/esp32/esp32_ulp.c +++ b/ports/esp32/esp32_ulp.c @@ -96,7 +96,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_ULP, MP_TYPE_FLAG_NONE, esp32_ulp_make_new, - locals_dict, (mp_obj_t)&esp32_ulp_locals_dict + locals_dict, &esp32_ulp_locals_dict ); #endif // CONFIG_IDF_TARGET_ESP32 diff --git a/ports/esp32/machine_adc.c b/ports/esp32/machine_adc.c index 5cc2d80384..c4e04159c0 100644 --- a/ports/esp32/machine_adc.c +++ b/ports/esp32/machine_adc.c @@ -262,5 +262,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, madc_make_new, print, madc_print, - locals_dict, (mp_obj_t)&madc_locals_dict + locals_dict, &madc_locals_dict ); diff --git a/ports/esp32/machine_adcblock.c b/ports/esp32/machine_adcblock.c index 770839e93e..ae3244f7fd 100644 --- a/ports/esp32/machine_adcblock.c +++ b/ports/esp32/machine_adcblock.c @@ -200,5 +200,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, madcblock_make_new, print, madcblock_print, - locals_dict, (mp_obj_dict_t *)&madcblock_locals_dict + locals_dict, &madcblock_locals_dict ); diff --git a/ports/esp32/machine_dac.c b/ports/esp32/machine_dac.c index c9b9c14e01..fbe33b0344 100644 --- a/ports/esp32/machine_dac.c +++ b/ports/esp32/machine_dac.c @@ -110,7 +110,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, mdac_make_new, print, mdac_print, - locals_dict, (mp_obj_t)&mdac_locals_dict + locals_dict, &mdac_locals_dict ); #endif // MICROPY_PY_MACHINE_DAC diff --git a/ports/esp32/machine_hw_spi.c b/ports/esp32/machine_hw_spi.c index 71583ef60e..51ea31ac1b 100644 --- a/ports/esp32/machine_hw_spi.c +++ b/ports/esp32/machine_hw_spi.c @@ -552,5 +552,5 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hw_spi_make_new, print, machine_hw_spi_print, protocol, &machine_hw_spi_p, - locals_dict, (mp_obj_dict_t *)&mp_machine_spi_locals_dict + locals_dict, &mp_machine_spi_locals_dict ); diff --git a/ports/esp32/machine_i2c.c b/ports/esp32/machine_i2c.c index 9e5be606db..895dc3a398 100644 --- a/ports/esp32/machine_i2c.c +++ b/ports/esp32/machine_i2c.c @@ -199,5 +199,5 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hw_i2c_make_new, print, machine_hw_i2c_print, protocol, &machine_hw_i2c_p, - locals_dict, (mp_obj_dict_t *)&mp_machine_i2c_locals_dict + locals_dict, &mp_machine_i2c_locals_dict ); diff --git a/ports/esp32/machine_i2s.c b/ports/esp32/machine_i2s.c index d30fb5d836..b853f418ad 100644 --- a/ports/esp32/machine_i2s.c +++ b/ports/esp32/machine_i2s.c @@ -838,7 +838,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &i2s_stream_p, - locals_dict, (mp_obj_dict_t *)&machine_i2s_locals_dict + locals_dict, &machine_i2s_locals_dict ); MP_REGISTER_ROOT_POINTER(struct _machine_i2s_obj_t *machine_i2s_obj[I2S_NUM_MAX]); diff --git a/ports/esp32/machine_pin.c b/ports/esp32/machine_pin.c index 1a1a3a0f8d..fd523a38ed 100644 --- a/ports/esp32/machine_pin.c +++ b/ports/esp32/machine_pin.c @@ -537,7 +537,7 @@ MP_DEFINE_CONST_OBJ_TYPE( print, machine_pin_print, call, machine_pin_call, protocol, &pin_pin_p, - locals_dict, (mp_obj_t)&machine_pin_locals_dict + locals_dict, &machine_pin_locals_dict ); /******************************************************************************/ @@ -730,7 +730,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, call, machine_pin_irq_call, - locals_dict, (mp_obj_dict_t *)&machine_pin_irq_locals_dict + locals_dict, &machine_pin_irq_locals_dict ); MP_REGISTER_ROOT_POINTER(mp_obj_t machine_pin_irq_handler[40]); diff --git a/ports/esp32/machine_rtc.c b/ports/esp32/machine_rtc.c index 6634bf5b03..19b83703fd 100644 --- a/ports/esp32/machine_rtc.c +++ b/ports/esp32/machine_rtc.c @@ -178,5 +178,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_RTC, MP_TYPE_FLAG_NONE, machine_rtc_make_new, - locals_dict, (mp_obj_t)&machine_rtc_locals_dict + locals_dict, &machine_rtc_locals_dict ); diff --git a/ports/esp32/machine_sdcard.c b/ports/esp32/machine_sdcard.c index 2d5663d476..0b6159157d 100644 --- a/ports/esp32/machine_sdcard.c +++ b/ports/esp32/machine_sdcard.c @@ -404,7 +404,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_SDCard, MP_TYPE_FLAG_NONE, machine_sdcard_make_new, - locals_dict, (mp_obj_dict_t *)&machine_sdcard_locals_dict + locals_dict, &machine_sdcard_locals_dict ); #endif // MICROPY_HW_ENABLE_SDCARD diff --git a/ports/esp32/machine_timer.c b/ports/esp32/machine_timer.c index 3b12950955..2fd40fa2af 100644 --- a/ports/esp32/machine_timer.c +++ b/ports/esp32/machine_timer.c @@ -283,7 +283,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, machine_timer_make_new, print, machine_timer_print, - locals_dict, (mp_obj_t)&machine_timer_locals_dict + locals_dict, &machine_timer_locals_dict ); MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *machine_timer_obj_head); diff --git a/ports/esp32/machine_touchpad.c b/ports/esp32/machine_touchpad.c index c5e3483b74..deba818dd1 100644 --- a/ports/esp32/machine_touchpad.c +++ b/ports/esp32/machine_touchpad.c @@ -139,7 +139,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_TouchPad, MP_TYPE_FLAG_NONE, mtp_make_new, - locals_dict, (mp_obj_t)&mtp_locals_dict + locals_dict, &mtp_locals_dict ); #endif // CONFIG_IDF_TARGET_ESP32 diff --git a/ports/esp32/machine_uart.c b/ports/esp32/machine_uart.c index 9df16ae419..6e091b8838 100644 --- a/ports/esp32/machine_uart.c +++ b/ports/esp32/machine_uart.c @@ -539,5 +539,5 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p, - locals_dict, (mp_obj_dict_t *)&machine_uart_locals_dict + locals_dict, &machine_uart_locals_dict ); diff --git a/ports/esp32/machine_wdt.c b/ports/esp32/machine_wdt.c index c2898c7fe1..bda9c6975e 100644 --- a/ports/esp32/machine_wdt.c +++ b/ports/esp32/machine_wdt.c @@ -88,5 +88,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_WDT, MP_TYPE_FLAG_NONE, machine_wdt_make_new, - locals_dict, (mp_obj_t)&machine_wdt_locals_dict + locals_dict, &machine_wdt_locals_dict ); diff --git a/ports/esp32/modsocket.c b/ports/esp32/modsocket.c index a2dcb3946c..e7e6f3c26e 100644 --- a/ports/esp32/modsocket.c +++ b/ports/esp32/modsocket.c @@ -791,7 +791,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, socket_make_new, protocol, &socket_stream_p, - locals_dict, (mp_obj_t)&socket_locals_dict + locals_dict, &socket_locals_dict ); STATIC mp_obj_t esp_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c index fc50e13c48..3c5aea5fb8 100644 --- a/ports/esp32/network_lan.c +++ b/ports/esp32/network_lan.c @@ -307,7 +307,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_LAN, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, - locals_dict, (mp_obj_dict_t *)&lan_if_locals_dict + locals_dict, &lan_if_locals_dict ); #endif diff --git a/ports/esp32/network_ppp.c b/ports/esp32/network_ppp.c index d6368d9f20..df07515c7d 100644 --- a/ports/esp32/network_ppp.c +++ b/ports/esp32/network_ppp.c @@ -283,5 +283,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_PPP, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, - locals_dict, (mp_obj_dict_t *)&ppp_if_locals_dict + locals_dict, &ppp_if_locals_dict ); diff --git a/ports/esp32/network_wlan.c b/ports/esp32/network_wlan.c index 6ca5f9a9ba..0f1f5de149 100644 --- a/ports/esp32/network_wlan.c +++ b/ports/esp32/network_wlan.c @@ -620,7 +620,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_WLAN, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, - locals_dict, (mp_obj_dict_t *)&wlan_if_locals_dict + locals_dict, &wlan_if_locals_dict ); STATIC const wlan_if_obj_t wlan_sta_obj = {{&wlan_if_type}, WIFI_IF_STA}; diff --git a/ports/esp8266/machine_adc.c b/ports/esp8266/machine_adc.c index bface7f7e1..b1e7b38435 100644 --- a/ports/esp8266/machine_adc.c +++ b/ports/esp8266/machine_adc.c @@ -95,5 +95,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, machine_adc_make_new, print, machine_adc_print, - locals_dict, (mp_obj_dict_t *)&machine_adc_locals_dict + locals_dict, &machine_adc_locals_dict ); diff --git a/ports/esp8266/machine_hspi.c b/ports/esp8266/machine_hspi.c index c0d4a677e3..3f449a1de9 100644 --- a/ports/esp8266/machine_hspi.c +++ b/ports/esp8266/machine_hspi.c @@ -182,7 +182,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hspi_make_new, print, machine_hspi_print, protocol, &machine_hspi_p, - locals_dict, (mp_obj_dict_t *)&mp_machine_spi_locals_dict + locals_dict, &mp_machine_spi_locals_dict ); #endif // MICROPY_PY_MACHINE_SPI diff --git a/ports/esp8266/machine_pin.c b/ports/esp8266/machine_pin.c index 8b759766cd..32ffca873d 100644 --- a/ports/esp8266/machine_pin.c +++ b/ports/esp8266/machine_pin.c @@ -458,7 +458,7 @@ MP_DEFINE_CONST_OBJ_TYPE( print, pyb_pin_print, call, pyb_pin_call, protocol, &pin_pin_p, - locals_dict, (mp_obj_dict_t *)&pyb_pin_locals_dict + locals_dict, &pyb_pin_locals_dict ); /******************************************************************************/ @@ -516,7 +516,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, call, pin_irq_call, - locals_dict, (mp_obj_dict_t *)&pin_irq_locals_dict + locals_dict, &pin_irq_locals_dict ); MP_REGISTER_ROOT_POINTER(mp_obj_t pin_irq_handler[16]); diff --git a/ports/esp8266/machine_rtc.c b/ports/esp8266/machine_rtc.c index 4235b325ef..cc6b79a031 100644 --- a/ports/esp8266/machine_rtc.c +++ b/ports/esp8266/machine_rtc.c @@ -267,5 +267,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_RTC, MP_TYPE_FLAG_NONE, pyb_rtc_make_new, - locals_dict, (mp_obj_dict_t *)&pyb_rtc_locals_dict + locals_dict, &pyb_rtc_locals_dict ); diff --git a/ports/esp8266/machine_uart.c b/ports/esp8266/machine_uart.c index 82f5189388..c737f854c3 100644 --- a/ports/esp8266/machine_uart.c +++ b/ports/esp8266/machine_uart.c @@ -352,7 +352,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p, - locals_dict, (mp_obj_dict_t *)&pyb_uart_locals_dict + locals_dict, &pyb_uart_locals_dict ); MP_REGISTER_ROOT_POINTER(byte * uart0_rxbuf); diff --git a/ports/esp8266/machine_wdt.c b/ports/esp8266/machine_wdt.c index d8c32ddd1a..26d5c9fa76 100644 --- a/ports/esp8266/machine_wdt.c +++ b/ports/esp8266/machine_wdt.c @@ -74,5 +74,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_WDT, MP_TYPE_FLAG_NONE, machine_wdt_make_new, - locals_dict, (mp_obj_dict_t *)&machine_wdt_locals_dict + locals_dict, &machine_wdt_locals_dict ); diff --git a/ports/esp8266/modmachine.c b/ports/esp8266/modmachine.c index 2bb2c7bd76..eb41e30f66 100644 --- a/ports/esp8266/modmachine.c +++ b/ports/esp8266/modmachine.c @@ -343,7 +343,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, esp_timer_make_new, print, esp_timer_print, - locals_dict, (mp_obj_dict_t *)&esp_timer_locals_dict + locals_dict, &esp_timer_locals_dict ); // this bit is unused in the Xtensa PS register diff --git a/ports/esp8266/modnetwork.c b/ports/esp8266/modnetwork.c index f78bf5da52..45a5a2be54 100644 --- a/ports/esp8266/modnetwork.c +++ b/ports/esp8266/modnetwork.c @@ -515,7 +515,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_WLAN, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, - locals_dict, (mp_obj_dict_t *)&wlan_if_locals_dict + locals_dict, &wlan_if_locals_dict ); STATIC mp_obj_t esp_phy_mode(size_t n_args, const mp_obj_t *args) { diff --git a/ports/mimxrt/machine_adc.c b/ports/mimxrt/machine_adc.c index cbac6b5734..7a19d1225e 100644 --- a/ports/mimxrt/machine_adc.c +++ b/ports/mimxrt/machine_adc.c @@ -123,7 +123,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, adc_obj_make_new, print, adc_obj_print, - locals_dict, (mp_obj_dict_t *)&adc_locals_dict + locals_dict, &adc_locals_dict ); void machine_adc_init(void) { diff --git a/ports/mimxrt/machine_i2c.c b/ports/mimxrt/machine_i2c.c index b8b6b7bc63..62dfd8204c 100644 --- a/ports/mimxrt/machine_i2c.c +++ b/ports/mimxrt/machine_i2c.c @@ -204,5 +204,5 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_i2c_make_new, print, machine_i2c_print, protocol, &machine_i2c_p, - locals_dict, (mp_obj_dict_t *)&mp_machine_i2c_locals_dict + locals_dict, &mp_machine_i2c_locals_dict ); diff --git a/ports/mimxrt/machine_i2s.c b/ports/mimxrt/machine_i2s.c index 68bf3a820f..13380b4ee6 100644 --- a/ports/mimxrt/machine_i2s.c +++ b/ports/mimxrt/machine_i2s.c @@ -1222,7 +1222,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &i2s_stream_p, - locals_dict, (mp_obj_dict_t *)&machine_i2s_locals_dict + locals_dict, &machine_i2s_locals_dict ); MP_REGISTER_ROOT_POINTER(struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM]); diff --git a/ports/mimxrt/machine_led.c b/ports/mimxrt/machine_led.c index d766c8f323..9fd98ef710 100644 --- a/ports/mimxrt/machine_led.c +++ b/ports/mimxrt/machine_led.c @@ -86,7 +86,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, led_obj_make_new, print, led_obj_print, - locals_dict, (mp_obj_dict_t *)&led_locals_dict + locals_dict, &led_locals_dict ); #endif diff --git a/ports/mimxrt/machine_pin.c b/ports/mimxrt/machine_pin.c index 7ec66d0eac..261e3e4148 100644 --- a/ports/mimxrt/machine_pin.c +++ b/ports/mimxrt/machine_pin.c @@ -63,7 +63,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_cpu, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, - locals_dict, (mp_obj_t)&machine_pin_cpu_pins_locals_dict + locals_dict, &machine_pin_cpu_pins_locals_dict ); MP_DEFINE_CONST_OBJ_TYPE( @@ -71,7 +71,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_board, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, - locals_dict, (mp_obj_t)&machine_pin_board_pins_locals_dict + locals_dict, &machine_pin_board_pins_locals_dict ); STATIC const mp_irq_methods_t machine_pin_irq_methods; @@ -428,7 +428,7 @@ MP_DEFINE_CONST_OBJ_TYPE( print, machine_pin_obj_print, call, machine_pin_obj_call, protocol, &machine_pin_obj_protocol, - locals_dict, (mp_obj_dict_t *)&machine_pin_locals_dict + locals_dict, &machine_pin_locals_dict ); // FIXME: Create actual pin_af type!!! @@ -438,7 +438,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, mp_pin_make_new, print, machine_pin_obj_print, - locals_dict, (mp_obj_dict_t *)&machine_pin_locals_dict + locals_dict, &machine_pin_locals_dict ); STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { diff --git a/ports/mimxrt/machine_rtc.c b/ports/mimxrt/machine_rtc.c index 5211027bdf..2e1a09dedb 100644 --- a/ports/mimxrt/machine_rtc.c +++ b/ports/mimxrt/machine_rtc.c @@ -171,5 +171,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_RTC, MP_TYPE_FLAG_NONE, machine_rtc_make_new, - locals_dict, (mp_obj_t)&machine_rtc_locals_dict + locals_dict, &machine_rtc_locals_dict ); diff --git a/ports/mimxrt/machine_sdcard.c b/ports/mimxrt/machine_sdcard.c index b7bdceef47..22f7e7c232 100644 --- a/ports/mimxrt/machine_sdcard.c +++ b/ports/mimxrt/machine_sdcard.c @@ -213,7 +213,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_SDCard, MP_TYPE_FLAG_NONE, sdcard_obj_make_new, - locals_dict, (mp_obj_dict_t *)&sdcard_locals_dict + locals_dict, &sdcard_locals_dict ); void machine_sdcard_init0(void) { diff --git a/ports/mimxrt/machine_spi.c b/ports/mimxrt/machine_spi.c index ff3cf4fb25..93b75e931e 100644 --- a/ports/mimxrt/machine_spi.c +++ b/ports/mimxrt/machine_spi.c @@ -258,5 +258,5 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_spi_make_new, print, machine_spi_print, protocol, &machine_spi_p, - locals_dict, (mp_obj_dict_t *)&mp_machine_spi_locals_dict + locals_dict, &mp_machine_spi_locals_dict ); diff --git a/ports/mimxrt/machine_timer.c b/ports/mimxrt/machine_timer.c index 9612388486..a6b61982f7 100644 --- a/ports/mimxrt/machine_timer.c +++ b/ports/mimxrt/machine_timer.c @@ -217,7 +217,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, machine_timer_make_new, print, machine_timer_print, - locals_dict, (mp_obj_dict_t *)&machine_timer_locals_dict + locals_dict, &machine_timer_locals_dict ); MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *timer_table[MICROPY_HW_PIT_NUM_CHANNELS]); diff --git a/ports/mimxrt/machine_uart.c b/ports/mimxrt/machine_uart.c index 4bb518eab2..9d4873274a 100644 --- a/ports/mimxrt/machine_uart.c +++ b/ports/mimxrt/machine_uart.c @@ -478,5 +478,5 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p, - locals_dict, (mp_obj_dict_t *)&machine_uart_locals_dict + locals_dict, &machine_uart_locals_dict ); diff --git a/ports/mimxrt/machine_wdt.c b/ports/mimxrt/machine_wdt.c index cde80f085b..e0b5c74b54 100644 --- a/ports/mimxrt/machine_wdt.c +++ b/ports/mimxrt/machine_wdt.c @@ -104,5 +104,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_WDT, MP_TYPE_FLAG_NONE, machine_wdt_make_new, - locals_dict, (mp_obj_dict_t *)&machine_wdt_locals_dict + locals_dict, &machine_wdt_locals_dict ); diff --git a/ports/mimxrt/mimxrt_flash.c b/ports/mimxrt/mimxrt_flash.c index 1a7d6cca8d..bd03c853d5 100644 --- a/ports/mimxrt/mimxrt_flash.c +++ b/ports/mimxrt/mimxrt_flash.c @@ -220,5 +220,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_Flash, MP_TYPE_FLAG_NONE, mimxrt_flash_make_new, - locals_dict, (mp_obj_dict_t *)&mimxrt_flash_locals_dict + locals_dict, &mimxrt_flash_locals_dict ); diff --git a/ports/mimxrt/network_lan.c b/ports/mimxrt/network_lan.c index 08c3c9e729..e15894294b 100644 --- a/ports/mimxrt/network_lan.c +++ b/ports/mimxrt/network_lan.c @@ -226,7 +226,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, network_lan_make_new, print, network_lan_print, - locals_dict, (mp_obj_dict_t *)&network_lan_locals_dict + locals_dict, &network_lan_locals_dict ); diff --git a/ports/nrf/boards/microbit/modules/microbitdisplay.c b/ports/nrf/boards/microbit/modules/microbitdisplay.c index 084cb09524..5cb25ea1ce 100644 --- a/ports/nrf/boards/microbit/modules/microbitdisplay.c +++ b/ports/nrf/boards/microbit/modules/microbitdisplay.c @@ -547,7 +547,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_MicroBitDisplay, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, - locals_dict, (mp_obj_dict_t*)µbit_display_locals_dict + locals_dict, µbit_display_locals_dict ); microbit_display_obj_t microbit_display_obj = { diff --git a/ports/nrf/boards/microbit/modules/microbitimage.c b/ports/nrf/boards/microbit/modules/microbitimage.c index 95b17bb6d3..4870b6738f 100644 --- a/ports/nrf/boards/microbit/modules/microbitimage.c +++ b/ports/nrf/boards/microbit/modules/microbitimage.c @@ -685,7 +685,7 @@ MP_DEFINE_CONST_OBJ_TYPE( microbit_image_make_new, print, microbit_image_print, binary_op, image_binary_op, - locals_dict, (mp_obj_dict_t*)µbit_image_locals_dict + locals_dict, µbit_image_locals_dict ); typedef struct _scrolling_string_t { diff --git a/ports/nrf/modules/board/led.c b/ports/nrf/modules/board/led.c index 5eef8f0464..577c2b6284 100644 --- a/ports/nrf/modules/board/led.c +++ b/ports/nrf/modules/board/led.c @@ -200,7 +200,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, led_obj_make_new, print, led_obj_print, - locals_dict, (mp_obj_dict_t*)&led_locals_dict + locals_dict, &led_locals_dict ); #else diff --git a/ports/nrf/modules/machine/adc.c b/ports/nrf/modules/machine/adc.c index 5814dcaa39..84db8d259f 100644 --- a/ports/nrf/modules/machine/adc.c +++ b/ports/nrf/modules/machine/adc.c @@ -299,7 +299,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_ADC, MP_TYPE_FLAG_NONE, machine_adc_make_new, - locals_dict, (mp_obj_dict_t*)&machine_adc_locals_dict, + locals_dict, &machine_adc_locals_dict, print, machine_adc_print ); diff --git a/ports/nrf/modules/machine/i2c.c b/ports/nrf/modules/machine/i2c.c index 8468684428..7cb55d0788 100644 --- a/ports/nrf/modules/machine/i2c.c +++ b/ports/nrf/modules/machine/i2c.c @@ -168,7 +168,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hard_i2c_make_new, print, machine_hard_i2c_print, protocol, &machine_hard_i2c_p, - locals_dict, (mp_obj_dict_t*)&mp_machine_i2c_locals_dict + locals_dict, &mp_machine_i2c_locals_dict ); #endif // MICROPY_PY_MACHINE_I2C diff --git a/ports/nrf/modules/machine/pin.c b/ports/nrf/modules/machine/pin.c index 835f6cf2bd..4f283e5dba 100644 --- a/ports/nrf/modules/machine/pin.c +++ b/ports/nrf/modules/machine/pin.c @@ -603,7 +603,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pin_make_new, print, pin_print, call, pin_call, - locals_dict, (mp_obj_dict_t*)&pin_locals_dict + locals_dict, &pin_locals_dict ); /// \moduleref machine @@ -678,7 +678,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, print, pin_af_obj_print, - locals_dict, (mp_obj_dict_t*)&pin_af_locals_dict + locals_dict, &pin_af_locals_dict ); MP_REGISTER_ROOT_POINTER(mp_obj_t pin_class_mapper); diff --git a/ports/nrf/modules/machine/pwm.c b/ports/nrf/modules/machine/pwm.c index d0ac0e9450..54e643ec55 100644 --- a/ports/nrf/modules/machine/pwm.c +++ b/ports/nrf/modules/machine/pwm.c @@ -345,7 +345,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, machine_pwm_make_new, print, machine_pwm_print, - locals_dict, (mp_obj_dict_t*)&machine_pwm_locals_dict + locals_dict, &machine_pwm_locals_dict ); #endif // MICROPY_PY_MACHINE_HW_PWM diff --git a/ports/nrf/modules/machine/rtcounter.c b/ports/nrf/modules/machine/rtcounter.c index 3c48c4bb1f..cafe08b6c6 100644 --- a/ports/nrf/modules/machine/rtcounter.c +++ b/ports/nrf/modules/machine/rtcounter.c @@ -268,7 +268,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, machine_rtc_make_new, print, rtc_print, - locals_dict, (mp_obj_dict_t*)&machine_rtc_locals_dict + locals_dict, &machine_rtc_locals_dict ); #endif // MICROPY_PY_MACHINE_RTCOUNTER diff --git a/ports/nrf/modules/machine/spi.c b/ports/nrf/modules/machine/spi.c index 22b0ff56e5..d5613a4643 100644 --- a/ports/nrf/modules/machine/spi.c +++ b/ports/nrf/modules/machine/spi.c @@ -434,7 +434,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_spi_make_new, print, machine_hard_spi_print, protocol, &machine_hard_spi_p, - locals_dict, (mp_obj_dict_t*)&machine_spi_locals_dict + locals_dict, &machine_spi_locals_dict ); #endif // MICROPY_PY_MACHINE_HW_SPI diff --git a/ports/nrf/modules/machine/temp.c b/ports/nrf/modules/machine/temp.c index 1e21f11253..00d6329b64 100644 --- a/ports/nrf/modules/machine/temp.c +++ b/ports/nrf/modules/machine/temp.c @@ -117,7 +117,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_Temp, MP_TYPE_FLAG_NONE, machine_temp_make_new, - locals_dict, (mp_obj_dict_t*)&machine_temp_locals_dict, + locals_dict, &machine_temp_locals_dict, print, machine_temp_print ); diff --git a/ports/nrf/modules/machine/timer.c b/ports/nrf/modules/machine/timer.c index 3724881aa8..f7f6101726 100644 --- a/ports/nrf/modules/machine/timer.c +++ b/ports/nrf/modules/machine/timer.c @@ -240,7 +240,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, machine_timer_make_new, print, timer_print, - locals_dict, (mp_obj_dict_t*)&machine_timer_locals_dict + locals_dict, &machine_timer_locals_dict ); #endif // MICROPY_PY_MACHINE_TIMER diff --git a/ports/nrf/modules/machine/uart.c b/ports/nrf/modules/machine/uart.c index 5c9ba83ab6..fc0bd682b4 100644 --- a/ports/nrf/modules/machine/uart.c +++ b/ports/nrf/modules/machine/uart.c @@ -379,7 +379,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p, - locals_dict, (mp_obj_dict_t*)&machine_hard_uart_locals_dict + locals_dict, &machine_hard_uart_locals_dict ); #endif // MICROPY_PY_MACHINE_UART diff --git a/ports/nrf/modules/nrf/flashbdev.c b/ports/nrf/modules/nrf/flashbdev.c index b67e86d0d0..84a3dd2520 100644 --- a/ports/nrf/modules/nrf/flashbdev.c +++ b/ports/nrf/modules/nrf/flashbdev.c @@ -189,7 +189,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, nrf_flashbdev_make_new, print, nrf_flashbdev_print, - locals_dict, (mp_obj_dict_t *)&nrf_flashbdev_locals_dict + locals_dict, &nrf_flashbdev_locals_dict ); void flashbdev_init(void) { diff --git a/ports/nrf/modules/ubluepy/ubluepy_characteristic.c b/ports/nrf/modules/ubluepy/ubluepy_characteristic.c index 5544ac6aef..2be7dab9d3 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_characteristic.c +++ b/ports/nrf/modules/ubluepy/ubluepy_characteristic.c @@ -215,7 +215,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, ubluepy_characteristic_make_new, print, ubluepy_characteristic_print, - locals_dict, (mp_obj_dict_t*)&ubluepy_characteristic_locals_dict + locals_dict, &ubluepy_characteristic_locals_dict ); #endif // MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL diff --git a/ports/nrf/modules/ubluepy/ubluepy_constants.c b/ports/nrf/modules/ubluepy/ubluepy_constants.c index e4637c8cbc..c6c3999245 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_constants.c +++ b/ports/nrf/modules/ubluepy/ubluepy_constants.c @@ -74,7 +74,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_ad_types, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, - locals_dict, (mp_obj_dict_t*)&ubluepy_constants_ad_types_locals_dict + locals_dict, &ubluepy_constants_ad_types_locals_dict ); STATIC const mp_rom_map_elem_t ubluepy_constants_locals_dict_table[] = { @@ -97,7 +97,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_constants, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, - locals_dict, (mp_obj_dict_t*)&ubluepy_constants_locals_dict + locals_dict, &ubluepy_constants_locals_dict ); #endif // MICROPY_PY_UBLUEPY diff --git a/ports/nrf/modules/ubluepy/ubluepy_delegate.c b/ports/nrf/modules/ubluepy/ubluepy_delegate.c index 71648767e6..dd19f70be4 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_delegate.c +++ b/ports/nrf/modules/ubluepy/ubluepy_delegate.c @@ -83,7 +83,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, ubluepy_delegate_make_new, print, ubluepy_delegate_print, - locals_dict, (mp_obj_dict_t*)&ubluepy_delegate_locals_dict + locals_dict, &ubluepy_delegate_locals_dict ); #endif // MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL diff --git a/ports/nrf/modules/ubluepy/ubluepy_descriptor.c b/ports/nrf/modules/ubluepy/ubluepy_descriptor.c index 07035460ae..d942d98223 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_descriptor.c +++ b/ports/nrf/modules/ubluepy/ubluepy_descriptor.c @@ -76,7 +76,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, ubluepy_descriptor_make_new, print, ubluepy_descriptor_print, - locals_dict, (mp_obj_dict_t*)&ubluepy_descriptor_locals_dict + locals_dict, &ubluepy_descriptor_locals_dict ); #endif // MICROPY_PY_UBLUEPY diff --git a/ports/nrf/modules/ubluepy/ubluepy_peripheral.c b/ports/nrf/modules/ubluepy/ubluepy_peripheral.c index 9c346a885b..9f638b45d7 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_peripheral.c +++ b/ports/nrf/modules/ubluepy/ubluepy_peripheral.c @@ -488,7 +488,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, ubluepy_peripheral_make_new, print, ubluepy_peripheral_print, - locals_dict, (mp_obj_dict_t*)&ubluepy_peripheral_locals_dict + locals_dict, &ubluepy_peripheral_locals_dict ); #endif // MICROPY_PY_UBLUEPY diff --git a/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c b/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c index 64a81d215d..5c74e2e92c 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c +++ b/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c @@ -142,7 +142,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, print, ubluepy_scan_entry_print, - locals_dict, (mp_obj_dict_t*)&ubluepy_scan_entry_locals_dict + locals_dict, &ubluepy_scan_entry_locals_dict ); #endif // MICROPY_PY_UBLUEPY_CENTRAL diff --git a/ports/nrf/modules/ubluepy/ubluepy_scanner.c b/ports/nrf/modules/ubluepy/ubluepy_scanner.c index c47044cf0c..b56ec349d0 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_scanner.c +++ b/ports/nrf/modules/ubluepy/ubluepy_scanner.c @@ -120,7 +120,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, ubluepy_scanner_make_new, print, ubluepy_scanner_print, - locals_dict, (mp_obj_dict_t*)&ubluepy_scanner_locals_dict + locals_dict, &ubluepy_scanner_locals_dict ); #endif // MICROPY_PY_UBLUEPY_CENTRAL diff --git a/ports/nrf/modules/ubluepy/ubluepy_service.c b/ports/nrf/modules/ubluepy/ubluepy_service.c index 9d0d6e5b95..2bec6befd6 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_service.c +++ b/ports/nrf/modules/ubluepy/ubluepy_service.c @@ -177,7 +177,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, ubluepy_service_make_new, print, ubluepy_service_print, - locals_dict, (mp_obj_dict_t*)&ubluepy_service_locals_dict + locals_dict, &ubluepy_service_locals_dict ); #endif // MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL diff --git a/ports/nrf/modules/ubluepy/ubluepy_uuid.c b/ports/nrf/modules/ubluepy/ubluepy_uuid.c index 0414a2a286..0fd6e75e5b 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_uuid.c +++ b/ports/nrf/modules/ubluepy/ubluepy_uuid.c @@ -166,7 +166,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, ubluepy_uuid_make_new, print, ubluepy_uuid_print, - locals_dict, (mp_obj_dict_t*)&ubluepy_uuid_locals_dict + locals_dict, &ubluepy_uuid_locals_dict ); #endif // MICROPY_PY_UBLUEPY diff --git a/ports/nrf/modules/uos/microbitfs.c b/ports/nrf/modules/uos/microbitfs.c index 63ac8c9321..d1b3201116 100644 --- a/ports/nrf/modules/uos/microbitfs.c +++ b/ports/nrf/modules/uos/microbitfs.c @@ -632,7 +632,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, protocol, &textio_stream_p, - locals_dict, (mp_obj_dict_t*)&uos_mbfs_file_locals_dict + locals_dict, &uos_mbfs_file_locals_dict ); @@ -647,7 +647,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, protocol, &fileio_stream_p, - locals_dict, (mp_obj_dict_t*)&uos_mbfs_file_locals_dict + locals_dict, &uos_mbfs_file_locals_dict ); // From micro:bit fileobj.c diff --git a/ports/nrf/pin_named_pins.c b/ports/nrf/pin_named_pins.c index 87fed746e6..84ec89f44a 100644 --- a/ports/nrf/pin_named_pins.c +++ b/ports/nrf/pin_named_pins.c @@ -42,7 +42,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, print, pin_named_pins_obj_print, - locals_dict, (mp_obj_t)&pin_cpu_pins_locals_dict + locals_dict, &pin_cpu_pins_locals_dict ); MP_DEFINE_CONST_OBJ_TYPE( @@ -51,7 +51,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, print, pin_named_pins_obj_print, - locals_dict, (mp_obj_t)&pin_board_pins_locals_dict + locals_dict, &pin_board_pins_locals_dict ); const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) { diff --git a/ports/pic16bit/modpybled.c b/ports/pic16bit/modpybled.c index fd4e8cce9c..2e5c2dcca3 100644 --- a/ports/pic16bit/modpybled.c +++ b/ports/pic16bit/modpybled.c @@ -90,5 +90,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, pyb_led_make_new, print, pyb_led_print, - locals_dict, (mp_obj_t)&pyb_led_locals_dict + locals_dict, &pyb_led_locals_dict ); diff --git a/ports/pic16bit/modpybswitch.c b/ports/pic16bit/modpybswitch.c index e1096b1daa..f27cfb9b09 100644 --- a/ports/pic16bit/modpybswitch.c +++ b/ports/pic16bit/modpybswitch.c @@ -78,5 +78,5 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_switch_make_new, print, pyb_switch_print, call, pyb_switch_call, - locals_dict, (mp_obj_t)&pyb_switch_locals_dict + locals_dict, &pyb_switch_locals_dict ); diff --git a/ports/renesas-ra/machine_i2c.c b/ports/renesas-ra/machine_i2c.c index eaca5ff4a8..563ea8787e 100644 --- a/ports/renesas-ra/machine_i2c.c +++ b/ports/renesas-ra/machine_i2c.c @@ -161,7 +161,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_I2C, MP_TYPE_FLAG_NONE, machine_i2c_make_new, - locals_dict, (void *)&mp_machine_i2c_locals_dict, + locals_dict, &mp_machine_i2c_locals_dict, print, machine_i2c_print, protocol, &machine_i2c_p ); diff --git a/ports/rp2/machine_adc.c b/ports/rp2/machine_adc.c index 549f8d5ecd..85562d5c07 100644 --- a/ports/rp2/machine_adc.c +++ b/ports/rp2/machine_adc.c @@ -119,5 +119,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, machine_adc_make_new, print, machine_adc_print, - locals_dict, (mp_obj_dict_t *)&machine_adc_locals_dict + locals_dict, &machine_adc_locals_dict ); diff --git a/ports/rp2/machine_i2c.c b/ports/rp2/machine_i2c.c index 91d8bb59b7..5ab93f6358 100644 --- a/ports/rp2/machine_i2c.c +++ b/ports/rp2/machine_i2c.c @@ -183,5 +183,5 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_i2c_make_new, print, machine_i2c_print, protocol, &machine_i2c_p, - locals_dict, (mp_obj_dict_t *)&mp_machine_i2c_locals_dict + locals_dict, &mp_machine_i2c_locals_dict ); diff --git a/ports/rp2/machine_i2s.c b/ports/rp2/machine_i2s.c index 8446a59781..9d70a476f3 100644 --- a/ports/rp2/machine_i2s.c +++ b/ports/rp2/machine_i2s.c @@ -1146,7 +1146,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &i2s_stream_p, - locals_dict, (mp_obj_dict_t *)&machine_i2s_locals_dict + locals_dict, &machine_i2s_locals_dict ); MP_REGISTER_ROOT_POINTER(void *machine_i2s_obj[2]); diff --git a/ports/rp2/machine_pin.c b/ports/rp2/machine_pin.c index 38670f09ab..8ccfbca3ab 100644 --- a/ports/rp2/machine_pin.c +++ b/ports/rp2/machine_pin.c @@ -649,7 +649,7 @@ MP_DEFINE_CONST_OBJ_TYPE( print, machine_pin_print, call, machine_pin_call, protocol, &pin_pin_p, - locals_dict, (mp_obj_t)&machine_pin_locals_dict + locals_dict, &machine_pin_locals_dict ); STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { diff --git a/ports/rp2/machine_rtc.c b/ports/rp2/machine_rtc.c index 73bdaee6c7..6b2c9ac71b 100644 --- a/ports/rp2/machine_rtc.c +++ b/ports/rp2/machine_rtc.c @@ -120,5 +120,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_RTC, MP_TYPE_FLAG_NONE, machine_rtc_make_new, - locals_dict, (mp_obj_t)&machine_rtc_locals_dict + locals_dict, &machine_rtc_locals_dict ); diff --git a/ports/rp2/machine_spi.c b/ports/rp2/machine_spi.c index f3ac8d7cf8..08c79712cf 100644 --- a/ports/rp2/machine_spi.c +++ b/ports/rp2/machine_spi.c @@ -297,7 +297,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_spi_make_new, print, machine_spi_print, protocol, &machine_spi_p, - locals_dict, (mp_obj_dict_t *)&mp_machine_spi_locals_dict + locals_dict, &mp_machine_spi_locals_dict ); mp_obj_base_t *mp_hal_get_spi_obj(mp_obj_t o) { diff --git a/ports/rp2/machine_timer.c b/ports/rp2/machine_timer.c index d3b6015529..66f632329c 100644 --- a/ports/rp2/machine_timer.c +++ b/ports/rp2/machine_timer.c @@ -162,5 +162,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, machine_timer_make_new, print, machine_timer_print, - locals_dict, (mp_obj_dict_t *)&machine_timer_locals_dict + locals_dict, &machine_timer_locals_dict ); diff --git a/ports/rp2/machine_uart.c b/ports/rp2/machine_uart.c index df6228058b..bb8bf51be6 100644 --- a/ports/rp2/machine_uart.c +++ b/ports/rp2/machine_uart.c @@ -588,7 +588,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p, - locals_dict, (mp_obj_dict_t *)&machine_uart_locals_dict + locals_dict, &machine_uart_locals_dict ); MP_REGISTER_ROOT_POINTER(void *rp2_uart_rx_buffer[2]); diff --git a/ports/rp2/machine_wdt.c b/ports/rp2/machine_wdt.c index e8c4333069..c224298d13 100644 --- a/ports/rp2/machine_wdt.c +++ b/ports/rp2/machine_wdt.c @@ -82,5 +82,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_WDT, MP_TYPE_FLAG_NONE, machine_wdt_make_new, - locals_dict, (mp_obj_dict_t *)&machine_wdt_locals_dict + locals_dict, &machine_wdt_locals_dict ); diff --git a/ports/rp2/rp2_flash.c b/ports/rp2/rp2_flash.c index 37a3412db5..df49c881c4 100644 --- a/ports/rp2/rp2_flash.c +++ b/ports/rp2/rp2_flash.c @@ -190,5 +190,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_Flash, MP_TYPE_FLAG_NONE, rp2_flash_make_new, - locals_dict, (mp_obj_dict_t *)&rp2_flash_locals_dict + locals_dict, &rp2_flash_locals_dict ); diff --git a/ports/rp2/rp2_pio.c b/ports/rp2/rp2_pio.c index 9a195bdd8a..cfba9cce5a 100644 --- a/ports/rp2/rp2_pio.c +++ b/ports/rp2/rp2_pio.c @@ -382,7 +382,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, rp2_pio_make_new, print, rp2_pio_print, - locals_dict, (mp_obj_dict_t *)&rp2_pio_locals_dict + locals_dict, &rp2_pio_locals_dict ); STATIC mp_uint_t rp2_pio_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { @@ -813,7 +813,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, rp2_state_machine_make_new, print, rp2_state_machine_print, - locals_dict, (mp_obj_dict_t *)&rp2_state_machine_locals_dict + locals_dict, &rp2_state_machine_locals_dict ); STATIC mp_uint_t rp2_state_machine_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { diff --git a/ports/samd/machine_led.c b/ports/samd/machine_led.c index 76aae8ffc5..7a9b2299ae 100644 --- a/ports/samd/machine_led.c +++ b/ports/samd/machine_led.c @@ -169,5 +169,5 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_led_make_new, print, machine_led_print, call, machine_led_call, - locals_dict, (mp_obj_t)&machine_led_locals_dict + locals_dict, &machine_led_locals_dict ); diff --git a/ports/samd/machine_pin.c b/ports/samd/machine_pin.c index d47982e0e1..75e1a2356c 100644 --- a/ports/samd/machine_pin.c +++ b/ports/samd/machine_pin.c @@ -295,7 +295,7 @@ MP_DEFINE_CONST_OBJ_TYPE( print, machine_pin_print, call, machine_pin_call, protocol, &pin_pin_p, - locals_dict, (mp_obj_t)&machine_pin_locals_dict + locals_dict, &machine_pin_locals_dict ); /* diff --git a/ports/samd/samd_flash.c b/ports/samd/samd_flash.c index 6c74b59a26..9d64768cfa 100644 --- a/ports/samd/samd_flash.c +++ b/ports/samd/samd_flash.c @@ -186,5 +186,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_Flash, MP_TYPE_FLAG_NONE, samd_flash_make_new, - locals_dict, (mp_obj_dict_t *)&samd_flash_locals_dict + locals_dict, &samd_flash_locals_dict ); diff --git a/ports/stm32/accel.c b/ports/stm32/accel.c index 276ce37d3a..05fd1898bc 100644 --- a/ports/stm32/accel.c +++ b/ports/stm32/accel.c @@ -286,7 +286,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_Accel, MP_TYPE_FLAG_NONE, pyb_accel_make_new, - locals_dict, (mp_obj_dict_t *)&pyb_accel_locals_dict + locals_dict, &pyb_accel_locals_dict ); #endif // MICROPY_HW_HAS_MMA7660 || MICROPY_HW_HAS_KXTJ3 diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index 7e627d088f..e0759439d1 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -709,7 +709,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, adc_make_new, print, adc_print, - locals_dict, (mp_obj_dict_t *)&adc_locals_dict + locals_dict, &adc_locals_dict ); /******************************************************************************/ @@ -917,7 +917,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_ADCAll, MP_TYPE_FLAG_NONE, adc_all_make_new, - locals_dict, (mp_obj_dict_t *)&adc_all_locals_dict + locals_dict, &adc_all_locals_dict ); #endif // MICROPY_HW_ENABLE_ADC diff --git a/ports/stm32/dac.c b/ports/stm32/dac.c index da50b30fef..ac8d76090e 100644 --- a/ports/stm32/dac.c +++ b/ports/stm32/dac.c @@ -508,7 +508,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, pyb_dac_make_new, print, pyb_dac_print, - locals_dict, (mp_obj_dict_t *)&pyb_dac_locals_dict + locals_dict, &pyb_dac_locals_dict ); #endif // MICROPY_HW_ENABLE_DAC diff --git a/ports/stm32/extint.c b/ports/stm32/extint.c index 4d2dc5d23b..0f28610cc3 100644 --- a/ports/stm32/extint.c +++ b/ports/stm32/extint.c @@ -665,7 +665,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, extint_make_new, print, extint_obj_print, - locals_dict, (mp_obj_dict_t *)&extint_locals_dict + locals_dict, &extint_locals_dict ); void extint_init0(void) { diff --git a/ports/stm32/lcd.c b/ports/stm32/lcd.c index a951ea7668..5017a68fe5 100644 --- a/ports/stm32/lcd.c +++ b/ports/stm32/lcd.c @@ -530,7 +530,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_LCD, MP_TYPE_FLAG_NONE, pyb_lcd_make_new, - locals_dict, (mp_obj_dict_t *)&pyb_lcd_locals_dict + locals_dict, &pyb_lcd_locals_dict ); #endif // MICROPY_HW_HAS_LCD diff --git a/ports/stm32/led.c b/ports/stm32/led.c index 6745ef60b8..6e3229ab32 100644 --- a/ports/stm32/led.c +++ b/ports/stm32/led.c @@ -387,7 +387,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, led_obj_make_new, print, led_obj_print, - locals_dict, (mp_obj_dict_t *)&led_locals_dict + locals_dict, &led_locals_dict ); #else diff --git a/ports/stm32/machine_adc.c b/ports/stm32/machine_adc.c index 682bae3a6d..3659073d06 100644 --- a/ports/stm32/machine_adc.c +++ b/ports/stm32/machine_adc.c @@ -498,7 +498,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, machine_adc_make_new, print, machine_adc_print, - locals_dict, (mp_obj_dict_t *)&machine_adc_locals_dict + locals_dict, &machine_adc_locals_dict ); #endif diff --git a/ports/stm32/machine_i2c.c b/ports/stm32/machine_i2c.c index 89970f234d..7927daac1b 100644 --- a/ports/stm32/machine_i2c.c +++ b/ports/stm32/machine_i2c.c @@ -243,7 +243,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hard_i2c_make_new, print, machine_hard_i2c_print, protocol, &machine_hard_i2c_p, - locals_dict, (mp_obj_dict_t *)&mp_machine_i2c_locals_dict + locals_dict, &mp_machine_i2c_locals_dict ); #endif // MICROPY_HW_ENABLE_HW_I2C diff --git a/ports/stm32/machine_i2s.c b/ports/stm32/machine_i2s.c index 7dc6439f25..93a465d07c 100644 --- a/ports/stm32/machine_i2s.c +++ b/ports/stm32/machine_i2s.c @@ -1123,7 +1123,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &i2s_stream_p, - locals_dict, (mp_obj_dict_t *)&machine_i2s_locals_dict + locals_dict, &machine_i2s_locals_dict ); MP_REGISTER_ROOT_POINTER(struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_MAX_I2S]); diff --git a/ports/stm32/machine_spi.c b/ports/stm32/machine_spi.c index 87561c2b7b..d64ff2af8f 100644 --- a/ports/stm32/machine_spi.c +++ b/ports/stm32/machine_spi.c @@ -142,5 +142,5 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hard_spi_make_new, print, machine_hard_spi_print, protocol, &machine_hard_spi_p, - locals_dict, (mp_obj_dict_t *)&mp_machine_spi_locals_dict + locals_dict, &mp_machine_spi_locals_dict ); diff --git a/ports/stm32/machine_timer.c b/ports/stm32/machine_timer.c index bd9dbe6098..2e0120ea81 100644 --- a/ports/stm32/machine_timer.c +++ b/ports/stm32/machine_timer.c @@ -142,5 +142,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, machine_timer_make_new, print, machine_timer_print, - locals_dict, (mp_obj_dict_t *)&machine_timer_locals_dict + locals_dict, &machine_timer_locals_dict ); diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index 4d25a0274c..5851d8cf35 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -669,5 +669,5 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p, - locals_dict, (mp_obj_dict_t *)&pyb_uart_locals_dict + locals_dict, &pyb_uart_locals_dict ); diff --git a/ports/stm32/network_lan.c b/ports/stm32/network_lan.c index f9c7d80b78..25a9555088 100644 --- a/ports/stm32/network_lan.c +++ b/ports/stm32/network_lan.c @@ -164,7 +164,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, network_lan_make_new, print, network_lan_print, - locals_dict, (mp_obj_dict_t *)&network_lan_locals_dict + locals_dict, &network_lan_locals_dict ); #endif // defined(MICROPY_HW_ETH_MDC) diff --git a/ports/stm32/pin.c b/ports/stm32/pin.c index 992046cd17..3c3cde0265 100644 --- a/ports/stm32/pin.c +++ b/ports/stm32/pin.c @@ -600,7 +600,7 @@ MP_DEFINE_CONST_OBJ_TYPE( print, pin_print, call, pin_call, protocol, &pin_pin_p, - locals_dict, (mp_obj_dict_t *)&pin_locals_dict + locals_dict, &pin_locals_dict ); /// \moduleref pyb @@ -676,7 +676,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, print, pin_af_obj_print, - locals_dict, (mp_obj_dict_t *)&pin_af_locals_dict + locals_dict, &pin_af_locals_dict ); MP_REGISTER_ROOT_POINTER(mp_obj_t pin_class_mapper); diff --git a/ports/stm32/pin_named_pins.c b/ports/stm32/pin_named_pins.c index 620888878c..1a35ec5787 100644 --- a/ports/stm32/pin_named_pins.c +++ b/ports/stm32/pin_named_pins.c @@ -36,7 +36,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_cpu, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, - locals_dict, (mp_obj_dict_t *)&pin_cpu_pins_locals_dict + locals_dict, &pin_cpu_pins_locals_dict ); MP_DEFINE_CONST_OBJ_TYPE( @@ -44,7 +44,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_board, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, - locals_dict, (mp_obj_dict_t *)&pin_board_pins_locals_dict + locals_dict, &pin_board_pins_locals_dict ); const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) { diff --git a/ports/stm32/pyb_can.c b/ports/stm32/pyb_can.c index 6fdfd2c854..a07fc92164 100644 --- a/ports/stm32/pyb_can.c +++ b/ports/stm32/pyb_can.c @@ -1079,7 +1079,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_can_make_new, print, pyb_can_print, protocol, &can_stream_p, - locals_dict, (mp_obj_dict_t *)&pyb_can_locals_dict + locals_dict, &pyb_can_locals_dict ); MP_REGISTER_ROOT_POINTER(struct _pyb_can_obj_t *pyb_can_obj_all[MICROPY_HW_MAX_CAN]); diff --git a/ports/stm32/pyb_i2c.c b/ports/stm32/pyb_i2c.c index ee6983a143..9071d92944 100644 --- a/ports/stm32/pyb_i2c.c +++ b/ports/stm32/pyb_i2c.c @@ -1110,7 +1110,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, pyb_i2c_make_new, print, pyb_i2c_print, - locals_dict, (mp_obj_dict_t *)&pyb_i2c_locals_dict + locals_dict, &pyb_i2c_locals_dict ); #endif // MICROPY_PY_PYB_LEGACY && MICROPY_HW_ENABLE_HW_I2C diff --git a/ports/stm32/pyb_spi.c b/ports/stm32/pyb_spi.c index b1425272fe..a225bd84e7 100644 --- a/ports/stm32/pyb_spi.c +++ b/ports/stm32/pyb_spi.c @@ -357,5 +357,5 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_spi_make_new, print, pyb_spi_print, protocol, &pyb_spi_p, - locals_dict, (mp_obj_dict_t *)&pyb_spi_locals_dict + locals_dict, &pyb_spi_locals_dict ); diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index c7698db143..f501ec23b1 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -842,5 +842,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_RTC, MP_TYPE_FLAG_NONE, pyb_rtc_make_new, - locals_dict, (mp_obj_dict_t *)&pyb_rtc_locals_dict + locals_dict, &pyb_rtc_locals_dict ); diff --git a/ports/stm32/sdcard.c b/ports/stm32/sdcard.c index b9cc051e7f..cbf1ade5c5 100644 --- a/ports/stm32/sdcard.c +++ b/ports/stm32/sdcard.c @@ -877,7 +877,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_SDCard, MP_TYPE_FLAG_NONE, pyb_sdcard_make_new, - locals_dict, (mp_obj_dict_t *)&pyb_sdcard_locals_dict + locals_dict, &pyb_sdcard_locals_dict ); #endif @@ -887,7 +887,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_MMCard, MP_TYPE_FLAG_NONE, pyb_mmcard_make_new, - locals_dict, (mp_obj_dict_t *)&pyb_sdcard_locals_dict + locals_dict, &pyb_sdcard_locals_dict ); #endif diff --git a/ports/stm32/servo.c b/ports/stm32/servo.c index d552f5e6b5..1b0ca0a882 100644 --- a/ports/stm32/servo.c +++ b/ports/stm32/servo.c @@ -342,7 +342,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, pyb_servo_make_new, print, pyb_servo_print, - locals_dict, (mp_obj_dict_t *)&pyb_servo_locals_dict + locals_dict, &pyb_servo_locals_dict ); #endif // MICROPY_HW_ENABLE_SERVO diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c index 92f7059493..a0154408dd 100644 --- a/ports/stm32/storage.c +++ b/ports/stm32/storage.c @@ -459,7 +459,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, pyb_flash_make_new, print, pyb_flash_print, - locals_dict, (mp_obj_dict_t *)&pyb_flash_locals_dict + locals_dict, &pyb_flash_locals_dict ); void pyb_flash_init_vfs(fs_user_mount_t *vfs) { diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index abf4c1f3fc..91c88df1b3 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -1477,7 +1477,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, pyb_timer_make_new, print, pyb_timer_print, - locals_dict, (mp_obj_dict_t *)&pyb_timer_locals_dict + locals_dict, &pyb_timer_locals_dict ); /// \moduleref pyb @@ -1617,7 +1617,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, print, pyb_timer_channel_print, - locals_dict, (mp_obj_dict_t *)&pyb_timer_channel_locals_dict + locals_dict, &pyb_timer_channel_locals_dict ); STATIC void timer_handle_irq_channel(pyb_timer_obj_t *tim, uint8_t channel, mp_obj_t callback) { diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 7c36765c28..df755fe984 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -945,7 +945,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &pyb_usb_vcp_stream_p, - locals_dict, (mp_obj_dict_t *)&pyb_usb_vcp_locals_dict + locals_dict, &pyb_usb_vcp_locals_dict ); /******************************************************************************/ @@ -1084,7 +1084,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, pyb_usb_hid_make_new, protocol, &pyb_usb_hid_stream_p, - locals_dict, (mp_obj_dict_t *)&pyb_usb_hid_locals_dict + locals_dict, &pyb_usb_hid_locals_dict ); #endif // MICROPY_HW_USB_HID diff --git a/ports/stm32/usrsw.c b/ports/stm32/usrsw.c index 137f4dabfa..7d406c0ecd 100644 --- a/ports/stm32/usrsw.c +++ b/ports/stm32/usrsw.c @@ -141,7 +141,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_switch_make_new, print, pyb_switch_print, call, pyb_switch_call, - locals_dict, (mp_obj_dict_t *)&pyb_switch_locals_dict + locals_dict, &pyb_switch_locals_dict ); MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_switch_callback); diff --git a/ports/stm32/wdt.c b/ports/stm32/wdt.c index e3b8e2e0ae..09780ea9d3 100644 --- a/ports/stm32/wdt.c +++ b/ports/stm32/wdt.c @@ -107,5 +107,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_WDT, MP_TYPE_FLAG_NONE, pyb_wdt_make_new, - locals_dict, (mp_obj_dict_t *)&pyb_wdt_locals_dict + locals_dict, &pyb_wdt_locals_dict ); diff --git a/ports/teensy/led.c b/ports/teensy/led.c index ca548431fe..dd4c65da39 100644 --- a/ports/teensy/led.c +++ b/ports/teensy/led.c @@ -140,5 +140,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, led_obj_make_new, print, led_obj_print, - locals_dict, (mp_obj_t)&led_locals_dict + locals_dict, &led_locals_dict ); diff --git a/ports/teensy/timer.c b/ports/teensy/timer.c index 4df2474335..a0f490d925 100644 --- a/ports/teensy/timer.c +++ b/ports/teensy/timer.c @@ -752,7 +752,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, pyb_timer_make_new, print, pyb_timer_print, - locals_dict, (mp_obj_t)&pyb_timer_locals_dict + locals_dict, &pyb_timer_locals_dict ); /// \moduleref pyb @@ -896,7 +896,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, print, pyb_timer_channel_print, - locals_dict, (mp_obj_t)&pyb_timer_channel_locals_dict + locals_dict, &pyb_timer_channel_locals_dict ); STATIC bool ftm_handle_irq_callback(pyb_timer_obj_t *self, mp_uint_t channel, mp_obj_t callback) { diff --git a/ports/teensy/uart.c b/ports/teensy/uart.c index 8957d92709..db5b8e2f44 100644 --- a/ports/teensy/uart.c +++ b/ports/teensy/uart.c @@ -489,5 +489,5 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, pyb_uart_make_new, print, pyb_uart_print, - locals_dict, (mp_obj_t)&pyb_uart_locals_dict + locals_dict, &pyb_uart_locals_dict ); diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index b4567417a2..7b4c0c0bf4 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -112,7 +112,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, protocol, &fileio_stream_p, - locals_dict, (mp_obj_dict_t *)&rawfile_locals_dict + locals_dict, &rawfile_locals_dict ); // stream read returns non-blocking error @@ -142,7 +142,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, protocol, &textio_stream_p2, - locals_dict, (mp_obj_dict_t *)&rawfile_locals_dict2 + locals_dict, &rawfile_locals_dict2 ); // str/bytes objects without a valid hash diff --git a/ports/unix/modffi.c b/ports/unix/modffi.c index 98f0a1aa0f..98fd8936b1 100644 --- a/ports/unix/modffi.c +++ b/ports/unix/modffi.c @@ -427,7 +427,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, ffimod_make_new, print, ffimod_print, - locals_dict, (mp_obj_dict_t *)&ffimod_locals_dict + locals_dict, &ffimod_locals_dict ); // FFI function @@ -565,7 +565,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, print, fficallback_print, - locals_dict, (mp_obj_dict_t *)&fficallback_locals_dict + locals_dict, &fficallback_locals_dict ); // FFI variable @@ -603,7 +603,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, print, ffivar_print, - locals_dict, (mp_obj_dict_t *)&ffivar_locals_dict + locals_dict, &ffivar_locals_dict ); // Generic opaque storage object (unused) diff --git a/ports/unix/modjni.c b/ports/unix/modjni.c index 72f95b645b..02368e4537 100644 --- a/ports/unix/modjni.c +++ b/ports/unix/modjni.c @@ -182,7 +182,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( print, jclass_print, attr, jclass_attr, call, jclass_call, - locals_dict, (mp_obj_dict_t *)&jclass_locals_dict + locals_dict, &jclass_locals_dict ); STATIC mp_obj_t new_jclass(jclass jc) { @@ -332,7 +332,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( attr, jobject_attr, subscr, jobject_subscr, getiter, subscr_getiter, - // .locals_dict = (mp_obj_dict_t*)&jobject_locals_dict, + // .locals_dict = &jobject_locals_dict, ); STATIC mp_obj_t new_jobject(jobject jo) { @@ -579,7 +579,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( print, jmethod_print, call, jmethod_call, // .attr = jobject_attr, - // .locals_dict = (mp_obj_dict_t*)&jobject_locals_dict, + // .locals_dict = &jobject_locals_dict, ); #ifdef __ANDROID__ diff --git a/ports/unix/moduselect.c b/ports/unix/moduselect.c index d8a8d1d8c3..baed88761c 100644 --- a/ports/unix/moduselect.c +++ b/ports/unix/moduselect.c @@ -318,7 +318,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_NULL_MAKE_NEW, getiter, mp_identity_getiter, iternext, poll_iternext, - locals_dict, (void *)&poll_locals_dict + locals_dict, &poll_locals_dict ); STATIC mp_obj_t select_poll(size_t n_args, const mp_obj_t *args) { diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c index 7e4476cbd0..21260f0b2a 100644 --- a/ports/unix/modusocket.c +++ b/ports/unix/modusocket.c @@ -525,7 +525,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, NULL, iternext, NULL, protocol, &usocket_stream_p, - locals_dict, (mp_obj_dict_t *)&usocket_locals_dict + locals_dict, &usocket_locals_dict ); #define BINADDR_MAX_LEN sizeof(struct in6_addr) diff --git a/ports/zephyr/machine_i2c.c b/ports/zephyr/machine_i2c.c index 60a1924d80..a844eceb50 100644 --- a/ports/zephyr/machine_i2c.c +++ b/ports/zephyr/machine_i2c.c @@ -133,7 +133,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hard_i2c_make_new, print, machine_hard_i2c_print, protocol, &machine_hard_i2c_p, - locals_dict, (mp_obj_dict_t *)&mp_machine_i2c_locals_dict + locals_dict, &mp_machine_i2c_locals_dict ); #endif // MICROPY_PY_MACHINE_I2C diff --git a/ports/zephyr/machine_pin.c b/ports/zephyr/machine_pin.c index 48303edd81..3114ac36fd 100644 --- a/ports/zephyr/machine_pin.c +++ b/ports/zephyr/machine_pin.c @@ -293,7 +293,7 @@ MP_DEFINE_CONST_OBJ_TYPE( print, machine_pin_print, call, machine_pin_call, protocol, &machine_pin_pin_p, - locals_dict, (mp_obj_t)&machine_pin_locals_dict + locals_dict, &machine_pin_locals_dict ); STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { diff --git a/ports/zephyr/machine_spi.c b/ports/zephyr/machine_spi.c index 6d9bf896b0..d990ed9c15 100644 --- a/ports/zephyr/machine_spi.c +++ b/ports/zephyr/machine_spi.c @@ -204,7 +204,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hard_spi_make_new, print, machine_hard_spi_print, protocol, &machine_hard_spi_p, - locals_dict, (mp_obj_dict_t *)&mp_machine_spi_locals_dict + locals_dict, &mp_machine_spi_locals_dict ); #endif // MICROPY_PY_MACHINE_SPI diff --git a/ports/zephyr/machine_uart.c b/ports/zephyr/machine_uart.c index 3f5df74657..9580d37907 100644 --- a/ports/zephyr/machine_uart.c +++ b/ports/zephyr/machine_uart.c @@ -163,5 +163,5 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p, - locals_dict, (mp_obj_dict_t *)&machine_uart_locals_dict + locals_dict, &machine_uart_locals_dict ); diff --git a/ports/zephyr/modusocket.c b/ports/zephyr/modusocket.c index a7bef74ca6..77f839fdd5 100644 --- a/ports/zephyr/modusocket.c +++ b/ports/zephyr/modusocket.c @@ -360,7 +360,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( socket_make_new, print, socket_print, protocol, &socket_stream_p, - locals_dict, (mp_obj_t)&socket_locals_dict + locals_dict, &socket_locals_dict ); // diff --git a/ports/zephyr/modzsensor.c b/ports/zephyr/modzsensor.c index 7c0b0193d3..beb4d6ad79 100644 --- a/ports/zephyr/modzsensor.c +++ b/ports/zephyr/modzsensor.c @@ -110,7 +110,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_Sensor, MP_TYPE_FLAG_NONE, sensor_make_new, - locals_dict, (void *)&sensor_locals_dict + locals_dict, &sensor_locals_dict ); STATIC const mp_rom_map_elem_t mp_module_zsensor_globals_table[] = { diff --git a/ports/zephyr/zephyr_storage.c b/ports/zephyr/zephyr_storage.c index ded7caa657..6ab8271d34 100644 --- a/ports/zephyr/zephyr_storage.c +++ b/ports/zephyr/zephyr_storage.c @@ -134,7 +134,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, zephyr_disk_access_make_new, print, zephyr_disk_access_print, - locals_dict, (mp_obj_dict_t *)&zephyr_disk_access_locals_dict + locals_dict, &zephyr_disk_access_locals_dict ); #endif // CONFIG_DISK_ACCESS @@ -256,6 +256,6 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, zephyr_flash_area_make_new, print, zephyr_flash_area_print, - locals_dict, (mp_obj_dict_t *)&zephyr_flash_area_locals_dict + locals_dict, &zephyr_flash_area_locals_dict ); #endif // CONFIG_FLASH_MAP diff --git a/py/modio.c b/py/modio.c index 093cb1f7e7..a1e04e4cac 100644 --- a/py/modio.c +++ b/py/modio.c @@ -198,7 +198,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, bufwriter_make_new, protocol, &bufwriter_stream_p, - locals_dict, (mp_obj_dict_t *)&bufwriter_locals_dict + locals_dict, &bufwriter_locals_dict ); #endif // MICROPY_PY_IO_BUFFEREDWRITER diff --git a/py/modthread.c b/py/modthread.c index 0a15447425..3116fe6bd9 100644 --- a/py/modthread.c +++ b/py/modthread.c @@ -121,7 +121,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_lock, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, - locals_dict, (mp_obj_dict_t *)&thread_lock_locals_dict + locals_dict, &thread_lock_locals_dict ); /****************************************************************/ diff --git a/py/objarray.c b/py/objarray.c index 8d0fe7f585..1cb163c4b9 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -582,7 +582,7 @@ MP_DEFINE_CONST_OBJ_TYPE( binary_op, array_binary_op, subscr, array_subscr, buffer, array_get_buffer, - locals_dict, (mp_obj_dict_t *)&mp_obj_array_locals_dict + locals_dict, &mp_obj_array_locals_dict ); #endif @@ -598,7 +598,7 @@ MP_DEFINE_CONST_OBJ_TYPE( binary_op, array_binary_op, subscr, array_subscr, buffer, array_get_buffer, - locals_dict, (mp_obj_dict_t *)&mp_obj_bytearray_locals_dict + locals_dict, &mp_obj_bytearray_locals_dict ); #endif @@ -610,7 +610,7 @@ MP_DEFINE_CONST_OBJ_TYPE( #endif #if MICROPY_PY_BUILTINS_BYTES_HEX -#define MEMORYVIEW_TYPE_LOCALS_DICT locals_dict, (mp_obj_dict_t *)&mp_obj_memoryview_locals_dict, +#define MEMORYVIEW_TYPE_LOCALS_DICT locals_dict, &mp_obj_memoryview_locals_dict, #else #define MEMORYVIEW_TYPE_LOCALS_DICT #endif diff --git a/py/objdeque.c b/py/objdeque.c index 22770317ab..1a8f76ca11 100644 --- a/py/objdeque.c +++ b/py/objdeque.c @@ -161,7 +161,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, deque_make_new, unary_op, deque_unary_op, - locals_dict, (mp_obj_dict_t *)&deque_locals_dict + locals_dict, &deque_locals_dict ); #endif // MICROPY_PY_COLLECTIONS_DEQUE diff --git a/py/objdict.c b/py/objdict.c index 6e217d5c9a..c65b14caad 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -599,7 +599,7 @@ MP_DEFINE_CONST_OBJ_TYPE( binary_op, dict_binary_op, subscr, dict_subscr, getiter, dict_getiter, - locals_dict, (mp_obj_dict_t *)&dict_locals_dict + locals_dict, &dict_locals_dict ); #if MICROPY_PY_COLLECTIONS_ORDEREDDICT @@ -614,7 +614,7 @@ MP_DEFINE_CONST_OBJ_TYPE( subscr, dict_subscr, getiter, dict_getiter, parent, &mp_type_dict, - locals_dict, (mp_obj_dict_t *)&dict_locals_dict + locals_dict, &dict_locals_dict ); #endif diff --git a/py/objgenerator.c b/py/objgenerator.c index 299f25e7bb..a960c23700 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -376,5 +376,5 @@ MP_DEFINE_CONST_OBJ_TYPE( unary_op, mp_generic_unary_op, getiter, mp_identity_getiter, iternext, gen_instance_iternext, - locals_dict, (mp_obj_dict_t *)&gen_instance_locals_dict + locals_dict, &gen_instance_locals_dict ); diff --git a/py/objint.c b/py/objint.c index d7a3f9eb9d..f06bc441f1 100644 --- a/py/objint.c +++ b/py/objint.c @@ -465,5 +465,5 @@ MP_DEFINE_CONST_OBJ_TYPE( print, mp_obj_int_print, unary_op, mp_obj_int_unary_op, binary_op, mp_obj_int_binary_op, - locals_dict, (mp_obj_dict_t *)&int_locals_dict + locals_dict, &int_locals_dict ); diff --git a/py/objlist.c b/py/objlist.c index 8c7921b989..5f9e99cc79 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -462,7 +462,7 @@ MP_DEFINE_CONST_OBJ_TYPE( binary_op, list_binary_op, subscr, list_subscr, getiter, list_getiter, - locals_dict, (mp_obj_dict_t *)&list_locals_dict + locals_dict, &list_locals_dict ); diff --git a/py/objobject.c b/py/objobject.c index 868a85b32a..ffad610707 100644 --- a/py/objobject.c +++ b/py/objobject.c @@ -112,7 +112,7 @@ STATIC MP_DEFINE_CONST_DICT(object_locals_dict, object_locals_dict_table); #endif #if MICROPY_CPYTHON_COMPAT -#define OBJECT_TYPE_LOCALS_DICT , locals_dict, (mp_obj_dict_t *)&object_locals_dict +#define OBJECT_TYPE_LOCALS_DICT , locals_dict, &object_locals_dict #else #define OBJECT_TYPE_LOCALS_DICT #endif diff --git a/py/objpolyiter.c b/py/objpolyiter.c index 326153182b..5bc397f6ec 100644 --- a/py/objpolyiter.c +++ b/py/objpolyiter.c @@ -85,6 +85,6 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_NULL_MAKE_NEW, getiter, mp_identity_getiter, iternext, polymorph_it_iternext, - locals_dict, (mp_obj_dict_t *)&mp_obj_polymorph_iter_locals_dict + locals_dict, &mp_obj_polymorph_iter_locals_dict ); #endif diff --git a/py/objproperty.c b/py/objproperty.c index 42c357f330..ce3b572591 100644 --- a/py/objproperty.c +++ b/py/objproperty.c @@ -95,7 +95,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_property, MP_TYPE_FLAG_NONE, property_make_new, - locals_dict, (mp_obj_dict_t *)&property_locals_dict + locals_dict, &property_locals_dict ); const mp_obj_t *mp_obj_property_get(mp_obj_t self_in) { diff --git a/py/objset.c b/py/objset.c index 8fc744a140..6f21bf15df 100644 --- a/py/objset.c +++ b/py/objset.c @@ -548,7 +548,7 @@ MP_DEFINE_CONST_OBJ_TYPE( unary_op, set_unary_op, binary_op, set_binary_op, getiter, set_getiter, - locals_dict, (mp_obj_dict_t *)&set_locals_dict + locals_dict, &set_locals_dict ); #if MICROPY_PY_BUILTINS_FROZENSET @@ -574,7 +574,7 @@ MP_DEFINE_CONST_OBJ_TYPE( unary_op, set_unary_op, binary_op, set_binary_op, getiter, set_getiter, - locals_dict, (mp_obj_dict_t *)&frozenset_locals_dict + locals_dict, &frozenset_locals_dict ); #endif diff --git a/py/objslice.c b/py/objslice.c index 7baca1fbe6..d1dbb24586 100644 --- a/py/objslice.c +++ b/py/objslice.c @@ -95,7 +95,7 @@ STATIC MP_DEFINE_CONST_DICT(slice_locals_dict, slice_locals_dict_table); #if MICROPY_PY_BUILTINS_SLICE_ATTRS #define SLICE_TYPE_ATTR_OR_LOCALS_DICT attr, slice_attr, #elif MICROPY_PY_BUILTINS_SLICE_INDICES -#define SLICE_TYPE_ATTR_OR_LOCALS_DICT locals_dict, (mp_obj_dict_t *)&slice_locals_dict, +#define SLICE_TYPE_ATTR_OR_LOCALS_DICT locals_dict, &slice_locals_dict, #else #define SLICE_TYPE_ATTR_OR_LOCALS_DICT #endif diff --git a/py/objstr.c b/py/objstr.c index 77ca269d42..d425055559 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -2153,7 +2153,7 @@ MP_DEFINE_CONST_OBJ_TYPE( subscr, bytes_subscr, getiter, mp_obj_new_str_iterator, buffer, mp_obj_str_get_buffer, - locals_dict, (mp_obj_dict_t *)&mp_obj_str_locals_dict + locals_dict, &mp_obj_str_locals_dict ); #endif // !MICROPY_PY_BUILTINS_STR_UNICODE @@ -2168,7 +2168,7 @@ MP_DEFINE_CONST_OBJ_TYPE( subscr, bytes_subscr, getiter, mp_obj_new_bytes_iterator, buffer, mp_obj_str_get_buffer, - locals_dict, (mp_obj_dict_t *)&mp_obj_bytes_locals_dict + locals_dict, &mp_obj_bytes_locals_dict ); // The zero-length bytes object, with data that includes a null-terminating byte diff --git a/py/objstringio.c b/py/objstringio.c index d781ccc789..77547f88cf 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -253,7 +253,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &stringio_stream_p, - locals_dict, (mp_obj_dict_t *)&stringio_locals_dict + locals_dict, &stringio_locals_dict ); #if MICROPY_PY_IO_BYTESIO @@ -272,7 +272,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &bytesio_stream_p, - locals_dict, (mp_obj_dict_t *)&stringio_locals_dict + locals_dict, &stringio_locals_dict ); #endif diff --git a/py/objstrunicode.c b/py/objstrunicode.c index afef1498e9..15c59e4e95 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -240,7 +240,7 @@ MP_DEFINE_CONST_OBJ_TYPE( subscr, str_subscr, getiter, mp_obj_new_str_iterator, buffer, mp_obj_str_get_buffer, - locals_dict, (mp_obj_dict_t *)&mp_obj_str_locals_dict + locals_dict, &mp_obj_str_locals_dict ); /******************************************************************************/ diff --git a/py/objtuple.c b/py/objtuple.c index b2ea6e380e..a684b13e6f 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -234,7 +234,7 @@ MP_DEFINE_CONST_OBJ_TYPE( binary_op, mp_obj_tuple_binary_op, subscr, mp_obj_tuple_subscr, getiter, mp_obj_tuple_getiter, - locals_dict, (mp_obj_dict_t *)&tuple_locals_dict + locals_dict, &tuple_locals_dict ); // the zero-length tuple diff --git a/shared/runtime/mpirq.c b/shared/runtime/mpirq.c index 763da6e0e4..889fa7a9a8 100644 --- a/shared/runtime/mpirq.c +++ b/shared/runtime/mpirq.c @@ -131,7 +131,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, call, mp_irq_call, - locals_dict, (mp_obj_dict_t *)&mp_irq_locals_dict + locals_dict, &mp_irq_locals_dict ); #endif // MICROPY_ENABLE_SCHEDULER diff --git a/shared/runtime/sys_stdio_mphal.c b/shared/runtime/sys_stdio_mphal.c index f1290853da..6d43425e29 100644 --- a/shared/runtime/sys_stdio_mphal.c +++ b/shared/runtime/sys_stdio_mphal.c @@ -132,7 +132,7 @@ MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &stdio_obj_stream_p, - locals_dict, (mp_obj_dict_t *)&stdio_locals_dict + locals_dict, &stdio_locals_dict ); const sys_stdio_obj_t mp_sys_stdin_obj = {{&stdio_obj_type}, .fd = STDIO_FD_IN}; @@ -168,7 +168,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( getiter, mp_identity_getiter, iternext, mp_stream_unbuffered_iter, protocol, &stdio_buffer_obj_stream_p, - locals_dict, (mp_obj_dict_t *)&stdio_locals_dict + locals_dict, &stdio_locals_dict ); STATIC const sys_stdio_obj_t stdio_buffer_obj = {{&stdio_buffer_obj_type}, .fd = 0}; // fd unused From 5ddf671944465411f90bd0968550b719d0dbdb80 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 14 Jul 2021 15:02:15 +1000 Subject: [PATCH 0419/1041] py/objexcept: Make MP_DEFINE_EXCEPTION use MP_DEFINE_CONST_OBJ_TYPE. Signed-off-by: Jim Mussared --- py/objexcept.h | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/py/objexcept.h b/py/objexcept.h index 384456bb51..5d56d67d73 100644 --- a/py/objexcept.h +++ b/py/objexcept.h @@ -41,13 +41,10 @@ void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kin void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest); #define MP_DEFINE_EXCEPTION(exc_name, base_name) \ - const mp_obj_type_t mp_type_##exc_name = { \ - { &mp_type_type }, \ - .name = MP_QSTR_##exc_name, \ - .print = mp_obj_exception_print, \ - .make_new = mp_obj_exception_make_new, \ - .attr = mp_obj_exception_attr, \ - .parent = &mp_type_##base_name, \ - }; + MP_DEFINE_CONST_OBJ_TYPE(mp_type_##exc_name, MP_QSTR_##exc_name, MP_TYPE_FLAG_NONE, mp_obj_exception_make_new, \ + print, mp_obj_exception_print, \ + attr, mp_obj_exception_attr, \ + parent, &mp_type_##base_name \ + ); #endif // MICROPY_INCLUDED_PY_OBJEXCEPT_H From e8355eb16357b0bd234a9bcab1c9e8b72fcdbabc Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 22 Apr 2022 13:05:56 +1000 Subject: [PATCH 0420/1041] py/obj: Add "full" and "empty" non-variable-length mp_obj_type_t. This will always have the maximum/minimum size of a mp_obj_type_t representation and can be used as a member in other structs. Signed-off-by: Jim Mussared --- examples/natmod/btree/btree_c.c | 2 +- examples/natmod/framebuf/framebuf.c | 2 +- examples/natmod/ure/ure.c | 4 ++-- examples/natmod/uzlib/uzlib.c | 2 +- extmod/modbtree.c | 2 +- extmod/modframebuf.c | 2 +- extmod/modnetwork.h | 3 ++- extmod/modure.c | 10 +++++----- extmod/network_ninaw10.c | 2 +- extmod/network_wiznet5k.c | 2 +- ports/cc3200/mods/modnetwork.h | 3 ++- ports/cc3200/mods/modwlan.c | 2 +- py/obj.h | 15 +++++++++++++-- py/objnamedtuple.h | 5 ++++- py/objtype.c | 5 ++++- 15 files changed, 40 insertions(+), 21 deletions(-) diff --git a/examples/natmod/btree/btree_c.c b/examples/natmod/btree/btree_c.c index 5e8a34ac40..e342b7d903 100644 --- a/examples/natmod/btree/btree_c.c +++ b/examples/natmod/btree/btree_c.c @@ -94,7 +94,7 @@ int mp_stream_posix_fsync(void *stream) { return res; } -mp_obj_type_t btree_type; +mp_obj_full_type_t btree_type; #include "extmod/modbtree.c" diff --git a/examples/natmod/framebuf/framebuf.c b/examples/natmod/framebuf/framebuf.c index 2eff61c817..98b44987b3 100644 --- a/examples/natmod/framebuf/framebuf.c +++ b/examples/natmod/framebuf/framebuf.c @@ -8,7 +8,7 @@ void *memset(void *s, int c, size_t n) { } #endif -mp_obj_type_t mp_type_framebuf; +mp_obj_full_type_t mp_type_framebuf; #include "extmod/modframebuf.c" diff --git a/examples/natmod/ure/ure.c b/examples/natmod/ure/ure.c index 175b93e395..d9e11760a7 100644 --- a/examples/natmod/ure/ure.c +++ b/examples/natmod/ure/ure.c @@ -32,8 +32,8 @@ void *memmove(void *dest, const void *src, size_t n) { return mp_fun_table.memmove_(dest, src, n); } -mp_obj_type_t match_type; -mp_obj_type_t re_type; +mp_obj_full_type_t match_type; +mp_obj_full_type_t re_type; #include "extmod/modure.c" diff --git a/examples/natmod/uzlib/uzlib.c b/examples/natmod/uzlib/uzlib.c index 99b3691761..24ab15d6f1 100644 --- a/examples/natmod/uzlib/uzlib.c +++ b/examples/natmod/uzlib/uzlib.c @@ -8,7 +8,7 @@ void *memset(void *s, int c, size_t n) { } #endif -mp_obj_type_t decompio_type; +mp_obj_full_type_t decompio_type; #include "extmod/moduzlib.c" diff --git a/extmod/modbtree.c b/extmod/modbtree.c index 15cb634163..60c6885e6b 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -67,7 +67,7 @@ void __dbpanic(DB *db) { } STATIC mp_obj_btree_t *btree_new(DB *db, mp_obj_t stream) { - mp_obj_btree_t *o = mp_obj_malloc(mp_obj_btree_t, &btree_type); + mp_obj_btree_t *o = mp_obj_malloc(mp_obj_btree_t, (mp_obj_type_t *)&btree_type); o->stream = stream; o->db = db; o->start_key = mp_const_none; diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index f29eab272f..5347be5643 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -841,7 +841,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( // this factory function is provided for backwards compatibility with old FrameBuffer1 class STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args_in) { - mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, &mp_type_framebuf); + mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, (mp_obj_type_t *)&mp_type_framebuf); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE); diff --git a/extmod/modnetwork.h b/extmod/modnetwork.h index 3481cc6dcc..55ee4eb4d3 100644 --- a/extmod/modnetwork.h +++ b/extmod/modnetwork.h @@ -62,7 +62,8 @@ mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_o struct _mod_network_socket_obj_t; typedef struct _mod_network_nic_type_t { - mp_obj_type_t base; + // Ensure that this struct is big enough to hold any type size. + mp_obj_full_type_t base; // API for non-socket operations int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out); diff --git a/extmod/modure.c b/extmod/modure.c index 4395992405..c0114c14fd 100644 --- a/extmod/modure.c +++ b/extmod/modure.c @@ -198,7 +198,7 @@ STATIC void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t STATIC mp_obj_t ure_exec(bool is_anchored, uint n_args, const mp_obj_t *args) { (void)n_args; mp_obj_re_t *self; - if (mp_obj_is_type(args[0], &re_type)) { + if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) { self = MP_OBJ_TO_PTR(args[0]); } else { self = MP_OBJ_TO_PTR(mod_re_compile(1, args)); @@ -217,7 +217,7 @@ STATIC mp_obj_t ure_exec(bool is_anchored, uint n_args, const mp_obj_t *args) { return mp_const_none; } - match->base.type = &match_type; + match->base.type = (mp_obj_type_t *)&match_type; match->num_matches = caps_num / 2; // caps_num counts start and end pointers match->str = args[1]; return MP_OBJ_FROM_PTR(match); @@ -282,7 +282,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_split_obj, 2, 3, re_split); STATIC mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) { mp_obj_re_t *self; - if (mp_obj_is_type(args[0], &re_type)) { + if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) { self = MP_OBJ_TO_PTR(args[0]); } else { self = MP_OBJ_TO_PTR(mod_re_compile(1, args)); @@ -305,7 +305,7 @@ STATIC mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) { vstr_t vstr_return; vstr_return.buf = NULL; // We'll init the vstr after the first match mp_obj_match_t *match = mp_local_alloc(sizeof(mp_obj_match_t) + caps_num * sizeof(char *)); - match->base.type = &match_type; + match->base.type = (mp_obj_type_t *)&match_type; match->num_matches = caps_num / 2; // caps_num counts start and end pointers match->str = where; @@ -430,7 +430,7 @@ STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) { if (size == -1) { goto error; } - mp_obj_re_t *o = mp_obj_malloc_var(mp_obj_re_t, char, size, &re_type); + mp_obj_re_t *o = mp_obj_malloc_var(mp_obj_re_t, char, size, (mp_obj_type_t *)&re_type); #if MICROPY_PY_URE_DEBUG int flags = 0; if (n_args > 1) { diff --git a/extmod/network_ninaw10.c b/extmod/network_ninaw10.c index 0906176d20..806819648d 100644 --- a/extmod/network_ninaw10.c +++ b/extmod/network_ninaw10.c @@ -774,7 +774,7 @@ static const mp_rom_map_elem_t nina_locals_dict_table[] = { static MP_DEFINE_CONST_DICT(nina_locals_dict, nina_locals_dict_table); -STATIC MP_DEFINE_CONST_OBJ_TYPE( +STATIC MP_DEFINE_CONST_OBJ_FULL_TYPE( mod_network_nic_type_nina_base, MP_QSTR_nina, MP_TYPE_FLAG_NONE, diff --git a/extmod/network_wiznet5k.c b/extmod/network_wiznet5k.c index 951a2966c9..1d7318827c 100644 --- a/extmod/network_wiznet5k.c +++ b/extmod/network_wiznet5k.c @@ -1024,7 +1024,7 @@ MP_DEFINE_CONST_OBJ_TYPE( locals_dict, &wiznet5k_locals_dict ); #else // WIZNET5K_PROVIDED_STACK -STATIC MP_DEFINE_CONST_OBJ_TYPE( +STATIC MP_DEFINE_CONST_OBJ_FULL_TYPE( mod_network_nic_type_wiznet5k_base, MP_QSTR_WIZNET5K, MP_TYPE_FLAG_NONE, diff --git a/ports/cc3200/mods/modnetwork.h b/ports/cc3200/mods/modnetwork.h index 6ec90a2bac..c15a6467f2 100644 --- a/ports/cc3200/mods/modnetwork.h +++ b/ports/cc3200/mods/modnetwork.h @@ -36,7 +36,8 @@ DEFINE TYPES ******************************************************************************/ typedef struct _mod_network_nic_type_t { - mp_obj_type_t base; + // Ensure that this struct is big enough to hold any type size. + mp_obj_full_type_t base; } mod_network_nic_type_t; typedef struct _mod_network_socket_base_t { diff --git a/ports/cc3200/mods/modwlan.c b/ports/cc3200/mods/modwlan.c index 1c99f075e9..1e82b07e08 100644 --- a/ports/cc3200/mods/modwlan.c +++ b/ports/cc3200/mods/modwlan.c @@ -1285,7 +1285,7 @@ STATIC const mp_rom_map_elem_t wlan_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(wlan_locals_dict, wlan_locals_dict_table); -STATIC MP_DEFINE_CONST_OBJ_TYPE( +STATIC MP_DEFINE_CONST_OBJ_FULL_TYPE( mod_network_nic_type_wlan_base, MP_QSTR_WLAN, MP_TYPE_FLAG_NONE, diff --git a/py/obj.h b/py/obj.h index 4ab7e0dc09..9c0f41dc3d 100644 --- a/py/obj.h +++ b/py/obj.h @@ -562,6 +562,9 @@ typedef mp_int_t (*mp_buffer_fun_t)(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_ bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); +// This struct will be updated to become a variable sized struct. In order to +// use this as a member, or allocate dynamically, use the mp_obj_empty_type_t +// or mp_obj_full_type_t structs below (which must be kept in sync). struct _mp_obj_type_t { // A type is an object so must start with this entry, which points to mp_type_type. mp_obj_base_t base; @@ -632,6 +635,13 @@ struct _mp_obj_type_t { struct _mp_obj_dict_t *locals_dict; }; +// Non-variable sized versions of mp_obj_type_t to be used as a member +// in other structs or for dynamic allocation. The fields are exactly +// as in mp_obj_type_t, but with a fixed size for the flexible array +// members. +typedef mp_obj_type_t mp_obj_empty_type_t; +typedef mp_obj_type_t mp_obj_full_type_t; + #define MP_TYPE_NULL_MAKE_NEW (NULL) // Implementation of MP_DEFINE_CONST_OBJ_TYPE for each number of arguments. @@ -657,14 +667,15 @@ struct _mp_obj_type_t { // of the 30th argument (30 is 13*2 + 4). #define MP_DEFINE_CONST_OBJ_TYPE_NARGS(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, N, ...) MP_DEFINE_CONST_OBJ_TYPE_NARGS_##N -// This macro is used to define a object type in ROM. +// These macros are used to define a object type in ROM. // Invoke as MP_DEFINE_CONST_OBJ_TYPE(_typename, _name, _flags, _make_new [, slot, func]*) -// It uses the number of arguments to select which MP_DEFINE_CONST_OBJ_TYPE_* +// They use the number of arguments to select which MP_DEFINE_CONST_OBJ_TYPE_* // macro to use based on the number of arguments. It works by shifting the // numeric values 12, 11, ... 0 by the number of arguments, such that the // 30th argument ends up being the number to use. The _INV values are // placeholders because the slot arguments come in pairs. #define MP_DEFINE_CONST_OBJ_TYPE(...) MP_DEFINE_CONST_OBJ_TYPE_EXPAND(MP_DEFINE_CONST_OBJ_TYPE_NARGS(__VA_ARGS__, _INV, 12, _INV, 11, _INV, 10, _INV, 9, _INV, 8, _INV, 7, _INV, 6, _INV, 5, _INV, 4, _INV, 3, _INV, 2, _INV, 1, _INV, 0)(mp_obj_type_t, __VA_ARGS__)) +#define MP_DEFINE_CONST_OBJ_FULL_TYPE(...) MP_DEFINE_CONST_OBJ_TYPE_EXPAND(MP_DEFINE_CONST_OBJ_TYPE_NARGS(__VA_ARGS__, _INV, 12, _INV, 11, _INV, 10, _INV, 9, _INV, 8, _INV, 7, _INV, 6, _INV, 5, _INV, 4, _INV, 3, _INV, 2, _INV, 1, _INV, 0)(mp_obj_full_type_t, __VA_ARGS__)) // Constant types, globally accessible extern const mp_obj_type_t mp_type_type; diff --git a/py/objnamedtuple.h b/py/objnamedtuple.h index d32af35afe..9f23351d5a 100644 --- a/py/objnamedtuple.h +++ b/py/objnamedtuple.h @@ -29,7 +29,10 @@ #include "py/objtuple.h" typedef struct _mp_obj_namedtuple_type_t { - mp_obj_type_t base; + // Must use the full-size version to avoid this being a variable sized member. + // This means that named tuples use slightly more RAM than necessary, but + // no worse than if we didn't have slots/split representation. + mp_obj_full_type_t base; size_t n_fields; qstr fields[]; } mp_obj_namedtuple_type_t; diff --git a/py/objtype.c b/py/objtype.c index 77fe8e22e3..cc5a5e5802 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -1148,7 +1148,10 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) #endif } - mp_obj_type_t *o = m_new0(mp_obj_type_t, 1); + // Allocate a full-sized mp_obj_full_type_t instance (i.e. all slots / extended fields). + // Given that Python types use almost all the slots anyway, this doesn't cost anything + // extra. + mp_obj_type_t *o = (mp_obj_type_t *)m_new0(mp_obj_full_type_t, 1); o->base.type = &mp_type_type; o->flags = base_flags; o->name = name; From a52cd5b07d6d6e2502fff2bbfb9e5b96562452a4 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 14 Jul 2021 17:14:16 +1000 Subject: [PATCH 0421/1041] py/obj: Add accessors for type slots and use everywhere. This is a no-op, but sets the stage for changing the mp_obj_type_t representation. Signed-off-by: Jim Mussared --- drivers/ninaw10/nina_wifi_bsp.c | 2 +- examples/natmod/btree/btree_c.c | 20 +-- examples/natmod/framebuf/framebuf.c | 4 +- examples/natmod/ure/ure.c | 8 +- examples/natmod/uzlib/uzlib.c | 6 +- extmod/machine_i2c.c | 22 +-- extmod/machine_signal.c | 2 +- extmod/machine_spi.c | 6 +- extmod/network_wiznet5k.c | 2 +- extmod/vfs.c | 5 +- extmod/virtpin.c | 4 +- .../nrf/modules/ubluepy/ubluepy_scan_entry.c | 2 +- ports/rp2/mpbthciport.c | 6 +- ports/unix/modffi.c | 4 +- py/builtinhelp.c | 4 +- py/dynruntime.h | 2 +- py/modbuiltins.c | 2 +- py/obj.c | 28 ++-- py/obj.h | 12 +- py/objarray.c | 2 +- py/objnamedtuple.c | 14 +- py/objtuple.c | 4 +- py/objtype.c | 136 +++++++++--------- py/opmethods.c | 12 +- py/runtime.c | 59 ++++---- py/stream.c | 25 ++-- py/stream.h | 2 +- 27 files changed, 207 insertions(+), 188 deletions(-) diff --git a/drivers/ninaw10/nina_wifi_bsp.c b/drivers/ninaw10/nina_wifi_bsp.c index a65ef7fd86..d5b1308536 100644 --- a/drivers/ninaw10/nina_wifi_bsp.c +++ b/drivers/ninaw10/nina_wifi_bsp.c @@ -137,7 +137,7 @@ int nina_bsp_spi_slave_deselect(void) { int nina_bsp_spi_transfer(const uint8_t *tx_buf, uint8_t *rx_buf, uint32_t size) { mp_obj_t mp_wifi_spi = MP_STATE_PORT(mp_wifi_spi); - ((mp_machine_spi_p_t *)machine_spi_type.protocol)->transfer(mp_wifi_spi, size, tx_buf, rx_buf); + ((mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(&machine_spi_type, protocol))->transfer(mp_wifi_spi, size, tx_buf, rx_buf); #if NINA_DEBUG for (int i = 0; i < size; i++) { if (tx_buf) { diff --git a/examples/natmod/btree/btree_c.c b/examples/natmod/btree/btree_c.c index e342b7d903..af7535a68f 100644 --- a/examples/natmod/btree/btree_c.c +++ b/examples/natmod/btree/btree_c.c @@ -51,7 +51,7 @@ int *__errno (void) ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) { mp_obj_base_t* o = stream; - const mp_stream_p_t *stream_p = o->type->protocol; + const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol); mp_uint_t out_sz = stream_p->write(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno); if (out_sz == MP_STREAM_ERROR) { return -1; @@ -62,7 +62,7 @@ ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) { ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) { mp_obj_base_t* o = stream; - const mp_stream_p_t *stream_p = o->type->protocol; + const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol); mp_uint_t out_sz = stream_p->read(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno); if (out_sz == MP_STREAM_ERROR) { return -1; @@ -73,7 +73,7 @@ ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) { off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) { const mp_obj_base_t* o = stream; - const mp_stream_p_t *stream_p = o->type->protocol; + const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol); struct mp_stream_seek_t seek_s; seek_s.offset = offset; seek_s.whence = whence; @@ -86,7 +86,7 @@ off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) { int mp_stream_posix_fsync(void *stream) { mp_obj_base_t* o = stream; - const mp_stream_p_t *stream_p = o->type->protocol; + const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol); mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_FLUSH, 0, &native_errno); if (res == MP_STREAM_ERROR) { return -1; @@ -124,11 +124,11 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a btree_type.base.type = (void*)&mp_fun_table.type_type; btree_type.name = MP_QSTR_btree; - btree_type.print = btree_print; - btree_type.getiter = btree_getiter; - btree_type.iternext = btree_iternext; - btree_type.binary_op = btree_binary_op; - btree_type.subscr = btree_subscr; + MP_OBJ_TYPE_SET_SLOT(&btree_type, print, btree_print, 0); + MP_OBJ_TYPE_SET_SLOT(&btree_type, getiter, btree_getiter, 1); + MP_OBJ_TYPE_SET_SLOT(&btree_type, iternext, btree_iternext, 2); + MP_OBJ_TYPE_SET_SLOT(&btree_type, binary_op, btree_binary_op, 3); + MP_OBJ_TYPE_SET_SLOT(&btree_type, subscr, btree_subscr, 4); btree_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_close), MP_OBJ_FROM_PTR(&btree_close_obj) }; btree_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_flush), MP_OBJ_FROM_PTR(&btree_flush_obj) }; btree_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_get), MP_OBJ_FROM_PTR(&btree_get_obj) }; @@ -137,7 +137,7 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a btree_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_keys), MP_OBJ_FROM_PTR(&btree_keys_obj) }; btree_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_values), MP_OBJ_FROM_PTR(&btree_values_obj) }; btree_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_items), MP_OBJ_FROM_PTR(&btree_items_obj) }; - btree_type.locals_dict = (void*)&btree_locals_dict; + MP_OBJ_TYPE_SET_SLOT(&btree_type, locals_dict, (void*)&btree_locals_dict, 5); mp_store_global(MP_QSTR__open, MP_OBJ_FROM_PTR(&btree_open_obj)); mp_store_global(MP_QSTR_INCL, MP_OBJ_NEW_SMALL_INT(FLAG_END_KEY_INCL)); diff --git a/examples/natmod/framebuf/framebuf.c b/examples/natmod/framebuf/framebuf.c index 98b44987b3..4c55729471 100644 --- a/examples/natmod/framebuf/framebuf.c +++ b/examples/natmod/framebuf/framebuf.c @@ -21,7 +21,7 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a mp_type_framebuf.base.type = (void*)&mp_type_type; mp_type_framebuf.name = MP_QSTR_FrameBuffer; mp_type_framebuf.make_new = framebuf_make_new; - mp_type_framebuf.buffer = framebuf_get_buffer; + MP_OBJ_TYPE_SET_SLOT(&mp_type_framebuf, buffer, framebuf_get_buffer, 0); framebuf_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill), MP_OBJ_FROM_PTR(&framebuf_fill_obj) }; framebuf_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill_rect), MP_OBJ_FROM_PTR(&framebuf_fill_rect_obj) }; framebuf_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_pixel), MP_OBJ_FROM_PTR(&framebuf_pixel_obj) }; @@ -33,7 +33,7 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a framebuf_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_blit), MP_OBJ_FROM_PTR(&framebuf_blit_obj) }; framebuf_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), MP_OBJ_FROM_PTR(&framebuf_scroll_obj) }; framebuf_locals_dict_table[10] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_text), MP_OBJ_FROM_PTR(&framebuf_text_obj) }; - mp_type_framebuf.locals_dict = (void*)&framebuf_locals_dict; + MP_OBJ_TYPE_SET_SLOT(&mp_type_framebuf, locals_dict, (void*)&framebuf_locals_dict, 1); mp_store_global(MP_QSTR_FrameBuffer, MP_OBJ_FROM_PTR(&mp_type_framebuf)); mp_store_global(MP_QSTR_FrameBuffer1, MP_OBJ_FROM_PTR(&legacy_framebuffer1_obj)); diff --git a/examples/natmod/ure/ure.c b/examples/natmod/ure/ure.c index d9e11760a7..d4bd680abd 100644 --- a/examples/natmod/ure/ure.c +++ b/examples/natmod/ure/ure.c @@ -54,21 +54,21 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a match_type.base.type = (void*)&mp_fun_table.type_type; match_type.name = MP_QSTR_match; - match_type.print = match_print; + MP_OBJ_TYPE_SET_SLOT(&match_type, print, match_print, 0); match_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_group), MP_OBJ_FROM_PTR(&match_group_obj) }; match_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_groups), MP_OBJ_FROM_PTR(&match_groups_obj) }; match_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_span), MP_OBJ_FROM_PTR(&match_span_obj) }; match_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_start), MP_OBJ_FROM_PTR(&match_start_obj) }; match_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_OBJ_FROM_PTR(&match_end_obj) }; - match_type.locals_dict = (void*)&match_locals_dict; + MP_OBJ_TYPE_SET_SLOT(&match_type, locals_dict, (void*)&match_locals_dict, 1); re_type.base.type = (void*)&mp_fun_table.type_type; re_type.name = MP_QSTR_ure; - re_type.print = re_print; + MP_OBJ_TYPE_SET_SLOT(&re_type, print, re_print, 0); re_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_match), MP_OBJ_FROM_PTR(&re_match_obj) }; re_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_search), MP_OBJ_FROM_PTR(&re_search_obj) }; re_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_split), MP_OBJ_FROM_PTR(&re_split_obj) }; - re_type.locals_dict = (void*)&re_locals_dict; + MP_OBJ_TYPE_SET_SLOT(&re_type, locals_dict, (void*)&re_locals_dict, 1); mp_store_global(MP_QSTR_compile, MP_OBJ_FROM_PTR(&mod_re_compile_obj)); mp_store_global(MP_QSTR_match, MP_OBJ_FROM_PTR(&re_match_obj)); diff --git a/examples/natmod/uzlib/uzlib.c b/examples/natmod/uzlib/uzlib.c index 24ab15d6f1..469452e8f8 100644 --- a/examples/natmod/uzlib/uzlib.c +++ b/examples/natmod/uzlib/uzlib.c @@ -20,12 +20,12 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a decompio_type.base.type = mp_fun_table.type_type; decompio_type.name = MP_QSTR_DecompIO; - decompio_type.make_new = decompio_make_new; - decompio_type.protocol = &decompio_stream_p; + decompio_type.make_new = &decompio_make_new; + MP_OBJ_TYPE_SET_SLOT(&decompio_type, protocol, &decompio_stream_p, 0); decompio_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_OBJ_FROM_PTR(&mp_stream_read_obj) }; decompio_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_OBJ_FROM_PTR(&mp_stream_readinto_obj) }; decompio_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_OBJ_FROM_PTR(&mp_stream_unbuffered_readline_obj) }; - decompio_type.locals_dict = (void*)&decompio_locals_dict; + MP_OBJ_TYPE_SET_SLOT(&decompio_type, locals_dict, (void*)&decompio_locals_dict, 1); mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uzlib)); mp_store_global(MP_QSTR_decompress, MP_OBJ_FROM_PTR(&mod_uzlib_decompress_obj)); diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c index 378bf8fc91..bb7ade6fcf 100644 --- a/extmod/machine_i2c.c +++ b/extmod/machine_i2c.c @@ -273,7 +273,7 @@ int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n } } - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol); int ret = i2c_p->transfer_single(self, addr, len, buf, flags); if (n > 1) { @@ -292,14 +292,14 @@ int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n } STATIC int mp_machine_i2c_readfrom(mp_obj_base_t *self, uint16_t addr, uint8_t *dest, size_t len, bool stop) { - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol); mp_machine_i2c_buf_t buf = {.len = len, .buf = dest}; unsigned int flags = MP_MACHINE_I2C_FLAG_READ | (stop ? MP_MACHINE_I2C_FLAG_STOP : 0); return i2c_p->transfer(self, addr, 1, &buf, flags); } STATIC int mp_machine_i2c_writeto(mp_obj_base_t *self, uint16_t addr, const uint8_t *src, size_t len, bool stop) { - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol); mp_machine_i2c_buf_t buf = {.len = len, .buf = (uint8_t *)src}; unsigned int flags = stop ? MP_MACHINE_I2C_FLAG_STOP : 0; return i2c_p->transfer(self, addr, 1, &buf, flags); @@ -310,7 +310,7 @@ STATIC int mp_machine_i2c_writeto(mp_obj_base_t *self, uint16_t addr, const uint STATIC mp_obj_t machine_i2c_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol); if (i2c_p->init == NULL) { mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported")); } @@ -338,7 +338,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan); STATIC mp_obj_t machine_i2c_start(mp_obj_t self_in) { mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol); if (i2c_p->start == NULL) { mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported")); } @@ -352,7 +352,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_start_obj, machine_i2c_start); STATIC mp_obj_t machine_i2c_stop(mp_obj_t self_in) { mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol); if (i2c_p->stop == NULL) { mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported")); } @@ -366,7 +366,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_stop_obj, machine_i2c_stop); STATIC mp_obj_t machine_i2c_readinto(size_t n_args, const mp_obj_t *args) { mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol); if (i2c_p->read == NULL) { mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported")); } @@ -390,7 +390,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readinto_obj, 2, 3, machine_i2c_ STATIC mp_obj_t machine_i2c_write(mp_obj_t self_in, mp_obj_t buf_in) { mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol); if (i2c_p->write == NULL) { mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported")); } @@ -486,7 +486,7 @@ STATIC mp_obj_t machine_i2c_writevto(size_t n_args, const mp_obj_t *args) { } // Do the I2C transfer - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol); int ret = i2c_p->transfer(self, addr, nbufs, bufs, stop ? MP_MACHINE_I2C_FLAG_STOP : 0); mp_local_free(bufs); @@ -519,7 +519,7 @@ STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t a #if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1 // The I2C transfer function may support the MP_MACHINE_I2C_FLAG_WRITE1 option - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol); if (i2c_p->transfer_supports_write1) { // Create partial write and read buffers mp_machine_i2c_buf_t bufs[2] = { @@ -556,7 +556,7 @@ STATIC int write_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t }; // Do I2C transfer - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol); return i2c_p->transfer(self, addr, 2, bufs, MP_MACHINE_I2C_FLAG_STOP); } diff --git a/extmod/machine_signal.c b/extmod/machine_signal.c index f665ffaa49..49ee6dfb4a 100644 --- a/extmod/machine_signal.c +++ b/extmod/machine_signal.c @@ -51,7 +51,7 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t if (n_args > 0 && mp_obj_is_obj(args[0])) { mp_obj_base_t *pin_base = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]); - pin_p = (mp_pin_p_t *)pin_base->type->protocol; + pin_p = (mp_pin_p_t *)MP_OBJ_TYPE_GET_SLOT_OR_NULL(pin_base->type, protocol); } if (pin_p == NULL) { diff --git a/extmod/machine_spi.c b/extmod/machine_spi.c index c7fc5877b1..54f1964e21 100644 --- a/extmod/machine_spi.c +++ b/extmod/machine_spi.c @@ -43,7 +43,7 @@ STATIC mp_obj_t machine_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]); - mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)s->type->protocol; + mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol); spi_p->init(s, n_args - 1, args + 1, kw_args); return mp_const_none; } @@ -51,7 +51,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_init_obj, 1, machine_spi_init); STATIC mp_obj_t machine_spi_deinit(mp_obj_t self) { mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(self); - mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)s->type->protocol; + mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol); if (spi_p->deinit != NULL) { spi_p->deinit(s); } @@ -61,7 +61,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_spi_deinit_obj, machine_spi_deinit); STATIC void mp_machine_spi_transfer(mp_obj_t self, size_t len, const void *src, void *dest) { mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(self); - mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)s->type->protocol; + mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol); spi_p->transfer(s, len, src, dest); } diff --git a/extmod/network_wiznet5k.c b/extmod/network_wiznet5k.c index 1d7318827c..82f836f691 100644 --- a/extmod/network_wiznet5k.c +++ b/extmod/network_wiznet5k.c @@ -744,7 +744,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size wiznet5k_obj.base.type = (mp_obj_type_t *)&mod_network_nic_type_wiznet5k; wiznet5k_obj.cris_state = 0; wiznet5k_obj.spi = spi; - wiznet5k_obj.spi_transfer = ((mp_machine_spi_p_t *)spi->type->protocol)->transfer; + wiznet5k_obj.spi_transfer = ((mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(spi->type, protocol))->transfer; wiznet5k_obj.cs = cs; wiznet5k_obj.rst = rst; #if WIZNET5K_WITH_LWIP_STACK diff --git a/extmod/vfs.c b/extmod/vfs.c index 0ef20e9281..00450e1005 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -132,8 +132,9 @@ mp_import_stat_t mp_vfs_import_stat(const char *path) { } // If the mounted object has the VFS protocol, call its import_stat helper - const mp_vfs_proto_t *proto = mp_obj_get_type(vfs->obj)->protocol; - if (proto != NULL) { + const mp_obj_type_t *type = mp_obj_get_type(vfs->obj); + if (MP_OBJ_TYPE_HAS_SLOT(type, protocol)) { + const mp_vfs_proto_t *proto = MP_OBJ_TYPE_GET_SLOT(type, protocol); return proto->import_stat(MP_OBJ_TO_PTR(vfs->obj), path_out); } diff --git a/extmod/virtpin.c b/extmod/virtpin.c index 71a11232d4..cd0b9f92f8 100644 --- a/extmod/virtpin.c +++ b/extmod/virtpin.c @@ -28,12 +28,12 @@ int mp_virtual_pin_read(mp_obj_t pin) { mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(pin); - mp_pin_p_t *pin_p = (mp_pin_p_t *)s->type->protocol; + mp_pin_p_t *pin_p = (mp_pin_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol); return pin_p->ioctl(pin, MP_PIN_READ, 0, NULL); } void mp_virtual_pin_write(mp_obj_t pin, int value) { mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(pin); - mp_pin_p_t *pin_p = (mp_pin_p_t *)s->type->protocol; + mp_pin_p_t *pin_p = (mp_pin_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol); pin_p->ioctl(pin, MP_PIN_WRITE, value, NULL); } diff --git a/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c b/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c index 5c74e2e92c..89ca65d18c 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c +++ b/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c @@ -91,7 +91,7 @@ STATIC mp_obj_t scan_entry_get_scan_data(mp_obj_t self_in) { mp_obj_t description = mp_const_none; - mp_map_t *constant_map = mp_obj_dict_get_map(ubluepy_constants_ad_types_type.locals_dict); + mp_map_t *constant_map = mp_obj_dict_get_map(MP_OBJ_TYPE_GET_SLOT(&ubluepy_constants_ad_types_type, locals_dict)); mp_map_elem_t *ad_types_table = MP_OBJ_TO_PTR(constant_map->table); uint16_t num_of_elements = constant_map->used; diff --git a/ports/rp2/mpbthciport.c b/ports/rp2/mpbthciport.c index 91c908b164..e37167a974 100644 --- a/ports/rp2/mpbthciport.c +++ b/ports/rp2/mpbthciport.c @@ -128,7 +128,7 @@ int mp_bluetooth_hci_uart_set_baudrate(uint32_t baudrate) { int mp_bluetooth_hci_uart_any(void) { int errcode = 0; - const mp_stream_p_t *proto = (mp_stream_p_t *)machine_uart_type.protocol; + const mp_stream_p_t *proto = (mp_stream_p_t *)MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, protocol); mp_uint_t ret = proto->ioctl(mp_bthci_uart, MP_STREAM_POLL, MP_STREAM_POLL_RD, &errcode); if (errcode != 0) { @@ -142,7 +142,7 @@ int mp_bluetooth_hci_uart_write(const uint8_t *buf, size_t len) { debug_printf("mp_bluetooth_hci_uart_write\n"); int errcode = 0; - const mp_stream_p_t *proto = (mp_stream_p_t *)machine_uart_type.protocol; + const mp_stream_p_t *proto = (mp_stream_p_t *)MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, protocol); mp_bluetooth_hci_controller_wakeup(); @@ -159,7 +159,7 @@ int mp_bluetooth_hci_uart_readchar(void) { if (mp_bluetooth_hci_uart_any()) { int errcode = 0; uint8_t buf = 0; - const mp_stream_p_t *proto = (mp_stream_p_t *)machine_uart_type.protocol; + const mp_stream_p_t *proto = (mp_stream_p_t *)MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, protocol); if (proto->read(mp_bthci_uart, (void *)&buf, 1, &errcode) < 0) { error_printf("mp_bluetooth_hci_uart_readchar: failed to read UART %d\n", errcode); return -1; diff --git a/ports/unix/modffi.c b/ports/unix/modffi.c index 98fd8936b1..04152f1ad4 100644 --- a/ports/unix/modffi.c +++ b/ports/unix/modffi.c @@ -506,10 +506,10 @@ STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const } else if (mp_obj_is_str(a)) { const char *s = mp_obj_str_get_str(a); values[i].ffi = (ffi_arg)(intptr_t)s; - } else if (((mp_obj_base_t *)MP_OBJ_TO_PTR(a))->type->buffer != NULL) { + } else if (MP_OBJ_TYPE_HAS_SLOT(((mp_obj_base_t *)MP_OBJ_TO_PTR(a))->type, buffer)) { mp_obj_base_t *o = (mp_obj_base_t *)MP_OBJ_TO_PTR(a); mp_buffer_info_t bufinfo; - int ret = o->type->buffer(MP_OBJ_FROM_PTR(o), &bufinfo, MP_BUFFER_READ); // TODO: MP_BUFFER_READ? + int ret = MP_OBJ_TYPE_GET_SLOT(o->type, buffer)(MP_OBJ_FROM_PTR(o), &bufinfo, MP_BUFFER_READ); // TODO: MP_BUFFER_READ? if (ret != 0) { goto error; } diff --git a/py/builtinhelp.c b/py/builtinhelp.c index 94f8beaff2..93d94a389d 100644 --- a/py/builtinhelp.c +++ b/py/builtinhelp.c @@ -143,8 +143,8 @@ STATIC void mp_help_print_obj(const mp_obj_t obj) { if (type == &mp_type_type) { type = MP_OBJ_TO_PTR(obj); } - if (type->locals_dict != NULL) { - map = &type->locals_dict->map; + if (MP_OBJ_TYPE_HAS_SLOT(type, locals_dict)) { + map = &MP_OBJ_TYPE_GET_SLOT(type, locals_dict)->map; } } if (map != NULL) { diff --git a/py/dynruntime.h b/py/dynruntime.h index fb748eb93f..be573bde2a 100644 --- a/py/dynruntime.h +++ b/py/dynruntime.h @@ -150,7 +150,7 @@ static inline mp_obj_t mp_obj_cast_to_native_base_dyn(mp_obj_t self_in, mp_const if (MP_OBJ_FROM_PTR(self_type) == native_type) { return self_in; - } else if (self_type->parent != native_type) { + } else if (MP_OBJ_TYPE_GET_SLOT_OR_NULL(self_type, parent) != native_type) { // The self_in object is not a direct descendant of native_type, so fail the cast. // This is a very simple version of mp_obj_is_subclass_fast that could be improved. return MP_OBJ_NULL; diff --git a/py/modbuiltins.c b/py/modbuiltins.c index f74db95cf5..152323b5ca 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -455,7 +455,7 @@ STATIC mp_obj_t mp_builtin___repl_print__(mp_obj_t o) { #if MICROPY_CAN_OVERRIDE_BUILTINS // Set "_" special variable mp_obj_t dest[2] = {MP_OBJ_SENTINEL, o}; - mp_type_module.attr(MP_OBJ_FROM_PTR(&mp_module_builtins), MP_QSTR__, dest); + MP_OBJ_TYPE_GET_SLOT(&mp_type_module, attr)(MP_OBJ_FROM_PTR(&mp_module_builtins), MP_QSTR__, dest); #endif } return mp_const_none; diff --git a/py/obj.c b/py/obj.c index eeadd3eedd..359c73b9c2 100644 --- a/py/obj.c +++ b/py/obj.c @@ -116,8 +116,8 @@ void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t } #endif const mp_obj_type_t *type = mp_obj_get_type(o_in); - if (type->print != NULL) { - type->print((mp_print_t *)print, o_in, kind); + if (MP_OBJ_TYPE_HAS_SLOT(type, print)) { + MP_OBJ_TYPE_GET_SLOT(type, print)((mp_print_t *)print, o_in, kind); } else { mp_printf(print, "<%q>", type->name); } @@ -170,8 +170,8 @@ bool mp_obj_is_true(mp_obj_t arg) { } } else { const mp_obj_type_t *type = mp_obj_get_type(arg); - if (type->unary_op != NULL) { - mp_obj_t result = type->unary_op(MP_UNARY_OP_BOOL, arg); + if (MP_OBJ_TYPE_HAS_SLOT(type, unary_op)) { + mp_obj_t result = MP_OBJ_TYPE_GET_SLOT(type, unary_op)(MP_UNARY_OP_BOOL, arg); if (result != MP_OBJ_NULL) { return result == mp_const_true; } @@ -189,7 +189,7 @@ bool mp_obj_is_true(mp_obj_t arg) { } bool mp_obj_is_callable(mp_obj_t o_in) { - const mp_call_fun_t call = mp_obj_get_type(o_in)->call; + const mp_call_fun_t call = MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(o_in), call); if (call != mp_obj_instance_call) { return call != NULL; } @@ -256,19 +256,19 @@ mp_obj_t mp_obj_equal_not_equal(mp_binary_op_t op, mp_obj_t o1, mp_obj_t o2) { const mp_obj_type_t *type = mp_obj_get_type(o1); // If a full equality test is not needed and the other object is a different // type then we don't need to bother trying the comparison. - if (type->binary_op != NULL && + if (MP_OBJ_TYPE_HAS_SLOT(type, binary_op) && ((type->flags & MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE) || mp_obj_get_type(o2) == type)) { // CPython is asymmetric: it will try __eq__ if there's no __ne__ but not the // other way around. If the class doesn't need a full test we can skip __ne__. if (op == MP_BINARY_OP_NOT_EQUAL && (type->flags & MP_TYPE_FLAG_EQ_HAS_NEQ_TEST)) { - mp_obj_t r = type->binary_op(MP_BINARY_OP_NOT_EQUAL, o1, o2); + mp_obj_t r = MP_OBJ_TYPE_GET_SLOT(type, binary_op)(MP_BINARY_OP_NOT_EQUAL, o1, o2); if (r != MP_OBJ_NULL) { return r; } } // Try calling __eq__. - mp_obj_t r = type->binary_op(MP_BINARY_OP_EQUAL, o1, o2); + mp_obj_t r = MP_OBJ_TYPE_GET_SLOT(type, binary_op)(MP_BINARY_OP_EQUAL, o1, o2); if (r != MP_OBJ_NULL) { if (op == MP_BINARY_OP_EQUAL) { return r; @@ -524,8 +524,8 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { return MP_OBJ_NEW_SMALL_INT(l); } else { const mp_obj_type_t *type = mp_obj_get_type(o_in); - if (type->unary_op != NULL) { - return type->unary_op(MP_UNARY_OP_LEN, o_in); + if (MP_OBJ_TYPE_HAS_SLOT(type, unary_op)) { + return MP_OBJ_TYPE_GET_SLOT(type, unary_op)(MP_UNARY_OP_LEN, o_in); } else { return MP_OBJ_NULL; } @@ -534,8 +534,8 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { const mp_obj_type_t *type = mp_obj_get_type(base); - if (type->subscr != NULL) { - mp_obj_t ret = type->subscr(base, index, value); + if (MP_OBJ_TYPE_HAS_SLOT(type, subscr)) { + mp_obj_t ret = MP_OBJ_TYPE_GET_SLOT(type, subscr)(base, index, value); if (ret != MP_OBJ_NULL) { return ret; } @@ -579,10 +579,10 @@ mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf) { bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) { const mp_obj_type_t *type = mp_obj_get_type(obj); - if (type->buffer == NULL) { + if (!MP_OBJ_TYPE_HAS_SLOT(type, buffer)) { return false; } - int ret = type->buffer(obj, bufinfo, flags); + int ret = MP_OBJ_TYPE_GET_SLOT(type, buffer)(obj, bufinfo, flags); if (ret != 0) { return false; } diff --git a/py/obj.h b/py/obj.h index 9c0f41dc3d..37e6f00524 100644 --- a/py/obj.h +++ b/py/obj.h @@ -660,6 +660,16 @@ typedef mp_obj_type_t mp_obj_full_type_t; #define MP_DEFINE_CONST_OBJ_TYPE_NARGS_11(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6, .f7 = v7, .f8 = v8, .f9 = v9, .f10 = v10, .f11 = v11 } #define MP_DEFINE_CONST_OBJ_TYPE_NARGS_12(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11, f12, v12) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6, .f7 = v7, .f8 = v8, .f9 = v9, .f10 = v10, .f11 = v11, .f12 = v12 } +// Always safe, checks if the type can and does have this slot. +#define MP_OBJ_TYPE_HAS_SLOT(t, f) ((t)->f) +// Requires you know that this type can have this slot. +#define MP_OBJ_TYPE_GET_SLOT(t, f) ((t)->f) +// Always safe, returns NULL if the type cannot have this slot. +#define MP_OBJ_TYPE_GET_SLOT_OR_NULL(t, f) ((t)->f) +#define MP_OBJ_TYPE_SET_SLOT(t, f, v, n) ((t)->f = v) +#define MP_OBJ_TYPE_OFFSETOF_SLOT(f) (offsetof(mp_obj_type_t, f)) +#define MP_OBJ_TYPE_HAS_SLOT_BY_OFFSET(t, offset) (*(void **)((char *)(t) + (offset)) != NULL) + // Workaround for https://docs.microsoft.com/en-us/cpp/preprocessor/preprocessor-experimental-overview?view=msvc-160#macro-arguments-are-unpacked #define MP_DEFINE_CONST_OBJ_TYPE_EXPAND(x) x @@ -822,7 +832,7 @@ void *mp_obj_malloc_helper(size_t num_bytes, const mp_obj_type_t *type); #endif #define mp_obj_is_int(o) (mp_obj_is_small_int(o) || mp_obj_is_exact_type(o, &mp_type_int)) #define mp_obj_is_str(o) (mp_obj_is_qstr(o) || mp_obj_is_exact_type(o, &mp_type_str)) -#define mp_obj_is_str_or_bytes(o) (mp_obj_is_qstr(o) || (mp_obj_is_obj(o) && ((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type->binary_op == mp_obj_str_binary_op)) +#define mp_obj_is_str_or_bytes(o) (mp_obj_is_qstr(o) || (mp_obj_is_obj(o) && MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type, binary_op) == mp_obj_str_binary_op)) #define mp_obj_is_dict_or_ordereddict(o) (mp_obj_is_obj(o) && ((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type->make_new == mp_obj_dict_make_new) #define mp_obj_is_fun(o) (mp_obj_is_obj(o) && (((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type->name == MP_QSTR_function)) diff --git a/py/objarray.c b/py/objarray.c index 1cb163c4b9..762a4105c5 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -443,7 +443,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value size_t src_len; void *src_items; size_t item_sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL); - if (mp_obj_is_obj(value) && ((mp_obj_base_t *)MP_OBJ_TO_PTR(value))->type->subscr == array_subscr) { + if (mp_obj_is_obj(value) && MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_base_t *)MP_OBJ_TO_PTR(value))->type, subscr) == array_subscr) { // value is array, bytearray or memoryview mp_obj_array_t *src_slice = MP_OBJ_TO_PTR(value); if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) { diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index b212993506..cc55aec0b9 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -157,14 +157,14 @@ STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t o->base.base.type = &mp_type_type; o->base.flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE; // can match tuple o->base.name = name; - o->base.print = namedtuple_print; o->base.make_new = namedtuple_make_new; - o->base.unary_op = mp_obj_tuple_unary_op; - o->base.binary_op = mp_obj_tuple_binary_op; - o->base.attr = namedtuple_attr; - o->base.subscr = mp_obj_tuple_subscr; - o->base.getiter = mp_obj_tuple_getiter; - o->base.parent = &mp_type_tuple; + MP_OBJ_TYPE_SET_SLOT(&o->base, print, namedtuple_print, 0); + MP_OBJ_TYPE_SET_SLOT(&o->base, unary_op, mp_obj_tuple_unary_op, 1); + MP_OBJ_TYPE_SET_SLOT(&o->base, binary_op, mp_obj_tuple_binary_op, 2); + MP_OBJ_TYPE_SET_SLOT(&o->base, attr, namedtuple_attr, 3); + MP_OBJ_TYPE_SET_SLOT(&o->base, subscr, mp_obj_tuple_subscr, 4); + MP_OBJ_TYPE_SET_SLOT(&o->base, getiter, mp_obj_tuple_getiter, 5); + MP_OBJ_TYPE_SET_SLOT(&o->base, parent, &mp_type_tuple, 6); return MP_OBJ_FROM_PTR(o); } diff --git a/py/objtuple.c b/py/objtuple.c index a684b13e6f..01b2fa1488 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -32,7 +32,7 @@ #include "py/runtime.h" // type check is done on getiter method to allow tuple, namedtuple, attrtuple -#define mp_obj_is_tuple_compatible(o) (mp_obj_get_type(o)->getiter == mp_obj_tuple_getiter) +#define mp_obj_is_tuple_compatible(o) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(o), getiter) == mp_obj_tuple_getiter) /******************************************************************************/ /* tuple */ @@ -111,7 +111,7 @@ STATIC mp_obj_t tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t anothe mp_check_self(mp_obj_is_tuple_compatible(self_in)); const mp_obj_type_t *another_type = mp_obj_get_type(another_in); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); - if (another_type->getiter != mp_obj_tuple_getiter) { + if (MP_OBJ_TYPE_GET_SLOT_OR_NULL(another_type, getiter) != mp_obj_tuple_getiter) { // Slow path for user subclasses another_in = mp_obj_cast_to_native_base(another_in, MP_OBJ_FROM_PTR(&mp_type_tuple)); if (another_in == MP_OBJ_NULL) { diff --git a/py/objtype.c b/py/objtype.c index cc5a5e5802..968d6eb3ac 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -59,13 +59,13 @@ STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_t // Native types don't have parents (at least not from our perspective) so end. *last_native_base = type; return count + 1; - } else if (type->parent == NULL) { + } else if (!MP_OBJ_TYPE_HAS_SLOT(type, parent)) { // No parents so end search here. return count; #if MICROPY_MULTIPLE_INHERITANCE - } else if (((mp_obj_base_t *)type->parent)->type == &mp_type_tuple) { + } else if (((mp_obj_base_t *)MP_OBJ_TYPE_GET_SLOT(type, parent))->type == &mp_type_tuple) { // Multiple parents, search through them all recursively. - const mp_obj_tuple_t *parent_tuple = type->parent; + const mp_obj_tuple_t *parent_tuple = MP_OBJ_TYPE_GET_SLOT(type, parent); const mp_obj_t *item = parent_tuple->items; const mp_obj_t *top = item + parent_tuple->len; for (; item < top; ++item) { @@ -77,7 +77,7 @@ STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_t #endif } else { // A single parent, use iteration to continue the search. - type = type->parent; + type = MP_OBJ_TYPE_GET_SLOT(type, parent); } } } @@ -118,7 +118,7 @@ mp_obj_instance_t *mp_obj_new_instance(const mp_obj_type_t *class, const mp_obj_ // will keep lookup->dest[0]'s value (should be MP_OBJ_NULL on invocation) if attribute // is not found // will set lookup->dest[0] to MP_OBJ_SENTINEL if special method was found in a native -// type base via slot id (as specified by lookup->meth_offset). As there can be only one +// type base via slot id (as specified by lookup->slot_offset). As there can be only one // native base, it's known that it applies to instance->subobj[0]. In most cases, we also // don't need to know which type it was - because instance->subobj[0] is of that type. // The only exception is when object is not yet constructed, then we need to know base @@ -127,7 +127,7 @@ mp_obj_instance_t *mp_obj_new_instance(const mp_obj_type_t *class, const mp_obj_ struct class_lookup_data { mp_obj_instance_t *obj; qstr attr; - size_t meth_offset; + size_t slot_offset; mp_obj_t *dest; bool is_type; }; @@ -141,19 +141,19 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_t // This avoids extra method_name => slot lookup. On the other hand, // this should not be applied to class types, as will result in extra // lookup either. - if (lookup->meth_offset != 0 && mp_obj_is_native_type(type)) { - if (*(void **)((char *)type + lookup->meth_offset) != NULL) { + if (lookup->slot_offset != 0 && mp_obj_is_native_type(type)) { + if (MP_OBJ_TYPE_HAS_SLOT_BY_OFFSET(type, lookup->slot_offset)) { DEBUG_printf("mp_obj_class_lookup: Matched special meth slot (off=%d) for %s\n", - lookup->meth_offset, qstr_str(lookup->attr)); + lookup->slot_offset, qstr_str(lookup->attr)); lookup->dest[0] = MP_OBJ_SENTINEL; return; } } - if (type->locals_dict != NULL) { + if (MP_OBJ_TYPE_HAS_SLOT(type, locals_dict)) { // search locals_dict (the set of methods/attributes) - assert(mp_obj_is_dict_or_ordereddict(MP_OBJ_FROM_PTR(type->locals_dict))); // MicroPython restriction, for now - mp_map_t *locals_map = &type->locals_dict->map; + assert(mp_obj_is_dict_or_ordereddict(MP_OBJ_FROM_PTR(MP_OBJ_TYPE_GET_SLOT(type, locals_dict)))); // MicroPython restriction, for now + mp_map_t *locals_map = &MP_OBJ_TYPE_GET_SLOT(type, locals_dict)->map; mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(lookup->attr), MP_MAP_LOOKUP); if (elem != NULL) { if (lookup->is_type) { @@ -197,12 +197,12 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_t // attribute not found, keep searching base classes - if (type->parent == NULL) { + if (!MP_OBJ_TYPE_HAS_SLOT(type, parent)) { DEBUG_printf("mp_obj_class_lookup: No more parents\n"); return; #if MICROPY_MULTIPLE_INHERITANCE - } else if (((mp_obj_base_t *)type->parent)->type == &mp_type_tuple) { - const mp_obj_tuple_t *parent_tuple = type->parent; + } else if (((mp_obj_base_t *)MP_OBJ_TYPE_GET_SLOT(type, parent))->type == &mp_type_tuple) { + const mp_obj_tuple_t *parent_tuple = MP_OBJ_TYPE_GET_SLOT(type, parent); const mp_obj_t *item = parent_tuple->items; const mp_obj_t *top = item + parent_tuple->len - 1; for (; item < top; ++item) { @@ -223,7 +223,7 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_t type = (mp_obj_type_t *)MP_OBJ_TO_PTR(*item); #endif } else { - type = type->parent; + type = MP_OBJ_TYPE_GET_SLOT(type, parent); } if (type == &mp_type_object) { // Not a "real" type @@ -239,7 +239,7 @@ STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k struct class_lookup_data lookup = { .obj = self, .attr = meth, - .meth_offset = offsetof(mp_obj_type_t, print), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(print), .dest = member, .is_type = false, }; @@ -247,7 +247,7 @@ STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k if (member[0] == MP_OBJ_NULL && kind == PRINT_STR) { // If there's no __str__, fall back to __repr__ lookup.attr = MP_QSTR___repr__; - lookup.meth_offset = 0; + lookup.slot_offset = 0; mp_obj_class_lookup(&lookup, self->base.type); } @@ -282,7 +282,7 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size struct class_lookup_data lookup = { .obj = NULL, .attr = MP_QSTR___new__, - .meth_offset = offsetof(mp_obj_type_t, make_new), + .slot_offset = offsetof(mp_obj_type_t, make_new), .dest = init_fn, .is_type = false, }; @@ -332,7 +332,7 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size init_fn[0] = init_fn[1] = MP_OBJ_NULL; lookup.obj = o; lookup.attr = MP_QSTR___init__; - lookup.meth_offset = 0; + lookup.slot_offset = 0; mp_obj_class_lookup(&lookup, self); if (init_fn[0] != MP_OBJ_NULL) { mp_obj_t init_ret; @@ -414,7 +414,7 @@ STATIC mp_obj_t instance_unary_op(mp_unary_op_t op, mp_obj_t self_in) { struct class_lookup_data lookup = { .obj = self, .attr = op_name, - .meth_offset = offsetof(mp_obj_type_t, unary_op), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(unary_op), .dest = member, .is_type = false, }; @@ -542,7 +542,7 @@ retry:; struct class_lookup_data lookup = { .obj = lhs, .attr = op_name, - .meth_offset = offsetof(mp_obj_type_t, binary_op), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(binary_op), .dest = dest, .is_type = false, }; @@ -608,7 +608,7 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des struct class_lookup_data lookup = { .obj = self, .attr = attr, - .meth_offset = 0, + .slot_offset = 0, .dest = dest, .is_type = false, }; @@ -693,7 +693,7 @@ STATIC bool mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t val struct class_lookup_data lookup = { .obj = self, .attr = attr, - .meth_offset = 0, + .slot_offset = 0, .dest = member, .is_type = false, }; @@ -815,7 +815,7 @@ STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value mp_obj_t member[4] = {MP_OBJ_NULL, MP_OBJ_NULL, index, value}; struct class_lookup_data lookup = { .obj = self, - .meth_offset = offsetof(mp_obj_type_t, subscr), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(subscr), .dest = member, .is_type = false, }; @@ -850,7 +850,7 @@ STATIC mp_obj_t mp_obj_instance_get_call(mp_obj_t self_in, mp_obj_t *member) { struct class_lookup_data lookup = { .obj = self, .attr = MP_QSTR___call__, - .meth_offset = offsetof(mp_obj_type_t, call), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(call), .dest = member, .is_type = false, }; @@ -889,7 +889,7 @@ mp_obj_t mp_obj_instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) struct class_lookup_data lookup = { .obj = self, .attr = MP_QSTR___iter__, - .meth_offset = offsetof(mp_obj_type_t, getiter), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(getiter), .dest = member, .is_type = false, }; @@ -901,7 +901,7 @@ mp_obj_t mp_obj_instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) if (iter_buf == NULL) { iter_buf = m_new_obj(mp_obj_iter_buf_t); } - return type->getiter(self->subobj[0], iter_buf); + return MP_OBJ_TYPE_GET_SLOT(type, getiter)(self->subobj[0], iter_buf); } else { return mp_call_method_n_kw(0, 0, member); } @@ -913,14 +913,14 @@ STATIC mp_int_t instance_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, struct class_lookup_data lookup = { .obj = self, .attr = MP_QSTR_, // don't actually look for a method - .meth_offset = offsetof(mp_obj_type_t, buffer), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(buffer), .dest = member, .is_type = false, }; mp_obj_class_lookup(&lookup, self->base.type); if (member[0] == MP_OBJ_SENTINEL) { const mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]); - return type->buffer(self->subobj[0], bufinfo, flags); + return MP_OBJ_TYPE_GET_SLOT(type, buffer)(self->subobj[0], bufinfo, flags); } else { return 1; // object does not support buffer protocol } @@ -1021,7 +1021,7 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (attr == MP_QSTR___dict__) { // Returns a read-only dict of the class attributes. // If the internal locals is not fixed, a copy will be created. - const mp_obj_dict_t *dict = self->locals_dict; + const mp_obj_dict_t *dict = MP_OBJ_TYPE_GET_SLOT_OR_NULL(self, locals_dict); if (!dict) { dict = &mp_const_empty_dict_obj; } @@ -1040,7 +1040,7 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { dest[0] = mp_const_empty_tuple; return; } - mp_obj_t parent_obj = self->parent ? MP_OBJ_FROM_PTR(self->parent) : MP_OBJ_FROM_PTR(&mp_type_object); + mp_obj_t parent_obj = MP_OBJ_TYPE_HAS_SLOT(self, parent) ? MP_OBJ_FROM_PTR(MP_OBJ_TYPE_GET_SLOT(self, parent)) : MP_OBJ_FROM_PTR(&mp_type_object); #if MICROPY_MULTIPLE_INHERITANCE if (mp_obj_is_type(parent_obj, &mp_type_tuple)) { dest[0] = parent_obj; @@ -1054,7 +1054,7 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { struct class_lookup_data lookup = { .obj = (mp_obj_instance_t *)self, .attr = attr, - .meth_offset = 0, + .slot_offset = 0, .dest = dest, .is_type = true, }; @@ -1062,9 +1062,9 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } else { // delete/store attribute - if (self->locals_dict != NULL) { - assert(mp_obj_is_dict_or_ordereddict(MP_OBJ_FROM_PTR(self->locals_dict))); // MicroPython restriction, for now - mp_map_t *locals_map = &self->locals_dict->map; + if (MP_OBJ_TYPE_HAS_SLOT(self, locals_dict)) { + assert(mp_obj_is_dict_or_ordereddict(MP_OBJ_FROM_PTR(MP_OBJ_TYPE_GET_SLOT(self, locals_dict)))); // MicroPython restriction, for now + mp_map_t *locals_map = &MP_OBJ_TYPE_GET_SLOT(self, locals_dict)->map; if (locals_map->is_fixed) { // can't apply delete/store to a fixed map return; @@ -1155,43 +1155,44 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) o->base.type = &mp_type_type; o->flags = base_flags; o->name = name; - o->print = instance_print; o->make_new = mp_obj_instance_make_new; - o->call = mp_obj_instance_call; - o->unary_op = instance_unary_op; - o->binary_op = instance_binary_op; - o->attr = mp_obj_instance_attr; - o->subscr = instance_subscr; - o->getiter = mp_obj_instance_getiter; - // o->iternext = ; not implemented - o->buffer = instance_get_buffer; + MP_OBJ_TYPE_SET_SLOT(o, print, instance_print, 0); + MP_OBJ_TYPE_SET_SLOT(o, call, mp_obj_instance_call, 1); + MP_OBJ_TYPE_SET_SLOT(o, unary_op, instance_unary_op, 2); + MP_OBJ_TYPE_SET_SLOT(o, binary_op, instance_binary_op, 3); + MP_OBJ_TYPE_SET_SLOT(o, attr, mp_obj_instance_attr, 4); + MP_OBJ_TYPE_SET_SLOT(o, subscr, instance_subscr, 5); + MP_OBJ_TYPE_SET_SLOT(o, getiter, mp_obj_instance_getiter, 6); + // MP_OBJ_TYPE_SET_SLOT(o, iternext, not implemented) + MP_OBJ_TYPE_SET_SLOT(o, buffer, instance_get_buffer, 7); if (bases_len > 0) { // Inherit protocol from a base class. This allows to define an // abstract base class which would translate C-level protocol to // Python method calls, and any subclass inheriting from it will // support this feature. - o->protocol = ((mp_obj_type_t *)MP_OBJ_TO_PTR(bases_items[0]))->protocol; + MP_OBJ_TYPE_SET_SLOT(o, protocol, MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_type_t *)MP_OBJ_TO_PTR(bases_items[0])), protocol), 8); if (bases_len >= 2) { #if MICROPY_MULTIPLE_INHERITANCE - o->parent = MP_OBJ_TO_PTR(bases_tuple); + MP_OBJ_TYPE_SET_SLOT(o, parent, MP_OBJ_TO_PTR(bases_tuple), 9); #else mp_raise_NotImplementedError(MP_ERROR_TEXT("multiple inheritance not supported")); #endif } else { - o->parent = MP_OBJ_TO_PTR(bases_items[0]); + MP_OBJ_TYPE_SET_SLOT(o, parent, MP_OBJ_TO_PTR(bases_items[0]), 9); } } - o->locals_dict = MP_OBJ_TO_PTR(locals_dict); + mp_obj_dict_t *locals_ptr = MP_OBJ_TO_PTR(locals_dict); + MP_OBJ_TYPE_SET_SLOT(o, locals_dict, locals_ptr, 10); #if ENABLE_SPECIAL_ACCESSORS // Check if the class has any special accessor methods if (!(o->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { - for (size_t i = 0; i < o->locals_dict->map.alloc; i++) { - if (mp_map_slot_is_filled(&o->locals_dict->map, i)) { - const mp_map_elem_t *elem = &o->locals_dict->map.table[i]; + for (size_t i = 0; i < locals_ptr->map.alloc; i++) { + if (mp_map_slot_is_filled(&locals_ptr->map, i)) { + const mp_map_elem_t *elem = &locals_ptr->map.table[i]; if (check_for_special_accessors(elem->key, elem->value)) { o->flags |= MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS; break; @@ -1207,7 +1208,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) mp_raise_TypeError(MP_ERROR_TEXT("multiple bases have instance lay-out conflict")); } - mp_map_t *locals_map = &o->locals_dict->map; + mp_map_t *locals_map = &MP_OBJ_TYPE_GET_SLOT(o, locals_dict)->map; mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(MP_QSTR___new__), MP_MAP_LOOKUP); if (elem != NULL) { // __new__ slot exists; check if it is a function @@ -1268,21 +1269,21 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { struct class_lookup_data lookup = { .obj = MP_OBJ_TO_PTR(self->obj), .attr = attr, - .meth_offset = 0, + .slot_offset = 0, .dest = dest, .is_type = false, }; - // Allow a call super().__init__() to reach any native base classes + // Allow a call super().__init__() to reach any native base classes. if (attr == MP_QSTR___init__) { - lookup.meth_offset = offsetof(mp_obj_type_t, make_new); + lookup.slot_offset = offsetof(mp_obj_type_t, make_new); } - if (type->parent == NULL) { + if (!MP_OBJ_TYPE_HAS_SLOT(type, parent)) { // no parents, do nothing #if MICROPY_MULTIPLE_INHERITANCE - } else if (((mp_obj_base_t *)type->parent)->type == &mp_type_tuple) { - const mp_obj_tuple_t *parent_tuple = type->parent; + } else if (((mp_obj_base_t *)MP_OBJ_TYPE_GET_SLOT(type, parent))->type == &mp_type_tuple) { + const mp_obj_tuple_t *parent_tuple = MP_OBJ_TYPE_GET_SLOT(type, parent); size_t len = parent_tuple->len; const mp_obj_t *items = parent_tuple->items; for (size_t i = 0; i < len; i++) { @@ -1292,14 +1293,15 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { // and we don't want to lookup native methods in object. continue; } + mp_obj_class_lookup(&lookup, (mp_obj_type_t *)MP_OBJ_TO_PTR(items[i])); if (dest[0] != MP_OBJ_NULL) { break; } } #endif - } else if (type->parent != &mp_type_object) { - mp_obj_class_lookup(&lookup, type->parent); + } else if (MP_OBJ_TYPE_GET_SLOT(type, parent) != &mp_type_object) { + mp_obj_class_lookup(&lookup, MP_OBJ_TYPE_GET_SLOT(type, parent)); } if (dest[0] != MP_OBJ_NULL) { @@ -1311,9 +1313,9 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { return; } - // Reset meth_offset so we don't look up any native methods in object, + // Reset slot_offset so we don't look up any native methods in object, // because object never takes up the native base-class slot. - lookup.meth_offset = 0; + lookup.slot_offset = 0; mp_obj_class_lookup(&lookup, &mp_type_object); } @@ -1352,13 +1354,13 @@ bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) { const mp_obj_type_t *self = MP_OBJ_TO_PTR(object); - if (self->parent == NULL) { + if (!MP_OBJ_TYPE_HAS_SLOT(self, parent)) { // type has no parents return false; #if MICROPY_MULTIPLE_INHERITANCE - } else if (((mp_obj_base_t *)self->parent)->type == &mp_type_tuple) { + } else if (((mp_obj_base_t *)MP_OBJ_TYPE_GET_SLOT(self, parent))->type == &mp_type_tuple) { // get the base objects (they should be type objects) - const mp_obj_tuple_t *parent_tuple = self->parent; + const mp_obj_tuple_t *parent_tuple = MP_OBJ_TYPE_GET_SLOT(self, parent); const mp_obj_t *item = parent_tuple->items; const mp_obj_t *top = item + parent_tuple->len - 1; @@ -1374,7 +1376,7 @@ bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) { #endif } else { // type has 1 parent - object = MP_OBJ_FROM_PTR(self->parent); + object = MP_OBJ_FROM_PTR(MP_OBJ_TYPE_GET_SLOT(self, parent)); } } } diff --git a/py/opmethods.c b/py/opmethods.c index 595cc088ba..c3931fd358 100644 --- a/py/opmethods.c +++ b/py/opmethods.c @@ -29,24 +29,28 @@ STATIC mp_obj_t op_getitem(mp_obj_t self_in, mp_obj_t key_in) { const mp_obj_type_t *type = mp_obj_get_type(self_in); - return type->subscr(self_in, key_in, MP_OBJ_SENTINEL); + // Note: assumes type must have subscr (only used by dict). + return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, MP_OBJ_SENTINEL); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_getitem_obj, op_getitem); STATIC mp_obj_t op_setitem(mp_obj_t self_in, mp_obj_t key_in, mp_obj_t value_in) { const mp_obj_type_t *type = mp_obj_get_type(self_in); - return type->subscr(self_in, key_in, value_in); + // Note: assumes type must have subscr (only used by dict). + return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, value_in); } MP_DEFINE_CONST_FUN_OBJ_3(mp_op_setitem_obj, op_setitem); STATIC mp_obj_t op_delitem(mp_obj_t self_in, mp_obj_t key_in) { const mp_obj_type_t *type = mp_obj_get_type(self_in); - return type->subscr(self_in, key_in, MP_OBJ_NULL); + // Note: assumes type must have subscr (only used by dict). + return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, MP_OBJ_NULL); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_delitem_obj, op_delitem); STATIC mp_obj_t op_contains(mp_obj_t lhs_in, mp_obj_t rhs_in) { const mp_obj_type_t *type = mp_obj_get_type(lhs_in); - return type->binary_op(MP_BINARY_OP_CONTAINS, lhs_in, rhs_in); + // Note: assumes type must have binary_op (only used by set/frozenset). + return MP_OBJ_TYPE_GET_SLOT(type, binary_op)(MP_BINARY_OP_CONTAINS, lhs_in, rhs_in); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_contains_obj, op_contains); diff --git a/py/runtime.c b/py/runtime.c index 27b4f05f04..d0e504a3d0 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -307,8 +307,8 @@ mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) { return MP_OBJ_NEW_SMALL_INT(h); } else { const mp_obj_type_t *type = mp_obj_get_type(arg); - if (type->unary_op != NULL) { - mp_obj_t result = type->unary_op(op, arg); + if (MP_OBJ_TYPE_HAS_SLOT(type, unary_op)) { + mp_obj_t result = MP_OBJ_TYPE_GET_SLOT(type, unary_op)(op, arg); if (result != MP_OBJ_NULL) { return result; } @@ -613,8 +613,8 @@ mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs const mp_obj_type_t *type; generic_binary_op: type = mp_obj_get_type(lhs); - if (type->binary_op != NULL) { - mp_obj_t result = type->binary_op(op, lhs, rhs); + if (MP_OBJ_TYPE_HAS_SLOT(type, binary_op)) { + mp_obj_t result = MP_OBJ_TYPE_GET_SLOT(type, binary_op)(op, lhs, rhs); if (result != MP_OBJ_NULL) { return result; } @@ -689,8 +689,8 @@ mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, size_t n_args, size_t n_kw, cons const mp_obj_type_t *type = mp_obj_get_type(fun_in); // do the call - if (type->call != NULL) { - return type->call(fun_in, n_args, n_kw, args); + if (MP_OBJ_TYPE_HAS_SLOT(type, call)) { + return MP_OBJ_TYPE_GET_SLOT(type, call)(fun_in, n_args, n_kw, args); } #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE @@ -1167,14 +1167,14 @@ void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest) { } #endif - if (attr == MP_QSTR___next__ && type->iternext != NULL) { + if (attr == MP_QSTR___next__ && MP_OBJ_TYPE_HAS_SLOT(type, iternext)) { dest[0] = MP_OBJ_FROM_PTR(&mp_builtin_next_obj); dest[1] = obj; return; } - if (type->attr != NULL) { + if (MP_OBJ_TYPE_HAS_SLOT(type, attr)) { // this type can do its own load, so call it - type->attr(obj, attr, dest); + MP_OBJ_TYPE_GET_SLOT(type, attr)(obj, attr, dest); // If type->attr has set dest[1] = MP_OBJ_SENTINEL, we should proceed // with lookups below (i.e. in locals_dict). If not, return right away. if (dest[1] != MP_OBJ_SENTINEL) { @@ -1183,11 +1183,11 @@ void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest) { // Clear the fail flag set by type->attr so it's like it never ran. dest[1] = MP_OBJ_NULL; } - if (type->locals_dict != NULL) { + if (MP_OBJ_TYPE_HAS_SLOT(type, locals_dict)) { // generic method lookup // this is a lookup in the object (ie not class or type) - assert(type->locals_dict->base.type == &mp_type_dict); // MicroPython restriction, for now - mp_map_t *locals_map = &type->locals_dict->map; + assert(MP_OBJ_TYPE_GET_SLOT(type, locals_dict)->base.type == &mp_type_dict); // MicroPython restriction, for now + mp_map_t *locals_map = &MP_OBJ_TYPE_GET_SLOT(type, locals_dict)->map; mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP); if (elem != NULL) { mp_convert_member_lookup(obj, type, elem->value, dest); @@ -1239,9 +1239,9 @@ void mp_load_method_protected(mp_obj_t obj, qstr attr, mp_obj_t *dest, bool catc void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), value); const mp_obj_type_t *type = mp_obj_get_type(base); - if (type->attr != NULL) { + if (MP_OBJ_TYPE_HAS_SLOT(type, attr)) { mp_obj_t dest[2] = {MP_OBJ_SENTINEL, value}; - type->attr(base, attr, dest); + MP_OBJ_TYPE_GET_SLOT(type, attr)(base, attr, dest); if (dest[0] == MP_OBJ_NULL) { // success return; @@ -1260,20 +1260,21 @@ mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { assert(o_in); const mp_obj_type_t *type = mp_obj_get_type(o_in); - // Check for native getiter which is the identity. We handle this case explicitly - // so we don't unnecessarily allocate any RAM for the iter_buf, which won't be used. - if (type->getiter == mp_identity_getiter) { - return o_in; - } - // check for native getiter (corresponds to __iter__) - if (type->getiter != NULL) { - if (iter_buf == NULL && type->getiter != mp_obj_instance_getiter) { + if (MP_OBJ_TYPE_HAS_SLOT(type, getiter)) { + // Check for native getiter which is the identity. We handle this case explicitly + // so we don't unnecessarily allocate any RAM for the iter_buf, which won't be used. + if (MP_OBJ_TYPE_GET_SLOT(type, getiter) == mp_identity_getiter) { + return o_in; + } + + // check for native getiter (corresponds to __iter__) + if (iter_buf == NULL && MP_OBJ_TYPE_GET_SLOT(type, getiter) != mp_obj_instance_getiter) { // if caller did not provide a buffer then allocate one on the heap // mp_obj_instance_getiter is special, it will allocate only if needed iter_buf = m_new_obj(mp_obj_iter_buf_t); } - mp_obj_t iter = type->getiter(o_in, iter_buf); + mp_obj_t iter = MP_OBJ_TYPE_GET_SLOT(type, getiter)(o_in, iter_buf); if (iter != MP_OBJ_NULL) { return iter; } @@ -1305,9 +1306,9 @@ mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { // may also raise StopIteration() mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) { const mp_obj_type_t *type = mp_obj_get_type(o_in); - if (type->iternext != NULL) { + if (MP_OBJ_TYPE_HAS_SLOT(type, iternext)) { MP_STATE_THREAD(stop_iteration_arg) = MP_OBJ_NULL; - return type->iternext(o_in); + return MP_OBJ_TYPE_GET_SLOT(type, iternext)(o_in); } else { // check for __next__ method mp_obj_t dest[2]; @@ -1331,9 +1332,9 @@ mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) { mp_obj_t mp_iternext(mp_obj_t o_in) { MP_STACK_CHECK(); // enumerate, filter, map and zip can recursively call mp_iternext const mp_obj_type_t *type = mp_obj_get_type(o_in); - if (type->iternext != NULL) { + if (MP_OBJ_TYPE_HAS_SLOT(type, iternext)) { MP_STATE_THREAD(stop_iteration_arg) = MP_OBJ_NULL; - return type->iternext(o_in); + return MP_OBJ_TYPE_GET_SLOT(type, iternext)(o_in); } else { // check for __next__ method mp_obj_t dest[2]; @@ -1371,9 +1372,9 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th return mp_obj_gen_resume(self_in, send_value, throw_value, ret_val); } - if (type->iternext != NULL && send_value == mp_const_none) { + if (MP_OBJ_TYPE_HAS_SLOT(type, iternext) && send_value == mp_const_none) { MP_STATE_THREAD(stop_iteration_arg) = MP_OBJ_NULL; - mp_obj_t ret = type->iternext(self_in); + mp_obj_t ret = MP_OBJ_TYPE_GET_SLOT(type, iternext)(self_in); *ret_val = ret; if (ret != MP_OBJ_STOP_ITERATION) { return MP_VM_RETURN_YIELD; diff --git a/py/stream.c b/py/stream.c index 87bed38f67..36325e7d41 100644 --- a/py/stream.c +++ b/py/stream.c @@ -84,15 +84,16 @@ mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf_, mp_uint_t size, int *errcode const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) { const mp_obj_type_t *type = mp_obj_get_type(self_in); - const mp_stream_p_t *stream_p = type->protocol; - if (stream_p == NULL - || ((flags & MP_STREAM_OP_READ) && stream_p->read == NULL) - || ((flags & MP_STREAM_OP_WRITE) && stream_p->write == NULL) - || ((flags & MP_STREAM_OP_IOCTL) && stream_p->ioctl == NULL)) { - // CPython: io.UnsupportedOperation, OSError subclass - mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("stream operation not supported")); + if (MP_OBJ_TYPE_HAS_SLOT(type, protocol)) { + const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(type, protocol); + if (!((flags & MP_STREAM_OP_READ) && stream_p->read == NULL) + && !((flags & MP_STREAM_OP_WRITE) && stream_p->write == NULL) + && !((flags & MP_STREAM_OP_IOCTL) && stream_p->ioctl == NULL)) { + return stream_p; + } } - return stream_p; + // CPython: io.UnsupportedOperation, OSError subclass + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("stream operation not supported")); } STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte flags) { @@ -517,7 +518,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_ioctl_obj, 2, 3, stream_ioctl); ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) { mp_obj_base_t *o = stream; - const mp_stream_p_t *stream_p = o->type->protocol; + const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol); mp_uint_t out_sz = stream_p->write(MP_OBJ_FROM_PTR(stream), buf, len, &errno); if (out_sz == MP_STREAM_ERROR) { return -1; @@ -528,7 +529,7 @@ ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) { ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) { mp_obj_base_t *o = stream; - const mp_stream_p_t *stream_p = o->type->protocol; + const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol); mp_uint_t out_sz = stream_p->read(MP_OBJ_FROM_PTR(stream), buf, len, &errno); if (out_sz == MP_STREAM_ERROR) { return -1; @@ -539,7 +540,7 @@ ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) { off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) { const mp_obj_base_t *o = stream; - const mp_stream_p_t *stream_p = o->type->protocol; + const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol); struct mp_stream_seek_t seek_s; seek_s.offset = offset; seek_s.whence = whence; @@ -552,7 +553,7 @@ off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) { int mp_stream_posix_fsync(void *stream) { mp_obj_base_t *o = stream; - const mp_stream_p_t *stream_p = o->type->protocol; + const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol); mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_FLUSH, 0, &errno); if (res == MP_STREAM_ERROR) { return -1; diff --git a/py/stream.h b/py/stream.h index 45f36ef5a6..4bc329b3e7 100644 --- a/py/stream.h +++ b/py/stream.h @@ -95,7 +95,7 @@ MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_ioctl_obj); // Object is assumed to have a non-NULL stream protocol with valid r/w/ioctl methods static inline const mp_stream_p_t *mp_get_stream(mp_const_obj_t self) { - return (const mp_stream_p_t *)((const mp_obj_base_t *)MP_OBJ_TO_PTR(self))->type->protocol; + return (const mp_stream_p_t *)MP_OBJ_TYPE_GET_SLOT(((const mp_obj_base_t *)MP_OBJ_TO_PTR(self))->type, protocol); } const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags); From 3ac8b5851e5f4dade465d52b91ed2ccc17851263 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 15 Jul 2021 15:04:40 +1000 Subject: [PATCH 0422/1041] py/obj: Add slot-index mp_obj_type_t representation. The existings mp_obj_type_t uses a sparse representation for slots for the capability methods of the type (eg print, make_new). This commit adds a compact slot-index representation. The basic idea is that where the mp_obj_type_t struct used to have 12 pointer fields, it now has 12 uint8_t indices, and a variable-length array of pointers. So in the best case (no fields used) it saves 12x4-12=36 bytes (on a 32-bit machine) and in the common case (three fields used) it saves 9x4-12=24 bytes. Overall with all associated changes, this slot-index representation reduces code size by 1000 to 3000 bytes on bare-metal ports. Performance is marginally better on a few tests (eg about 1% better on misc_pystone.py and misc_raytrace.py on PYBv1.1), but overall marginally worse by a percent or so. See issue #7542 for further analysis and discussion. Signed-off-by: Jim Mussared --- py/mpconfig.h | 7 +++ py/obj.h | 121 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 125 insertions(+), 3 deletions(-) diff --git a/py/mpconfig.h b/py/mpconfig.h index 698d264d2e..0045fa1985 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -145,6 +145,13 @@ #define MICROPY_OBJ_IMMEDIATE_OBJS (MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D) #endif +#define MICROPY_OBJ_TYPE_REPR_FULL (0) +#define MICROPY_OBJ_TYPE_REPR_SLOT_INDEX (1) + +#ifndef MICROPY_OBJ_TYPE_REPR +#define MICROPY_OBJ_TYPE_REPR (MICROPY_OBJ_TYPE_REPR_FULL) +#endif + /*****************************************************************************/ /* Memory allocation policy */ diff --git a/py/obj.h b/py/obj.h index 37e6f00524..c17e0e5f18 100644 --- a/py/obj.h +++ b/py/obj.h @@ -575,12 +575,13 @@ struct _mp_obj_type_t { // The name of this type, a qstr. uint16_t name; - // Corresponds to __repr__ and __str__ special methods. - mp_print_fun_t print; - // Corresponds to __new__ and __init__ special methods, to make an instance of the type. mp_make_new_fun_t make_new; + #if MICROPY_OBJ_TYPE_REPR == MICROPY_OBJ_TYPE_REPR_FULL + // Corresponds to __repr__ and __str__ special methods. + mp_print_fun_t print; + // Corresponds to __call__ special method, ie T(...). mp_call_fun_t call; @@ -633,17 +634,87 @@ struct _mp_obj_type_t { // A dict mapping qstrs to objects local methods/constants/etc. struct _mp_obj_dict_t *locals_dict; + + #elif MICROPY_OBJ_TYPE_REPR == MICROPY_OBJ_TYPE_REPR_SLOT_INDEX + + // Ideally these would be only 4 bits, but the extra overhead of + // accessing them adds more code, and we also need to be able to + // take the address of them for mp_obj_class_lookup. + uint8_t slot_index_print; + uint8_t slot_index_call; + uint8_t slot_index_unary_op; + uint8_t slot_index_binary_op; + uint8_t slot_index_attr; + uint8_t slot_index_subscr; + uint8_t slot_index_getiter; + uint8_t slot_index_iternext; + uint8_t slot_index_buffer; + uint8_t slot_index_protocol; + uint8_t slot_index_parent; + uint8_t slot_index_locals_dict; + + const void *slots[]; + + #endif }; // Non-variable sized versions of mp_obj_type_t to be used as a member // in other structs or for dynamic allocation. The fields are exactly // as in mp_obj_type_t, but with a fixed size for the flexible array // members. +#if MICROPY_OBJ_TYPE_REPR == MICROPY_OBJ_TYPE_REPR_FULL typedef mp_obj_type_t mp_obj_empty_type_t; typedef mp_obj_type_t mp_obj_full_type_t; +#else +typedef struct _mp_obj_empty_type_t { + mp_obj_base_t base; + uint16_t flags; + uint16_t name; + mp_make_new_fun_t make_new; + + uint8_t slot_index_print; + uint8_t slot_index_call; + uint8_t slot_index_unary_op; + uint8_t slot_index_binary_op; + uint8_t slot_index_attr; + uint8_t slot_index_subscr; + uint8_t slot_index_getiter; + uint8_t slot_index_iternext; + uint8_t slot_index_buffer; + uint8_t slot_index_protocol; + uint8_t slot_index_parent; + uint8_t slot_index_locals_dict; + + // No slots member. +} mp_obj_empty_type_t; + +typedef struct _mp_obj_full_type_t { + mp_obj_base_t base; + uint16_t flags; + uint16_t name; + mp_make_new_fun_t make_new; + + uint8_t slot_index_print; + uint8_t slot_index_call; + uint8_t slot_index_unary_op; + uint8_t slot_index_binary_op; + uint8_t slot_index_attr; + uint8_t slot_index_subscr; + uint8_t slot_index_getiter; + uint8_t slot_index_iternext; + uint8_t slot_index_buffer; + uint8_t slot_index_protocol; + uint8_t slot_index_parent; + uint8_t slot_index_locals_dict; + + // Explicitly add 12 slots. + const void *slots[12]; +} mp_obj_full_type_t; +#endif #define MP_TYPE_NULL_MAKE_NEW (NULL) +#if MICROPY_OBJ_TYPE_REPR == MICROPY_OBJ_TYPE_REPR_FULL // Implementation of MP_DEFINE_CONST_OBJ_TYPE for each number of arguments. // Do not use these directly, instead use MP_DEFINE_CONST_OBJ_TYPE. #define MP_DEFINE_CONST_OBJ_TYPE_NARGS_0(_struct_type, _typename, _name, _flags, _make_new) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new } @@ -670,6 +741,50 @@ typedef mp_obj_type_t mp_obj_full_type_t; #define MP_OBJ_TYPE_OFFSETOF_SLOT(f) (offsetof(mp_obj_type_t, f)) #define MP_OBJ_TYPE_HAS_SLOT_BY_OFFSET(t, offset) (*(void **)((char *)(t) + (offset)) != NULL) +#elif MICROPY_OBJ_TYPE_REPR == MICROPY_OBJ_TYPE_REPR_SLOT_INDEX + +#define _MP_OBJ_TYPE_SLOT_TYPE_print (mp_print_fun_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_call (mp_call_fun_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_unary_op (mp_unary_op_fun_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_binary_op (mp_binary_op_fun_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_attr (mp_attr_fun_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_subscr (mp_subscr_fun_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_getiter (mp_getiter_fun_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_iternext (mp_fun_1_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_buffer (mp_buffer_fun_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_protocol (const void *) +#define _MP_OBJ_TYPE_SLOT_TYPE_parent (const void *) +#define _MP_OBJ_TYPE_SLOT_TYPE_locals_dict (struct _mp_obj_dict_t *) + +// Implementation of MP_DEFINE_CONST_OBJ_TYPE for each number of arguments. +// Do not use these directly, instead use MP_DEFINE_CONST_OBJ_TYPE. +// Generated with: +// for i in range(13): +// print(f"#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_{i}(_struct_type, _typename, _name, _flags, _make_new{''.join(f', f{j+1}, v{j+1}' for j in range(i))}) const _struct_type _typename = {{ .base = {{ &mp_type_type }}, .name = _name, .flags = _flags, .make_new = _make_new{''.join(f', .slot_index_##f{j+1} = {j+1}' for j in range(i))}{', .slots = { ' + ''.join(f'v{j+1}, ' for j in range(i)) + '}' if i else '' } }}") +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_0(_struct_type, _typename, _name, _flags, _make_new) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_1(_struct_type, _typename, _name, _flags, _make_new, f1, v1) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slots = { v1, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_2(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slots = { v1, v2, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_3(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slots = { v1, v2, v3, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_4(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slots = { v1, v2, v3, v4, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_5(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slots = { v1, v2, v3, v4, v5, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_6(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slots = { v1, v2, v3, v4, v5, v6, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_7(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slots = { v1, v2, v3, v4, v5, v6, v7, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_8(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_9(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_10(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_11(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_12(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11, f12, v12) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slot_index_##f12 = 12, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, } } + +#define MP_OBJ_TYPE_HAS_SLOT(t, f) ((t)->slot_index_##f) +#define MP_OBJ_TYPE_GET_SLOT(t, f) (_MP_OBJ_TYPE_SLOT_TYPE_##f(t)->slots[(t)->slot_index_##f - 1]) +#define MP_OBJ_TYPE_GET_SLOT_OR_NULL(t, f) (_MP_OBJ_TYPE_SLOT_TYPE_##f(MP_OBJ_TYPE_HAS_SLOT(t, f) ? MP_OBJ_TYPE_GET_SLOT(t, f) : NULL)) +#define MP_OBJ_TYPE_SET_SLOT(t, f, v, n) ((t)->slot_index_##f = (n) + 1, (t)->slots[(t)->slot_index_##f - 1] = (void *)v) +#define MP_OBJ_TYPE_OFFSETOF_SLOT(f) (offsetof(mp_obj_type_t, slot_index_##f)) +// For everything except make_new, the offset is to the uint8_t index. For make_new, we need to check the pointer. +#define MP_OBJ_TYPE_HAS_SLOT_BY_OFFSET(t, offset) (*(uint8_t *)((char *)(t) + (offset)) != 0 || (offset == offsetof(mp_obj_type_t, make_new) && t->make_new)) + +#endif + // Workaround for https://docs.microsoft.com/en-us/cpp/preprocessor/preprocessor-experimental-overview?view=msvc-160#macro-arguments-are-unpacked #define MP_DEFINE_CONST_OBJ_TYPE_EXPAND(x) x From cb0ffdd2bf25dcac3c230bdc1168d492aabaf573 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 22 Jun 2022 11:24:41 +1000 Subject: [PATCH 0423/1041] py/obj: Remove basic mp_obj_type_t sparse representation. This makes the slots-based representation the only option. Signed-off-by: Jim Mussared --- py/mpconfig.h | 7 ----- py/obj.h | 85 +++++++++++---------------------------------------- 2 files changed, 17 insertions(+), 75 deletions(-) diff --git a/py/mpconfig.h b/py/mpconfig.h index 0045fa1985..698d264d2e 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -145,13 +145,6 @@ #define MICROPY_OBJ_IMMEDIATE_OBJS (MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D) #endif -#define MICROPY_OBJ_TYPE_REPR_FULL (0) -#define MICROPY_OBJ_TYPE_REPR_SLOT_INDEX (1) - -#ifndef MICROPY_OBJ_TYPE_REPR -#define MICROPY_OBJ_TYPE_REPR (MICROPY_OBJ_TYPE_REPR_FULL) -#endif - /*****************************************************************************/ /* Memory allocation policy */ diff --git a/py/obj.h b/py/obj.h index c17e0e5f18..878fa67348 100644 --- a/py/obj.h +++ b/py/obj.h @@ -578,17 +578,22 @@ struct _mp_obj_type_t { // Corresponds to __new__ and __init__ special methods, to make an instance of the type. mp_make_new_fun_t make_new; - #if MICROPY_OBJ_TYPE_REPR == MICROPY_OBJ_TYPE_REPR_FULL + // Slots: For the rest of the fields, the slot index points to the + // relevant function in the variable-length "slots" field. Ideally these + // would be only 4 bits, but the extra overhead of accessing them adds + // more code, and we also need to be able to take the address of them for + // mp_obj_class_lookup. + // Corresponds to __repr__ and __str__ special methods. - mp_print_fun_t print; + uint8_t slot_index_print; // Corresponds to __call__ special method, ie T(...). - mp_call_fun_t call; + uint8_t slot_index_call; // Implements unary and binary operations. // Can return MP_OBJ_NULL if the operation is not supported. - mp_unary_op_fun_t unary_op; - mp_binary_op_fun_t binary_op; + uint8_t slot_index_unary_op; + uint8_t slot_index_binary_op; // Implements load, store and delete attribute. // @@ -602,70 +607,46 @@ struct _mp_obj_type_t { // dest[0,1] = {MP_OBJ_SENTINEL, object} means store // return: for fail, do nothing // for success set dest[0] = MP_OBJ_NULL - mp_attr_fun_t attr; + uint8_t slot_index_attr; // Implements load, store and delete subscripting: // - value = MP_OBJ_SENTINEL means load // - value = MP_OBJ_NULL means delete // - all other values mean store the value // Can return MP_OBJ_NULL if operation not supported. - mp_subscr_fun_t subscr; + uint8_t slot_index_subscr; // Corresponds to __iter__ special method. // Can use the given mp_obj_iter_buf_t to store iterator object, // otherwise can return a pointer to an object on the heap. - mp_getiter_fun_t getiter; + uint8_t slot_index_getiter; // Corresponds to __next__ special method. May return MP_OBJ_STOP_ITERATION // as an optimisation instead of raising StopIteration() with no args. - mp_fun_1_t iternext; + uint8_t slot_index_iternext; // Implements the buffer protocol if supported by this type. - mp_buffer_fun_t buffer; + uint8_t slot_index_buffer; // One of disjoint protocols (interfaces), like mp_stream_p_t, etc. - const void *protocol; + uint8_t slot_index_protocol; // A pointer to the parents of this type: // - 0 parents: pointer is NULL (object is implicitly the single parent) // - 1 parent: a pointer to the type of that parent // - 2 or more parents: pointer to a tuple object containing the parent types - const void *parent; + uint8_t slot_index_parent; // A dict mapping qstrs to objects local methods/constants/etc. - struct _mp_obj_dict_t *locals_dict; - - #elif MICROPY_OBJ_TYPE_REPR == MICROPY_OBJ_TYPE_REPR_SLOT_INDEX - - // Ideally these would be only 4 bits, but the extra overhead of - // accessing them adds more code, and we also need to be able to - // take the address of them for mp_obj_class_lookup. - uint8_t slot_index_print; - uint8_t slot_index_call; - uint8_t slot_index_unary_op; - uint8_t slot_index_binary_op; - uint8_t slot_index_attr; - uint8_t slot_index_subscr; - uint8_t slot_index_getiter; - uint8_t slot_index_iternext; - uint8_t slot_index_buffer; - uint8_t slot_index_protocol; - uint8_t slot_index_parent; uint8_t slot_index_locals_dict; const void *slots[]; - - #endif }; // Non-variable sized versions of mp_obj_type_t to be used as a member // in other structs or for dynamic allocation. The fields are exactly // as in mp_obj_type_t, but with a fixed size for the flexible array // members. -#if MICROPY_OBJ_TYPE_REPR == MICROPY_OBJ_TYPE_REPR_FULL -typedef mp_obj_type_t mp_obj_empty_type_t; -typedef mp_obj_type_t mp_obj_full_type_t; -#else typedef struct _mp_obj_empty_type_t { mp_obj_base_t base; uint16_t flags; @@ -710,39 +691,9 @@ typedef struct _mp_obj_full_type_t { // Explicitly add 12 slots. const void *slots[12]; } mp_obj_full_type_t; -#endif #define MP_TYPE_NULL_MAKE_NEW (NULL) -#if MICROPY_OBJ_TYPE_REPR == MICROPY_OBJ_TYPE_REPR_FULL -// Implementation of MP_DEFINE_CONST_OBJ_TYPE for each number of arguments. -// Do not use these directly, instead use MP_DEFINE_CONST_OBJ_TYPE. -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_0(_struct_type, _typename, _name, _flags, _make_new) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_1(_struct_type, _typename, _name, _flags, _make_new, f1, v1) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1 } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_2(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2 } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_3(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3 } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_4(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4 } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_5(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5 } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_6(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6 } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_7(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6, .f7 = v7 } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_8(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6, .f7 = v7, .f8 = v8 } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_9(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6, .f7 = v7, .f8 = v8, .f9 = v9 } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_10(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6, .f7 = v7, .f8 = v8, .f9 = v9, .f10 = v10 } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_11(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6, .f7 = v7, .f8 = v8, .f9 = v9, .f10 = v10, .f11 = v11 } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_12(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11, f12, v12) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .f1 = v1, .f2 = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6, .f7 = v7, .f8 = v8, .f9 = v9, .f10 = v10, .f11 = v11, .f12 = v12 } - -// Always safe, checks if the type can and does have this slot. -#define MP_OBJ_TYPE_HAS_SLOT(t, f) ((t)->f) -// Requires you know that this type can have this slot. -#define MP_OBJ_TYPE_GET_SLOT(t, f) ((t)->f) -// Always safe, returns NULL if the type cannot have this slot. -#define MP_OBJ_TYPE_GET_SLOT_OR_NULL(t, f) ((t)->f) -#define MP_OBJ_TYPE_SET_SLOT(t, f, v, n) ((t)->f = v) -#define MP_OBJ_TYPE_OFFSETOF_SLOT(f) (offsetof(mp_obj_type_t, f)) -#define MP_OBJ_TYPE_HAS_SLOT_BY_OFFSET(t, offset) (*(void **)((char *)(t) + (offset)) != NULL) - -#elif MICROPY_OBJ_TYPE_REPR == MICROPY_OBJ_TYPE_REPR_SLOT_INDEX - #define _MP_OBJ_TYPE_SLOT_TYPE_print (mp_print_fun_t) #define _MP_OBJ_TYPE_SLOT_TYPE_call (mp_call_fun_t) #define _MP_OBJ_TYPE_SLOT_TYPE_unary_op (mp_unary_op_fun_t) @@ -783,8 +734,6 @@ typedef struct _mp_obj_full_type_t { // For everything except make_new, the offset is to the uint8_t index. For make_new, we need to check the pointer. #define MP_OBJ_TYPE_HAS_SLOT_BY_OFFSET(t, offset) (*(uint8_t *)((char *)(t) + (offset)) != 0 || (offset == offsetof(mp_obj_type_t, make_new) && t->make_new)) -#endif - // Workaround for https://docs.microsoft.com/en-us/cpp/preprocessor/preprocessor-experimental-overview?view=msvc-160#macro-arguments-are-unpacked #define MP_DEFINE_CONST_OBJ_TYPE_EXPAND(x) x From 165388e4eb5db1207f4d839abe77d417d4c3f7c3 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 13 Sep 2022 23:56:52 +1000 Subject: [PATCH 0424/1041] py/objtype: Optimise slot RAM usage for instance types. In all cases other than where you have a native base with a protocol, it now fits into 4 GC blocks (like it did before the slots representation). Signed-off-by: Jim Mussared --- py/misc.h | 1 + py/objnamedtuple.c | 3 +-- py/objtype.c | 33 ++++++++++++++++++++------------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/py/misc.h b/py/misc.h index 134325f894..7350d2f9b0 100644 --- a/py/misc.h +++ b/py/misc.h @@ -72,6 +72,7 @@ typedef unsigned int uint; #define m_new_obj(type) (m_new(type, 1)) #define m_new_obj_maybe(type) (m_new_maybe(type, 1)) #define m_new_obj_var(obj_type, var_type, var_num) ((obj_type *)m_malloc(sizeof(obj_type) + sizeof(var_type) * (var_num))) +#define m_new_obj_var0(obj_type, var_type, var_num) ((obj_type *)m_malloc0(sizeof(obj_type) + sizeof(var_type) * (var_num))) #define m_new_obj_var_maybe(obj_type, var_type, var_num) ((obj_type *)m_malloc_maybe(sizeof(obj_type) + sizeof(var_type) * (var_num))) #if MICROPY_ENABLE_FINALISER #define m_new_obj_with_finaliser(type) ((type *)(m_malloc_with_finaliser(sizeof(type)))) diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index cc55aec0b9..5666521617 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -143,8 +143,7 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args, } mp_obj_namedtuple_type_t *mp_obj_new_namedtuple_base(size_t n_fields, mp_obj_t *fields) { - mp_obj_namedtuple_type_t *o = m_new_obj_var(mp_obj_namedtuple_type_t, qstr, n_fields); - memset(&o->base, 0, sizeof(o->base)); + mp_obj_namedtuple_type_t *o = m_new_obj_var0(mp_obj_namedtuple_type_t, qstr, n_fields); o->n_fields = n_fields; for (size_t i = 0; i < n_fields; i++) { o->fields[i] = mp_obj_str_get_qstr(fields[i]); diff --git a/py/objtype.c b/py/objtype.c index 968d6eb3ac..5b4e375bcc 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -1148,10 +1148,15 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) #endif } - // Allocate a full-sized mp_obj_full_type_t instance (i.e. all slots / extended fields). - // Given that Python types use almost all the slots anyway, this doesn't cost anything - // extra. - mp_obj_type_t *o = (mp_obj_type_t *)m_new0(mp_obj_full_type_t, 1); + const void *base_protocol = NULL; + if (bases_len > 0) { + base_protocol = MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_type_t *)MP_OBJ_TO_PTR(bases_items[0])), protocol); + } + + // Allocate a variable-sized mp_obj_type_t with as many slots as we need + // (currently 9, plus 1 for base, plus 1 for base-protocol). + // Note: 11 slots pushes it from 4 to 5 GC blocks. + mp_obj_type_t *o = m_new_obj_var0(mp_obj_type_t, void *, 9 + (bases_len ? 1 : 0) + (base_protocol ? 1 : 0)); o->base.type = &mp_type_type; o->flags = base_flags; o->name = name; @@ -1166,13 +1171,10 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) // MP_OBJ_TYPE_SET_SLOT(o, iternext, not implemented) MP_OBJ_TYPE_SET_SLOT(o, buffer, instance_get_buffer, 7); - if (bases_len > 0) { - // Inherit protocol from a base class. This allows to define an - // abstract base class which would translate C-level protocol to - // Python method calls, and any subclass inheriting from it will - // support this feature. - MP_OBJ_TYPE_SET_SLOT(o, protocol, MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_type_t *)MP_OBJ_TO_PTR(bases_items[0])), protocol), 8); + mp_obj_dict_t *locals_ptr = MP_OBJ_TO_PTR(locals_dict); + MP_OBJ_TYPE_SET_SLOT(o, locals_dict, locals_ptr, 8); + if (bases_len > 0) { if (bases_len >= 2) { #if MICROPY_MULTIPLE_INHERITANCE MP_OBJ_TYPE_SET_SLOT(o, parent, MP_OBJ_TO_PTR(bases_tuple), 9); @@ -1182,10 +1184,15 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) } else { MP_OBJ_TYPE_SET_SLOT(o, parent, MP_OBJ_TO_PTR(bases_items[0]), 9); } - } - mp_obj_dict_t *locals_ptr = MP_OBJ_TO_PTR(locals_dict); - MP_OBJ_TYPE_SET_SLOT(o, locals_dict, locals_ptr, 10); + // Inherit protocol from a base class. This allows to define an + // abstract base class which would translate C-level protocol to + // Python method calls, and any subclass inheriting from it will + // support this feature. + if (base_protocol) { + MP_OBJ_TYPE_SET_SLOT(o, protocol, base_protocol, 10); + } + } #if ENABLE_SPECIAL_ACCESSORS // Check if the class has any special accessor methods From 3c6127dfcfc63a2b48c31f751d1ae2c385874c8a Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 14 Sep 2022 00:39:48 +1000 Subject: [PATCH 0425/1041] py/objnamedtuple: Optimise slot RAM usage for namedtuple. Rather than reserving a full 12-slot mp_obj_type_t, reserve enough room for seven and cast as necessary. Signed-off-by: Jim Mussared --- py/objnamedtuple.c | 25 +++++++++++++------------ py/objnamedtuple.h | 7 +++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index 5666521617..52536be8b4 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -104,7 +104,7 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args, #elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED mp_raise_msg_varg(&mp_type_TypeError, MP_ERROR_TEXT("%q() takes %d positional arguments but %d were given"), - type->base.name, num_fields, n_args + n_kw); + ((mp_obj_type_t *)&type->base)->name, num_fields, n_args + n_kw); #endif } @@ -153,17 +153,18 @@ mp_obj_namedtuple_type_t *mp_obj_new_namedtuple_base(size_t n_fields, mp_obj_t * STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t *fields) { mp_obj_namedtuple_type_t *o = mp_obj_new_namedtuple_base(n_fields, fields); - o->base.base.type = &mp_type_type; - o->base.flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE; // can match tuple - o->base.name = name; - o->base.make_new = namedtuple_make_new; - MP_OBJ_TYPE_SET_SLOT(&o->base, print, namedtuple_print, 0); - MP_OBJ_TYPE_SET_SLOT(&o->base, unary_op, mp_obj_tuple_unary_op, 1); - MP_OBJ_TYPE_SET_SLOT(&o->base, binary_op, mp_obj_tuple_binary_op, 2); - MP_OBJ_TYPE_SET_SLOT(&o->base, attr, namedtuple_attr, 3); - MP_OBJ_TYPE_SET_SLOT(&o->base, subscr, mp_obj_tuple_subscr, 4); - MP_OBJ_TYPE_SET_SLOT(&o->base, getiter, mp_obj_tuple_getiter, 5); - MP_OBJ_TYPE_SET_SLOT(&o->base, parent, &mp_type_tuple, 6); + mp_obj_type_t *type = (mp_obj_type_t *)&o->base; + type->base.type = &mp_type_type; + type->flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE; // can match tuple + type->name = name; + type->make_new = namedtuple_make_new; + MP_OBJ_TYPE_SET_SLOT(type, print, namedtuple_print, 0); + MP_OBJ_TYPE_SET_SLOT(type, unary_op, mp_obj_tuple_unary_op, 1); + MP_OBJ_TYPE_SET_SLOT(type, binary_op, mp_obj_tuple_binary_op, 2); + MP_OBJ_TYPE_SET_SLOT(type, attr, namedtuple_attr, 3); + MP_OBJ_TYPE_SET_SLOT(type, subscr, mp_obj_tuple_subscr, 4); + MP_OBJ_TYPE_SET_SLOT(type, getiter, mp_obj_tuple_getiter, 5); + MP_OBJ_TYPE_SET_SLOT(type, parent, &mp_type_tuple, 6); return MP_OBJ_FROM_PTR(o); } diff --git a/py/objnamedtuple.h b/py/objnamedtuple.h index 9f23351d5a..db4a3d87d8 100644 --- a/py/objnamedtuple.h +++ b/py/objnamedtuple.h @@ -29,10 +29,9 @@ #include "py/objtuple.h" typedef struct _mp_obj_namedtuple_type_t { - // Must use the full-size version to avoid this being a variable sized member. - // This means that named tuples use slightly more RAM than necessary, but - // no worse than if we didn't have slots/split representation. - mp_obj_full_type_t base; + // This is a mp_obj_type_t with seven slots. + mp_obj_empty_type_t base; + void *slots[7]; size_t n_fields; qstr fields[]; } mp_obj_namedtuple_type_t; From 6da41b59007c9e9a2443ae17278d32210034a63f Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 16 Sep 2022 23:57:38 +1000 Subject: [PATCH 0426/1041] py/obj: Merge getiter and iternext mp_obj_type_t slots. The goal here is to remove a slot (making way to turn make_new into a slot) as well as reduce code size by the ~40 references to mp_identity_getiter and mp_stream_unbuffered_iter. This introduces two new type flags: - MP_TYPE_FLAG_ITER_IS_ITERNEXT: This means that the "iter" slot in the type is "iternext", and should use the identity getiter. - MP_TYPE_FLAG_ITER_IS_CUSTOM: This means that the "iter" slot is a pointer to a mp_getiter_iternext_custom_t instance, which then defines both getiter and iternext. And a third flag that is the OR of both, MP_TYPE_FLAG_ITER_IS_STREAM: This means that the type should use the identity getiter, and mp_stream_unbuffered_iter as iternext. Finally, MP_TYPE_FLAG_ITER_IS_GETITER is defined as a no-op flag to give the default case where "iter" is "getiter". Signed-off-by: Jim Mussared --- examples/natmod/btree/btree_c.c | 14 +++-- extmod/modbtree.c | 10 +++- extmod/moduasyncio.c | 10 +++- extmod/moduselect.c | 5 +- extmod/modussl_axtls.c | 2 - extmod/modussl_mbedtls.c | 2 - extmod/vfs_fat_file.c | 8 +-- extmod/vfs_lfsx_file.c | 8 +-- extmod/vfs_posix_file.c | 8 +-- ports/cc3200/mods/modussl.c | 3 - ports/cc3200/mods/pybuart.c | 4 +- ports/esp32/machine_i2s.c | 4 +- ports/esp32/machine_uart.c | 4 +- ports/esp8266/machine_uart.c | 4 +- ports/mimxrt/machine_i2s.c | 4 +- ports/mimxrt/machine_uart.c | 4 +- ports/nrf/boards/microbit/modules/iters.c | 5 +- .../boards/microbit/modules/microbitimage.c | 20 +++---- ports/nrf/modules/machine/uart.c | 4 +- ports/renesas-ra/machine_uart.c | 4 +- ports/rp2/machine_i2s.c | 4 +- ports/rp2/machine_uart.c | 4 +- ports/stm32/machine_i2s.c | 4 +- ports/stm32/machine_uart.c | 4 +- ports/stm32/usb.c | 4 +- ports/unix/modjni.c | 4 +- ports/unix/moduselect.c | 5 +- ports/unix/modusocket.c | 2 - ports/zephyr/machine_uart.c | 4 +- py/obj.c | 8 +-- py/obj.h | 56 ++++++++++++------- py/objarray.c | 17 +++--- py/objattrtuple.c | 4 +- py/objdict.c | 17 +++--- py/objenumerate.c | 5 +- py/objfilter.c | 5 +- py/objgenerator.c | 5 +- py/objgetitemiter.c | 5 +- py/objlist.c | 4 +- py/objmap.c | 5 +- py/objnamedtuple.c | 2 +- py/objpolyiter.c | 10 ++-- py/objrange.c | 7 +-- py/objreversed.c | 5 +- py/objset.c | 8 +-- py/objstr.c | 4 +- py/objstringio.c | 8 +-- py/objstrunicode.c | 4 +- py/objtuple.c | 8 +-- py/objtype.c | 23 +++++--- py/objzip.c | 5 +- py/runtime.c | 52 +++++++++++------ shared/runtime/sys_stdio_mphal.c | 8 +-- tests/basics/io_stringio_base.py | 24 ++++++++ 54 files changed, 234 insertions(+), 227 deletions(-) create mode 100644 tests/basics/io_stringio_base.py diff --git a/examples/natmod/btree/btree_c.c b/examples/natmod/btree/btree_c.c index af7535a68f..c897f2e9a3 100644 --- a/examples/natmod/btree/btree_c.c +++ b/examples/natmod/btree/btree_c.c @@ -95,6 +95,7 @@ int mp_stream_posix_fsync(void *stream) { } mp_obj_full_type_t btree_type; +mp_getiter_iternext_custom_t btree_getiter_iternext; #include "extmod/modbtree.c" @@ -122,13 +123,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_open_obj, 5, 5, btree_open); mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { MP_DYNRUNTIME_INIT_ENTRY + btree_getiter_iternext.getiter = btree_getiter; + btree_getiter_iternext.iternext = btree_iternext; + btree_type.base.type = (void*)&mp_fun_table.type_type; + btree_type.flags = MP_TYPE_FLAG_ITER_IS_CUSTOM; btree_type.name = MP_QSTR_btree; MP_OBJ_TYPE_SET_SLOT(&btree_type, print, btree_print, 0); - MP_OBJ_TYPE_SET_SLOT(&btree_type, getiter, btree_getiter, 1); - MP_OBJ_TYPE_SET_SLOT(&btree_type, iternext, btree_iternext, 2); - MP_OBJ_TYPE_SET_SLOT(&btree_type, binary_op, btree_binary_op, 3); - MP_OBJ_TYPE_SET_SLOT(&btree_type, subscr, btree_subscr, 4); + MP_OBJ_TYPE_SET_SLOT(&btree_type, iter, &btree_getiter_iternext, 1); + MP_OBJ_TYPE_SET_SLOT(&btree_type, binary_op, btree_binary_op, 2); + MP_OBJ_TYPE_SET_SLOT(&btree_type, subscr, btree_subscr, 3); btree_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_close), MP_OBJ_FROM_PTR(&btree_close_obj) }; btree_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_flush), MP_OBJ_FROM_PTR(&btree_flush_obj) }; btree_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_get), MP_OBJ_FROM_PTR(&btree_get_obj) }; @@ -137,7 +141,7 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a btree_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_keys), MP_OBJ_FROM_PTR(&btree_keys_obj) }; btree_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_values), MP_OBJ_FROM_PTR(&btree_values_obj) }; btree_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_items), MP_OBJ_FROM_PTR(&btree_items_obj) }; - MP_OBJ_TYPE_SET_SLOT(&btree_type, locals_dict, (void*)&btree_locals_dict, 5); + MP_OBJ_TYPE_SET_SLOT(&btree_type, locals_dict, (void*)&btree_locals_dict, 4); mp_store_global(MP_QSTR__open, MP_OBJ_FROM_PTR(&btree_open_obj)); mp_store_global(MP_QSTR_INCL, MP_OBJ_NEW_SMALL_INT(FLAG_END_KEY_INCL)); diff --git a/extmod/modbtree.c b/extmod/modbtree.c index 60c6885e6b..f21fe3ff94 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -319,15 +319,19 @@ STATIC const mp_rom_map_elem_t btree_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(btree_locals_dict, btree_locals_dict_table); +STATIC const mp_getiter_iternext_custom_t btree_getiter_iternext = { + .getiter = btree_getiter, + .iternext = btree_iternext, +}; + STATIC MP_DEFINE_CONST_OBJ_TYPE( btree_type, MP_QSTR_btree, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_CUSTOM, MP_TYPE_NULL_MAKE_NEW, // Save on qstr's, reuse same as for module print, btree_print, - getiter, btree_getiter, - iternext, btree_iternext, + iter, &btree_getiter_iternext, binary_op, btree_binary_op, subscr, btree_subscr, locals_dict, &btree_locals_dict diff --git a/extmod/moduasyncio.c b/extmod/moduasyncio.c index 5467642096..b0eb8b6509 100644 --- a/extmod/moduasyncio.c +++ b/extmod/moduasyncio.c @@ -287,14 +287,18 @@ STATIC mp_obj_t task_iternext(mp_obj_t self_in) { return mp_const_none; } +STATIC const mp_getiter_iternext_custom_t task_getiter_iternext = { + .getiter = task_getiter, + .iternext = task_iternext, +}; + STATIC MP_DEFINE_CONST_OBJ_TYPE( task_type, MP_QSTR_Task, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_CUSTOM, task_make_new, attr, task_attr, - getiter, task_getiter, - iternext, task_iternext + iter, &task_getiter_iternext ); /******************************************************************************/ diff --git a/extmod/moduselect.c b/extmod/moduselect.c index 352b15d983..58bd1169a9 100644 --- a/extmod/moduselect.c +++ b/extmod/moduselect.c @@ -339,10 +339,9 @@ STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table); STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_poll, MP_QSTR_poll, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, MP_TYPE_NULL_MAKE_NEW, - getiter, mp_identity_getiter, - iternext, poll_iternext, + iter, poll_iternext, locals_dict, &poll_locals_dict ); diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c index 78470ea6df..a6d606d560 100644 --- a/extmod/modussl_axtls.c +++ b/extmod/modussl_axtls.c @@ -321,8 +321,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_NULL_MAKE_NEW, // Save on qstr's, reuse same as for module print, ussl_socket_print, - getiter, NULL, - iternext, NULL, protocol, &ussl_socket_stream_p, locals_dict, &ussl_socket_locals_dict ); diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c index 76ca3ac719..50712980ba 100644 --- a/extmod/modussl_mbedtls.c +++ b/extmod/modussl_mbedtls.c @@ -399,8 +399,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_NULL_MAKE_NEW, // Save on qstr's, reuse same as for module print, socket_print, - getiter, NULL, - iternext, NULL, protocol, &ussl_socket_stream_p, locals_dict, &ussl_socket_locals_dict ); diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index 00980459db..ca2e2b446f 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -179,11 +179,9 @@ STATIC const mp_stream_p_t vfs_fat_fileio_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( mp_type_vfs_fat_fileio, MP_QSTR_FileIO, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, MP_TYPE_NULL_MAKE_NEW, print, file_obj_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &vfs_fat_fileio_stream_p, locals_dict, &vfs_fat_rawfile_locals_dict ); @@ -198,11 +196,9 @@ STATIC const mp_stream_p_t vfs_fat_textio_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( mp_type_vfs_fat_textio, MP_QSTR_TextIOWrapper, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, MP_TYPE_NULL_MAKE_NEW, print, file_obj_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &vfs_fat_textio_stream_p, locals_dict, &vfs_fat_rawfile_locals_dict ); diff --git a/extmod/vfs_lfsx_file.c b/extmod/vfs_lfsx_file.c index fda1b97b2a..f97641b7b9 100644 --- a/extmod/vfs_lfsx_file.c +++ b/extmod/vfs_lfsx_file.c @@ -223,11 +223,9 @@ STATIC const mp_stream_p_t MP_VFS_LFSx(fileio_stream_p) = { MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_VFS_LFSx_(_fileio), MP_QSTR_FileIO, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, MP_TYPE_NULL_MAKE_NEW, print, MP_VFS_LFSx(file_print), - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &MP_VFS_LFSx(fileio_stream_p), locals_dict, &MP_VFS_LFSx(file_locals_dict) ); @@ -242,11 +240,9 @@ STATIC const mp_stream_p_t MP_VFS_LFSx(textio_stream_p) = { MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_VFS_LFSx_(_textio), MP_QSTR_TextIOWrapper, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, MP_TYPE_NULL_MAKE_NEW, print, MP_VFS_LFSx(file_print), - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &MP_VFS_LFSx(textio_stream_p), locals_dict, &MP_VFS_LFSx(file_locals_dict) ); diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index f0b5436fe1..729d914d3a 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -252,11 +252,9 @@ STATIC const mp_stream_p_t vfs_posix_fileio_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( mp_type_vfs_posix_fileio, MP_QSTR_FileIO, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, MP_TYPE_NULL_MAKE_NEW, print, vfs_posix_file_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &vfs_posix_fileio_stream_p, locals_dict, &vfs_posix_rawfile_locals_dict ); @@ -271,11 +269,9 @@ STATIC const mp_stream_p_t vfs_posix_textio_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( mp_type_vfs_posix_textio, MP_QSTR_TextIOWrapper, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, MP_TYPE_NULL_MAKE_NEW, print, vfs_posix_file_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &vfs_posix_textio_stream_p, locals_dict, &vfs_posix_rawfile_locals_dict ); diff --git a/ports/cc3200/mods/modussl.c b/ports/cc3200/mods/modussl.c index abc9917c81..118cbd06f8 100644 --- a/ports/cc3200/mods/modussl.c +++ b/ports/cc3200/mods/modussl.c @@ -64,9 +64,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( ssl_socket_type, MP_QSTR_ussl, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, - getiter, NULL, - iternext, NULL, protocol, &socket_stream_p, locals_dict, &socket_locals_dict ); diff --git a/ports/cc3200/mods/pybuart.c b/ports/cc3200/mods/pybuart.c index e7896c4ca5..f92f544732 100644 --- a/ports/cc3200/mods/pybuart.c +++ b/ports/cc3200/mods/pybuart.c @@ -688,11 +688,9 @@ STATIC const mp_irq_methods_t uart_irq_methods = { MP_DEFINE_CONST_OBJ_TYPE( pyb_uart_type, MP_QSTR_UART, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, pyb_uart_make_new, print, pyb_uart_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p, locals_dict, &pyb_uart_locals_dict ); diff --git a/ports/esp32/machine_i2s.c b/ports/esp32/machine_i2s.c index b853f418ad..6e18394cc5 100644 --- a/ports/esp32/machine_i2s.c +++ b/ports/esp32/machine_i2s.c @@ -832,11 +832,9 @@ STATIC const mp_stream_p_t i2s_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( machine_i2s_type, MP_QSTR_I2S, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, machine_i2s_make_new, print, machine_i2s_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &i2s_stream_p, locals_dict, &machine_i2s_locals_dict ); diff --git a/ports/esp32/machine_uart.c b/ports/esp32/machine_uart.c index 6e091b8838..1f404154fc 100644 --- a/ports/esp32/machine_uart.c +++ b/ports/esp32/machine_uart.c @@ -533,11 +533,9 @@ STATIC const mp_stream_p_t uart_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( machine_uart_type, MP_QSTR_UART, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, machine_uart_make_new, print, machine_uart_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p, locals_dict, &machine_uart_locals_dict ); diff --git a/ports/esp8266/machine_uart.c b/ports/esp8266/machine_uart.c index c737f854c3..af6231c219 100644 --- a/ports/esp8266/machine_uart.c +++ b/ports/esp8266/machine_uart.c @@ -346,11 +346,9 @@ STATIC const mp_stream_p_t uart_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( pyb_uart_type, MP_QSTR_UART, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, pyb_uart_make_new, print, pyb_uart_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p, locals_dict, &pyb_uart_locals_dict ); diff --git a/ports/mimxrt/machine_i2s.c b/ports/mimxrt/machine_i2s.c index 13380b4ee6..b6c630138b 100644 --- a/ports/mimxrt/machine_i2s.c +++ b/ports/mimxrt/machine_i2s.c @@ -1216,11 +1216,9 @@ STATIC const mp_stream_p_t i2s_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( machine_i2s_type, MP_QSTR_I2S, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, machine_i2s_make_new, print, machine_i2s_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &i2s_stream_p, locals_dict, &machine_i2s_locals_dict ); diff --git a/ports/mimxrt/machine_uart.c b/ports/mimxrt/machine_uart.c index 9d4873274a..e93d2478f3 100644 --- a/ports/mimxrt/machine_uart.c +++ b/ports/mimxrt/machine_uart.c @@ -472,11 +472,9 @@ STATIC const mp_stream_p_t uart_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( machine_uart_type, MP_QSTR_UART, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, machine_uart_make_new, print, machine_uart_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p, locals_dict, &machine_uart_locals_dict ); diff --git a/ports/nrf/boards/microbit/modules/iters.c b/ports/nrf/boards/microbit/modules/iters.c index 296fc1f51c..2fe1486691 100644 --- a/ports/nrf/boards/microbit/modules/iters.c +++ b/ports/nrf/boards/microbit/modules/iters.c @@ -46,10 +46,9 @@ static mp_obj_t microbit_repeat_iter_next(mp_obj_t iter_in) { MP_DEFINE_CONST_OBJ_TYPE( microbit_repeat_iterator_type, MP_QSTR_iterator, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, MP_TYPE_NULL_MAKE_NEW, - getiter, mp_identity_getiter, - iternext, microbit_repeat_iter_next + iter, microbit_repeat_iter_next ); mp_obj_t microbit_repeat_iterator(mp_obj_t iterable) { diff --git a/ports/nrf/boards/microbit/modules/microbitimage.c b/ports/nrf/boards/microbit/modules/microbitimage.c index 4870b6738f..b22c2e29ac 100644 --- a/ports/nrf/boards/microbit/modules/microbitimage.c +++ b/ports/nrf/boards/microbit/modules/microbitimage.c @@ -824,18 +824,16 @@ STATIC mp_obj_t microbit_scrolling_string_iter_next(mp_obj_t o_in) { MP_DEFINE_CONST_OBJ_TYPE( microbit_scrolling_string_type, MP_QSTR_ScrollingString, - MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, - getiter, get_microbit_scrolling_string_iter + MP_TYPE_FLAG_ITER_IS_GETITER, + iter, get_microbit_scrolling_string_iter ); MP_DEFINE_CONST_OBJ_TYPE( microbit_scrolling_string_iterator_type, MP_QSTR_iterator, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, MP_TYPE_NULL_MAKE_NEW, - getiter, mp_identity_getiter, - iternext, microbit_scrolling_string_iter_next + iter, microbit_scrolling_string_iter_next ); /** Facade types to present a string as a sequence of images. @@ -877,11 +875,10 @@ static mp_obj_t microbit_facade_iterator(mp_obj_t iterable_in, mp_obj_iter_buf_t MP_DEFINE_CONST_OBJ_TYPE( string_image_facade_type, MP_QSTR_Facade, - MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, + MP_TYPE_FLAG_ITER_IS_GETITER, unary_op, facade_unary_op, subscr, string_image_facade_subscr, - getiter, microbit_facade_iterator + iter, microbit_facade_iterator ); @@ -914,10 +911,9 @@ static mp_obj_t microbit_facade_iter_next(mp_obj_t iter_in) { MP_DEFINE_CONST_OBJ_TYPE( microbit_facade_iterator_type, MP_QSTR_iterator, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, MP_TYPE_NULL_MAKE_NEW, - getiter, mp_identity_getiter, - iternext, microbit_facade_iter_next + iter, microbit_facade_iter_next ); mp_obj_t microbit_facade_iterator(mp_obj_t iterable_in, mp_obj_iter_buf_t *iter_buf) { diff --git a/ports/nrf/modules/machine/uart.c b/ports/nrf/modules/machine/uart.c index fc0bd682b4..ca0fcf859a 100644 --- a/ports/nrf/modules/machine/uart.c +++ b/ports/nrf/modules/machine/uart.c @@ -373,11 +373,9 @@ STATIC const mp_stream_p_t uart_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( machine_hard_uart_type, MP_QSTR_UART, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, machine_hard_uart_make_new, print, machine_hard_uart_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p, locals_dict, &machine_hard_uart_locals_dict ); diff --git a/ports/renesas-ra/machine_uart.c b/ports/renesas-ra/machine_uart.c index 11f5d6825e..6fa84ca821 100644 --- a/ports/renesas-ra/machine_uart.c +++ b/ports/renesas-ra/machine_uart.c @@ -574,12 +574,10 @@ STATIC const mp_stream_p_t uart_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( machine_uart_type, MP_QSTR_UART, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, machine_uart_make_new, locals_dict, &machine_uart_locals_dict, print, machine_uart_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p ); diff --git a/ports/rp2/machine_i2s.c b/ports/rp2/machine_i2s.c index 9d70a476f3..53ff7417d7 100644 --- a/ports/rp2/machine_i2s.c +++ b/ports/rp2/machine_i2s.c @@ -1140,11 +1140,9 @@ STATIC const mp_stream_p_t i2s_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( machine_i2s_type, MP_QSTR_I2S, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, machine_i2s_make_new, print, machine_i2s_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &i2s_stream_p, locals_dict, &machine_i2s_locals_dict ); diff --git a/ports/rp2/machine_uart.c b/ports/rp2/machine_uart.c index bb8bf51be6..06f7e9aaac 100644 --- a/ports/rp2/machine_uart.c +++ b/ports/rp2/machine_uart.c @@ -582,11 +582,9 @@ STATIC const mp_stream_p_t uart_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( machine_uart_type, MP_QSTR_UART, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, machine_uart_make_new, print, machine_uart_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p, locals_dict, &machine_uart_locals_dict ); diff --git a/ports/stm32/machine_i2s.c b/ports/stm32/machine_i2s.c index 93a465d07c..d68648bc34 100644 --- a/ports/stm32/machine_i2s.c +++ b/ports/stm32/machine_i2s.c @@ -1117,11 +1117,9 @@ STATIC const mp_stream_p_t i2s_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( machine_i2s_type, MP_QSTR_I2S, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, machine_i2s_make_new, print, machine_i2s_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &i2s_stream_p, locals_dict, &machine_i2s_locals_dict ); diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index 5851d8cf35..4ccff8c136 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -663,11 +663,9 @@ STATIC const mp_stream_p_t uart_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( pyb_uart_type, MP_QSTR_UART, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, pyb_uart_make_new, print, pyb_uart_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p, locals_dict, &pyb_uart_locals_dict ); diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index df755fe984..e389ef68f2 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -939,11 +939,9 @@ STATIC const mp_stream_p_t pyb_usb_vcp_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( pyb_usb_vcp_type, MP_QSTR_USB_VCP, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, pyb_usb_vcp_make_new, print, pyb_usb_vcp_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &pyb_usb_vcp_stream_p, locals_dict, &pyb_usb_vcp_locals_dict ); diff --git a/ports/unix/modjni.c b/ports/unix/modjni.c index 02368e4537..e6b874b235 100644 --- a/ports/unix/modjni.c +++ b/ports/unix/modjni.c @@ -325,13 +325,13 @@ STATIC mp_obj_t subscr_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { STATIC MP_DEFINE_CONST_OBJ_TYPE( jobject_type, MP_QSTR_jobject, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_GETITER, MP_TYPE_NULL_MAKE_NEW, print, jobject_print, unary_op, jobject_unary_op, attr, jobject_attr, subscr, jobject_subscr, - getiter, subscr_getiter, + iter, subscr_getiter, // .locals_dict = &jobject_locals_dict, ); diff --git a/ports/unix/moduselect.c b/ports/unix/moduselect.c index baed88761c..674841bf18 100644 --- a/ports/unix/moduselect.c +++ b/ports/unix/moduselect.c @@ -314,10 +314,9 @@ STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table); STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_poll, MP_QSTR_poll, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, MP_TYPE_NULL_MAKE_NEW, - getiter, mp_identity_getiter, - iternext, poll_iternext, + iter, poll_iternext, locals_dict, &poll_locals_dict ); diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c index 21260f0b2a..dfbf15cd3e 100644 --- a/ports/unix/modusocket.c +++ b/ports/unix/modusocket.c @@ -522,8 +522,6 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, socket_make_new, print, socket_print, - getiter, NULL, - iternext, NULL, protocol, &usocket_stream_p, locals_dict, &usocket_locals_dict ); diff --git a/ports/zephyr/machine_uart.c b/ports/zephyr/machine_uart.c index 9580d37907..867c5ae886 100644 --- a/ports/zephyr/machine_uart.c +++ b/ports/zephyr/machine_uart.c @@ -157,11 +157,9 @@ STATIC const mp_stream_p_t uart_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( machine_uart_type, MP_QSTR_UART, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, machine_uart_make_new, print, machine_uart_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &uart_stream_p, locals_dict, &machine_uart_locals_dict ); diff --git a/py/obj.c b/py/obj.c index 359c73b9c2..eb17308fed 100644 --- a/py/obj.c +++ b/py/obj.c @@ -572,10 +572,10 @@ mp_obj_t mp_identity(mp_obj_t self) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity); -mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf) { - (void)iter_buf; - return self; -} +// mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf) { +// (void)iter_buf; +// return self; +// } bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) { const mp_obj_type_t *type = mp_obj_get_type(obj); diff --git a/py/obj.h b/py/obj.h index 878fa67348..b1d722080c 100644 --- a/py/obj.h +++ b/py/obj.h @@ -507,12 +507,20 @@ typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *); // Flags for type behaviour (mp_obj_type_t.flags) // If MP_TYPE_FLAG_EQ_NOT_REFLEXIVE is clear then __eq__ is reflexive (A==A returns True). // If MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE is clear then the type can't be equal to an -// instance of any different class that also clears this flag. If this flag is set -// then the type may check for equality against a different type. +// instance of any different class that also clears this flag. If this flag is set +// then the type may check for equality against a different type. // If MP_TYPE_FLAG_EQ_HAS_NEQ_TEST is clear then the type only implements the __eq__ -// operator and not the __ne__ operator. If it's set then __ne__ may be implemented. +// operator and not the __ne__ operator. If it's set then __ne__ may be implemented. // If MP_TYPE_FLAG_BINDS_SELF is set then the type as a method binds self as the first arg. // If MP_TYPE_FLAG_BUILTIN_FUN is set then the type is a built-in function type. +// MP_TYPE_FLAG_ITER_IS_GETITER is a no-op flag that means the default behaviour for the +// iter slot and it's the getiter function. +// If MP_TYPE_FLAG_ITER_IS_ITERNEXT is set then the "iter" slot is the iternext +// function and getiter will be automatically implemented as "return self". +// If MP_TYPE_FLAG_ITER_IS_CUSTOM is set then the "iter" slot is a pointer to a +// mp_getiter_iternext_custom_t struct instance (with both .getiter and .iternext set). +// If MP_TYPE_FLAG_ITER_IS_STREAM is set then the type implicitly gets a "return self" +// getiter, and mp_stream_unbuffered_iter for iternext. #define MP_TYPE_FLAG_NONE (0x0000) #define MP_TYPE_FLAG_IS_SUBCLASSED (0x0001) #define MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS (0x0002) @@ -521,6 +529,10 @@ typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *); #define MP_TYPE_FLAG_EQ_HAS_NEQ_TEST (0x0010) #define MP_TYPE_FLAG_BINDS_SELF (0x0020) #define MP_TYPE_FLAG_BUILTIN_FUN (0x0040) +#define MP_TYPE_FLAG_ITER_IS_GETITER (0x0000) +#define MP_TYPE_FLAG_ITER_IS_ITERNEXT (0x0080) +#define MP_TYPE_FLAG_ITER_IS_CUSTOM (0x0100) +#define MP_TYPE_FLAG_ITER_IS_STREAM (MP_TYPE_FLAG_ITER_IS_ITERNEXT | MP_TYPE_FLAG_ITER_IS_CUSTOM) typedef enum { PRINT_STR = 0, @@ -548,6 +560,13 @@ typedef mp_obj_t (*mp_binary_op_fun_t)(mp_binary_op_t op, mp_obj_t, mp_obj_t); typedef void (*mp_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t *dest); typedef mp_obj_t (*mp_subscr_fun_t)(mp_obj_t self_in, mp_obj_t index, mp_obj_t value); typedef mp_obj_t (*mp_getiter_fun_t)(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf); +typedef mp_fun_1_t mp_iternext_fun_t; + +// For MP_TYPE_FLAG_ITER_IS_CUSTOM, the "getiter" slot points to an instance of this type. +typedef struct _mp_getiter_iternext_custom_t { + mp_getiter_fun_t getiter; + mp_iternext_fun_t iternext; +} mp_getiter_iternext_custom_t; // Buffer protocol typedef struct _mp_buffer_info_t { @@ -616,14 +635,17 @@ struct _mp_obj_type_t { // Can return MP_OBJ_NULL if operation not supported. uint8_t slot_index_subscr; - // Corresponds to __iter__ special method. - // Can use the given mp_obj_iter_buf_t to store iterator object, - // otherwise can return a pointer to an object on the heap. - uint8_t slot_index_getiter; - - // Corresponds to __next__ special method. May return MP_OBJ_STOP_ITERATION - // as an optimisation instead of raising StopIteration() with no args. - uint8_t slot_index_iternext; + // This slot's behaviour depends on the MP_TYPE_FLAG_ITER_IS_* flags above. + // - If MP_TYPE_FLAG_ITER_IS_GETITER flag is set, then this corresponds to the __iter__ + // special method (of type mp_getiter_fun_t). Can use the given mp_obj_iter_buf_t + // to store the iterator object, otherwise can return a pointer to an object on the heap. + // - If MP_TYPE_FLAG_ITER_IS_ITERNEXT is set, then this corresponds to __next__ special method. + // May return MP_OBJ_STOP_ITERATION as an optimisation instead of raising StopIteration() + // with no args. The type will implicitly implement getiter as "return self". + // - If MP_TYPE_FLAG_ITER_IS_CUSTOM is set, then this slot must point to an + // mp_getiter_iternext_custom_t instance with both the getiter and iternext fields set. + // - If MP_TYPE_FLAG_ITER_IS_STREAM is set, this this slot should be unset. + uint8_t slot_index_iter; // Implements the buffer protocol if supported by this type. uint8_t slot_index_buffer; @@ -659,8 +681,7 @@ typedef struct _mp_obj_empty_type_t { uint8_t slot_index_binary_op; uint8_t slot_index_attr; uint8_t slot_index_subscr; - uint8_t slot_index_getiter; - uint8_t slot_index_iternext; + uint8_t slot_index_iter; uint8_t slot_index_buffer; uint8_t slot_index_protocol; uint8_t slot_index_parent; @@ -681,15 +702,14 @@ typedef struct _mp_obj_full_type_t { uint8_t slot_index_binary_op; uint8_t slot_index_attr; uint8_t slot_index_subscr; - uint8_t slot_index_getiter; - uint8_t slot_index_iternext; + uint8_t slot_index_iter; uint8_t slot_index_buffer; uint8_t slot_index_protocol; uint8_t slot_index_parent; uint8_t slot_index_locals_dict; // Explicitly add 12 slots. - const void *slots[12]; + const void *slots[11]; } mp_obj_full_type_t; #define MP_TYPE_NULL_MAKE_NEW (NULL) @@ -700,8 +720,7 @@ typedef struct _mp_obj_full_type_t { #define _MP_OBJ_TYPE_SLOT_TYPE_binary_op (mp_binary_op_fun_t) #define _MP_OBJ_TYPE_SLOT_TYPE_attr (mp_attr_fun_t) #define _MP_OBJ_TYPE_SLOT_TYPE_subscr (mp_subscr_fun_t) -#define _MP_OBJ_TYPE_SLOT_TYPE_getiter (mp_getiter_fun_t) -#define _MP_OBJ_TYPE_SLOT_TYPE_iternext (mp_fun_1_t) +#define _MP_OBJ_TYPE_SLOT_TYPE_iter (const void *) #define _MP_OBJ_TYPE_SLOT_TYPE_buffer (mp_buffer_fun_t) #define _MP_OBJ_TYPE_SLOT_TYPE_protocol (const void *) #define _MP_OBJ_TYPE_SLOT_TYPE_parent (const void *) @@ -1162,7 +1181,6 @@ qstr mp_obj_fun_get_name(mp_const_obj_t fun); mp_obj_t mp_identity(mp_obj_t self); MP_DECLARE_CONST_FUN_OBJ_1(mp_identity_obj); -mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf); // module typedef struct _mp_obj_module_t { diff --git a/py/objarray.c b/py/objarray.c index 762a4105c5..0d1032929f 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -574,10 +574,10 @@ STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_ui MP_DEFINE_CONST_OBJ_TYPE( mp_type_array, MP_QSTR_array, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_GETITER, array_make_new, print, array_print, - getiter, array_iterator_new, + iter, array_iterator_new, unary_op, array_unary_op, binary_op, array_binary_op, subscr, array_subscr, @@ -590,10 +590,10 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_DEFINE_CONST_OBJ_TYPE( mp_type_bytearray, MP_QSTR_bytearray, - MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, + MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER, bytearray_make_new, print, array_print, - getiter, array_iterator_new, + iter, array_iterator_new, unary_op, array_unary_op, binary_op, array_binary_op, subscr, array_subscr, @@ -618,9 +618,9 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_DEFINE_CONST_OBJ_TYPE( mp_type_memoryview, MP_QSTR_memoryview, - MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, + MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER, memoryview_make_new, - getiter, array_iterator_new, + iter, array_iterator_new, unary_op, array_unary_op, binary_op, array_binary_op, MEMORYVIEW_TYPE_LOCALS_DICT @@ -676,10 +676,9 @@ STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) { STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_array_it, MP_QSTR_iterator, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, MP_TYPE_NULL_MAKE_NEW, - getiter, mp_identity_getiter, - iternext, array_it_iternext + iter, array_it_iternext ); STATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf) { diff --git a/py/objattrtuple.c b/py/objattrtuple.c index 0d41ee5235..2e207f4cf0 100644 --- a/py/objattrtuple.c +++ b/py/objattrtuple.c @@ -83,7 +83,7 @@ mp_obj_t mp_obj_new_attrtuple(const qstr *fields, size_t n, const mp_obj_t *item MP_DEFINE_CONST_OBJ_TYPE( mp_type_attrtuple, MP_QSTR_tuple, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_GETITER, MP_TYPE_NULL_MAKE_NEW, // reuse tuple to save on a qstr print, mp_obj_attrtuple_print, @@ -91,7 +91,7 @@ MP_DEFINE_CONST_OBJ_TYPE( binary_op, mp_obj_tuple_binary_op, attr, mp_obj_attrtuple_attr, subscr, mp_obj_tuple_subscr, - getiter, mp_obj_tuple_getiter + iter, mp_obj_tuple_getiter ); #endif // MICROPY_PY_ATTRTUPLE diff --git a/py/objdict.c b/py/objdict.c index c65b14caad..7755d7b786 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -464,10 +464,9 @@ STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) { STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_dict_view_it, MP_QSTR_iterator, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, MP_TYPE_NULL_MAKE_NEW, - getiter, mp_identity_getiter, - iternext, dict_view_it_iternext + iter, dict_view_it_iternext ); STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in, mp_obj_iter_buf_t *iter_buf) { @@ -517,11 +516,11 @@ STATIC mp_obj_t dict_view_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_dict_view, MP_QSTR_dict_view, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_GETITER, MP_TYPE_NULL_MAKE_NEW, print, dict_view_print, binary_op, dict_view_binary_op, - getiter, dict_view_getiter + iter, dict_view_getiter ); STATIC mp_obj_t mp_obj_new_dict_view(mp_obj_t dict, mp_dict_view_kind_t kind) { @@ -592,13 +591,13 @@ STATIC MP_DEFINE_CONST_DICT(dict_locals_dict, dict_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE( mp_type_dict, MP_QSTR_dict, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_GETITER, mp_obj_dict_make_new, print, dict_print, unary_op, dict_unary_op, binary_op, dict_binary_op, subscr, dict_subscr, - getiter, dict_getiter, + iter, dict_getiter, locals_dict, &dict_locals_dict ); @@ -606,13 +605,13 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_DEFINE_CONST_OBJ_TYPE( mp_type_ordereddict, MP_QSTR_OrderedDict, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_GETITER, mp_obj_dict_make_new, print, dict_print, unary_op, dict_unary_op, binary_op, dict_binary_op, subscr, dict_subscr, - getiter, dict_getiter, + iter, dict_getiter, parent, &mp_type_dict, locals_dict, &dict_locals_dict ); diff --git a/py/objenumerate.c b/py/objenumerate.c index f4f4ff6ae1..eea9e3e381 100644 --- a/py/objenumerate.c +++ b/py/objenumerate.c @@ -70,10 +70,9 @@ STATIC mp_obj_t enumerate_make_new(const mp_obj_type_t *type, size_t n_args, siz MP_DEFINE_CONST_OBJ_TYPE( mp_type_enumerate, MP_QSTR_enumerate, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, enumerate_make_new, - iternext, enumerate_iternext, - getiter, mp_identity_getiter + iter, enumerate_iternext ); STATIC mp_obj_t enumerate_iternext(mp_obj_t self_in) { diff --git a/py/objfilter.c b/py/objfilter.c index 2b57300af3..bfe651f40d 100644 --- a/py/objfilter.c +++ b/py/objfilter.c @@ -63,10 +63,9 @@ STATIC mp_obj_t filter_iternext(mp_obj_t self_in) { MP_DEFINE_CONST_OBJ_TYPE( mp_type_filter, MP_QSTR_filter, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, filter_make_new, - getiter, mp_identity_getiter, - iternext, filter_iternext + iter, filter_iternext ); #endif // MICROPY_PY_BUILTINS_FILTER diff --git a/py/objgenerator.c b/py/objgenerator.c index a960c23700..d8515c13ce 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -370,11 +370,10 @@ STATIC MP_DEFINE_CONST_DICT(gen_instance_locals_dict, gen_instance_locals_dict_t MP_DEFINE_CONST_OBJ_TYPE( mp_type_gen_instance, MP_QSTR_generator, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, MP_TYPE_NULL_MAKE_NEW, print, gen_instance_print, unary_op, mp_generic_unary_op, - getiter, mp_identity_getiter, - iternext, gen_instance_iternext, + iter, gen_instance_iternext, locals_dict, &gen_instance_locals_dict ); diff --git a/py/objgetitemiter.c b/py/objgetitemiter.c index ed2dfbbe1f..134cbcd629 100644 --- a/py/objgetitemiter.c +++ b/py/objgetitemiter.c @@ -59,10 +59,9 @@ STATIC mp_obj_t it_iternext(mp_obj_t self_in) { STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_it, MP_QSTR_iterator, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, MP_TYPE_NULL_MAKE_NEW, - getiter, mp_identity_getiter, - iternext, it_iternext + iter, it_iternext ); // args are those returned from mp_load_method_maybe (ie either an attribute or a method) diff --git a/py/objlist.c b/py/objlist.c index 5f9e99cc79..8d18344ea8 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -455,13 +455,13 @@ STATIC MP_DEFINE_CONST_DICT(list_locals_dict, list_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE( mp_type_list, MP_QSTR_list, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_GETITER, list_make_new, print, list_print, unary_op, list_unary_op, binary_op, list_binary_op, subscr, list_subscr, - getiter, list_getiter, + iter, list_getiter, locals_dict, &list_locals_dict ); diff --git a/py/objmap.c b/py/objmap.c index dc305e21b5..115832e387 100644 --- a/py/objmap.c +++ b/py/objmap.c @@ -66,8 +66,7 @@ STATIC mp_obj_t map_iternext(mp_obj_t self_in) { MP_DEFINE_CONST_OBJ_TYPE( mp_type_map, MP_QSTR_map, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, map_make_new, - getiter, mp_identity_getiter, - iternext, map_iternext + iter, map_iternext ); diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index 52536be8b4..3b45d8f76f 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -163,7 +163,7 @@ STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t MP_OBJ_TYPE_SET_SLOT(type, binary_op, mp_obj_tuple_binary_op, 2); MP_OBJ_TYPE_SET_SLOT(type, attr, namedtuple_attr, 3); MP_OBJ_TYPE_SET_SLOT(type, subscr, mp_obj_tuple_subscr, 4); - MP_OBJ_TYPE_SET_SLOT(type, getiter, mp_obj_tuple_getiter, 5); + MP_OBJ_TYPE_SET_SLOT(type, iter, mp_obj_tuple_getiter, 5); MP_OBJ_TYPE_SET_SLOT(type, parent, &mp_type_tuple, 6); return MP_OBJ_FROM_PTR(o); } diff --git a/py/objpolyiter.c b/py/objpolyiter.c index 5bc397f6ec..7a45b6b73f 100644 --- a/py/objpolyiter.c +++ b/py/objpolyiter.c @@ -48,10 +48,9 @@ STATIC mp_obj_t polymorph_it_iternext(mp_obj_t self_in) { MP_DEFINE_CONST_OBJ_TYPE( mp_type_polymorph_iter, MP_QSTR_iterator, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, MP_TYPE_NULL_MAKE_NEW, - getiter, mp_identity_getiter, - iternext, polymorph_it_iternext + iter, polymorph_it_iternext ); #if MICROPY_ENABLE_FINALISER @@ -81,10 +80,9 @@ STATIC MP_DEFINE_CONST_DICT(mp_obj_polymorph_iter_locals_dict, mp_obj_polymorph_ MP_DEFINE_CONST_OBJ_TYPE( mp_type_polymorph_iter_with_finaliser, MP_QSTR_iterator, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, MP_TYPE_NULL_MAKE_NEW, - getiter, mp_identity_getiter, - iternext, polymorph_it_iternext, + iter, polymorph_it_iternext, locals_dict, &mp_obj_polymorph_iter_locals_dict ); #endif diff --git a/py/objrange.c b/py/objrange.c index 3140504b2b..1ad8f6031f 100644 --- a/py/objrange.c +++ b/py/objrange.c @@ -53,10 +53,9 @@ STATIC mp_obj_t range_it_iternext(mp_obj_t o_in) { STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_range_it, MP_QSTR_iterator, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, MP_TYPE_NULL_MAKE_NEW, - getiter, mp_identity_getiter, - iternext, range_it_iternext + iter, range_it_iternext ); STATIC mp_obj_t mp_obj_new_range_iterator(mp_int_t cur, mp_int_t stop, mp_int_t step, mp_obj_iter_buf_t *iter_buf) { @@ -232,5 +231,5 @@ MP_DEFINE_CONST_OBJ_TYPE( print, range_print, unary_op, range_unary_op, subscr, range_subscr, - getiter, range_getiter + iter, range_getiter ); diff --git a/py/objreversed.c b/py/objreversed.c index bc1f07ddec..e265266d3f 100644 --- a/py/objreversed.c +++ b/py/objreversed.c @@ -71,10 +71,9 @@ STATIC mp_obj_t reversed_iternext(mp_obj_t self_in) { MP_DEFINE_CONST_OBJ_TYPE( mp_type_reversed, MP_QSTR_reversed, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, reversed_make_new, - getiter, mp_identity_getiter, - iternext, reversed_iternext + iter, reversed_iternext ); #endif // MICROPY_PY_BUILTINS_REVERSED diff --git a/py/objset.c b/py/objset.c index 6f21bf15df..b827f49f40 100644 --- a/py/objset.c +++ b/py/objset.c @@ -542,12 +542,12 @@ STATIC MP_DEFINE_CONST_DICT(set_locals_dict, set_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE( mp_type_set, MP_QSTR_set, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_GETITER, set_make_new, print, set_print, unary_op, set_unary_op, binary_op, set_binary_op, - getiter, set_getiter, + iter, set_getiter, locals_dict, &set_locals_dict ); @@ -568,12 +568,12 @@ STATIC MP_DEFINE_CONST_DICT(frozenset_locals_dict, frozenset_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE( mp_type_frozenset, MP_QSTR_frozenset, - MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, + MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER, set_make_new, print, set_print, unary_op, set_unary_op, binary_op, set_binary_op, - getiter, set_getiter, + iter, set_getiter, locals_dict, &frozenset_locals_dict ); #endif diff --git a/py/objstr.c b/py/objstr.c index d425055559..12f6e15d04 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -2151,7 +2151,7 @@ MP_DEFINE_CONST_OBJ_TYPE( print, str_print, binary_op, mp_obj_str_binary_op, subscr, bytes_subscr, - getiter, mp_obj_new_str_iterator, + iter, mp_obj_new_str_iterator, buffer, mp_obj_str_get_buffer, locals_dict, &mp_obj_str_locals_dict ); @@ -2166,7 +2166,7 @@ MP_DEFINE_CONST_OBJ_TYPE( print, str_print, binary_op, mp_obj_str_binary_op, subscr, bytes_subscr, - getiter, mp_obj_new_bytes_iterator, + iter, mp_obj_new_bytes_iterator, buffer, mp_obj_str_get_buffer, locals_dict, &mp_obj_bytes_locals_dict ); diff --git a/py/objstringio.c b/py/objstringio.c index 77547f88cf..4e19b83999 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -247,11 +247,9 @@ STATIC const mp_stream_p_t stringio_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( mp_type_stringio, MP_QSTR_StringIO, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, stringio_make_new, print, stringio_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &stringio_stream_p, locals_dict, &stringio_locals_dict ); @@ -266,11 +264,9 @@ STATIC const mp_stream_p_t bytesio_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( mp_type_bytesio, MP_QSTR_BytesIO, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, stringio_make_new, print, stringio_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &bytesio_stream_p, locals_dict, &stringio_locals_dict ); diff --git a/py/objstrunicode.c b/py/objstrunicode.c index 15c59e4e95..9b28841ecd 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -232,13 +232,13 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { MP_DEFINE_CONST_OBJ_TYPE( mp_type_str, MP_QSTR_str, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_GETITER, mp_obj_str_make_new, print, uni_print, unary_op, uni_unary_op, binary_op, mp_obj_str_binary_op, subscr, str_subscr, - getiter, mp_obj_new_str_iterator, + iter, mp_obj_new_str_iterator, buffer, mp_obj_str_get_buffer, locals_dict, &mp_obj_str_locals_dict ); diff --git a/py/objtuple.c b/py/objtuple.c index 01b2fa1488..485d44c52a 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -32,7 +32,7 @@ #include "py/runtime.h" // type check is done on getiter method to allow tuple, namedtuple, attrtuple -#define mp_obj_is_tuple_compatible(o) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(o), getiter) == mp_obj_tuple_getiter) +#define mp_obj_is_tuple_compatible(o) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(o), iter) == mp_obj_tuple_getiter) /******************************************************************************/ /* tuple */ @@ -111,7 +111,7 @@ STATIC mp_obj_t tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t anothe mp_check_self(mp_obj_is_tuple_compatible(self_in)); const mp_obj_type_t *another_type = mp_obj_get_type(another_in); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); - if (MP_OBJ_TYPE_GET_SLOT_OR_NULL(another_type, getiter) != mp_obj_tuple_getiter) { + if (MP_OBJ_TYPE_GET_SLOT_OR_NULL(another_type, iter) != mp_obj_tuple_getiter) { // Slow path for user subclasses another_in = mp_obj_cast_to_native_base(another_in, MP_OBJ_FROM_PTR(&mp_type_tuple)); if (another_in == MP_OBJ_NULL) { @@ -227,13 +227,13 @@ STATIC MP_DEFINE_CONST_DICT(tuple_locals_dict, tuple_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE( mp_type_tuple, MP_QSTR_tuple, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_GETITER, mp_obj_tuple_make_new, print, mp_obj_tuple_print, unary_op, mp_obj_tuple_unary_op, binary_op, mp_obj_tuple_binary_op, subscr, mp_obj_tuple_subscr, - getiter, mp_obj_tuple_getiter, + iter, mp_obj_tuple_getiter, locals_dict, &tuple_locals_dict ); diff --git a/py/objtype.c b/py/objtype.c index 5b4e375bcc..183dce071e 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -142,7 +142,10 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_t // this should not be applied to class types, as will result in extra // lookup either. if (lookup->slot_offset != 0 && mp_obj_is_native_type(type)) { - if (MP_OBJ_TYPE_HAS_SLOT_BY_OFFSET(type, lookup->slot_offset)) { + // Check if there is a non-zero value in the specified slot index, + // with a special case for getiter where the slot won't be set + // for MP_TYPE_FLAG_ITER_IS_STREAM. + if (MP_OBJ_TYPE_HAS_SLOT_BY_OFFSET(type, lookup->slot_offset) || (lookup->slot_offset == MP_OBJ_TYPE_OFFSETOF_SLOT(iter) && type->flags & MP_TYPE_FLAG_ITER_IS_STREAM)) { DEBUG_printf("mp_obj_class_lookup: Matched special meth slot (off=%d) for %s\n", lookup->slot_offset, qstr_str(lookup->attr)); lookup->dest[0] = MP_OBJ_SENTINEL; @@ -889,7 +892,7 @@ mp_obj_t mp_obj_instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) struct class_lookup_data lookup = { .obj = self, .attr = MP_QSTR___iter__, - .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(getiter), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(iter), .dest = member, .is_type = false, }; @@ -898,10 +901,14 @@ mp_obj_t mp_obj_instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) return MP_OBJ_NULL; } else if (member[0] == MP_OBJ_SENTINEL) { const mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]); - if (iter_buf == NULL) { - iter_buf = m_new_obj(mp_obj_iter_buf_t); + if (type->flags & MP_TYPE_FLAG_ITER_IS_ITERNEXT) { + return self->subobj[0]; + } else { + if (iter_buf == NULL) { + iter_buf = m_new_obj(mp_obj_iter_buf_t); + } + return ((mp_getiter_fun_t)MP_OBJ_TYPE_GET_SLOT(type, iter))(self->subobj[0], iter_buf); } - return MP_OBJ_TYPE_GET_SLOT(type, getiter)(self->subobj[0], iter_buf); } else { return mp_call_method_n_kw(0, 0, member); } @@ -1122,7 +1129,9 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) // Basic validation of base classes uint16_t base_flags = MP_TYPE_FLAG_EQ_NOT_REFLEXIVE - | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_EQ_HAS_NEQ_TEST; + | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE + | MP_TYPE_FLAG_EQ_HAS_NEQ_TEST + | MP_TYPE_FLAG_ITER_IS_GETITER; size_t bases_len; mp_obj_t *bases_items; mp_obj_tuple_get(bases_tuple, &bases_len, &bases_items); @@ -1167,7 +1176,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) MP_OBJ_TYPE_SET_SLOT(o, binary_op, instance_binary_op, 3); MP_OBJ_TYPE_SET_SLOT(o, attr, mp_obj_instance_attr, 4); MP_OBJ_TYPE_SET_SLOT(o, subscr, instance_subscr, 5); - MP_OBJ_TYPE_SET_SLOT(o, getiter, mp_obj_instance_getiter, 6); + MP_OBJ_TYPE_SET_SLOT(o, iter, mp_obj_instance_getiter, 6); // MP_OBJ_TYPE_SET_SLOT(o, iternext, not implemented) MP_OBJ_TYPE_SET_SLOT(o, buffer, instance_get_buffer, 7); diff --git a/py/objzip.c b/py/objzip.c index 0ceafd97f2..34d73465ef 100644 --- a/py/objzip.c +++ b/py/objzip.c @@ -69,8 +69,7 @@ STATIC mp_obj_t zip_iternext(mp_obj_t self_in) { MP_DEFINE_CONST_OBJ_TYPE( mp_type_zip, MP_QSTR_zip, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_ITERNEXT, zip_make_new, - getiter, mp_identity_getiter, - iternext, zip_iternext + iter, zip_iternext ); diff --git a/py/runtime.c b/py/runtime.c index d0e504a3d0..ec628bfe14 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -61,6 +61,8 @@ const mp_obj_module_t mp_module___main__ = { MP_REGISTER_MODULE(MP_QSTR___main__, mp_module___main__); +#define TYPE_HAS_ITERNEXT(type) (type->flags & (MP_TYPE_FLAG_ITER_IS_ITERNEXT | MP_TYPE_FLAG_ITER_IS_CUSTOM | MP_TYPE_FLAG_ITER_IS_STREAM)) + void mp_init(void) { qstr_init(); @@ -1167,7 +1169,7 @@ void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest) { } #endif - if (attr == MP_QSTR___next__ && MP_OBJ_TYPE_HAS_SLOT(type, iternext)) { + if (attr == MP_QSTR___next__ && TYPE_HAS_ITERNEXT(type)) { dest[0] = MP_OBJ_FROM_PTR(&mp_builtin_next_obj); dest[1] = obj; return; @@ -1260,21 +1262,26 @@ mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { assert(o_in); const mp_obj_type_t *type = mp_obj_get_type(o_in); + // Most types that use iternext just use the identity getiter. We handle this case explicitly + // so we don't unnecessarily allocate any RAM for the iter_buf, which won't be used. + if ((type->flags & MP_TYPE_FLAG_ITER_IS_ITERNEXT) == MP_TYPE_FLAG_ITER_IS_ITERNEXT || (type->flags & MP_TYPE_FLAG_ITER_IS_STREAM) == MP_TYPE_FLAG_ITER_IS_STREAM) { + return o_in; + } - if (MP_OBJ_TYPE_HAS_SLOT(type, getiter)) { - // Check for native getiter which is the identity. We handle this case explicitly - // so we don't unnecessarily allocate any RAM for the iter_buf, which won't be used. - if (MP_OBJ_TYPE_GET_SLOT(type, getiter) == mp_identity_getiter) { - return o_in; - } - + if (MP_OBJ_TYPE_HAS_SLOT(type, iter)) { // check for native getiter (corresponds to __iter__) - if (iter_buf == NULL && MP_OBJ_TYPE_GET_SLOT(type, getiter) != mp_obj_instance_getiter) { + if (iter_buf == NULL && MP_OBJ_TYPE_GET_SLOT(type, iter) != mp_obj_instance_getiter) { // if caller did not provide a buffer then allocate one on the heap // mp_obj_instance_getiter is special, it will allocate only if needed iter_buf = m_new_obj(mp_obj_iter_buf_t); } - mp_obj_t iter = MP_OBJ_TYPE_GET_SLOT(type, getiter)(o_in, iter_buf); + mp_getiter_fun_t getiter; + if (type->flags & MP_TYPE_FLAG_ITER_IS_CUSTOM) { + getiter = ((mp_getiter_iternext_custom_t *)MP_OBJ_TYPE_GET_SLOT(type, iter))->getiter; + } else { + getiter = (mp_getiter_fun_t)MP_OBJ_TYPE_GET_SLOT(type, iter); + } + mp_obj_t iter = getiter(o_in, iter_buf); if (iter != MP_OBJ_NULL) { return iter; } @@ -1302,13 +1309,26 @@ mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { } +STATIC mp_fun_1_t type_get_iternext(const mp_obj_type_t *type) { + if ((type->flags & MP_TYPE_FLAG_ITER_IS_STREAM) == MP_TYPE_FLAG_ITER_IS_STREAM) { + mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self); + return mp_stream_unbuffered_iter; + } else if (type->flags & MP_TYPE_FLAG_ITER_IS_ITERNEXT) { + return (mp_fun_1_t)MP_OBJ_TYPE_GET_SLOT(type, iter); + } else if (type->flags & MP_TYPE_FLAG_ITER_IS_CUSTOM) { + return ((mp_getiter_iternext_custom_t *)MP_OBJ_TYPE_GET_SLOT(type, iter))->iternext; + } else { + return NULL; + } +} + // may return MP_OBJ_STOP_ITERATION as an optimisation instead of raise StopIteration() // may also raise StopIteration() mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) { const mp_obj_type_t *type = mp_obj_get_type(o_in); - if (MP_OBJ_TYPE_HAS_SLOT(type, iternext)) { + if (TYPE_HAS_ITERNEXT(type)) { MP_STATE_THREAD(stop_iteration_arg) = MP_OBJ_NULL; - return MP_OBJ_TYPE_GET_SLOT(type, iternext)(o_in); + return type_get_iternext(type)(o_in); } else { // check for __next__ method mp_obj_t dest[2]; @@ -1332,9 +1352,9 @@ mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) { mp_obj_t mp_iternext(mp_obj_t o_in) { MP_STACK_CHECK(); // enumerate, filter, map and zip can recursively call mp_iternext const mp_obj_type_t *type = mp_obj_get_type(o_in); - if (MP_OBJ_TYPE_HAS_SLOT(type, iternext)) { + if (TYPE_HAS_ITERNEXT(type)) { MP_STATE_THREAD(stop_iteration_arg) = MP_OBJ_NULL; - return MP_OBJ_TYPE_GET_SLOT(type, iternext)(o_in); + return type_get_iternext(type)(o_in); } else { // check for __next__ method mp_obj_t dest[2]; @@ -1372,9 +1392,9 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th return mp_obj_gen_resume(self_in, send_value, throw_value, ret_val); } - if (MP_OBJ_TYPE_HAS_SLOT(type, iternext) && send_value == mp_const_none) { + if (TYPE_HAS_ITERNEXT(type) && send_value == mp_const_none) { MP_STATE_THREAD(stop_iteration_arg) = MP_OBJ_NULL; - mp_obj_t ret = MP_OBJ_TYPE_GET_SLOT(type, iternext)(self_in); + mp_obj_t ret = type_get_iternext(type)(self_in); *ret_val = ret; if (ret != MP_OBJ_STOP_ITERATION) { return MP_VM_RETURN_YIELD; diff --git a/shared/runtime/sys_stdio_mphal.c b/shared/runtime/sys_stdio_mphal.c index 6d43425e29..325f93dde1 100644 --- a/shared/runtime/sys_stdio_mphal.c +++ b/shared/runtime/sys_stdio_mphal.c @@ -126,11 +126,9 @@ STATIC const mp_stream_p_t stdio_obj_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( stdio_obj_type, MP_QSTR_FileIO, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, MP_TYPE_NULL_MAKE_NEW, print, stdio_obj_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &stdio_obj_stream_p, locals_dict, &stdio_locals_dict ); @@ -162,11 +160,9 @@ STATIC const mp_stream_p_t stdio_buffer_obj_stream_p = { STATIC MP_DEFINE_CONST_OBJ_TYPE( stdio_buffer_obj_type, MP_QSTR_FileIO, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_ITER_IS_STREAM, MP_TYPE_NULL_MAKE_NEW, print, stdio_obj_print, - getiter, mp_identity_getiter, - iternext, mp_stream_unbuffered_iter, protocol, &stdio_buffer_obj_stream_p, locals_dict, &stdio_locals_dict ); diff --git a/tests/basics/io_stringio_base.py b/tests/basics/io_stringio_base.py new file mode 100644 index 0000000000..dffc879074 --- /dev/null +++ b/tests/basics/io_stringio_base.py @@ -0,0 +1,24 @@ +# Checks that an instance type inheriting from a native base that uses +# MP_TYPE_FLAG_ITER_IS_STREAM will still have a getiter. + +try: + import uio as io +except ImportError: + import io + +a = io.StringIO() +a.write("hello\nworld\nmicro\npython\n") +a.seek(0) + +for line in a: + print(line) + +class X(io.StringIO): + pass + +b = X() +b.write("hello\nworld\nmicro\npython\n") +b.seek(0) + +for line in b: + print(line) From 94beeabd2ee179d587942046555833e022241f24 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 17 Sep 2022 00:31:23 +1000 Subject: [PATCH 0427/1041] py/obj: Convert make_new into a mp_obj_type_t slot. Instead of being an explicit field, it's now a slot like all the other methods. This is a marginal code size improvement because most types have a make_new (100/138 on PYBV11), however it improves consistency in how types are declared, removing the special case for make_new. Signed-off-by: Jim Mussared --- drivers/ninaw10/nina_wifi_bsp.c | 2 +- examples/natmod/framebuf/framebuf.c | 6 +- examples/natmod/uzlib/uzlib.c | 6 +- extmod/machine_i2c.c | 2 +- extmod/machine_i2c.h | 2 +- extmod/machine_mem.c | 1 - extmod/machine_pinbase.c | 2 +- extmod/machine_pwm.c | 2 +- extmod/machine_signal.c | 2 +- extmod/machine_spi.c | 2 +- extmod/machine_spi.h | 2 +- extmod/modbluetooth.c | 4 +- extmod/modbtree.c | 1 - extmod/modframebuf.c | 2 +- extmod/modlwip.c | 4 +- extmod/moduasyncio.c | 4 +- extmod/moducryptolib.c | 2 +- extmod/moductypes.c | 2 +- extmod/moduhashlib.c | 6 +- extmod/modure.c | 2 - extmod/moduselect.c | 1 - extmod/modusocket.c | 2 +- extmod/modussl_axtls.c | 1 - extmod/modussl_mbedtls.c | 1 - extmod/modutimeq.c | 2 +- extmod/moduwebsocket.c | 2 +- extmod/moduzlib.c | 2 +- extmod/modwebrepl.c | 2 +- extmod/network_cyw43.c | 2 +- extmod/network_ninaw10.c | 4 +- extmod/network_wiznet5k.c | 6 +- extmod/vfs.c | 6 +- extmod/vfs_fat.c | 2 +- extmod/vfs_fat_file.c | 2 - extmod/vfs_lfsx.c | 2 +- extmod/vfs_lfsx_file.c | 2 - extmod/vfs_posix.c | 2 +- extmod/vfs_posix_file.c | 2 - ports/cc3200/misc/mpirq.c | 1 - ports/cc3200/mods/modnetwork.c | 2 +- ports/cc3200/mods/moduhashlib.c | 4 +- ports/cc3200/mods/modusocket.c | 2 +- ports/cc3200/mods/modwlan.c | 2 +- ports/cc3200/mods/pybadc.c | 3 +- ports/cc3200/mods/pybflash.c | 2 +- ports/cc3200/mods/pybi2c.c | 2 +- ports/cc3200/mods/pybpin.c | 3 +- ports/cc3200/mods/pybrtc.c | 2 +- ports/cc3200/mods/pybsd.c | 2 +- ports/cc3200/mods/pybsleep.c | 3 +- ports/cc3200/mods/pybspi.c | 2 +- ports/cc3200/mods/pybtimer.c | 3 +- ports/cc3200/mods/pybuart.c | 2 +- ports/cc3200/mods/pybwdt.c | 2 +- ports/esp32/esp32_nvs.c | 2 +- ports/esp32/esp32_partition.c | 2 +- ports/esp32/esp32_rmt.c | 2 +- ports/esp32/esp32_ulp.c | 2 +- ports/esp32/machine_adc.c | 2 +- ports/esp32/machine_adcblock.c | 2 +- ports/esp32/machine_dac.c | 2 +- ports/esp32/machine_hw_spi.c | 2 +- ports/esp32/machine_i2c.c | 2 +- ports/esp32/machine_i2s.c | 2 +- ports/esp32/machine_pin.c | 3 +- ports/esp32/machine_rtc.c | 2 +- ports/esp32/machine_sdcard.c | 2 +- ports/esp32/machine_timer.c | 2 +- ports/esp32/machine_touchpad.c | 2 +- ports/esp32/machine_uart.c | 2 +- ports/esp32/machine_wdt.c | 2 +- ports/esp32/modsocket.c | 2 +- ports/esp32/network_lan.c | 1 - ports/esp32/network_ppp.c | 1 - ports/esp32/network_wlan.c | 1 - ports/esp8266/machine_adc.c | 2 +- ports/esp8266/machine_hspi.c | 2 +- ports/esp8266/machine_pin.c | 3 +- ports/esp8266/machine_rtc.c | 2 +- ports/esp8266/machine_uart.c | 2 +- ports/esp8266/machine_wdt.c | 2 +- ports/esp8266/main.c | 2 +- ports/esp8266/modmachine.c | 2 +- ports/esp8266/modnetwork.c | 1 - ports/mimxrt/machine_adc.c | 2 +- ports/mimxrt/machine_i2c.c | 2 +- ports/mimxrt/machine_i2s.c | 2 +- ports/mimxrt/machine_led.c | 2 +- ports/mimxrt/machine_pin.c | 6 +- ports/mimxrt/machine_rtc.c | 2 +- ports/mimxrt/machine_sdcard.c | 2 +- ports/mimxrt/machine_spi.c | 2 +- ports/mimxrt/machine_timer.c | 2 +- ports/mimxrt/machine_uart.c | 2 +- ports/mimxrt/machine_wdt.c | 2 +- ports/mimxrt/mimxrt_flash.c | 2 +- ports/mimxrt/network_lan.c | 2 +- ports/nrf/boards/microbit/modules/iters.c | 1 - .../boards/microbit/modules/microbitdisplay.c | 1 - .../boards/microbit/modules/microbitimage.c | 4 +- ports/nrf/main.c | 2 +- ports/nrf/modules/board/led.c | 2 +- ports/nrf/modules/machine/adc.c | 2 +- ports/nrf/modules/machine/i2c.c | 2 +- ports/nrf/modules/machine/pin.c | 3 +- ports/nrf/modules/machine/pwm.c | 2 +- ports/nrf/modules/machine/rtcounter.c | 2 +- ports/nrf/modules/machine/spi.c | 2 +- ports/nrf/modules/machine/temp.c | 2 +- ports/nrf/modules/machine/timer.c | 2 +- ports/nrf/modules/machine/uart.c | 2 +- ports/nrf/modules/nrf/flashbdev.c | 2 +- .../modules/ubluepy/ubluepy_characteristic.c | 2 +- ports/nrf/modules/ubluepy/ubluepy_constants.c | 2 - ports/nrf/modules/ubluepy/ubluepy_delegate.c | 2 +- .../nrf/modules/ubluepy/ubluepy_descriptor.c | 2 +- .../nrf/modules/ubluepy/ubluepy_peripheral.c | 2 +- .../nrf/modules/ubluepy/ubluepy_scan_entry.c | 1 - ports/nrf/modules/ubluepy/ubluepy_scanner.c | 2 +- ports/nrf/modules/ubluepy/ubluepy_service.c | 2 +- ports/nrf/modules/ubluepy/ubluepy_uuid.c | 2 +- ports/nrf/modules/uos/microbitfs.c | 2 - ports/nrf/pin_named_pins.c | 2 - ports/pic16bit/modpybled.c | 2 +- ports/pic16bit/modpybswitch.c | 2 +- ports/renesas-ra/extint.c | 2 +- ports/renesas-ra/led.c | 2 +- ports/renesas-ra/machine_adc.c | 2 +- ports/renesas-ra/machine_i2c.c | 2 +- ports/renesas-ra/machine_pin.c | 4 +- ports/renesas-ra/machine_rtc.c | 2 +- ports/renesas-ra/machine_spi.c | 2 +- ports/renesas-ra/machine_timer.c | 2 +- ports/renesas-ra/machine_uart.c | 2 +- ports/renesas-ra/main.c | 2 +- ports/renesas-ra/storage.c | 2 +- ports/renesas-ra/timer.c | 3 +- ports/renesas-ra/usrsw.c | 2 +- ports/rp2/machine_adc.c | 2 +- ports/rp2/machine_i2c.c | 2 +- ports/rp2/machine_i2s.c | 2 +- ports/rp2/machine_pin.c | 2 +- ports/rp2/machine_rtc.c | 2 +- ports/rp2/machine_spi.c | 2 +- ports/rp2/machine_timer.c | 2 +- ports/rp2/machine_uart.c | 2 +- ports/rp2/machine_wdt.c | 2 +- ports/rp2/mpbthciport.c | 2 +- ports/rp2/rp2_flash.c | 2 +- ports/rp2/rp2_pio.c | 4 +- ports/samd/machine_led.c | 2 +- ports/samd/machine_pin.c | 2 +- ports/samd/samd_flash.c | 2 +- ports/stm32/accel.c | 2 +- ports/stm32/adc.c | 4 +- ports/stm32/boards/LEGO_HUB_NO6/cc2564.c | 2 +- ports/stm32/dac.c | 2 +- ports/stm32/extint.c | 2 +- ports/stm32/lcd.c | 2 +- ports/stm32/led.c | 2 +- ports/stm32/machine_adc.c | 2 +- ports/stm32/machine_i2c.c | 2 +- ports/stm32/machine_i2s.c | 2 +- ports/stm32/machine_spi.c | 2 +- ports/stm32/machine_timer.c | 2 +- ports/stm32/machine_uart.c | 2 +- ports/stm32/main.c | 2 +- ports/stm32/network_lan.c | 2 +- ports/stm32/pin.c | 3 +- ports/stm32/pin_named_pins.c | 2 - ports/stm32/pyb_can.c | 2 +- ports/stm32/pyb_i2c.c | 2 +- ports/stm32/pyb_spi.c | 2 +- ports/stm32/rtc.c | 2 +- ports/stm32/sdcard.c | 4 +- ports/stm32/servo.c | 2 +- ports/stm32/storage.c | 2 +- ports/stm32/timer.c | 3 +- ports/stm32/usb.c | 4 +- ports/stm32/usrsw.c | 2 +- ports/stm32/wdt.c | 2 +- ports/teensy/led.c | 2 +- ports/teensy/timer.c | 3 +- ports/teensy/uart.c | 2 +- ports/unix/coverage.c | 2 - ports/unix/main.c | 2 +- ports/unix/modffi.c | 8 +-- ports/unix/modjni.c | 3 - ports/unix/moduselect.c | 1 - ports/unix/modusocket.c | 2 +- ports/zephyr/machine_i2c.c | 2 +- ports/zephyr/machine_pin.c | 2 +- ports/zephyr/machine_spi.c | 2 +- ports/zephyr/machine_uart.c | 2 +- ports/zephyr/main.c | 4 +- ports/zephyr/modusocket.c | 2 +- ports/zephyr/modzsensor.c | 2 +- ports/zephyr/zephyr_storage.c | 4 +- py/builtinevex.c | 3 +- py/dynruntime.h | 2 +- py/modbuiltins.c | 2 +- py/modio.c | 4 +- py/modthread.c | 1 - py/obj.h | 56 +++++++++---------- py/objarray.c | 7 +-- py/objattrtuple.c | 1 - py/objbool.c | 2 +- py/objboundmeth.c | 1 - py/objcell.c | 2 +- py/objclosure.c | 1 - py/objcomplex.c | 3 +- py/objdeque.c | 2 +- py/objdict.c | 6 +- py/objenumerate.c | 2 +- py/objexcept.c | 12 ++-- py/objexcept.h | 3 +- py/objfilter.c | 2 +- py/objfloat.c | 3 +- py/objfun.c | 13 ++--- py/objgenerator.c | 3 - py/objgetitemiter.c | 1 - py/objint.c | 2 +- py/objlist.c | 4 +- py/objlist.h | 1 + py/objmap.c | 2 +- py/objmodule.c | 1 - py/objnamedtuple.c | 16 +++--- py/objnamedtuple.h | 4 +- py/objnone.c | 1 - py/objobject.c | 2 +- py/objpolyiter.c | 2 - py/objproperty.c | 2 +- py/objrange.c | 3 +- py/objreversed.c | 2 +- py/objset.c | 4 +- py/objsingleton.c | 2 +- py/objslice.c | 1 - py/objstr.c | 6 +- py/objstringio.c | 4 +- py/objstrunicode.c | 2 +- py/objtuple.c | 2 +- py/objtype.c | 56 +++++++++---------- py/objtype.h | 4 +- py/objzip.c | 2 +- py/profile.c | 2 - py/runtime.c | 1 - shared/runtime/mpirq.c | 1 - shared/runtime/sys_stdio_mphal.c | 2 - 248 files changed, 316 insertions(+), 397 deletions(-) diff --git a/drivers/ninaw10/nina_wifi_bsp.c b/drivers/ninaw10/nina_wifi_bsp.c index d5b1308536..c65fb111fb 100644 --- a/drivers/ninaw10/nina_wifi_bsp.c +++ b/drivers/ninaw10/nina_wifi_bsp.c @@ -73,7 +73,7 @@ int nina_bsp_init(void) { MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_BAUDRATE), }; - MP_STATE_PORT(mp_wifi_spi) = machine_spi_type.make_new((mp_obj_t)&machine_spi_type, 2, 0, args); + MP_STATE_PORT(mp_wifi_spi) = MP_OBJ_TYPE_GET_SLOT(&machine_spi_type, make_new)((mp_obj_t)&machine_spi_type, 2, 0, args); return 0; } diff --git a/examples/natmod/framebuf/framebuf.c b/examples/natmod/framebuf/framebuf.c index 4c55729471..32b67eabcf 100644 --- a/examples/natmod/framebuf/framebuf.c +++ b/examples/natmod/framebuf/framebuf.c @@ -20,8 +20,8 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a mp_type_framebuf.base.type = (void*)&mp_type_type; mp_type_framebuf.name = MP_QSTR_FrameBuffer; - mp_type_framebuf.make_new = framebuf_make_new; - MP_OBJ_TYPE_SET_SLOT(&mp_type_framebuf, buffer, framebuf_get_buffer, 0); + MP_OBJ_TYPE_SET_SLOT(&mp_type_framebuf, make_new, framebuf_make_new, 0); + MP_OBJ_TYPE_SET_SLOT(&mp_type_framebuf, buffer, framebuf_get_buffer, 1); framebuf_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill), MP_OBJ_FROM_PTR(&framebuf_fill_obj) }; framebuf_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill_rect), MP_OBJ_FROM_PTR(&framebuf_fill_rect_obj) }; framebuf_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_pixel), MP_OBJ_FROM_PTR(&framebuf_pixel_obj) }; @@ -33,7 +33,7 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a framebuf_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_blit), MP_OBJ_FROM_PTR(&framebuf_blit_obj) }; framebuf_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), MP_OBJ_FROM_PTR(&framebuf_scroll_obj) }; framebuf_locals_dict_table[10] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_text), MP_OBJ_FROM_PTR(&framebuf_text_obj) }; - MP_OBJ_TYPE_SET_SLOT(&mp_type_framebuf, locals_dict, (void*)&framebuf_locals_dict, 1); + MP_OBJ_TYPE_SET_SLOT(&mp_type_framebuf, locals_dict, (void*)&framebuf_locals_dict, 2); mp_store_global(MP_QSTR_FrameBuffer, MP_OBJ_FROM_PTR(&mp_type_framebuf)); mp_store_global(MP_QSTR_FrameBuffer1, MP_OBJ_FROM_PTR(&legacy_framebuffer1_obj)); diff --git a/examples/natmod/uzlib/uzlib.c b/examples/natmod/uzlib/uzlib.c index 469452e8f8..9cf58b10e7 100644 --- a/examples/natmod/uzlib/uzlib.c +++ b/examples/natmod/uzlib/uzlib.c @@ -20,12 +20,12 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a decompio_type.base.type = mp_fun_table.type_type; decompio_type.name = MP_QSTR_DecompIO; - decompio_type.make_new = &decompio_make_new; - MP_OBJ_TYPE_SET_SLOT(&decompio_type, protocol, &decompio_stream_p, 0); + MP_OBJ_TYPE_SET_SLOT(&decompio_type, make_new, &decompio_make_new, 0); + MP_OBJ_TYPE_SET_SLOT(&decompio_type, protocol, &decompio_stream_p, 1); decompio_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_OBJ_FROM_PTR(&mp_stream_read_obj) }; decompio_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_OBJ_FROM_PTR(&mp_stream_readinto_obj) }; decompio_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_OBJ_FROM_PTR(&mp_stream_unbuffered_readline_obj) }; - MP_OBJ_TYPE_SET_SLOT(&decompio_type, locals_dict, (void*)&decompio_locals_dict, 1); + MP_OBJ_TYPE_SET_SLOT(&decompio_type, locals_dict, (void*)&decompio_locals_dict, 2); mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uzlib)); mp_store_global(MP_QSTR_decompress, MP_OBJ_FROM_PTR(&mod_uzlib_decompress_obj)); diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c index bb7ade6fcf..3563b3243c 100644 --- a/extmod/machine_i2c.c +++ b/extmod/machine_i2c.c @@ -734,7 +734,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_machine_soft_i2c_type, MP_QSTR_SoftI2C, MP_TYPE_FLAG_NONE, - mp_machine_soft_i2c_make_new, + make_new, mp_machine_soft_i2c_make_new, print, mp_machine_soft_i2c_print, protocol, &mp_machine_soft_i2c_p, locals_dict, &mp_machine_i2c_locals_dict diff --git a/extmod/machine_i2c.h b/extmod/machine_i2c.h index a3363d4c34..600145bfed 100644 --- a/extmod/machine_i2c.h +++ b/extmod/machine_i2c.h @@ -38,7 +38,7 @@ --n_args; \ ++all_args; \ } \ - return mp_machine_soft_i2c_type.make_new(&mp_machine_soft_i2c_type, n_args, n_kw, all_args); \ + return MP_OBJ_TYPE_GET_SLOT(&mp_machine_soft_i2c_type, make_new)(&mp_machine_soft_i2c_type, n_args, n_kw, all_args); \ } \ } while (0) diff --git a/extmod/machine_mem.c b/extmod/machine_mem.c index 422e99d3ce..f27356e028 100644 --- a/extmod/machine_mem.c +++ b/extmod/machine_mem.c @@ -105,7 +105,6 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_mem_type, MP_QSTR_mem, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, machine_mem_print, subscr, machine_mem_subscr ); diff --git a/extmod/machine_pinbase.c b/extmod/machine_pinbase.c index 617dd1280c..8607e6ed3d 100644 --- a/extmod/machine_pinbase.c +++ b/extmod/machine_pinbase.c @@ -81,7 +81,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_pinbase_type, MP_QSTR_PinBase, MP_TYPE_FLAG_NONE, - pinbase_make_new, + make_new, pinbase_make_new, protocol, &pinbase_pin_p ); diff --git a/extmod/machine_pwm.c b/extmod/machine_pwm.c index f12f70a2d1..220d34d7da 100644 --- a/extmod/machine_pwm.c +++ b/extmod/machine_pwm.c @@ -136,7 +136,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_pwm_type, MP_QSTR_PWM, MP_TYPE_FLAG_NONE, - mp_machine_pwm_make_new, + make_new, mp_machine_pwm_make_new, print, mp_machine_pwm_print, locals_dict, &machine_pwm_locals_dict ); diff --git a/extmod/machine_signal.c b/extmod/machine_signal.c index 49ee6dfb4a..7922ed7077 100644 --- a/extmod/machine_signal.c +++ b/extmod/machine_signal.c @@ -176,7 +176,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_signal_type, MP_QSTR_Signal, MP_TYPE_FLAG_NONE, - signal_make_new, + make_new, signal_make_new, call, signal_call, protocol, &signal_pin_p, locals_dict, &signal_locals_dict diff --git a/extmod/machine_spi.c b/extmod/machine_spi.c index 54f1964e21..bb35cff38e 100644 --- a/extmod/machine_spi.c +++ b/extmod/machine_spi.c @@ -255,7 +255,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_machine_soft_spi_type, MP_QSTR_SoftSPI, MP_TYPE_FLAG_NONE, - mp_machine_soft_spi_make_new, + make_new, mp_machine_soft_spi_make_new, print, mp_machine_soft_spi_print, protocol, &mp_machine_soft_spi_p, locals_dict, &mp_machine_spi_locals_dict diff --git a/extmod/machine_spi.h b/extmod/machine_spi.h index ca92c719a8..93ee8d00ca 100644 --- a/extmod/machine_spi.h +++ b/extmod/machine_spi.h @@ -39,7 +39,7 @@ --n_args; \ ++all_args; \ } \ - return mp_machine_soft_spi_type.make_new(&mp_machine_soft_spi_type, n_args, n_kw, all_args); \ + return MP_OBJ_TYPE_GET_SLOT(&mp_machine_soft_spi_type, make_new)(&mp_machine_soft_spi_type, n_args, n_kw, all_args); \ } \ } while (0) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 2e058fc7de..9c168483ba 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -244,7 +244,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_bluetooth_uuid, MP_QSTR_UUID, MP_TYPE_FLAG_NONE, - bluetooth_uuid_make_new, + make_new, bluetooth_uuid_make_new, unary_op, bluetooth_uuid_unary_op, binary_op, bluetooth_uuid_binary_op, print, bluetooth_uuid_print, @@ -980,7 +980,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_bluetooth_ble, MP_QSTR_BLE, MP_TYPE_FLAG_NONE, - bluetooth_ble_make_new, + make_new, bluetooth_ble_make_new, locals_dict, &bluetooth_ble_locals_dict ); diff --git a/extmod/modbtree.c b/extmod/modbtree.c index f21fe3ff94..2da65a2c7a 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -328,7 +328,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( btree_type, MP_QSTR_btree, MP_TYPE_FLAG_ITER_IS_CUSTOM, - MP_TYPE_NULL_MAKE_NEW, // Save on qstr's, reuse same as for module print, btree_print, iter, &btree_getiter_iternext, diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index 5347be5643..e7825b5912 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -833,7 +833,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_framebuf, MP_QSTR_FrameBuffer, MP_TYPE_FLAG_NONE, - framebuf_make_new, + make_new, framebuf_make_new, buffer, framebuf_get_buffer, locals_dict, &framebuf_locals_dict ); diff --git a/extmod/modlwip.c b/extmod/modlwip.c index 2f5da36f40..f64a5a6250 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -181,7 +181,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( lwip_slip_type, MP_QSTR_slip, MP_TYPE_FLAG_NONE, - lwip_slip_make_new, + make_new, lwip_slip_make_new, locals_dict, &lwip_slip_locals_dict ); @@ -1599,7 +1599,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( lwip_socket_type, MP_QSTR_socket, MP_TYPE_FLAG_NONE, - lwip_socket_make_new, + make_new, lwip_socket_make_new, print, lwip_socket_print, protocol, &lwip_socket_stream_p, locals_dict, &lwip_socket_locals_dict diff --git a/extmod/moduasyncio.c b/extmod/moduasyncio.c index b0eb8b6509..021e0da1be 100644 --- a/extmod/moduasyncio.c +++ b/extmod/moduasyncio.c @@ -148,7 +148,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( task_queue_type, MP_QSTR_TaskQueue, MP_TYPE_FLAG_NONE, - task_queue_make_new, + make_new, task_queue_make_new, locals_dict, &task_queue_locals_dict ); @@ -296,7 +296,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( task_type, MP_QSTR_Task, MP_TYPE_FLAG_ITER_IS_CUSTOM, - task_make_new, + make_new, task_make_new, attr, task_attr, iter, &task_getiter_iternext ); diff --git a/extmod/moducryptolib.c b/extmod/moducryptolib.c index e4625c21a8..fc3fcfd90d 100644 --- a/extmod/moducryptolib.c +++ b/extmod/moducryptolib.c @@ -352,7 +352,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( ucryptolib_aes_type, MP_QSTR_aes, MP_TYPE_FLAG_NONE, - ucryptolib_aes_make_new, + make_new, ucryptolib_aes_make_new, locals_dict, &ucryptolib_aes_locals_dict ); diff --git a/extmod/moductypes.c b/extmod/moductypes.c index a9ad500c2d..15c36290a9 100644 --- a/extmod/moductypes.c +++ b/extmod/moductypes.c @@ -638,7 +638,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( uctypes_struct_type, MP_QSTR_struct, MP_TYPE_FLAG_NONE, - uctypes_struct_make_new, + make_new, uctypes_struct_make_new, print, uctypes_struct_print, attr, uctypes_struct_attr, subscr, uctypes_struct_subscr, diff --git a/extmod/moduhashlib.c b/extmod/moduhashlib.c index 9535e00b40..64e15c444d 100644 --- a/extmod/moduhashlib.c +++ b/extmod/moduhashlib.c @@ -161,7 +161,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( uhashlib_sha256_type, MP_QSTR_sha256, MP_TYPE_FLAG_NONE, - uhashlib_sha256_make_new, + make_new, uhashlib_sha256_make_new, locals_dict, &uhashlib_sha256_locals_dict ); #endif @@ -255,7 +255,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( uhashlib_sha1_type, MP_QSTR_sha1, MP_TYPE_FLAG_NONE, - uhashlib_sha1_make_new, + make_new, uhashlib_sha1_make_new, locals_dict, &uhashlib_sha1_locals_dict ); #endif @@ -349,7 +349,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( uhashlib_md5_type, MP_QSTR_md5, MP_TYPE_FLAG_NONE, - uhashlib_md5_make_new, + make_new, uhashlib_md5_make_new, locals_dict, &uhashlib_md5_locals_dict ); #endif // MICROPY_PY_UHASHLIB_MD5 diff --git a/extmod/modure.c b/extmod/modure.c index c0114c14fd..801e5df897 100644 --- a/extmod/modure.c +++ b/extmod/modure.c @@ -183,7 +183,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( match_type, MP_QSTR_match, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, match_print, locals_dict, &match_locals_dict ); @@ -417,7 +416,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( re_type, MP_QSTR_ure, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, re_print, locals_dict, &re_locals_dict ); diff --git a/extmod/moduselect.c b/extmod/moduselect.c index 58bd1169a9..128154a4b6 100644 --- a/extmod/moduselect.c +++ b/extmod/moduselect.c @@ -340,7 +340,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_poll, MP_QSTR_poll, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - MP_TYPE_NULL_MAKE_NEW, iter, poll_iternext, locals_dict, &poll_locals_dict ); diff --git a/extmod/modusocket.c b/extmod/modusocket.c index fc16d7e270..194ee6899e 100644 --- a/extmod/modusocket.c +++ b/extmod/modusocket.c @@ -532,7 +532,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( socket_type, MP_QSTR_socket, MP_TYPE_FLAG_NONE, - socket_make_new, + make_new, socket_make_new, protocol, &socket_stream_p, locals_dict, &socket_locals_dict, print, socket_print diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c index a6d606d560..2eae465048 100644 --- a/extmod/modussl_axtls.c +++ b/extmod/modussl_axtls.c @@ -318,7 +318,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( ussl_socket_type, MP_QSTR_ussl, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, // Save on qstr's, reuse same as for module print, ussl_socket_print, protocol, &ussl_socket_stream_p, diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c index 50712980ba..95cf12c975 100644 --- a/extmod/modussl_mbedtls.c +++ b/extmod/modussl_mbedtls.c @@ -396,7 +396,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( ussl_socket_type, MP_QSTR_ussl, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, // Save on qstr's, reuse same as for module print, socket_print, protocol, &ussl_socket_stream_p, diff --git a/extmod/modutimeq.c b/extmod/modutimeq.c index 1a7575adc9..1a38104eaf 100644 --- a/extmod/modutimeq.c +++ b/extmod/modutimeq.c @@ -213,7 +213,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( utimeq_type, MP_QSTR_utimeq, MP_TYPE_FLAG_NONE, - utimeq_make_new, + make_new, utimeq_make_new, unary_op, utimeq_unary_op, locals_dict, &utimeq_locals_dict ); diff --git a/extmod/moduwebsocket.c b/extmod/moduwebsocket.c index c6be50d0e1..9b12fc8635 100644 --- a/extmod/moduwebsocket.c +++ b/extmod/moduwebsocket.c @@ -294,7 +294,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( websocket_type, MP_QSTR_websocket, MP_TYPE_FLAG_NONE, - websocket_make_new, + make_new, websocket_make_new, protocol, &websocket_stream_p, locals_dict, &websocket_locals_dict ); diff --git a/extmod/moduzlib.c b/extmod/moduzlib.c index 533168d0b0..14d15321a3 100644 --- a/extmod/moduzlib.c +++ b/extmod/moduzlib.c @@ -144,7 +144,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( decompio_type, MP_QSTR_DecompIO, MP_TYPE_FLAG_NONE, - decompio_make_new, + make_new, decompio_make_new, protocol, &decompio_stream_p, locals_dict, &decompio_locals_dict ); diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c index fc5ca35ea0..d86f358962 100644 --- a/extmod/modwebrepl.c +++ b/extmod/modwebrepl.c @@ -346,7 +346,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( webrepl_type, MP_QSTR__webrepl, MP_TYPE_FLAG_NONE, - webrepl_make_new, + make_new, webrepl_make_new, protocol, &webrepl_stream_p, locals_dict, &webrepl_locals_dict ); diff --git a/extmod/network_cyw43.c b/extmod/network_cyw43.c index 329ba53ef5..87d9b9f614 100644 --- a/extmod/network_cyw43.c +++ b/extmod/network_cyw43.c @@ -500,7 +500,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_network_cyw43_type, MP_QSTR_CYW43, MP_TYPE_FLAG_NONE, - network_cyw43_make_new, + make_new, network_cyw43_make_new, print, network_cyw43_print, locals_dict, &network_cyw43_locals_dict ); diff --git a/extmod/network_ninaw10.c b/extmod/network_ninaw10.c index 806819648d..f4cc0b2224 100644 --- a/extmod/network_ninaw10.c +++ b/extmod/network_ninaw10.c @@ -159,7 +159,7 @@ STATIC mp_obj_t network_ninaw10_active(size_t n_args, const mp_obj_t *args) { MP_OBJ_NEW_QSTR(MP_QSTR_freq), MP_OBJ_NEW_SMALL_INT(10), MP_OBJ_NEW_QSTR(MP_QSTR_callback), MP_OBJ_FROM_PTR(&network_ninaw10_timer_callback_obj), }; - MP_STATE_PORT(mp_wifi_timer) = machine_timer_type.make_new((mp_obj_t)&machine_timer_type, 0, 2, timer_args); + MP_STATE_PORT(mp_wifi_timer) = MP_OBJ_TYPE_GET_SLOT(&machine_timer_type, make_new)((mp_obj_t)&machine_timer_type, 0, 2, timer_args); } } else { nina_deinit(); @@ -778,7 +778,7 @@ STATIC MP_DEFINE_CONST_OBJ_FULL_TYPE( mod_network_nic_type_nina_base, MP_QSTR_nina, MP_TYPE_FLAG_NONE, - network_ninaw10_make_new, + make_new, network_ninaw10_make_new, locals_dict, &nina_locals_dict ); diff --git a/extmod/network_wiznet5k.c b/extmod/network_wiznet5k.c index 82f836f691..af20145081 100644 --- a/extmod/network_wiznet5k.c +++ b/extmod/network_wiznet5k.c @@ -708,7 +708,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size MP_ROM_QSTR(MP_QSTR_miso), mp_pin_make_new(NULL, 1, 0, &miso_obj), MP_ROM_QSTR(MP_QSTR_mosi), mp_pin_make_new(NULL, 1, 0, &mosi_obj), }; - spi = MP_OBJ_TO_PTR(machine_spi_type.make_new((mp_obj_t)&machine_spi_type, 2, 3, args)); + spi = MP_OBJ_TO_PTR(MP_OBJ_TYPE_GET_SLOT(&machine_spi_type, make_new)((mp_obj_t)&machine_spi_type, 2, 3, args)); cs = mp_hal_get_pin_obj(mp_pin_make_new(NULL, 1, 0, (mp_obj_t[]) {MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_PIN_CS)})); rst = mp_hal_get_pin_obj(mp_pin_make_new(NULL, 1, 0, (mp_obj_t[]) {MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_PIN_RST)})); @@ -1020,7 +1020,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mod_network_nic_type_wiznet5k, MP_QSTR_WIZNET5K, MP_TYPE_FLAG_NONE, - wiznet5k_make_new, + make_new, wiznet5k_make_new, locals_dict, &wiznet5k_locals_dict ); #else // WIZNET5K_PROVIDED_STACK @@ -1028,7 +1028,7 @@ STATIC MP_DEFINE_CONST_OBJ_FULL_TYPE( mod_network_nic_type_wiznet5k_base, MP_QSTR_WIZNET5K, MP_TYPE_FLAG_NONE, - wiznet5k_make_new, + make_new, wiznet5k_make_new, locals_dict, &wiznet5k_locals_dict ); diff --git a/extmod/vfs.c b/extmod/vfs.c index 00450e1005..af63ceb37e 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -173,7 +173,7 @@ STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) { #if MICROPY_VFS_LFS1 if (memcmp(&buf[32], "littlefs", 8) == 0) { // LFS1 - mp_obj_t vfs = mp_type_vfs_lfs1.make_new(&mp_type_vfs_lfs1, 1, 0, &bdev_obj); + mp_obj_t vfs = MP_OBJ_TYPE_GET_SLOT(&mp_type_vfs_lfs1, make_new)(&mp_type_vfs_lfs1, 1, 0, &bdev_obj); nlr_pop(); return vfs; } @@ -181,7 +181,7 @@ STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) { #if MICROPY_VFS_LFS2 if (memcmp(&buf[0], "littlefs", 8) == 0) { // LFS2 - mp_obj_t vfs = mp_type_vfs_lfs2.make_new(&mp_type_vfs_lfs2, 1, 0, &bdev_obj); + mp_obj_t vfs = MP_OBJ_TYPE_GET_SLOT(&mp_type_vfs_lfs2, make_new)(&mp_type_vfs_lfs2, 1, 0, &bdev_obj); nlr_pop(); return vfs; } @@ -194,7 +194,7 @@ STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) { #endif #if MICROPY_VFS_FAT - return mp_fat_vfs_type.make_new(&mp_fat_vfs_type, 1, 0, &bdev_obj); + return MP_OBJ_TYPE_GET_SLOT(&mp_fat_vfs_type, make_new)(&mp_fat_vfs_type, 1, 0, &bdev_obj); #endif // no filesystem found diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 7c18a51633..efb6bf7e98 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -435,7 +435,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_fat_vfs_type, MP_QSTR_VfsFat, MP_TYPE_FLAG_NONE, - fat_vfs_make_new, + make_new, fat_vfs_make_new, protocol, &fat_vfs_proto, locals_dict, &fat_vfs_locals_dict ); diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index ca2e2b446f..07e6df9bf9 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -180,7 +180,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_vfs_fat_fileio, MP_QSTR_FileIO, MP_TYPE_FLAG_ITER_IS_STREAM, - MP_TYPE_NULL_MAKE_NEW, print, file_obj_print, protocol, &vfs_fat_fileio_stream_p, locals_dict, &vfs_fat_rawfile_locals_dict @@ -197,7 +196,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_vfs_fat_textio, MP_QSTR_TextIOWrapper, MP_TYPE_FLAG_ITER_IS_STREAM, - MP_TYPE_NULL_MAKE_NEW, print, file_obj_print, protocol, &vfs_fat_textio_stream_p, locals_dict, &vfs_fat_rawfile_locals_dict diff --git a/extmod/vfs_lfsx.c b/extmod/vfs_lfsx.c index 33e2ef5519..d9617817f9 100644 --- a/extmod/vfs_lfsx.c +++ b/extmod/vfs_lfsx.c @@ -512,7 +512,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_VFS_LFSx, VFS_LFSx_QSTR, MP_TYPE_FLAG_NONE, - MP_VFS_LFSx(make_new), + make_new, MP_VFS_LFSx(make_new), protocol, &MP_VFS_LFSx(proto), locals_dict, &MP_VFS_LFSx(locals_dict) ); diff --git a/extmod/vfs_lfsx_file.c b/extmod/vfs_lfsx_file.c index f97641b7b9..2c87fd5b99 100644 --- a/extmod/vfs_lfsx_file.c +++ b/extmod/vfs_lfsx_file.c @@ -224,7 +224,6 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_VFS_LFSx_(_fileio), MP_QSTR_FileIO, MP_TYPE_FLAG_ITER_IS_STREAM, - MP_TYPE_NULL_MAKE_NEW, print, MP_VFS_LFSx(file_print), protocol, &MP_VFS_LFSx(fileio_stream_p), locals_dict, &MP_VFS_LFSx(file_locals_dict) @@ -241,7 +240,6 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_VFS_LFSx_(_textio), MP_QSTR_TextIOWrapper, MP_TYPE_FLAG_ITER_IS_STREAM, - MP_TYPE_NULL_MAKE_NEW, print, MP_VFS_LFSx(file_print), protocol, &MP_VFS_LFSx(textio_stream_p), locals_dict, &MP_VFS_LFSx(file_locals_dict) diff --git a/extmod/vfs_posix.c b/extmod/vfs_posix.c index b02827e864..3694ebaf99 100644 --- a/extmod/vfs_posix.c +++ b/extmod/vfs_posix.c @@ -402,7 +402,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_vfs_posix, MP_QSTR_VfsPosix, MP_TYPE_FLAG_NONE, - vfs_posix_make_new, + make_new, vfs_posix_make_new, protocol, &vfs_posix_proto, locals_dict, &vfs_posix_locals_dict ); diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index 729d914d3a..4a37489686 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -253,7 +253,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_vfs_posix_fileio, MP_QSTR_FileIO, MP_TYPE_FLAG_ITER_IS_STREAM, - MP_TYPE_NULL_MAKE_NEW, print, vfs_posix_file_print, protocol, &vfs_posix_fileio_stream_p, locals_dict, &vfs_posix_rawfile_locals_dict @@ -270,7 +269,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_vfs_posix_textio, MP_QSTR_TextIOWrapper, MP_TYPE_FLAG_ITER_IS_STREAM, - MP_TYPE_NULL_MAKE_NEW, print, vfs_posix_file_print, protocol, &vfs_posix_textio_stream_p, locals_dict, &vfs_posix_rawfile_locals_dict diff --git a/ports/cc3200/misc/mpirq.c b/ports/cc3200/misc/mpirq.c index 9c3c2f7196..eb813fa4c6 100644 --- a/ports/cc3200/misc/mpirq.c +++ b/ports/cc3200/misc/mpirq.c @@ -194,7 +194,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_irq_type, MP_QSTR_irq, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, call, mp_irq_call, locals_dict, &mp_irq_locals_dict ); diff --git a/ports/cc3200/mods/modnetwork.c b/ports/cc3200/mods/modnetwork.c index 0a72a1ab32..590e872683 100644 --- a/ports/cc3200/mods/modnetwork.c +++ b/ports/cc3200/mods/modnetwork.c @@ -175,7 +175,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( network_server_type, MP_QSTR_Server, MP_TYPE_FLAG_NONE, - network_server_make_new, + make_new, network_server_make_new, locals_dict, &network_server_locals_dict ); #endif diff --git a/ports/cc3200/mods/moduhashlib.c b/ports/cc3200/mods/moduhashlib.c index 4a759d8ea5..302ff335ff 100644 --- a/ports/cc3200/mods/moduhashlib.c +++ b/ports/cc3200/mods/moduhashlib.c @@ -181,7 +181,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( sha1_type, MP_QSTR_sha1, MP_TYPE_FLAG_NONE, - hash_make_new, + make_new, hash_make_new, locals_dict, &hash_locals_dict ); @@ -189,7 +189,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( sha256_type, MP_QSTR_sha256, MP_TYPE_FLAG_NONE, - hash_make_new, + make_new, hash_make_new, locals_dict, &hash_locals_dict ); diff --git a/ports/cc3200/mods/modusocket.c b/ports/cc3200/mods/modusocket.c index 55d504a709..cd1489fb4a 100644 --- a/ports/cc3200/mods/modusocket.c +++ b/ports/cc3200/mods/modusocket.c @@ -763,7 +763,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( socket_type, MP_QSTR_socket, MP_TYPE_FLAG_NONE, - socket_make_new, + make_new, socket_make_new, protocol, &socket_stream_p, locals_dict, &socket_locals_dict ); diff --git a/ports/cc3200/mods/modwlan.c b/ports/cc3200/mods/modwlan.c index 1e82b07e08..6cf1cbee4e 100644 --- a/ports/cc3200/mods/modwlan.c +++ b/ports/cc3200/mods/modwlan.c @@ -1289,7 +1289,7 @@ STATIC MP_DEFINE_CONST_OBJ_FULL_TYPE( mod_network_nic_type_wlan_base, MP_QSTR_WLAN, MP_TYPE_FLAG_NONE, - wlan_make_new, + make_new, wlan_make_new, locals_dict, &wlan_locals_dict ); diff --git a/ports/cc3200/mods/pybadc.c b/ports/cc3200/mods/pybadc.c index a14f9aced2..7466428256 100644 --- a/ports/cc3200/mods/pybadc.c +++ b/ports/cc3200/mods/pybadc.c @@ -237,7 +237,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_adc_type, MP_QSTR_ADC, MP_TYPE_FLAG_NONE, - adc_make_new, + make_new, adc_make_new, print, adc_print, locals_dict, &adc_locals_dict ); @@ -305,7 +305,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( pyb_adc_channel_type, MP_QSTR_ADCChannel, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, adc_channel_print, call, adc_channel_call, locals_dict, &adc_channel_locals_dict diff --git a/ports/cc3200/mods/pybflash.c b/ports/cc3200/mods/pybflash.c index a6d1e23fbf..46b7be234f 100644 --- a/ports/cc3200/mods/pybflash.c +++ b/ports/cc3200/mods/pybflash.c @@ -88,7 +88,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_flash_type, MP_QSTR_Flash, MP_TYPE_FLAG_NONE, - pyb_flash_make_new, + make_new, pyb_flash_make_new, locals_dict, &pyb_flash_locals_dict ); diff --git a/ports/cc3200/mods/pybi2c.c b/ports/cc3200/mods/pybi2c.c index de92cc7c32..5d77dc8367 100644 --- a/ports/cc3200/mods/pybi2c.c +++ b/ports/cc3200/mods/pybi2c.c @@ -525,7 +525,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_i2c_type, MP_QSTR_I2C, MP_TYPE_FLAG_NONE, - pyb_i2c_make_new, + make_new, pyb_i2c_make_new, print, pyb_i2c_print, locals_dict, &pyb_i2c_locals_dict ); diff --git a/ports/cc3200/mods/pybpin.c b/ports/cc3200/mods/pybpin.c index 374d09ddfb..f04ca75654 100644 --- a/ports/cc3200/mods/pybpin.c +++ b/ports/cc3200/mods/pybpin.c @@ -935,7 +935,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pin_type, MP_QSTR_Pin, MP_TYPE_FLAG_NONE, - pin_make_new, + make_new, pin_make_new, print, pin_print, call, pin_call, locals_dict, &pin_locals_dict @@ -957,7 +957,6 @@ MP_DEFINE_CONST_OBJ_TYPE( pin_board_pins_obj_type, MP_QSTR_board, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, pin_named_pins_obj_print, locals_dict, &pin_board_pins_locals_dict ); diff --git a/ports/cc3200/mods/pybrtc.c b/ports/cc3200/mods/pybrtc.c index ed7a20fecb..21e729dbf1 100644 --- a/ports/cc3200/mods/pybrtc.c +++ b/ports/cc3200/mods/pybrtc.c @@ -473,7 +473,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_rtc_type, MP_QSTR_RTC, MP_TYPE_FLAG_NONE, - pyb_rtc_make_new, + make_new, pyb_rtc_make_new, locals_dict, &pyb_rtc_locals_dict ); diff --git a/ports/cc3200/mods/pybsd.c b/ports/cc3200/mods/pybsd.c index 968a6a87ec..209c3b5a85 100644 --- a/ports/cc3200/mods/pybsd.c +++ b/ports/cc3200/mods/pybsd.c @@ -216,6 +216,6 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_sd_type, MP_QSTR_SD, MP_TYPE_FLAG_NONE, - pyb_sd_make_new, + make_new, pyb_sd_make_new, locals_dict, &pyb_sd_locals_dict ); diff --git a/ports/cc3200/mods/pybsleep.c b/ports/cc3200/mods/pybsleep.c index 423099991f..ffb281e6b1 100644 --- a/ports/cc3200/mods/pybsleep.c +++ b/ports/cc3200/mods/pybsleep.c @@ -128,8 +128,7 @@ STATIC pybsleep_wake_reason_t pybsleep_wake_reason = PYB_SLP_WAKED_PWRON; STATIC MP_DEFINE_CONST_OBJ_TYPE( pyb_sleep_type, MP_QSTR_sleep, - MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW + MP_TYPE_FLAG_NONE ); /****************************************************************************** diff --git a/ports/cc3200/mods/pybspi.c b/ports/cc3200/mods/pybspi.c index 7d83fabfde..61086ec2e1 100644 --- a/ports/cc3200/mods/pybspi.c +++ b/ports/cc3200/mods/pybspi.c @@ -381,7 +381,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_spi_type, MP_QSTR_SPI, MP_TYPE_FLAG_NONE, - pyb_spi_make_new, + make_new, pyb_spi_make_new, print, pyb_spi_print, locals_dict, &pyb_spi_locals_dict ); diff --git a/ports/cc3200/mods/pybtimer.c b/ports/cc3200/mods/pybtimer.c index 14e1deb083..be365f3c92 100644 --- a/ports/cc3200/mods/pybtimer.c +++ b/ports/cc3200/mods/pybtimer.c @@ -463,7 +463,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_timer_type, MP_QSTR_Timer, MP_TYPE_FLAG_NONE, - pyb_timer_make_new, + make_new, pyb_timer_make_new, print, pyb_timer_print, locals_dict, &pyb_timer_locals_dict ); @@ -726,7 +726,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( pyb_timer_channel_type, MP_QSTR_TimerChannel, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, pyb_timer_channel_print, locals_dict, &pyb_timer_channel_locals_dict ); diff --git a/ports/cc3200/mods/pybuart.c b/ports/cc3200/mods/pybuart.c index f92f544732..424ca251ec 100644 --- a/ports/cc3200/mods/pybuart.c +++ b/ports/cc3200/mods/pybuart.c @@ -689,7 +689,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_uart_type, MP_QSTR_UART, MP_TYPE_FLAG_ITER_IS_STREAM, - pyb_uart_make_new, + make_new, pyb_uart_make_new, print, pyb_uart_print, protocol, &uart_stream_p, locals_dict, &pyb_uart_locals_dict diff --git a/ports/cc3200/mods/pybwdt.c b/ports/cc3200/mods/pybwdt.c index 3c1f9eb195..589f53cf12 100644 --- a/ports/cc3200/mods/pybwdt.c +++ b/ports/cc3200/mods/pybwdt.c @@ -154,7 +154,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_wdt_type, MP_QSTR_WDT, MP_TYPE_FLAG_NONE, - pyb_wdt_make_new, + make_new, pyb_wdt_make_new, locals_dict, &pybwdt_locals_dict ); diff --git a/ports/esp32/esp32_nvs.c b/ports/esp32/esp32_nvs.c index d935a13d6f..0b3661918c 100644 --- a/ports/esp32/esp32_nvs.c +++ b/ports/esp32/esp32_nvs.c @@ -145,7 +145,7 @@ MP_DEFINE_CONST_OBJ_TYPE( esp32_nvs_type, MP_QSTR_NVS, MP_TYPE_FLAG_NONE, - esp32_nvs_make_new, + make_new, esp32_nvs_make_new, print, esp32_nvs_print, locals_dict, &esp32_nvs_locals_dict ); diff --git a/ports/esp32/esp32_partition.c b/ports/esp32/esp32_partition.c index 6ce1e90b4c..17aa34e560 100644 --- a/ports/esp32/esp32_partition.c +++ b/ports/esp32/esp32_partition.c @@ -288,7 +288,7 @@ MP_DEFINE_CONST_OBJ_TYPE( esp32_partition_type, MP_QSTR_Partition, MP_TYPE_FLAG_NONE, - esp32_partition_make_new, + make_new, esp32_partition_make_new, print, esp32_partition_print, locals_dict, &esp32_partition_locals_dict ); diff --git a/ports/esp32/esp32_rmt.c b/ports/esp32/esp32_rmt.c index ee09ac5200..78c8c8acee 100644 --- a/ports/esp32/esp32_rmt.c +++ b/ports/esp32/esp32_rmt.c @@ -376,7 +376,7 @@ MP_DEFINE_CONST_OBJ_TYPE( esp32_rmt_type, MP_QSTR_RMT, MP_TYPE_FLAG_NONE, - esp32_rmt_make_new, + make_new, esp32_rmt_make_new, print, esp32_rmt_print, locals_dict, &esp32_rmt_locals_dict ); diff --git a/ports/esp32/esp32_ulp.c b/ports/esp32/esp32_ulp.c index 5030f98067..843bdb2366 100644 --- a/ports/esp32/esp32_ulp.c +++ b/ports/esp32/esp32_ulp.c @@ -95,7 +95,7 @@ MP_DEFINE_CONST_OBJ_TYPE( esp32_ulp_type, MP_QSTR_ULP, MP_TYPE_FLAG_NONE, - esp32_ulp_make_new, + make_new, esp32_ulp_make_new, locals_dict, &esp32_ulp_locals_dict ); diff --git a/ports/esp32/machine_adc.c b/ports/esp32/machine_adc.c index c4e04159c0..1e20186b97 100644 --- a/ports/esp32/machine_adc.c +++ b/ports/esp32/machine_adc.c @@ -260,7 +260,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_adc_type, MP_QSTR_ADC, MP_TYPE_FLAG_NONE, - madc_make_new, + make_new, madc_make_new, print, madc_print, locals_dict, &madc_locals_dict ); diff --git a/ports/esp32/machine_adcblock.c b/ports/esp32/machine_adcblock.c index ae3244f7fd..afe8fdea40 100644 --- a/ports/esp32/machine_adcblock.c +++ b/ports/esp32/machine_adcblock.c @@ -198,7 +198,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_adcblock_type, MP_QSTR_ADCBlock, MP_TYPE_FLAG_NONE, - madcblock_make_new, + make_new, madcblock_make_new, print, madcblock_print, locals_dict, &madcblock_locals_dict ); diff --git a/ports/esp32/machine_dac.c b/ports/esp32/machine_dac.c index fbe33b0344..0e85dc9c9b 100644 --- a/ports/esp32/machine_dac.c +++ b/ports/esp32/machine_dac.c @@ -108,7 +108,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_dac_type, MP_QSTR_DAC, MP_TYPE_FLAG_NONE, - mdac_make_new, + make_new, mdac_make_new, print, mdac_print, locals_dict, &mdac_locals_dict ); diff --git a/ports/esp32/machine_hw_spi.c b/ports/esp32/machine_hw_spi.c index 51ea31ac1b..05b1c871cb 100644 --- a/ports/esp32/machine_hw_spi.c +++ b/ports/esp32/machine_hw_spi.c @@ -549,7 +549,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hw_spi_type, MP_QSTR_SPI, MP_TYPE_FLAG_NONE, - machine_hw_spi_make_new, + make_new, machine_hw_spi_make_new, print, machine_hw_spi_print, protocol, &machine_hw_spi_p, locals_dict, &mp_machine_spi_locals_dict diff --git a/ports/esp32/machine_i2c.c b/ports/esp32/machine_i2c.c index 895dc3a398..9244343dcf 100644 --- a/ports/esp32/machine_i2c.c +++ b/ports/esp32/machine_i2c.c @@ -196,7 +196,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hw_i2c_type, MP_QSTR_I2C, MP_TYPE_FLAG_NONE, - machine_hw_i2c_make_new, + make_new, machine_hw_i2c_make_new, print, machine_hw_i2c_print, protocol, &machine_hw_i2c_p, locals_dict, &mp_machine_i2c_locals_dict diff --git a/ports/esp32/machine_i2s.c b/ports/esp32/machine_i2s.c index 6e18394cc5..eecf715498 100644 --- a/ports/esp32/machine_i2s.c +++ b/ports/esp32/machine_i2s.c @@ -833,7 +833,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_i2s_type, MP_QSTR_I2S, MP_TYPE_FLAG_ITER_IS_STREAM, - machine_i2s_make_new, + make_new, machine_i2s_make_new, print, machine_i2s_print, protocol, &i2s_stream_p, locals_dict, &machine_i2s_locals_dict diff --git a/ports/esp32/machine_pin.c b/ports/esp32/machine_pin.c index fd523a38ed..4f6f948d52 100644 --- a/ports/esp32/machine_pin.c +++ b/ports/esp32/machine_pin.c @@ -533,7 +533,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_pin_type, MP_QSTR_Pin, MP_TYPE_FLAG_NONE, - mp_pin_make_new, + make_new, mp_pin_make_new, print, machine_pin_print, call, machine_pin_call, protocol, &pin_pin_p, @@ -728,7 +728,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( machine_pin_irq_type, MP_QSTR_IRQ, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, call, machine_pin_irq_call, locals_dict, &machine_pin_irq_locals_dict ); diff --git a/ports/esp32/machine_rtc.c b/ports/esp32/machine_rtc.c index 19b83703fd..3d620336c9 100644 --- a/ports/esp32/machine_rtc.c +++ b/ports/esp32/machine_rtc.c @@ -177,6 +177,6 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_rtc_type, MP_QSTR_RTC, MP_TYPE_FLAG_NONE, - machine_rtc_make_new, + make_new, machine_rtc_make_new, locals_dict, &machine_rtc_locals_dict ); diff --git a/ports/esp32/machine_sdcard.c b/ports/esp32/machine_sdcard.c index 0b6159157d..801a26f378 100644 --- a/ports/esp32/machine_sdcard.c +++ b/ports/esp32/machine_sdcard.c @@ -403,7 +403,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_sdcard_type, MP_QSTR_SDCard, MP_TYPE_FLAG_NONE, - machine_sdcard_make_new, + make_new, machine_sdcard_make_new, locals_dict, &machine_sdcard_locals_dict ); diff --git a/ports/esp32/machine_timer.c b/ports/esp32/machine_timer.c index 2fd40fa2af..83fe81f6ee 100644 --- a/ports/esp32/machine_timer.c +++ b/ports/esp32/machine_timer.c @@ -281,7 +281,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_timer_type, MP_QSTR_Timer, MP_TYPE_FLAG_NONE, - machine_timer_make_new, + make_new, machine_timer_make_new, print, machine_timer_print, locals_dict, &machine_timer_locals_dict ); diff --git a/ports/esp32/machine_touchpad.c b/ports/esp32/machine_touchpad.c index deba818dd1..ad1f6c9474 100644 --- a/ports/esp32/machine_touchpad.c +++ b/ports/esp32/machine_touchpad.c @@ -138,7 +138,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_touchpad_type, MP_QSTR_TouchPad, MP_TYPE_FLAG_NONE, - mtp_make_new, + make_new, mtp_make_new, locals_dict, &mtp_locals_dict ); diff --git a/ports/esp32/machine_uart.c b/ports/esp32/machine_uart.c index 1f404154fc..4cfa31b71d 100644 --- a/ports/esp32/machine_uart.c +++ b/ports/esp32/machine_uart.c @@ -534,7 +534,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_uart_type, MP_QSTR_UART, MP_TYPE_FLAG_ITER_IS_STREAM, - machine_uart_make_new, + 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/machine_wdt.c b/ports/esp32/machine_wdt.c index bda9c6975e..4ccf417b60 100644 --- a/ports/esp32/machine_wdt.c +++ b/ports/esp32/machine_wdt.c @@ -87,6 +87,6 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_wdt_type, MP_QSTR_WDT, MP_TYPE_FLAG_NONE, - machine_wdt_make_new, + make_new, machine_wdt_make_new, locals_dict, &machine_wdt_locals_dict ); diff --git a/ports/esp32/modsocket.c b/ports/esp32/modsocket.c index e7e6f3c26e..334c5bae33 100644 --- a/ports/esp32/modsocket.c +++ b/ports/esp32/modsocket.c @@ -789,7 +789,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( socket_type, MP_QSTR_socket, MP_TYPE_FLAG_NONE, - socket_make_new, + make_new, socket_make_new, protocol, &socket_stream_p, locals_dict, &socket_locals_dict ); diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c index 3c5aea5fb8..c57d7815d7 100644 --- a/ports/esp32/network_lan.c +++ b/ports/esp32/network_lan.c @@ -306,7 +306,6 @@ MP_DEFINE_CONST_OBJ_TYPE( lan_if_type, MP_QSTR_LAN, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, locals_dict, &lan_if_locals_dict ); diff --git a/ports/esp32/network_ppp.c b/ports/esp32/network_ppp.c index df07515c7d..703cdc7889 100644 --- a/ports/esp32/network_ppp.c +++ b/ports/esp32/network_ppp.c @@ -282,6 +282,5 @@ MP_DEFINE_CONST_OBJ_TYPE( ppp_if_type, MP_QSTR_PPP, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, locals_dict, &ppp_if_locals_dict ); diff --git a/ports/esp32/network_wlan.c b/ports/esp32/network_wlan.c index 0f1f5de149..f0b458e6dd 100644 --- a/ports/esp32/network_wlan.c +++ b/ports/esp32/network_wlan.c @@ -619,7 +619,6 @@ MP_DEFINE_CONST_OBJ_TYPE( wlan_if_type, MP_QSTR_WLAN, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, locals_dict, &wlan_if_locals_dict ); diff --git a/ports/esp8266/machine_adc.c b/ports/esp8266/machine_adc.c index b1e7b38435..f4fd32db9c 100644 --- a/ports/esp8266/machine_adc.c +++ b/ports/esp8266/machine_adc.c @@ -93,7 +93,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_adc_type, MP_QSTR_ADC, MP_TYPE_FLAG_NONE, - machine_adc_make_new, + make_new, machine_adc_make_new, print, machine_adc_print, locals_dict, &machine_adc_locals_dict ); diff --git a/ports/esp8266/machine_hspi.c b/ports/esp8266/machine_hspi.c index 3f449a1de9..2edb294ade 100644 --- a/ports/esp8266/machine_hspi.c +++ b/ports/esp8266/machine_hspi.c @@ -179,7 +179,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hspi_type, MP_QSTR_HSPI, MP_TYPE_FLAG_NONE, - machine_hspi_make_new, + make_new, machine_hspi_make_new, print, machine_hspi_print, protocol, &machine_hspi_p, locals_dict, &mp_machine_spi_locals_dict diff --git a/ports/esp8266/machine_pin.c b/ports/esp8266/machine_pin.c index 32ffca873d..ea17728e23 100644 --- a/ports/esp8266/machine_pin.c +++ b/ports/esp8266/machine_pin.c @@ -454,7 +454,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_pin_type, MP_QSTR_Pin, MP_TYPE_FLAG_NONE, - mp_pin_make_new, + make_new, mp_pin_make_new, print, pyb_pin_print, call, pyb_pin_call, protocol, &pin_pin_p, @@ -514,7 +514,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( pin_irq_type, MP_QSTR_IRQ, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, call, pin_irq_call, locals_dict, &pin_irq_locals_dict ); diff --git a/ports/esp8266/machine_rtc.c b/ports/esp8266/machine_rtc.c index cc6b79a031..d8cbb8f824 100644 --- a/ports/esp8266/machine_rtc.c +++ b/ports/esp8266/machine_rtc.c @@ -266,6 +266,6 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_rtc_type, MP_QSTR_RTC, MP_TYPE_FLAG_NONE, - pyb_rtc_make_new, + make_new, pyb_rtc_make_new, locals_dict, &pyb_rtc_locals_dict ); diff --git a/ports/esp8266/machine_uart.c b/ports/esp8266/machine_uart.c index af6231c219..873b12b2fa 100644 --- a/ports/esp8266/machine_uart.c +++ b/ports/esp8266/machine_uart.c @@ -347,7 +347,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_uart_type, MP_QSTR_UART, MP_TYPE_FLAG_ITER_IS_STREAM, - pyb_uart_make_new, + make_new, pyb_uart_make_new, print, pyb_uart_print, protocol, &uart_stream_p, locals_dict, &pyb_uart_locals_dict diff --git a/ports/esp8266/machine_wdt.c b/ports/esp8266/machine_wdt.c index 26d5c9fa76..39a5d51119 100644 --- a/ports/esp8266/machine_wdt.c +++ b/ports/esp8266/machine_wdt.c @@ -73,6 +73,6 @@ MP_DEFINE_CONST_OBJ_TYPE( esp_wdt_type, MP_QSTR_WDT, MP_TYPE_FLAG_NONE, - machine_wdt_make_new, + make_new, machine_wdt_make_new, locals_dict, &machine_wdt_locals_dict ); diff --git a/ports/esp8266/main.c b/ports/esp8266/main.c index ded5e58abf..583540a81c 100644 --- a/ports/esp8266/main.c +++ b/ports/esp8266/main.c @@ -68,7 +68,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] = pyb_uart_type.make_new(&pyb_uart_type, 2, 0, args); + args[0] = MP_OBJ_TYPE_GET_SLOT(&pyb_uart_type, make_new)(&pyb_uart_type, 2, 0, args); args[1] = MP_OBJ_NEW_SMALL_INT(1); mp_uos_dupterm_obj.fun.var(2, args); } diff --git a/ports/esp8266/modmachine.c b/ports/esp8266/modmachine.c index eb41e30f66..af46cbbfe7 100644 --- a/ports/esp8266/modmachine.c +++ b/ports/esp8266/modmachine.c @@ -341,7 +341,7 @@ MP_DEFINE_CONST_OBJ_TYPE( esp_timer_type, MP_QSTR_Timer, MP_TYPE_FLAG_NONE, - esp_timer_make_new, + make_new, esp_timer_make_new, print, esp_timer_print, locals_dict, &esp_timer_locals_dict ); diff --git a/ports/esp8266/modnetwork.c b/ports/esp8266/modnetwork.c index 45a5a2be54..ec62528a08 100644 --- a/ports/esp8266/modnetwork.c +++ b/ports/esp8266/modnetwork.c @@ -514,7 +514,6 @@ MP_DEFINE_CONST_OBJ_TYPE( wlan_if_type, MP_QSTR_WLAN, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, locals_dict, &wlan_if_locals_dict ); diff --git a/ports/mimxrt/machine_adc.c b/ports/mimxrt/machine_adc.c index 7a19d1225e..d63157d36e 100644 --- a/ports/mimxrt/machine_adc.c +++ b/ports/mimxrt/machine_adc.c @@ -121,7 +121,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_adc_type, MP_QSTR_ADC, MP_TYPE_FLAG_NONE, - adc_obj_make_new, + make_new, adc_obj_make_new, print, adc_obj_print, locals_dict, &adc_locals_dict ); diff --git a/ports/mimxrt/machine_i2c.c b/ports/mimxrt/machine_i2c.c index 62dfd8204c..f00ba6b1ba 100644 --- a/ports/mimxrt/machine_i2c.c +++ b/ports/mimxrt/machine_i2c.c @@ -201,7 +201,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_i2c_type, MP_QSTR_I2C, MP_TYPE_FLAG_NONE, - machine_i2c_make_new, + make_new, machine_i2c_make_new, print, machine_i2c_print, protocol, &machine_i2c_p, locals_dict, &mp_machine_i2c_locals_dict diff --git a/ports/mimxrt/machine_i2s.c b/ports/mimxrt/machine_i2s.c index b6c630138b..1733140fb5 100644 --- a/ports/mimxrt/machine_i2s.c +++ b/ports/mimxrt/machine_i2s.c @@ -1217,7 +1217,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_i2s_type, MP_QSTR_I2S, MP_TYPE_FLAG_ITER_IS_STREAM, - machine_i2s_make_new, + make_new, machine_i2s_make_new, print, machine_i2s_print, protocol, &i2s_stream_p, locals_dict, &machine_i2s_locals_dict diff --git a/ports/mimxrt/machine_led.c b/ports/mimxrt/machine_led.c index 9fd98ef710..8dd74b32ba 100644 --- a/ports/mimxrt/machine_led.c +++ b/ports/mimxrt/machine_led.c @@ -84,7 +84,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_led_type, MP_QSTR_LED, MP_TYPE_FLAG_NONE, - led_obj_make_new, + make_new, led_obj_make_new, print, led_obj_print, locals_dict, &led_locals_dict ); diff --git a/ports/mimxrt/machine_pin.c b/ports/mimxrt/machine_pin.c index 261e3e4148..836bd8524b 100644 --- a/ports/mimxrt/machine_pin.c +++ b/ports/mimxrt/machine_pin.c @@ -62,7 +62,6 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_pin_cpu_pins_obj_type, MP_QSTR_cpu, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, locals_dict, &machine_pin_cpu_pins_locals_dict ); @@ -70,7 +69,6 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_pin_board_pins_obj_type, MP_QSTR_board, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, locals_dict, &machine_pin_board_pins_locals_dict ); @@ -424,7 +422,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_pin_type, MP_QSTR_Pin, MP_TYPE_FLAG_NONE, - mp_pin_make_new, + make_new, mp_pin_make_new, print, machine_pin_obj_print, call, machine_pin_obj_call, protocol, &machine_pin_obj_protocol, @@ -436,7 +434,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_pin_af_type, MP_QSTR_PinAF, MP_TYPE_FLAG_NONE, - mp_pin_make_new, + make_new, mp_pin_make_new, print, machine_pin_obj_print, locals_dict, &machine_pin_locals_dict ); diff --git a/ports/mimxrt/machine_rtc.c b/ports/mimxrt/machine_rtc.c index 2e1a09dedb..da7a437491 100644 --- a/ports/mimxrt/machine_rtc.c +++ b/ports/mimxrt/machine_rtc.c @@ -170,6 +170,6 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_rtc_type, MP_QSTR_RTC, MP_TYPE_FLAG_NONE, - machine_rtc_make_new, + make_new, machine_rtc_make_new, locals_dict, &machine_rtc_locals_dict ); diff --git a/ports/mimxrt/machine_sdcard.c b/ports/mimxrt/machine_sdcard.c index 22f7e7c232..9254faf14a 100644 --- a/ports/mimxrt/machine_sdcard.c +++ b/ports/mimxrt/machine_sdcard.c @@ -212,7 +212,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_sdcard_type, MP_QSTR_SDCard, MP_TYPE_FLAG_NONE, - sdcard_obj_make_new, + make_new, sdcard_obj_make_new, locals_dict, &sdcard_locals_dict ); diff --git a/ports/mimxrt/machine_spi.c b/ports/mimxrt/machine_spi.c index 93b75e931e..a3a6bb414e 100644 --- a/ports/mimxrt/machine_spi.c +++ b/ports/mimxrt/machine_spi.c @@ -255,7 +255,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_spi_type, MP_QSTR_SPI, MP_TYPE_FLAG_NONE, - machine_spi_make_new, + make_new, machine_spi_make_new, print, machine_spi_print, protocol, &machine_spi_p, locals_dict, &mp_machine_spi_locals_dict diff --git a/ports/mimxrt/machine_timer.c b/ports/mimxrt/machine_timer.c index a6b61982f7..a237272390 100644 --- a/ports/mimxrt/machine_timer.c +++ b/ports/mimxrt/machine_timer.c @@ -215,7 +215,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_timer_type, MP_QSTR_Timer, MP_TYPE_FLAG_NONE, - machine_timer_make_new, + make_new, machine_timer_make_new, print, machine_timer_print, locals_dict, &machine_timer_locals_dict ); diff --git a/ports/mimxrt/machine_uart.c b/ports/mimxrt/machine_uart.c index e93d2478f3..a0706c8f4f 100644 --- a/ports/mimxrt/machine_uart.c +++ b/ports/mimxrt/machine_uart.c @@ -473,7 +473,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_uart_type, MP_QSTR_UART, MP_TYPE_FLAG_ITER_IS_STREAM, - machine_uart_make_new, + 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/machine_wdt.c b/ports/mimxrt/machine_wdt.c index e0b5c74b54..f5f14f9ef7 100644 --- a/ports/mimxrt/machine_wdt.c +++ b/ports/mimxrt/machine_wdt.c @@ -103,6 +103,6 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_wdt_type, MP_QSTR_WDT, MP_TYPE_FLAG_NONE, - machine_wdt_make_new, + make_new, machine_wdt_make_new, locals_dict, &machine_wdt_locals_dict ); diff --git a/ports/mimxrt/mimxrt_flash.c b/ports/mimxrt/mimxrt_flash.c index bd03c853d5..fd2e7558f9 100644 --- a/ports/mimxrt/mimxrt_flash.c +++ b/ports/mimxrt/mimxrt_flash.c @@ -219,6 +219,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mimxrt_flash_type, MP_QSTR_Flash, MP_TYPE_FLAG_NONE, - mimxrt_flash_make_new, + make_new, mimxrt_flash_make_new, locals_dict, &mimxrt_flash_locals_dict ); diff --git a/ports/mimxrt/network_lan.c b/ports/mimxrt/network_lan.c index e15894294b..0842cde82d 100644 --- a/ports/mimxrt/network_lan.c +++ b/ports/mimxrt/network_lan.c @@ -224,7 +224,7 @@ MP_DEFINE_CONST_OBJ_TYPE( network_lan_type, MP_QSTR_LAN, MP_TYPE_FLAG_NONE, - network_lan_make_new, + make_new, network_lan_make_new, print, network_lan_print, locals_dict, &network_lan_locals_dict ); diff --git a/ports/nrf/boards/microbit/modules/iters.c b/ports/nrf/boards/microbit/modules/iters.c index 2fe1486691..e6762421eb 100644 --- a/ports/nrf/boards/microbit/modules/iters.c +++ b/ports/nrf/boards/microbit/modules/iters.c @@ -47,7 +47,6 @@ MP_DEFINE_CONST_OBJ_TYPE( microbit_repeat_iterator_type, MP_QSTR_iterator, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - MP_TYPE_NULL_MAKE_NEW, iter, microbit_repeat_iter_next ); diff --git a/ports/nrf/boards/microbit/modules/microbitdisplay.c b/ports/nrf/boards/microbit/modules/microbitdisplay.c index 5cb25ea1ce..e4e4d13fe4 100644 --- a/ports/nrf/boards/microbit/modules/microbitdisplay.c +++ b/ports/nrf/boards/microbit/modules/microbitdisplay.c @@ -546,7 +546,6 @@ MP_DEFINE_CONST_OBJ_TYPE( microbit_display_type, MP_QSTR_MicroBitDisplay, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, locals_dict, µbit_display_locals_dict ); diff --git a/ports/nrf/boards/microbit/modules/microbitimage.c b/ports/nrf/boards/microbit/modules/microbitimage.c index b22c2e29ac..17d737dba5 100644 --- a/ports/nrf/boards/microbit/modules/microbitimage.c +++ b/ports/nrf/boards/microbit/modules/microbitimage.c @@ -682,7 +682,7 @@ MP_DEFINE_CONST_OBJ_TYPE( microbit_image_type, MP_QSTR_MicroBitImage, MP_TYPE_FLAG_NONE, - microbit_image_make_new, + make_new, microbit_image_make_new, print, microbit_image_print, binary_op, image_binary_op, locals_dict, µbit_image_locals_dict @@ -832,7 +832,6 @@ MP_DEFINE_CONST_OBJ_TYPE( microbit_scrolling_string_iterator_type, MP_QSTR_iterator, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - MP_TYPE_NULL_MAKE_NEW, iter, microbit_scrolling_string_iter_next ); @@ -912,7 +911,6 @@ MP_DEFINE_CONST_OBJ_TYPE( microbit_facade_iterator_type, MP_QSTR_iterator, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - MP_TYPE_NULL_MAKE_NEW, iter, microbit_facade_iter_next ); diff --git a/ports/nrf/main.c b/ports/nrf/main.c index 83466626fc..bcfaafd39c 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -170,7 +170,7 @@ soft_reset: MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_NEW_SMALL_INT(115200), }; - MP_STATE_PORT(board_stdio_uart) = machine_hard_uart_type.make_new((mp_obj_t)&machine_hard_uart_type, MP_ARRAY_SIZE(args), 0, args); + MP_STATE_PORT(board_stdio_uart) = MP_OBJ_TYPE_GET_SLOT(&machine_hard_uart_type, make_new)((mp_obj_t)&machine_hard_uart_type, MP_ARRAY_SIZE(args), 0, args); } #endif diff --git a/ports/nrf/modules/board/led.c b/ports/nrf/modules/board/led.c index 577c2b6284..57065a4851 100644 --- a/ports/nrf/modules/board/led.c +++ b/ports/nrf/modules/board/led.c @@ -198,7 +198,7 @@ MP_DEFINE_CONST_OBJ_TYPE( board_led_type, MP_QSTR_LED, MP_TYPE_FLAG_NONE, - led_obj_make_new, + make_new, led_obj_make_new, print, led_obj_print, locals_dict, &led_locals_dict ); diff --git a/ports/nrf/modules/machine/adc.c b/ports/nrf/modules/machine/adc.c index 84db8d259f..df9d23465a 100644 --- a/ports/nrf/modules/machine/adc.c +++ b/ports/nrf/modules/machine/adc.c @@ -298,7 +298,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_adc_type, MP_QSTR_ADC, MP_TYPE_FLAG_NONE, - machine_adc_make_new, + make_new, machine_adc_make_new, locals_dict, &machine_adc_locals_dict, print, machine_adc_print ); diff --git a/ports/nrf/modules/machine/i2c.c b/ports/nrf/modules/machine/i2c.c index 7cb55d0788..c16c3669ec 100644 --- a/ports/nrf/modules/machine/i2c.c +++ b/ports/nrf/modules/machine/i2c.c @@ -165,7 +165,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hard_i2c_type, MP_QSTR_I2C, MP_TYPE_FLAG_NONE, - machine_hard_i2c_make_new, + make_new, machine_hard_i2c_make_new, print, machine_hard_i2c_print, protocol, &machine_hard_i2c_p, locals_dict, &mp_machine_i2c_locals_dict diff --git a/ports/nrf/modules/machine/pin.c b/ports/nrf/modules/machine/pin.c index 4f283e5dba..db5cc9cbb1 100644 --- a/ports/nrf/modules/machine/pin.c +++ b/ports/nrf/modules/machine/pin.c @@ -600,7 +600,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pin_type, MP_QSTR_Pin, MP_TYPE_FLAG_NONE, - pin_make_new, + make_new, pin_make_new, print, pin_print, call, pin_call, locals_dict, &pin_locals_dict @@ -676,7 +676,6 @@ MP_DEFINE_CONST_OBJ_TYPE( pin_af_type, MP_QSTR_PinAF, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, pin_af_obj_print, locals_dict, &pin_af_locals_dict ); diff --git a/ports/nrf/modules/machine/pwm.c b/ports/nrf/modules/machine/pwm.c index 54e643ec55..862e1907cb 100644 --- a/ports/nrf/modules/machine/pwm.c +++ b/ports/nrf/modules/machine/pwm.c @@ -343,7 +343,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hard_pwm_type, MP_QSTR_PWM, MP_TYPE_FLAG_NONE, - machine_pwm_make_new, + make_new, machine_pwm_make_new, print, machine_pwm_print, locals_dict, &machine_pwm_locals_dict ); diff --git a/ports/nrf/modules/machine/rtcounter.c b/ports/nrf/modules/machine/rtcounter.c index cafe08b6c6..d52ca3e9a3 100644 --- a/ports/nrf/modules/machine/rtcounter.c +++ b/ports/nrf/modules/machine/rtcounter.c @@ -266,7 +266,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_rtcounter_type, MP_QSTR_RTCounter, MP_TYPE_FLAG_NONE, - machine_rtc_make_new, + make_new, machine_rtc_make_new, print, rtc_print, locals_dict, &machine_rtc_locals_dict ); diff --git a/ports/nrf/modules/machine/spi.c b/ports/nrf/modules/machine/spi.c index d5613a4643..fd7f7bb5bc 100644 --- a/ports/nrf/modules/machine/spi.c +++ b/ports/nrf/modules/machine/spi.c @@ -431,7 +431,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hard_spi_type, MP_QSTR_SPI, MP_TYPE_FLAG_NONE, - machine_spi_make_new, + make_new, machine_spi_make_new, print, machine_hard_spi_print, protocol, &machine_hard_spi_p, locals_dict, &machine_spi_locals_dict diff --git a/ports/nrf/modules/machine/temp.c b/ports/nrf/modules/machine/temp.c index 00d6329b64..dff15a9d14 100644 --- a/ports/nrf/modules/machine/temp.c +++ b/ports/nrf/modules/machine/temp.c @@ -116,7 +116,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_temp_type, MP_QSTR_Temp, MP_TYPE_FLAG_NONE, - machine_temp_make_new, + make_new, machine_temp_make_new, locals_dict, &machine_temp_locals_dict, print, machine_temp_print ); diff --git a/ports/nrf/modules/machine/timer.c b/ports/nrf/modules/machine/timer.c index f7f6101726..091e6d0e32 100644 --- a/ports/nrf/modules/machine/timer.c +++ b/ports/nrf/modules/machine/timer.c @@ -238,7 +238,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_timer_type, MP_QSTR_Timer, MP_TYPE_FLAG_NONE, - machine_timer_make_new, + make_new, machine_timer_make_new, print, timer_print, locals_dict, &machine_timer_locals_dict ); diff --git a/ports/nrf/modules/machine/uart.c b/ports/nrf/modules/machine/uart.c index ca0fcf859a..035a30df9c 100644 --- a/ports/nrf/modules/machine/uart.c +++ b/ports/nrf/modules/machine/uart.c @@ -374,7 +374,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hard_uart_type, MP_QSTR_UART, MP_TYPE_FLAG_ITER_IS_STREAM, - machine_hard_uart_make_new, + make_new, machine_hard_uart_make_new, print, machine_hard_uart_print, protocol, &uart_stream_p, locals_dict, &machine_hard_uart_locals_dict diff --git a/ports/nrf/modules/nrf/flashbdev.c b/ports/nrf/modules/nrf/flashbdev.c index 84a3dd2520..e92919cac5 100644 --- a/ports/nrf/modules/nrf/flashbdev.c +++ b/ports/nrf/modules/nrf/flashbdev.c @@ -187,7 +187,7 @@ MP_DEFINE_CONST_OBJ_TYPE( nrf_flashbdev_type, MP_QSTR_Flash, MP_TYPE_FLAG_NONE, - nrf_flashbdev_make_new, + make_new, nrf_flashbdev_make_new, print, nrf_flashbdev_print, locals_dict, &nrf_flashbdev_locals_dict ); diff --git a/ports/nrf/modules/ubluepy/ubluepy_characteristic.c b/ports/nrf/modules/ubluepy/ubluepy_characteristic.c index 2be7dab9d3..7b9e3af6a3 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_characteristic.c +++ b/ports/nrf/modules/ubluepy/ubluepy_characteristic.c @@ -213,7 +213,7 @@ MP_DEFINE_CONST_OBJ_TYPE( ubluepy_characteristic_type, MP_QSTR_Characteristic, MP_TYPE_FLAG_NONE, - ubluepy_characteristic_make_new, + make_new, ubluepy_characteristic_make_new, print, ubluepy_characteristic_print, locals_dict, &ubluepy_characteristic_locals_dict ); diff --git a/ports/nrf/modules/ubluepy/ubluepy_constants.c b/ports/nrf/modules/ubluepy/ubluepy_constants.c index c6c3999245..cad9adbb03 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_constants.c +++ b/ports/nrf/modules/ubluepy/ubluepy_constants.c @@ -73,7 +73,6 @@ MP_DEFINE_CONST_OBJ_TYPE( ubluepy_constants_ad_types_type, MP_QSTR_ad_types, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, locals_dict, &ubluepy_constants_ad_types_locals_dict ); @@ -96,7 +95,6 @@ MP_DEFINE_CONST_OBJ_TYPE( ubluepy_constants_type, MP_QSTR_constants, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, locals_dict, &ubluepy_constants_locals_dict ); diff --git a/ports/nrf/modules/ubluepy/ubluepy_delegate.c b/ports/nrf/modules/ubluepy/ubluepy_delegate.c index dd19f70be4..43720b4186 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_delegate.c +++ b/ports/nrf/modules/ubluepy/ubluepy_delegate.c @@ -81,7 +81,7 @@ MP_DEFINE_CONST_OBJ_TYPE( ubluepy_delegate_type, MP_QSTR_DefaultDelegate, MP_TYPE_FLAG_NONE, - ubluepy_delegate_make_new, + make_new, ubluepy_delegate_make_new, print, ubluepy_delegate_print, locals_dict, &ubluepy_delegate_locals_dict ); diff --git a/ports/nrf/modules/ubluepy/ubluepy_descriptor.c b/ports/nrf/modules/ubluepy/ubluepy_descriptor.c index d942d98223..062b421094 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_descriptor.c +++ b/ports/nrf/modules/ubluepy/ubluepy_descriptor.c @@ -74,7 +74,7 @@ MP_DEFINE_CONST_OBJ_TYPE( ubluepy_descriptor_type, MP_QSTR_Descriptor, MP_TYPE_FLAG_NONE, - ubluepy_descriptor_make_new, + make_new, ubluepy_descriptor_make_new, print, ubluepy_descriptor_print, locals_dict, &ubluepy_descriptor_locals_dict ); diff --git a/ports/nrf/modules/ubluepy/ubluepy_peripheral.c b/ports/nrf/modules/ubluepy/ubluepy_peripheral.c index 9f638b45d7..d2a9e0011d 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_peripheral.c +++ b/ports/nrf/modules/ubluepy/ubluepy_peripheral.c @@ -486,7 +486,7 @@ MP_DEFINE_CONST_OBJ_TYPE( ubluepy_peripheral_type, MP_QSTR_Peripheral, MP_TYPE_FLAG_NONE, - ubluepy_peripheral_make_new, + make_new, ubluepy_peripheral_make_new, print, ubluepy_peripheral_print, locals_dict, &ubluepy_peripheral_locals_dict ); diff --git a/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c b/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c index 89ca65d18c..2dd4f57860 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c +++ b/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c @@ -140,7 +140,6 @@ MP_DEFINE_CONST_OBJ_TYPE( ubluepy_scan_entry_type, MP_QSTR_ScanEntry, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, ubluepy_scan_entry_print, locals_dict, &ubluepy_scan_entry_locals_dict ); diff --git a/ports/nrf/modules/ubluepy/ubluepy_scanner.c b/ports/nrf/modules/ubluepy/ubluepy_scanner.c index b56ec349d0..ffb7e94671 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_scanner.c +++ b/ports/nrf/modules/ubluepy/ubluepy_scanner.c @@ -118,7 +118,7 @@ MP_DEFINE_CONST_OBJ_TYPE( ubluepy_scanner_type, MP_QSTR_Scanner, MP_TYPE_FLAG_NONE, - ubluepy_scanner_make_new, + make_new, ubluepy_scanner_make_new, print, ubluepy_scanner_print, locals_dict, &ubluepy_scanner_locals_dict ); diff --git a/ports/nrf/modules/ubluepy/ubluepy_service.c b/ports/nrf/modules/ubluepy/ubluepy_service.c index 2bec6befd6..bf336d04c5 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_service.c +++ b/ports/nrf/modules/ubluepy/ubluepy_service.c @@ -175,7 +175,7 @@ MP_DEFINE_CONST_OBJ_TYPE( ubluepy_service_type, MP_QSTR_Service, MP_TYPE_FLAG_NONE, - ubluepy_service_make_new, + make_new, ubluepy_service_make_new, print, ubluepy_service_print, locals_dict, &ubluepy_service_locals_dict ); diff --git a/ports/nrf/modules/ubluepy/ubluepy_uuid.c b/ports/nrf/modules/ubluepy/ubluepy_uuid.c index 0fd6e75e5b..abfe3cadd5 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_uuid.c +++ b/ports/nrf/modules/ubluepy/ubluepy_uuid.c @@ -164,7 +164,7 @@ MP_DEFINE_CONST_OBJ_TYPE( ubluepy_uuid_type, MP_QSTR_UUID, MP_TYPE_FLAG_NONE, - ubluepy_uuid_make_new, + make_new, ubluepy_uuid_make_new, print, ubluepy_uuid_print, locals_dict, &ubluepy_uuid_locals_dict ); diff --git a/ports/nrf/modules/uos/microbitfs.c b/ports/nrf/modules/uos/microbitfs.c index d1b3201116..6d697e1d1a 100644 --- a/ports/nrf/modules/uos/microbitfs.c +++ b/ports/nrf/modules/uos/microbitfs.c @@ -630,7 +630,6 @@ MP_DEFINE_CONST_OBJ_TYPE( uos_mbfs_textio_type, MP_QSTR_TextIO, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, protocol, &textio_stream_p, locals_dict, &uos_mbfs_file_locals_dict ); @@ -645,7 +644,6 @@ MP_DEFINE_CONST_OBJ_TYPE( uos_mbfs_fileio_type, MP_QSTR_FileIO, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, protocol, &fileio_stream_p, locals_dict, &uos_mbfs_file_locals_dict ); diff --git a/ports/nrf/pin_named_pins.c b/ports/nrf/pin_named_pins.c index 84ec89f44a..30e60692f7 100644 --- a/ports/nrf/pin_named_pins.c +++ b/ports/nrf/pin_named_pins.c @@ -40,7 +40,6 @@ MP_DEFINE_CONST_OBJ_TYPE( pin_cpu_pins_obj_type, MP_QSTR_cpu, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, pin_named_pins_obj_print, locals_dict, &pin_cpu_pins_locals_dict ); @@ -49,7 +48,6 @@ MP_DEFINE_CONST_OBJ_TYPE( pin_board_pins_obj_type, MP_QSTR_board, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, pin_named_pins_obj_print, locals_dict, &pin_board_pins_locals_dict ); diff --git a/ports/pic16bit/modpybled.c b/ports/pic16bit/modpybled.c index 2e5c2dcca3..47e83e0409 100644 --- a/ports/pic16bit/modpybled.c +++ b/ports/pic16bit/modpybled.c @@ -88,7 +88,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_led_type, MP_QSTR_LED, MP_TYPE_FLAG_NONE, - pyb_led_make_new, + make_new, pyb_led_make_new, print, pyb_led_print, locals_dict, &pyb_led_locals_dict ); diff --git a/ports/pic16bit/modpybswitch.c b/ports/pic16bit/modpybswitch.c index f27cfb9b09..b7192c5bba 100644 --- a/ports/pic16bit/modpybswitch.c +++ b/ports/pic16bit/modpybswitch.c @@ -75,7 +75,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_switch_type, MP_QSTR_Switch, MP_TYPE_FLAG_NONE, - pyb_switch_make_new, + make_new, pyb_switch_make_new, print, pyb_switch_print, call, pyb_switch_call, locals_dict, &pyb_switch_locals_dict diff --git a/ports/renesas-ra/extint.c b/ports/renesas-ra/extint.c index 496a50c3e8..915c23e3cd 100644 --- a/ports/renesas-ra/extint.c +++ b/ports/renesas-ra/extint.c @@ -378,7 +378,7 @@ MP_DEFINE_CONST_OBJ_TYPE( extint_type, MP_QSTR_ExtInt, MP_TYPE_FLAG_NONE, - extint_make_new, + make_new, extint_make_new, locals_dict, &extint_locals_dict, print, extint_obj_print ); diff --git a/ports/renesas-ra/led.c b/ports/renesas-ra/led.c index 9a3f1d40e9..a2284c5339 100644 --- a/ports/renesas-ra/led.c +++ b/ports/renesas-ra/led.c @@ -174,7 +174,7 @@ MP_DEFINE_CONST_OBJ_TYPE( ra_led_type, MP_QSTR_LED, MP_TYPE_FLAG_NONE, - led_obj_make_new, + make_new, led_obj_make_new, locals_dict, &led_locals_dict, print, led_obj_print ); diff --git a/ports/renesas-ra/machine_adc.c b/ports/renesas-ra/machine_adc.c index 99e35f48d9..b71c3db4b0 100644 --- a/ports/renesas-ra/machine_adc.c +++ b/ports/renesas-ra/machine_adc.c @@ -130,7 +130,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_adc_type, MP_QSTR_ADC, MP_TYPE_FLAG_NONE, - machine_adc_make_new, + make_new, machine_adc_make_new, locals_dict, &machine_adc_locals_dict, print, machine_adc_print ); diff --git a/ports/renesas-ra/machine_i2c.c b/ports/renesas-ra/machine_i2c.c index 563ea8787e..16bd589964 100644 --- a/ports/renesas-ra/machine_i2c.c +++ b/ports/renesas-ra/machine_i2c.c @@ -160,7 +160,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_i2c_type, MP_QSTR_I2C, MP_TYPE_FLAG_NONE, - machine_i2c_make_new, + make_new, machine_i2c_make_new, locals_dict, &mp_machine_i2c_locals_dict, print, machine_i2c_print, protocol, &machine_i2c_p diff --git a/ports/renesas-ra/machine_pin.c b/ports/renesas-ra/machine_pin.c index 17ef1e19a4..0e393b64e5 100644 --- a/ports/renesas-ra/machine_pin.c +++ b/ports/renesas-ra/machine_pin.c @@ -353,7 +353,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_pin_type, MP_QSTR_Pin, MP_TYPE_FLAG_NONE, - mp_pin_make_new, + make_new, mp_pin_make_new, locals_dict, &machine_pin_locals_dict, print, machine_pin_print, call, machine_pin_call, @@ -393,7 +393,6 @@ MP_DEFINE_CONST_OBJ_TYPE( pin_cpu_pins_obj_type, MP_QSTR_cpu, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, locals_dict, &pin_cpu_pins_locals_dict ); @@ -401,7 +400,6 @@ MP_DEFINE_CONST_OBJ_TYPE( pin_board_pins_obj_type, MP_QSTR_board, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, locals_dict, &pin_board_pins_locals_dict ); diff --git a/ports/renesas-ra/machine_rtc.c b/ports/renesas-ra/machine_rtc.c index c3f64c6971..e699bea0bc 100644 --- a/ports/renesas-ra/machine_rtc.c +++ b/ports/renesas-ra/machine_rtc.c @@ -345,6 +345,6 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_rtc_type, MP_QSTR_RTC, MP_TYPE_FLAG_NONE, - machine_rtc_make_new, + make_new, machine_rtc_make_new, locals_dict, &machine_rtc_locals_dict ); diff --git a/ports/renesas-ra/machine_spi.c b/ports/renesas-ra/machine_spi.c index d0e8b03bd1..b9f5b1ad1b 100644 --- a/ports/renesas-ra/machine_spi.c +++ b/ports/renesas-ra/machine_spi.c @@ -301,7 +301,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hard_spi_type, MP_QSTR_SPI, MP_TYPE_FLAG_NONE, - machine_hard_spi_make_new, + make_new, machine_hard_spi_make_new, locals_dict, &mp_machine_spi_locals_dict, print, machine_hard_spi_print, protocol, &machine_hard_spi_p diff --git a/ports/renesas-ra/machine_timer.c b/ports/renesas-ra/machine_timer.c index f3e5aafb7c..0f6ff80d27 100644 --- a/ports/renesas-ra/machine_timer.c +++ b/ports/renesas-ra/machine_timer.c @@ -140,7 +140,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_timer_type, MP_QSTR_Timer, MP_TYPE_FLAG_NONE, - machine_timer_make_new, + make_new, machine_timer_make_new, locals_dict, &machine_timer_locals_dict, print, machine_timer_print ); diff --git a/ports/renesas-ra/machine_uart.c b/ports/renesas-ra/machine_uart.c index 6fa84ca821..86505ea0b9 100644 --- a/ports/renesas-ra/machine_uart.c +++ b/ports/renesas-ra/machine_uart.c @@ -575,7 +575,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_uart_type, MP_QSTR_UART, MP_TYPE_FLAG_ITER_IS_STREAM, - machine_uart_make_new, + make_new, machine_uart_make_new, locals_dict, &machine_uart_locals_dict, print, machine_uart_print, protocol, &uart_stream_p diff --git a/ports/renesas-ra/main.c b/ports/renesas-ra/main.c index a87ddbd868..d403dbacbe 100644 --- a/ports/renesas-ra/main.c +++ b/ports/renesas-ra/main.c @@ -182,7 +182,7 @@ MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { if (len != -1) { // Detected a littlefs filesystem so create correct block device for it mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR_len), MP_OBJ_NEW_SMALL_INT(len) }; - bdev = pyb_flash_type.make_new(&pyb_flash_type, 0, 1, args); + bdev = MP_OBJ_TYPE_GET_SLOT(&pyb_flash_type, make_new)(&pyb_flash_type, 0, 1, args); } #endif diff --git a/ports/renesas-ra/storage.c b/ports/renesas-ra/storage.c index f573894a50..18dff97800 100644 --- a/ports/renesas-ra/storage.c +++ b/ports/renesas-ra/storage.c @@ -404,7 +404,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_flash_type, MP_QSTR_Flash, MP_TYPE_FLAG_NONE, - pyb_flash_make_new, + make_new, pyb_flash_make_new, locals_dict, &pyb_flash_locals_dict, print, pyb_flash_print ); diff --git a/ports/renesas-ra/timer.c b/ports/renesas-ra/timer.c index 8f7acbcdaa..04bd752b98 100644 --- a/ports/renesas-ra/timer.c +++ b/ports/renesas-ra/timer.c @@ -414,7 +414,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_timer_type, MP_QSTR_Timer, MP_TYPE_FLAG_NONE, - pyb_timer_make_new, + make_new, pyb_timer_make_new, locals_dict, &pyb_timer_locals_dict, print, pyb_timer_print ); @@ -507,7 +507,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( pyb_timer_channel_type, MP_QSTR_TimerChannel, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, locals_dict, &pyb_timer_channel_locals_dict, print, pyb_timer_channel_print ); diff --git a/ports/renesas-ra/usrsw.c b/ports/renesas-ra/usrsw.c index 4107d7850d..edbe519683 100644 --- a/ports/renesas-ra/usrsw.c +++ b/ports/renesas-ra/usrsw.c @@ -139,7 +139,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_switch_type, MP_QSTR_Switch, MP_TYPE_FLAG_NONE, - pyb_switch_make_new, + make_new, pyb_switch_make_new, locals_dict, &pyb_switch_locals_dict, print, pyb_switch_print, call, pyb_switch_call diff --git a/ports/rp2/machine_adc.c b/ports/rp2/machine_adc.c index 85562d5c07..9e3d7f57a8 100644 --- a/ports/rp2/machine_adc.c +++ b/ports/rp2/machine_adc.c @@ -117,7 +117,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_adc_type, MP_QSTR_ADC, MP_TYPE_FLAG_NONE, - machine_adc_make_new, + make_new, machine_adc_make_new, print, machine_adc_print, locals_dict, &machine_adc_locals_dict ); diff --git a/ports/rp2/machine_i2c.c b/ports/rp2/machine_i2c.c index 5ab93f6358..00dc36a4e0 100644 --- a/ports/rp2/machine_i2c.c +++ b/ports/rp2/machine_i2c.c @@ -180,7 +180,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hw_i2c_type, MP_QSTR_I2C, MP_TYPE_FLAG_NONE, - machine_i2c_make_new, + make_new, machine_i2c_make_new, print, machine_i2c_print, protocol, &machine_i2c_p, locals_dict, &mp_machine_i2c_locals_dict diff --git a/ports/rp2/machine_i2s.c b/ports/rp2/machine_i2s.c index 53ff7417d7..d5175471ae 100644 --- a/ports/rp2/machine_i2s.c +++ b/ports/rp2/machine_i2s.c @@ -1141,7 +1141,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_i2s_type, MP_QSTR_I2S, MP_TYPE_FLAG_ITER_IS_STREAM, - machine_i2s_make_new, + make_new, machine_i2s_make_new, print, machine_i2s_print, protocol, &i2s_stream_p, locals_dict, &machine_i2s_locals_dict diff --git a/ports/rp2/machine_pin.c b/ports/rp2/machine_pin.c index 8ccfbca3ab..9abcf064e7 100644 --- a/ports/rp2/machine_pin.c +++ b/ports/rp2/machine_pin.c @@ -645,7 +645,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_pin_type, MP_QSTR_Pin, MP_TYPE_FLAG_NONE, - mp_pin_make_new, + make_new, mp_pin_make_new, print, machine_pin_print, call, machine_pin_call, protocol, &pin_pin_p, diff --git a/ports/rp2/machine_rtc.c b/ports/rp2/machine_rtc.c index 6b2c9ac71b..a9d3426cf8 100644 --- a/ports/rp2/machine_rtc.c +++ b/ports/rp2/machine_rtc.c @@ -119,6 +119,6 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_rtc_type, MP_QSTR_RTC, MP_TYPE_FLAG_NONE, - machine_rtc_make_new, + make_new, machine_rtc_make_new, locals_dict, &machine_rtc_locals_dict ); diff --git a/ports/rp2/machine_spi.c b/ports/rp2/machine_spi.c index 08c79712cf..b2b879c9a8 100644 --- a/ports/rp2/machine_spi.c +++ b/ports/rp2/machine_spi.c @@ -294,7 +294,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_spi_type, MP_QSTR_SPI, MP_TYPE_FLAG_NONE, - machine_spi_make_new, + make_new, machine_spi_make_new, print, machine_spi_print, protocol, &machine_spi_p, locals_dict, &mp_machine_spi_locals_dict diff --git a/ports/rp2/machine_timer.c b/ports/rp2/machine_timer.c index 66f632329c..e4fbb03af4 100644 --- a/ports/rp2/machine_timer.c +++ b/ports/rp2/machine_timer.c @@ -160,7 +160,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_timer_type, MP_QSTR_Timer, MP_TYPE_FLAG_NONE, - machine_timer_make_new, + make_new, machine_timer_make_new, print, machine_timer_print, locals_dict, &machine_timer_locals_dict ); diff --git a/ports/rp2/machine_uart.c b/ports/rp2/machine_uart.c index 06f7e9aaac..e4881cd4f1 100644 --- a/ports/rp2/machine_uart.c +++ b/ports/rp2/machine_uart.c @@ -583,7 +583,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_uart_type, MP_QSTR_UART, MP_TYPE_FLAG_ITER_IS_STREAM, - machine_uart_make_new, + make_new, machine_uart_make_new, print, machine_uart_print, protocol, &uart_stream_p, locals_dict, &machine_uart_locals_dict diff --git a/ports/rp2/machine_wdt.c b/ports/rp2/machine_wdt.c index c224298d13..6574a6180f 100644 --- a/ports/rp2/machine_wdt.c +++ b/ports/rp2/machine_wdt.c @@ -81,6 +81,6 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_wdt_type, MP_QSTR_WDT, MP_TYPE_FLAG_NONE, - machine_wdt_make_new, + make_new, machine_wdt_make_new, locals_dict, &machine_wdt_locals_dict ); diff --git a/ports/rp2/mpbthciport.c b/ports/rp2/mpbthciport.c index e37167a974..8840fe52f1 100644 --- a/ports/rp2/mpbthciport.c +++ b/ports/rp2/mpbthciport.c @@ -103,7 +103,7 @@ int mp_bluetooth_hci_uart_init(uint32_t port, uint32_t baudrate) { // This is a statically-allocated UART (see machine_uart.c), and doesn't // contain any heap pointers other than the ringbufs (which are already // root pointers), so no need to track this as a root pointer. - mp_bthci_uart = machine_uart_type.make_new((mp_obj_t)&machine_uart_type, 2, 2, args); + mp_bthci_uart = MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, make_new)((mp_obj_t)&machine_uart_type, 2, 2, args); // Start the HCI polling to process any initial events/packets. mp_bluetooth_hci_start_polling(); diff --git a/ports/rp2/rp2_flash.c b/ports/rp2/rp2_flash.c index df49c881c4..0a94b6cc90 100644 --- a/ports/rp2/rp2_flash.c +++ b/ports/rp2/rp2_flash.c @@ -189,6 +189,6 @@ MP_DEFINE_CONST_OBJ_TYPE( rp2_flash_type, MP_QSTR_Flash, MP_TYPE_FLAG_NONE, - rp2_flash_make_new, + make_new, rp2_flash_make_new, locals_dict, &rp2_flash_locals_dict ); diff --git a/ports/rp2/rp2_pio.c b/ports/rp2/rp2_pio.c index cfba9cce5a..87deaf7e5f 100644 --- a/ports/rp2/rp2_pio.c +++ b/ports/rp2/rp2_pio.c @@ -380,7 +380,7 @@ MP_DEFINE_CONST_OBJ_TYPE( rp2_pio_type, MP_QSTR_PIO, MP_TYPE_FLAG_NONE, - rp2_pio_make_new, + make_new, rp2_pio_make_new, print, rp2_pio_print, locals_dict, &rp2_pio_locals_dict ); @@ -811,7 +811,7 @@ MP_DEFINE_CONST_OBJ_TYPE( rp2_state_machine_type, MP_QSTR_StateMachine, MP_TYPE_FLAG_NONE, - rp2_state_machine_make_new, + make_new, rp2_state_machine_make_new, print, rp2_state_machine_print, locals_dict, &rp2_state_machine_locals_dict ); diff --git a/ports/samd/machine_led.c b/ports/samd/machine_led.c index 7a9b2299ae..03b47e7cf2 100644 --- a/ports/samd/machine_led.c +++ b/ports/samd/machine_led.c @@ -166,7 +166,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_led_type, MP_QSTR_LED, MP_TYPE_FLAG_NONE, - mp_led_make_new, + make_new, mp_led_make_new, print, machine_led_print, call, machine_led_call, locals_dict, &machine_led_locals_dict diff --git a/ports/samd/machine_pin.c b/ports/samd/machine_pin.c index 75e1a2356c..5f9cbfb99b 100644 --- a/ports/samd/machine_pin.c +++ b/ports/samd/machine_pin.c @@ -291,7 +291,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_pin_type, MP_QSTR_Pin, MP_TYPE_FLAG_NONE, - mp_pin_make_new, + make_new, mp_pin_make_new, print, machine_pin_print, call, machine_pin_call, protocol, &pin_pin_p, diff --git a/ports/samd/samd_flash.c b/ports/samd/samd_flash.c index 9d64768cfa..522522ef84 100644 --- a/ports/samd/samd_flash.c +++ b/ports/samd/samd_flash.c @@ -185,6 +185,6 @@ MP_DEFINE_CONST_OBJ_TYPE( samd_flash_type, MP_QSTR_Flash, MP_TYPE_FLAG_NONE, - samd_flash_make_new, + make_new, samd_flash_make_new, locals_dict, &samd_flash_locals_dict ); diff --git a/ports/stm32/accel.c b/ports/stm32/accel.c index 05fd1898bc..19e16831ea 100644 --- a/ports/stm32/accel.c +++ b/ports/stm32/accel.c @@ -285,7 +285,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_accel_type, MP_QSTR_Accel, MP_TYPE_FLAG_NONE, - pyb_accel_make_new, + make_new, pyb_accel_make_new, locals_dict, &pyb_accel_locals_dict ); diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index e0759439d1..712e9b3ade 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -707,7 +707,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_adc_type, MP_QSTR_ADC, MP_TYPE_FLAG_NONE, - adc_make_new, + make_new, adc_make_new, print, adc_print, locals_dict, &adc_locals_dict ); @@ -916,7 +916,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_adc_all_type, MP_QSTR_ADCAll, MP_TYPE_FLAG_NONE, - adc_all_make_new, + make_new, adc_all_make_new, locals_dict, &adc_all_locals_dict ); diff --git a/ports/stm32/boards/LEGO_HUB_NO6/cc2564.c b/ports/stm32/boards/LEGO_HUB_NO6/cc2564.c index 50ba81c57a..6ec20935f0 100644 --- a/ports/stm32/boards/LEGO_HUB_NO6/cc2564.c +++ b/ports/stm32/boards/LEGO_HUB_NO6/cc2564.c @@ -63,7 +63,7 @@ int mp_bluetooth_hci_controller_init(void) { // tim_ch = tim.channel(TIM_CH, pyb.Timer.PWM, pin=btclk) // tim_ch.pulse_width_percent(50) mp_obj_t args[6] = { MP_OBJ_NEW_SMALL_INT(CC2564_TIMER_BT_SLOWCLOCK_TIM), MP_OBJ_NEW_QSTR(MP_QSTR_freq), MP_OBJ_NEW_SMALL_INT(32768), MP_OBJ_NULL }; - mp_obj_t tim = pyb_timer_type.make_new(&pyb_timer_type, 1, 1, args); + mp_obj_t tim = MP_OBJ_TYPE_GET_SLOT(&pyb_timer_type, make_new)(&pyb_timer_type, 1, 1, args); mp_load_method(tim, MP_QSTR_channel, args); args[2] = MP_OBJ_NEW_SMALL_INT(CC2564_TIMER_BT_SLOWCLOCK_TIM_CH); args[3] = MP_OBJ_NEW_SMALL_INT(0); // CHANNEL_MODE_PWM_NORMAL diff --git a/ports/stm32/dac.c b/ports/stm32/dac.c index ac8d76090e..36ef9387f8 100644 --- a/ports/stm32/dac.c +++ b/ports/stm32/dac.c @@ -506,7 +506,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_dac_type, MP_QSTR_DAC, MP_TYPE_FLAG_NONE, - pyb_dac_make_new, + make_new, pyb_dac_make_new, print, pyb_dac_print, locals_dict, &pyb_dac_locals_dict ); diff --git a/ports/stm32/extint.c b/ports/stm32/extint.c index 0f28610cc3..ca23261ca7 100644 --- a/ports/stm32/extint.c +++ b/ports/stm32/extint.c @@ -663,7 +663,7 @@ MP_DEFINE_CONST_OBJ_TYPE( extint_type, MP_QSTR_ExtInt, MP_TYPE_FLAG_NONE, - extint_make_new, + make_new, extint_make_new, print, extint_obj_print, locals_dict, &extint_locals_dict ); diff --git a/ports/stm32/lcd.c b/ports/stm32/lcd.c index 5017a68fe5..e5d7f30efb 100644 --- a/ports/stm32/lcd.c +++ b/ports/stm32/lcd.c @@ -529,7 +529,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_lcd_type, MP_QSTR_LCD, MP_TYPE_FLAG_NONE, - pyb_lcd_make_new, + make_new, pyb_lcd_make_new, locals_dict, &pyb_lcd_locals_dict ); diff --git a/ports/stm32/led.c b/ports/stm32/led.c index 6e3229ab32..fa211f1e14 100644 --- a/ports/stm32/led.c +++ b/ports/stm32/led.c @@ -385,7 +385,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_led_type, MP_QSTR_LED, MP_TYPE_FLAG_NONE, - led_obj_make_new, + make_new, led_obj_make_new, print, led_obj_print, locals_dict, &led_locals_dict ); diff --git a/ports/stm32/machine_adc.c b/ports/stm32/machine_adc.c index 3659073d06..000b478f86 100644 --- a/ports/stm32/machine_adc.c +++ b/ports/stm32/machine_adc.c @@ -496,7 +496,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_adc_type, MP_QSTR_ADC, MP_TYPE_FLAG_NONE, - machine_adc_make_new, + make_new, machine_adc_make_new, print, machine_adc_print, locals_dict, &machine_adc_locals_dict ); diff --git a/ports/stm32/machine_i2c.c b/ports/stm32/machine_i2c.c index 7927daac1b..9a2d338f54 100644 --- a/ports/stm32/machine_i2c.c +++ b/ports/stm32/machine_i2c.c @@ -240,7 +240,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hard_i2c_type, MP_QSTR_I2C, MP_TYPE_FLAG_NONE, - machine_hard_i2c_make_new, + make_new, machine_hard_i2c_make_new, print, machine_hard_i2c_print, protocol, &machine_hard_i2c_p, locals_dict, &mp_machine_i2c_locals_dict diff --git a/ports/stm32/machine_i2s.c b/ports/stm32/machine_i2s.c index d68648bc34..83ac6bc124 100644 --- a/ports/stm32/machine_i2s.c +++ b/ports/stm32/machine_i2s.c @@ -1118,7 +1118,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_i2s_type, MP_QSTR_I2S, MP_TYPE_FLAG_ITER_IS_STREAM, - machine_i2s_make_new, + make_new, machine_i2s_make_new, print, machine_i2s_print, protocol, &i2s_stream_p, locals_dict, &machine_i2s_locals_dict diff --git a/ports/stm32/machine_spi.c b/ports/stm32/machine_spi.c index d64ff2af8f..718ae1af5e 100644 --- a/ports/stm32/machine_spi.c +++ b/ports/stm32/machine_spi.c @@ -139,7 +139,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hard_spi_type, MP_QSTR_SPI, MP_TYPE_FLAG_NONE, - machine_hard_spi_make_new, + make_new, machine_hard_spi_make_new, print, machine_hard_spi_print, protocol, &machine_hard_spi_p, locals_dict, &mp_machine_spi_locals_dict diff --git a/ports/stm32/machine_timer.c b/ports/stm32/machine_timer.c index 2e0120ea81..640d1d200f 100644 --- a/ports/stm32/machine_timer.c +++ b/ports/stm32/machine_timer.c @@ -140,7 +140,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_timer_type, MP_QSTR_Timer, MP_TYPE_FLAG_NONE, - machine_timer_make_new, + make_new, machine_timer_make_new, print, machine_timer_print, locals_dict, &machine_timer_locals_dict ); diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index 4ccff8c136..bb35bac5cc 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -664,7 +664,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_uart_type, MP_QSTR_UART, MP_TYPE_FLAG_ITER_IS_STREAM, - pyb_uart_make_new, + 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 c001234704..7f864a018c 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -182,7 +182,7 @@ MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { if (len != -1) { // Detected a littlefs filesystem so create correct block device for it mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR_len), MP_OBJ_NEW_SMALL_INT(len) }; - bdev = pyb_flash_type.make_new(&pyb_flash_type, 0, 1, args); + bdev = MP_OBJ_TYPE_GET_SLOT(&pyb_flash_type, make_new)(&pyb_flash_type, 0, 1, args); } #endif diff --git a/ports/stm32/network_lan.c b/ports/stm32/network_lan.c index 25a9555088..556adebd8f 100644 --- a/ports/stm32/network_lan.c +++ b/ports/stm32/network_lan.c @@ -162,7 +162,7 @@ MP_DEFINE_CONST_OBJ_TYPE( network_lan_type, MP_QSTR_LAN, MP_TYPE_FLAG_NONE, - network_lan_make_new, + make_new, network_lan_make_new, print, network_lan_print, locals_dict, &network_lan_locals_dict ); diff --git a/ports/stm32/pin.c b/ports/stm32/pin.c index 3c3cde0265..0e4a7e9938 100644 --- a/ports/stm32/pin.c +++ b/ports/stm32/pin.c @@ -596,7 +596,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pin_type, MP_QSTR_Pin, MP_TYPE_FLAG_NONE, - mp_pin_make_new, + make_new, mp_pin_make_new, print, pin_print, call, pin_call, protocol, &pin_pin_p, @@ -674,7 +674,6 @@ MP_DEFINE_CONST_OBJ_TYPE( pin_af_type, MP_QSTR_PinAF, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, pin_af_obj_print, locals_dict, &pin_af_locals_dict ); diff --git a/ports/stm32/pin_named_pins.c b/ports/stm32/pin_named_pins.c index 1a35ec5787..8eeb4ed32b 100644 --- a/ports/stm32/pin_named_pins.c +++ b/ports/stm32/pin_named_pins.c @@ -35,7 +35,6 @@ MP_DEFINE_CONST_OBJ_TYPE( pin_cpu_pins_obj_type, MP_QSTR_cpu, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, locals_dict, &pin_cpu_pins_locals_dict ); @@ -43,7 +42,6 @@ MP_DEFINE_CONST_OBJ_TYPE( pin_board_pins_obj_type, MP_QSTR_board, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, locals_dict, &pin_board_pins_locals_dict ); diff --git a/ports/stm32/pyb_can.c b/ports/stm32/pyb_can.c index a07fc92164..69e807c79d 100644 --- a/ports/stm32/pyb_can.c +++ b/ports/stm32/pyb_can.c @@ -1076,7 +1076,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_can_type, MP_QSTR_CAN, MP_TYPE_FLAG_NONE, - pyb_can_make_new, + make_new, pyb_can_make_new, print, pyb_can_print, protocol, &can_stream_p, locals_dict, &pyb_can_locals_dict diff --git a/ports/stm32/pyb_i2c.c b/ports/stm32/pyb_i2c.c index 9071d92944..0cbb640473 100644 --- a/ports/stm32/pyb_i2c.c +++ b/ports/stm32/pyb_i2c.c @@ -1108,7 +1108,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_i2c_type, MP_QSTR_I2C, MP_TYPE_FLAG_NONE, - pyb_i2c_make_new, + make_new, pyb_i2c_make_new, print, pyb_i2c_print, locals_dict, &pyb_i2c_locals_dict ); diff --git a/ports/stm32/pyb_spi.c b/ports/stm32/pyb_spi.c index a225bd84e7..54582f8e54 100644 --- a/ports/stm32/pyb_spi.c +++ b/ports/stm32/pyb_spi.c @@ -354,7 +354,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_spi_type, MP_QSTR_SPI, MP_TYPE_FLAG_NONE, - pyb_spi_make_new, + make_new, pyb_spi_make_new, print, pyb_spi_print, protocol, &pyb_spi_p, locals_dict, &pyb_spi_locals_dict diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index f501ec23b1..aacfc3805e 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -841,6 +841,6 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_rtc_type, MP_QSTR_RTC, MP_TYPE_FLAG_NONE, - pyb_rtc_make_new, + make_new, pyb_rtc_make_new, locals_dict, &pyb_rtc_locals_dict ); diff --git a/ports/stm32/sdcard.c b/ports/stm32/sdcard.c index cbf1ade5c5..964ed49a67 100644 --- a/ports/stm32/sdcard.c +++ b/ports/stm32/sdcard.c @@ -876,7 +876,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_sdcard_type, MP_QSTR_SDCard, MP_TYPE_FLAG_NONE, - pyb_sdcard_make_new, + make_new, pyb_sdcard_make_new, locals_dict, &pyb_sdcard_locals_dict ); #endif @@ -886,7 +886,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_mmcard_type, MP_QSTR_MMCard, MP_TYPE_FLAG_NONE, - pyb_mmcard_make_new, + make_new, pyb_mmcard_make_new, locals_dict, &pyb_sdcard_locals_dict ); #endif diff --git a/ports/stm32/servo.c b/ports/stm32/servo.c index 1b0ca0a882..e0aa2d6b69 100644 --- a/ports/stm32/servo.c +++ b/ports/stm32/servo.c @@ -340,7 +340,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_servo_type, MP_QSTR_Servo, MP_TYPE_FLAG_NONE, - pyb_servo_make_new, + make_new, pyb_servo_make_new, print, pyb_servo_print, locals_dict, &pyb_servo_locals_dict ); diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c index a0154408dd..848602a787 100644 --- a/ports/stm32/storage.c +++ b/ports/stm32/storage.c @@ -457,7 +457,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_flash_type, MP_QSTR_Flash, MP_TYPE_FLAG_NONE, - pyb_flash_make_new, + make_new, pyb_flash_make_new, print, pyb_flash_print, locals_dict, &pyb_flash_locals_dict ); diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index 91c88df1b3..7a6ccd4dfd 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -1475,7 +1475,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_timer_type, MP_QSTR_Timer, MP_TYPE_FLAG_NONE, - pyb_timer_make_new, + make_new, pyb_timer_make_new, print, pyb_timer_print, locals_dict, &pyb_timer_locals_dict ); @@ -1615,7 +1615,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( pyb_timer_channel_type, MP_QSTR_TimerChannel, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, pyb_timer_channel_print, locals_dict, &pyb_timer_channel_locals_dict ); diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index e389ef68f2..12c5e497de 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -940,7 +940,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_usb_vcp_type, MP_QSTR_USB_VCP, MP_TYPE_FLAG_ITER_IS_STREAM, - pyb_usb_vcp_make_new, + make_new, pyb_usb_vcp_make_new, print, pyb_usb_vcp_print, protocol, &pyb_usb_vcp_stream_p, locals_dict, &pyb_usb_vcp_locals_dict @@ -1080,7 +1080,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_usb_hid_type, MP_QSTR_USB_HID, MP_TYPE_FLAG_NONE, - pyb_usb_hid_make_new, + make_new, pyb_usb_hid_make_new, protocol, &pyb_usb_hid_stream_p, locals_dict, &pyb_usb_hid_locals_dict ); diff --git a/ports/stm32/usrsw.c b/ports/stm32/usrsw.c index 7d406c0ecd..170c01bd6d 100644 --- a/ports/stm32/usrsw.c +++ b/ports/stm32/usrsw.c @@ -138,7 +138,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_switch_type, MP_QSTR_Switch, MP_TYPE_FLAG_NONE, - pyb_switch_make_new, + make_new, pyb_switch_make_new, print, pyb_switch_print, call, pyb_switch_call, locals_dict, &pyb_switch_locals_dict diff --git a/ports/stm32/wdt.c b/ports/stm32/wdt.c index 09780ea9d3..e541e4d36b 100644 --- a/ports/stm32/wdt.c +++ b/ports/stm32/wdt.c @@ -106,6 +106,6 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_wdt_type, MP_QSTR_WDT, MP_TYPE_FLAG_NONE, - pyb_wdt_make_new, + make_new, pyb_wdt_make_new, locals_dict, &pyb_wdt_locals_dict ); diff --git a/ports/teensy/led.c b/ports/teensy/led.c index dd4c65da39..46c6ae492f 100644 --- a/ports/teensy/led.c +++ b/ports/teensy/led.c @@ -138,7 +138,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_led_type, MP_QSTR_LED, MP_TYPE_FLAG_NONE, - led_obj_make_new, + make_new, led_obj_make_new, print, led_obj_print, locals_dict, &led_locals_dict ); diff --git a/ports/teensy/timer.c b/ports/teensy/timer.c index a0f490d925..8c7609e447 100644 --- a/ports/teensy/timer.c +++ b/ports/teensy/timer.c @@ -750,7 +750,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_timer_type, MP_QSTR_Timer, MP_TYPE_FLAG_NONE, - pyb_timer_make_new, + make_new, pyb_timer_make_new, print, pyb_timer_print, locals_dict, &pyb_timer_locals_dict ); @@ -894,7 +894,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( pyb_timer_channel_type, MP_QSTR_TimerChannel, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, pyb_timer_channel_print, locals_dict, &pyb_timer_channel_locals_dict ); diff --git a/ports/teensy/uart.c b/ports/teensy/uart.c index db5b8e2f44..e71f676d0a 100644 --- a/ports/teensy/uart.c +++ b/ports/teensy/uart.c @@ -487,7 +487,7 @@ MP_DEFINE_CONST_OBJ_TYPE( pyb_uart_type, MP_QSTR_UART, MP_TYPE_FLAG_NONE, - pyb_uart_make_new, + make_new, pyb_uart_make_new, print, pyb_uart_print, locals_dict, &pyb_uart_locals_dict ); diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index 7b4c0c0bf4..8b7fc7de67 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -110,7 +110,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_stest_fileio, MP_QSTR_stest_fileio, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, protocol, &fileio_stream_p, locals_dict, &rawfile_locals_dict ); @@ -140,7 +139,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_stest_textio2, MP_QSTR_stest_textio2, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, protocol, &textio_stream_p2, locals_dict, &rawfile_locals_dict2 ); diff --git a/ports/unix/main.c b/ports/unix/main.c index 4f019b6c2c..44823ee174 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -518,7 +518,7 @@ MP_NOINLINE int main_(int argc, char **argv) { { // Mount the host FS at the root of our internal VFS mp_obj_t args[2] = { - mp_type_vfs_posix.make_new(&mp_type_vfs_posix, 0, 0, NULL), + MP_OBJ_TYPE_GET_SLOT(&mp_type_vfs_posix, make_new)(&mp_type_vfs_posix, 0, 0, NULL), MP_OBJ_NEW_QSTR(MP_QSTR__slash_), }; mp_vfs_mount(2, args, (mp_map_t *)&mp_const_empty_map); diff --git a/ports/unix/modffi.c b/ports/unix/modffi.c index 04152f1ad4..3df748b80d 100644 --- a/ports/unix/modffi.c +++ b/ports/unix/modffi.c @@ -425,7 +425,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( ffimod_type, MP_QSTR_ffimod, MP_TYPE_FLAG_NONE, - ffimod_make_new, + make_new, ffimod_make_new, print, ffimod_print, locals_dict, &ffimod_locals_dict ); @@ -535,7 +535,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( ffifunc_type, MP_QSTR_ffifunc, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, ffifunc_print, call, ffifunc_call ); @@ -563,7 +562,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( fficallback_type, MP_QSTR_fficallback, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, fficallback_print, locals_dict, &fficallback_locals_dict ); @@ -601,7 +599,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( ffivar_type, MP_QSTR_ffivar, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, ffivar_print, locals_dict, &ffivar_locals_dict ); @@ -613,8 +610,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( opaque_type, MP_QSTR_opaqueval, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, - // .print = opaque_print, + make_new, // .print = opaque_print, ); */ diff --git a/ports/unix/modjni.c b/ports/unix/modjni.c index e6b874b235..5988876f88 100644 --- a/ports/unix/modjni.c +++ b/ports/unix/modjni.c @@ -178,7 +178,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( jclass_type, MP_QSTR_jclass, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, jclass_print, attr, jclass_attr, call, jclass_call, @@ -326,7 +325,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( jobject_type, MP_QSTR_jobject, MP_TYPE_FLAG_ITER_IS_GETITER, - MP_TYPE_NULL_MAKE_NEW, print, jobject_print, unary_op, jobject_unary_op, attr, jobject_attr, @@ -575,7 +573,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( jmethod_type, MP_QSTR_jmethod, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, jmethod_print, call, jmethod_call, // .attr = jobject_attr, diff --git a/ports/unix/moduselect.c b/ports/unix/moduselect.c index 674841bf18..8f71813e70 100644 --- a/ports/unix/moduselect.c +++ b/ports/unix/moduselect.c @@ -315,7 +315,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_poll, MP_QSTR_poll, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - MP_TYPE_NULL_MAKE_NEW, iter, poll_iternext, locals_dict, &poll_locals_dict ); diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c index dfbf15cd3e..a32fc60163 100644 --- a/ports/unix/modusocket.c +++ b/ports/unix/modusocket.c @@ -520,7 +520,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_socket, MP_QSTR_socket, MP_TYPE_FLAG_NONE, - socket_make_new, + make_new, socket_make_new, print, socket_print, protocol, &usocket_stream_p, locals_dict, &usocket_locals_dict diff --git a/ports/zephyr/machine_i2c.c b/ports/zephyr/machine_i2c.c index a844eceb50..8f0f25257b 100644 --- a/ports/zephyr/machine_i2c.c +++ b/ports/zephyr/machine_i2c.c @@ -130,7 +130,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hard_i2c_type, MP_QSTR_I2C, MP_TYPE_FLAG_NONE, - machine_hard_i2c_make_new, + make_new, machine_hard_i2c_make_new, print, machine_hard_i2c_print, protocol, &machine_hard_i2c_p, locals_dict, &mp_machine_i2c_locals_dict diff --git a/ports/zephyr/machine_pin.c b/ports/zephyr/machine_pin.c index 3114ac36fd..be0698651b 100644 --- a/ports/zephyr/machine_pin.c +++ b/ports/zephyr/machine_pin.c @@ -289,7 +289,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_pin_type, MP_QSTR_Pin, MP_TYPE_FLAG_NONE, - mp_pin_make_new, + make_new, mp_pin_make_new, print, machine_pin_print, call, machine_pin_call, protocol, &machine_pin_pin_p, diff --git a/ports/zephyr/machine_spi.c b/ports/zephyr/machine_spi.c index d990ed9c15..19d4ae6dee 100644 --- a/ports/zephyr/machine_spi.c +++ b/ports/zephyr/machine_spi.c @@ -201,7 +201,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_hard_spi_type, MP_QSTR_SPI, MP_TYPE_FLAG_NONE, - machine_hard_spi_make_new, + make_new, machine_hard_spi_make_new, print, machine_hard_spi_print, protocol, &machine_hard_spi_p, locals_dict, &mp_machine_spi_locals_dict diff --git a/ports/zephyr/machine_uart.c b/ports/zephyr/machine_uart.c index 867c5ae886..b989c0f481 100644 --- a/ports/zephyr/machine_uart.c +++ b/ports/zephyr/machine_uart.c @@ -158,7 +158,7 @@ MP_DEFINE_CONST_OBJ_TYPE( machine_uart_type, MP_QSTR_UART, MP_TYPE_FLAG_ITER_IS_STREAM, - machine_uart_make_new, + 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/main.c b/ports/zephyr/main.c index c638f38920..869449e7df 100644 --- a/ports/zephyr/main.c +++ b/ports/zephyr/main.c @@ -104,11 +104,11 @@ STATIC void vfs_init(void) { #ifdef CONFIG_DISK_DRIVER_SDMMC mp_obj_t args[] = { mp_obj_new_str(CONFIG_SDMMC_VOLUME_NAME, strlen(CONFIG_SDMMC_VOLUME_NAME)) }; - bdev = zephyr_disk_access_type.make_new(&zephyr_disk_access_type, ARRAY_SIZE(args), 0, args); + bdev = MP_OBJ_TYPE_GET_SLOT(&zephyr_disk_access_type, make_new)(&zephyr_disk_access_type, ARRAY_SIZE(args), 0, args); mount_point_str = "/sd"; #elif defined(CONFIG_FLASH_MAP) && FLASH_AREA_LABEL_EXISTS(storage) mp_obj_t args[] = { MP_OBJ_NEW_SMALL_INT(FLASH_AREA_ID(storage)), MP_OBJ_NEW_SMALL_INT(4096) }; - bdev = zephyr_flash_area_type.make_new(&zephyr_flash_area_type, ARRAY_SIZE(args), 0, args); + bdev = MP_OBJ_TYPE_GET_SLOT(&zephyr_flash_area_type, make_new)(&zephyr_flash_area_type, ARRAY_SIZE(args), 0, args); mount_point_str = "/flash"; #endif diff --git a/ports/zephyr/modusocket.c b/ports/zephyr/modusocket.c index 77f839fdd5..c79f73a9d2 100644 --- a/ports/zephyr/modusocket.c +++ b/ports/zephyr/modusocket.c @@ -357,7 +357,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( socket_type, MP_QSTR_socket, MP_TYPE_FLAG_NONE, - socket_make_new, + make_new, socket_make_new, print, socket_print, protocol, &socket_stream_p, locals_dict, &socket_locals_dict diff --git a/ports/zephyr/modzsensor.c b/ports/zephyr/modzsensor.c index beb4d6ad79..e35a1716f4 100644 --- a/ports/zephyr/modzsensor.c +++ b/ports/zephyr/modzsensor.c @@ -109,7 +109,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( sensor_type, MP_QSTR_Sensor, MP_TYPE_FLAG_NONE, - sensor_make_new, + make_new, sensor_make_new, locals_dict, &sensor_locals_dict ); diff --git a/ports/zephyr/zephyr_storage.c b/ports/zephyr/zephyr_storage.c index 6ab8271d34..498fea6fb1 100644 --- a/ports/zephyr/zephyr_storage.c +++ b/ports/zephyr/zephyr_storage.c @@ -132,7 +132,7 @@ MP_DEFINE_CONST_OBJ_TYPE( zephyr_disk_access_type, MP_QSTR_DiskAccess, MP_TYPE_FLAG_NONE, - zephyr_disk_access_make_new, + make_new, zephyr_disk_access_make_new, print, zephyr_disk_access_print, locals_dict, &zephyr_disk_access_locals_dict ); @@ -254,7 +254,7 @@ MP_DEFINE_CONST_OBJ_TYPE( zephyr_flash_area_type, MP_QSTR_FlashArea, MP_TYPE_FLAG_NONE, - zephyr_flash_area_make_new, + make_new, zephyr_flash_area_make_new, print, zephyr_flash_area_print, locals_dict, &zephyr_flash_area_locals_dict ); diff --git a/py/builtinevex.c b/py/builtinevex.c index 403cd95a9d..173978ef52 100644 --- a/py/builtinevex.c +++ b/py/builtinevex.c @@ -41,8 +41,7 @@ typedef struct _mp_obj_code_t { STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_code, MP_QSTR_code, - MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW + MP_TYPE_FLAG_NONE ); STATIC mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_dict_t *globals, mp_obj_dict_t *locals) { diff --git a/py/dynruntime.h b/py/dynruntime.h index be573bde2a..8564715c0b 100644 --- a/py/dynruntime.h +++ b/py/dynruntime.h @@ -105,7 +105,7 @@ static inline void *m_realloc_dyn(void *ptr, size_t new_num_bytes) { #define mp_const_none ((mp_obj_t)mp_fun_table.const_none) #define mp_const_false ((mp_obj_t)mp_fun_table.const_false) #define mp_const_true ((mp_obj_t)mp_fun_table.const_true) -#define mp_const_empty_bytes (mp_type_bytes.make_new(NULL, 0, 0, NULL)) +#define mp_const_empty_bytes (MP_OBJ_TYPE_GET_SLOT(&mp_type_bytes, make_new)(NULL, 0, 0, NULL)) #define mp_const_empty_tuple (mp_fun_table.new_tuple(0, NULL)) #define mp_obj_new_bool(b) ((b) ? (mp_obj_t)mp_fun_table.const_true : (mp_obj_t)mp_fun_table.const_false) diff --git a/py/modbuiltins.c b/py/modbuiltins.c index 152323b5ca..06e9f1acb5 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -547,7 +547,7 @@ STATIC mp_obj_t mp_builtin_sorted(size_t n_args, const mp_obj_t *args, mp_map_t if (n_args > 1) { mp_raise_TypeError(MP_ERROR_TEXT("must use keyword argument for key function")); } - mp_obj_t self = mp_type_list.make_new(&mp_type_list, 1, 0, args); + mp_obj_t self = mp_obj_list_make_new(&mp_type_list, 1, 0, args); mp_obj_list_sort(1, &self, kwargs); return self; diff --git a/py/modio.c b/py/modio.c index a1e04e4cac..9ec6bbcc4e 100644 --- a/py/modio.c +++ b/py/modio.c @@ -101,7 +101,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_iobase, MP_QSTR_IOBase, MP_TYPE_FLAG_NONE, - iobase_make_new, + make_new, iobase_make_new, protocol, &iobase_p ); @@ -196,7 +196,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_bufwriter, MP_QSTR_BufferedWriter, MP_TYPE_FLAG_NONE, - bufwriter_make_new, + make_new, bufwriter_make_new, protocol, &bufwriter_stream_p, locals_dict, &bufwriter_locals_dict ); diff --git a/py/modthread.c b/py/modthread.c index 3116fe6bd9..51d63e4703 100644 --- a/py/modthread.c +++ b/py/modthread.c @@ -120,7 +120,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_thread_lock, MP_QSTR_lock, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, locals_dict, &thread_lock_locals_dict ); diff --git a/py/obj.h b/py/obj.h index b1d722080c..34adfbd0f0 100644 --- a/py/obj.h +++ b/py/obj.h @@ -594,15 +594,15 @@ struct _mp_obj_type_t { // The name of this type, a qstr. uint16_t name; - // Corresponds to __new__ and __init__ special methods, to make an instance of the type. - mp_make_new_fun_t make_new; - // Slots: For the rest of the fields, the slot index points to the // relevant function in the variable-length "slots" field. Ideally these // would be only 4 bits, but the extra overhead of accessing them adds // more code, and we also need to be able to take the address of them for // mp_obj_class_lookup. + // Corresponds to __new__ and __init__ special methods, to make an instance of the type. + uint8_t slot_index_make_new; + // Corresponds to __repr__ and __str__ special methods. uint8_t slot_index_print; @@ -673,8 +673,8 @@ typedef struct _mp_obj_empty_type_t { mp_obj_base_t base; uint16_t flags; uint16_t name; - mp_make_new_fun_t make_new; + uint8_t slot_index_make_new; uint8_t slot_index_print; uint8_t slot_index_call; uint8_t slot_index_unary_op; @@ -694,8 +694,8 @@ typedef struct _mp_obj_full_type_t { mp_obj_base_t base; uint16_t flags; uint16_t name; - mp_make_new_fun_t make_new; + uint8_t slot_index_make_new; uint8_t slot_index_print; uint8_t slot_index_call; uint8_t slot_index_unary_op; @@ -712,8 +712,7 @@ typedef struct _mp_obj_full_type_t { const void *slots[11]; } mp_obj_full_type_t; -#define MP_TYPE_NULL_MAKE_NEW (NULL) - +#define _MP_OBJ_TYPE_SLOT_TYPE_make_new (mp_make_new_fun_t) #define _MP_OBJ_TYPE_SLOT_TYPE_print (mp_print_fun_t) #define _MP_OBJ_TYPE_SLOT_TYPE_call (mp_call_fun_t) #define _MP_OBJ_TYPE_SLOT_TYPE_unary_op (mp_unary_op_fun_t) @@ -730,42 +729,41 @@ typedef struct _mp_obj_full_type_t { // Do not use these directly, instead use MP_DEFINE_CONST_OBJ_TYPE. // Generated with: // for i in range(13): -// print(f"#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_{i}(_struct_type, _typename, _name, _flags, _make_new{''.join(f', f{j+1}, v{j+1}' for j in range(i))}) const _struct_type _typename = {{ .base = {{ &mp_type_type }}, .name = _name, .flags = _flags, .make_new = _make_new{''.join(f', .slot_index_##f{j+1} = {j+1}' for j in range(i))}{', .slots = { ' + ''.join(f'v{j+1}, ' for j in range(i)) + '}' if i else '' } }}") -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_0(_struct_type, _typename, _name, _flags, _make_new) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_1(_struct_type, _typename, _name, _flags, _make_new, f1, v1) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slots = { v1, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_2(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slots = { v1, v2, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_3(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slots = { v1, v2, v3, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_4(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slots = { v1, v2, v3, v4, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_5(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slots = { v1, v2, v3, v4, v5, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_6(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slots = { v1, v2, v3, v4, v5, v6, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_7(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slots = { v1, v2, v3, v4, v5, v6, v7, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_8(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_9(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_10(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_11(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_12(_struct_type, _typename, _name, _flags, _make_new, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11, f12, v12) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .make_new = _make_new, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slot_index_##f12 = 12, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, } } +// print(f"#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_{i}(_struct_type, _typename, _name, _flags{''.join(f', f{j+1}, v{j+1}' for j in range(i))}) const _struct_type _typename = {{ .base = {{ &mp_type_type }}, .name = _name, .flags = _flags{''.join(f', .slot_index_##f{j+1} = {j+1}' for j in range(i))}{', .slots = { ' + ''.join(f'v{j+1}, ' for j in range(i)) + '}' if i else '' } }}") +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_0(_struct_type, _typename, _name, _flags) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_1(_struct_type, _typename, _name, _flags, f1, v1) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slots = { v1, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_2(_struct_type, _typename, _name, _flags, f1, v1, f2, v2) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slots = { v1, v2, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_3(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slots = { v1, v2, v3, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_4(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slots = { v1, v2, v3, v4, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_5(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slots = { v1, v2, v3, v4, v5, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_6(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slots = { v1, v2, v3, v4, v5, v6, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_7(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slots = { v1, v2, v3, v4, v5, v6, v7, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_8(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_9(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_10(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_11(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_12(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11, f12, v12) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slot_index_##f12 = 12, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, } } #define MP_OBJ_TYPE_HAS_SLOT(t, f) ((t)->slot_index_##f) #define MP_OBJ_TYPE_GET_SLOT(t, f) (_MP_OBJ_TYPE_SLOT_TYPE_##f(t)->slots[(t)->slot_index_##f - 1]) #define MP_OBJ_TYPE_GET_SLOT_OR_NULL(t, f) (_MP_OBJ_TYPE_SLOT_TYPE_##f(MP_OBJ_TYPE_HAS_SLOT(t, f) ? MP_OBJ_TYPE_GET_SLOT(t, f) : NULL)) #define MP_OBJ_TYPE_SET_SLOT(t, f, v, n) ((t)->slot_index_##f = (n) + 1, (t)->slots[(t)->slot_index_##f - 1] = (void *)v) #define MP_OBJ_TYPE_OFFSETOF_SLOT(f) (offsetof(mp_obj_type_t, slot_index_##f)) -// For everything except make_new, the offset is to the uint8_t index. For make_new, we need to check the pointer. -#define MP_OBJ_TYPE_HAS_SLOT_BY_OFFSET(t, offset) (*(uint8_t *)((char *)(t) + (offset)) != 0 || (offset == offsetof(mp_obj_type_t, make_new) && t->make_new)) +#define MP_OBJ_TYPE_HAS_SLOT_BY_OFFSET(t, offset) (*(uint8_t *)((char *)(t) + (offset)) != 0) // Workaround for https://docs.microsoft.com/en-us/cpp/preprocessor/preprocessor-experimental-overview?view=msvc-160#macro-arguments-are-unpacked #define MP_DEFINE_CONST_OBJ_TYPE_EXPAND(x) x // This macro evaluates to MP_DEFINE_CONST_OBJ_TYPE_NARGS_##N, where N is the value -// of the 30th argument (30 is 13*2 + 4). -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, N, ...) MP_DEFINE_CONST_OBJ_TYPE_NARGS_##N +// of the 29th argument (29 is 13*2 + 3). +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, N, ...) MP_DEFINE_CONST_OBJ_TYPE_NARGS_##N // These macros are used to define a object type in ROM. // Invoke as MP_DEFINE_CONST_OBJ_TYPE(_typename, _name, _flags, _make_new [, slot, func]*) // They use the number of arguments to select which MP_DEFINE_CONST_OBJ_TYPE_* // macro to use based on the number of arguments. It works by shifting the // numeric values 12, 11, ... 0 by the number of arguments, such that the -// 30th argument ends up being the number to use. The _INV values are +// 29th argument ends up being the number to use. The _INV values are // placeholders because the slot arguments come in pairs. #define MP_DEFINE_CONST_OBJ_TYPE(...) MP_DEFINE_CONST_OBJ_TYPE_EXPAND(MP_DEFINE_CONST_OBJ_TYPE_NARGS(__VA_ARGS__, _INV, 12, _INV, 11, _INV, 10, _INV, 9, _INV, 8, _INV, 7, _INV, 6, _INV, 5, _INV, 4, _INV, 3, _INV, 2, _INV, 1, _INV, 0)(mp_obj_type_t, __VA_ARGS__)) #define MP_DEFINE_CONST_OBJ_FULL_TYPE(...) MP_DEFINE_CONST_OBJ_TYPE_EXPAND(MP_DEFINE_CONST_OBJ_TYPE_NARGS(__VA_ARGS__, _INV, 12, _INV, 11, _INV, 10, _INV, 9, _INV, 8, _INV, 7, _INV, 6, _INV, 5, _INV, 4, _INV, 3, _INV, 2, _INV, 1, _INV, 0)(mp_obj_full_type_t, __VA_ARGS__)) @@ -916,7 +914,7 @@ void *mp_obj_malloc_helper(size_t num_bytes, const mp_obj_type_t *type); #define mp_obj_is_int(o) (mp_obj_is_small_int(o) || mp_obj_is_exact_type(o, &mp_type_int)) #define mp_obj_is_str(o) (mp_obj_is_qstr(o) || mp_obj_is_exact_type(o, &mp_type_str)) #define mp_obj_is_str_or_bytes(o) (mp_obj_is_qstr(o) || (mp_obj_is_obj(o) && MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type, binary_op) == mp_obj_str_binary_op)) -#define mp_obj_is_dict_or_ordereddict(o) (mp_obj_is_obj(o) && ((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type->make_new == mp_obj_dict_make_new) +#define mp_obj_is_dict_or_ordereddict(o) (mp_obj_is_obj(o) && MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type, make_new) == mp_obj_dict_make_new) #define mp_obj_is_fun(o) (mp_obj_is_obj(o) && (((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type->name == MP_QSTR_function)) mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict); @@ -1032,7 +1030,7 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in); mp_uint_t mp_obj_int_get_uint_checked(mp_const_obj_t self_in); // exception -#define mp_obj_is_native_exception_instance(o) (mp_obj_get_type(o)->make_new == mp_obj_exception_make_new) +#define mp_obj_is_native_exception_instance(o) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(o), make_new) == mp_obj_exception_make_new) bool mp_obj_is_exception_type(mp_obj_t self_in); bool mp_obj_is_exception_instance(mp_obj_t self_in); bool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type); @@ -1044,7 +1042,7 @@ mp_obj_t mp_obj_exception_make_new(const mp_obj_type_t *type_in, size_t n_args, mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in); void mp_init_emergency_exception_buf(void); static inline mp_obj_t mp_obj_new_exception_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg) { - assert(exc_type->make_new == mp_obj_exception_make_new); + assert(MP_OBJ_TYPE_GET_SLOT_OR_NULL(exc_type, make_new) == mp_obj_exception_make_new); return mp_obj_exception_make_new(exc_type, 1, 0, &arg); } diff --git a/py/objarray.c b/py/objarray.c index 0d1032929f..42fc0749d2 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -575,7 +575,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_array, MP_QSTR_array, MP_TYPE_FLAG_ITER_IS_GETITER, - array_make_new, + make_new, array_make_new, print, array_print, iter, array_iterator_new, unary_op, array_unary_op, @@ -591,7 +591,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_bytearray, MP_QSTR_bytearray, MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER, - bytearray_make_new, + make_new, bytearray_make_new, print, array_print, iter, array_iterator_new, unary_op, array_unary_op, @@ -619,7 +619,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_memoryview, MP_QSTR_memoryview, MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER, - memoryview_make_new, + make_new, memoryview_make_new, iter, array_iterator_new, unary_op, array_unary_op, binary_op, array_binary_op, @@ -677,7 +677,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_array_it, MP_QSTR_iterator, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - MP_TYPE_NULL_MAKE_NEW, iter, array_it_iternext ); diff --git a/py/objattrtuple.c b/py/objattrtuple.c index 2e207f4cf0..fbe04bedb8 100644 --- a/py/objattrtuple.c +++ b/py/objattrtuple.c @@ -84,7 +84,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_attrtuple, MP_QSTR_tuple, MP_TYPE_FLAG_ITER_IS_GETITER, - MP_TYPE_NULL_MAKE_NEW, // reuse tuple to save on a qstr print, mp_obj_attrtuple_print, unary_op, mp_obj_tuple_unary_op, diff --git a/py/objbool.c b/py/objbool.c index 5d014bbb8e..3267ff98bb 100644 --- a/py/objbool.c +++ b/py/objbool.c @@ -89,7 +89,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_bool, MP_QSTR_bool, MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, - bool_make_new, + make_new, bool_make_new, print, bool_print, unary_op, bool_unary_op, binary_op, bool_binary_op diff --git a/py/objboundmeth.c b/py/objboundmeth.c index f4b3b9b7df..8486f876f9 100644 --- a/py/objboundmeth.c +++ b/py/objboundmeth.c @@ -111,7 +111,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_bound_meth, MP_QSTR_bound_method, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, BOUND_METH_TYPE_PRINT BOUND_METH_TYPE_ATTR call, bound_meth_call diff --git a/py/objcell.c b/py/objcell.c index b100fae4fe..0a74e29d20 100644 --- a/py/objcell.c +++ b/py/objcell.c @@ -48,7 +48,7 @@ STATIC void cell_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t k STATIC MP_DEFINE_CONST_OBJ_TYPE( // cell representation is just value in < > - mp_type_cell, MP_QSTR_, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW + mp_type_cell, MP_QSTR_, MP_TYPE_FLAG_NONE CELL_TYPE_PRINT ); diff --git a/py/objclosure.c b/py/objclosure.c index 45a3e83c46..6059d18100 100644 --- a/py/objclosure.c +++ b/py/objclosure.c @@ -99,7 +99,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_closure, MP_QSTR_closure, MP_TYPE_FLAG_BINDS_SELF, - MP_TYPE_NULL_MAKE_NEW, CLOSURE_TYPE_ATTR CLOSURE_TYPE_PRINT call, closure_call diff --git a/py/objcomplex.c b/py/objcomplex.c index cf213d718a..ddd103eeb4 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -152,7 +152,8 @@ STATIC void complex_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } MP_DEFINE_CONST_OBJ_TYPE( - mp_type_complex, MP_QSTR_complex, MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, complex_make_new, + mp_type_complex, MP_QSTR_complex, MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, + make_new, complex_make_new, print, complex_print, unary_op, complex_unary_op, binary_op, complex_binary_op, diff --git a/py/objdeque.c b/py/objdeque.c index 1a8f76ca11..8b52b8d387 100644 --- a/py/objdeque.c +++ b/py/objdeque.c @@ -159,7 +159,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_deque, MP_QSTR_deque, MP_TYPE_FLAG_NONE, - deque_make_new, + make_new, deque_make_new, unary_op, deque_unary_op, locals_dict, &deque_locals_dict ); diff --git a/py/objdict.c b/py/objdict.c index 7755d7b786..68c33961c7 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -465,7 +465,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_dict_view_it, MP_QSTR_iterator, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - MP_TYPE_NULL_MAKE_NEW, iter, dict_view_it_iternext ); @@ -517,7 +516,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_dict_view, MP_QSTR_dict_view, MP_TYPE_FLAG_ITER_IS_GETITER, - MP_TYPE_NULL_MAKE_NEW, print, dict_view_print, binary_op, dict_view_binary_op, iter, dict_view_getiter @@ -592,7 +590,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_dict, MP_QSTR_dict, MP_TYPE_FLAG_ITER_IS_GETITER, - mp_obj_dict_make_new, + make_new, mp_obj_dict_make_new, print, dict_print, unary_op, dict_unary_op, binary_op, dict_binary_op, @@ -606,7 +604,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_ordereddict, MP_QSTR_OrderedDict, MP_TYPE_FLAG_ITER_IS_GETITER, - mp_obj_dict_make_new, + make_new, mp_obj_dict_make_new, print, dict_print, unary_op, dict_unary_op, binary_op, dict_binary_op, diff --git a/py/objenumerate.c b/py/objenumerate.c index eea9e3e381..40bed919ed 100644 --- a/py/objenumerate.c +++ b/py/objenumerate.c @@ -71,7 +71,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_enumerate, MP_QSTR_enumerate, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - enumerate_make_new, + make_new, enumerate_make_new, iter, enumerate_iternext ); diff --git a/py/objexcept.c b/py/objexcept.c index 190213e12f..3b76ae62cc 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -288,7 +288,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_BaseException, MP_QSTR_BaseException, MP_TYPE_FLAG_NONE, - mp_obj_exception_make_new, + make_new, mp_obj_exception_make_new, print, mp_obj_exception_print, attr, mp_obj_exception_attr ); @@ -375,12 +375,12 @@ MP_DEFINE_EXCEPTION(Exception, BaseException) // *FORMAT-ON* mp_obj_t mp_obj_new_exception(const mp_obj_type_t *exc_type) { - assert(exc_type->make_new == mp_obj_exception_make_new); + assert(MP_OBJ_TYPE_GET_SLOT_OR_NULL(exc_type, make_new) == mp_obj_exception_make_new); return mp_obj_exception_make_new(exc_type, 0, 0, NULL); } mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, size_t n_args, const mp_obj_t *args) { - assert(exc_type->make_new == mp_obj_exception_make_new); + assert(MP_OBJ_TYPE_GET_SLOT_OR_NULL(exc_type, make_new) == mp_obj_exception_make_new); return mp_obj_exception_make_new(exc_type, n_args, 0, args); } @@ -388,7 +388,7 @@ mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, size_t n_args, mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, mp_rom_error_text_t msg) { // Check that the given type is an exception type - assert(exc_type->make_new == mp_obj_exception_make_new); + assert(MP_OBJ_TYPE_GET_SLOT_OR_NULL(exc_type, make_new) == mp_obj_exception_make_new); // Try to allocate memory for the message mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t); @@ -467,7 +467,7 @@ mp_obj_t mp_obj_new_exception_msg_vlist(const mp_obj_type_t *exc_type, mp_rom_er assert(fmt != NULL); // Check that the given type is an exception type - assert(exc_type->make_new == mp_obj_exception_make_new); + assert(MP_OBJ_TYPE_GET_SLOT_OR_NULL(exc_type, make_new) == mp_obj_exception_make_new); // Try to allocate memory for the message mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t); @@ -538,7 +538,7 @@ bool mp_obj_is_exception_type(mp_obj_t self_in) { if (mp_obj_is_type(self_in, &mp_type_type)) { // optimisation when self_in is a builtin exception mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in); - if (self->make_new == mp_obj_exception_make_new) { + if (MP_OBJ_TYPE_GET_SLOT_OR_NULL(self, make_new) == mp_obj_exception_make_new) { return true; } } diff --git a/py/objexcept.h b/py/objexcept.h index 5d56d67d73..d532f66609 100644 --- a/py/objexcept.h +++ b/py/objexcept.h @@ -41,7 +41,8 @@ void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kin void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest); #define MP_DEFINE_EXCEPTION(exc_name, base_name) \ - MP_DEFINE_CONST_OBJ_TYPE(mp_type_##exc_name, MP_QSTR_##exc_name, MP_TYPE_FLAG_NONE, mp_obj_exception_make_new, \ + MP_DEFINE_CONST_OBJ_TYPE(mp_type_##exc_name, MP_QSTR_##exc_name, MP_TYPE_FLAG_NONE, \ + make_new, mp_obj_exception_make_new, \ print, mp_obj_exception_print, \ attr, mp_obj_exception_attr, \ parent, &mp_type_##base_name \ diff --git a/py/objfilter.c b/py/objfilter.c index bfe651f40d..2a657fde4b 100644 --- a/py/objfilter.c +++ b/py/objfilter.c @@ -64,7 +64,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_filter, MP_QSTR_filter, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - filter_make_new, + make_new, filter_make_new, iter, filter_iternext ); diff --git a/py/objfloat.c b/py/objfloat.c index 9ecbab7a4d..c862b4843b 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -183,7 +183,8 @@ STATIC mp_obj_t float_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs } MP_DEFINE_CONST_OBJ_TYPE( - mp_type_float, MP_QSTR_float, MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, float_make_new, + mp_type_float, MP_QSTR_float, MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, + make_new, float_make_new, print, float_print, unary_op, float_unary_op, binary_op, float_binary_op diff --git a/py/objfun.c b/py/objfun.c index d6ff354575..390ddaa2d2 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -57,7 +57,7 @@ STATIC mp_obj_t fun_builtin_0_call(mp_obj_t self_in, size_t n_args, size_t n_kw, } MP_DEFINE_CONST_OBJ_TYPE( - mp_type_fun_builtin_0, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, MP_TYPE_NULL_MAKE_NEW, + mp_type_fun_builtin_0, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, call, fun_builtin_0_call, unary_op, mp_generic_unary_op ); @@ -70,7 +70,7 @@ STATIC mp_obj_t fun_builtin_1_call(mp_obj_t self_in, size_t n_args, size_t n_kw, } MP_DEFINE_CONST_OBJ_TYPE( - mp_type_fun_builtin_1, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, MP_TYPE_NULL_MAKE_NEW, + mp_type_fun_builtin_1, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, call, fun_builtin_1_call, unary_op, mp_generic_unary_op ); @@ -83,7 +83,7 @@ STATIC mp_obj_t fun_builtin_2_call(mp_obj_t self_in, size_t n_args, size_t n_kw, } MP_DEFINE_CONST_OBJ_TYPE( - mp_type_fun_builtin_2, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, MP_TYPE_NULL_MAKE_NEW, + mp_type_fun_builtin_2, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, call, fun_builtin_2_call, unary_op, mp_generic_unary_op ); @@ -96,7 +96,7 @@ STATIC mp_obj_t fun_builtin_3_call(mp_obj_t self_in, size_t n_args, size_t n_kw, } MP_DEFINE_CONST_OBJ_TYPE( - mp_type_fun_builtin_3, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, MP_TYPE_NULL_MAKE_NEW, + mp_type_fun_builtin_3, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, call, fun_builtin_3_call, unary_op, mp_generic_unary_op ); @@ -125,7 +125,7 @@ STATIC mp_obj_t fun_builtin_var_call(mp_obj_t self_in, size_t n_args, size_t n_k } MP_DEFINE_CONST_OBJ_TYPE( - mp_type_fun_builtin_var, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, MP_TYPE_NULL_MAKE_NEW, + mp_type_fun_builtin_var, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, call, fun_builtin_var_call, unary_op, mp_generic_unary_op ); @@ -368,7 +368,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_fun_bc, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF, - MP_TYPE_NULL_MAKE_NEW, FUN_BC_TYPE_PRINT FUN_BC_TYPE_ATTR call, fun_bc_call, @@ -431,7 +430,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_fun_native, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF, - MP_TYPE_NULL_MAKE_NEW, FUN_BC_TYPE_PRINT FUN_BC_TYPE_ATTR call, fun_native_call, @@ -542,7 +540,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_fun_asm, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF, - MP_TYPE_NULL_MAKE_NEW, call, fun_asm_call, unary_op, mp_generic_unary_op ); diff --git a/py/objgenerator.c b/py/objgenerator.c index d8515c13ce..8175dbd683 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -80,7 +80,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_gen_wrap, MP_QSTR_generator, MP_TYPE_FLAG_BINDS_SELF, - MP_TYPE_NULL_MAKE_NEW, GEN_WRAP_TYPE_ATTR call, gen_wrap_call, unary_op, mp_generic_unary_op @@ -146,7 +145,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_native_gen_wrap, MP_QSTR_generator, MP_TYPE_FLAG_BINDS_SELF, - MP_TYPE_NULL_MAKE_NEW, call, native_gen_wrap_call, NATIVE_GEN_WRAP_TYPE_ATTR unary_op, mp_generic_unary_op @@ -371,7 +369,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_gen_instance, MP_QSTR_generator, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - MP_TYPE_NULL_MAKE_NEW, print, gen_instance_print, unary_op, mp_generic_unary_op, iter, gen_instance_iternext, diff --git a/py/objgetitemiter.c b/py/objgetitemiter.c index 134cbcd629..c598d1daac 100644 --- a/py/objgetitemiter.c +++ b/py/objgetitemiter.c @@ -60,7 +60,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_it, MP_QSTR_iterator, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - MP_TYPE_NULL_MAKE_NEW, iter, it_iternext ); diff --git a/py/objint.c b/py/objint.c index f06bc441f1..1a3ad86947 100644 --- a/py/objint.c +++ b/py/objint.c @@ -461,7 +461,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_int, MP_QSTR_int, MP_TYPE_FLAG_NONE, - mp_obj_int_make_new, + make_new, mp_obj_int_make_new, print, mp_obj_int_print, unary_op, mp_obj_int_unary_op, binary_op, mp_obj_int_binary_op, diff --git a/py/objlist.c b/py/objlist.c index 8d18344ea8..18da91ba3a 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -71,7 +71,7 @@ STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) { return list; } -STATIC mp_obj_t list_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +mp_obj_t mp_obj_list_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 0, 1, false); @@ -456,7 +456,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_list, MP_QSTR_list, MP_TYPE_FLAG_ITER_IS_GETITER, - list_make_new, + make_new, mp_obj_list_make_new, print, list_print, unary_op, list_unary_op, binary_op, list_binary_op, diff --git a/py/objlist.h b/py/objlist.h index a43663db76..a3bba68028 100644 --- a/py/objlist.h +++ b/py/objlist.h @@ -36,5 +36,6 @@ typedef struct _mp_obj_list_t { } mp_obj_list_t; void mp_obj_list_init(mp_obj_list_t *o, size_t n); +mp_obj_t mp_obj_list_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args); #endif // MICROPY_INCLUDED_PY_OBJLIST_H diff --git a/py/objmap.c b/py/objmap.c index 115832e387..e7e594cd2c 100644 --- a/py/objmap.c +++ b/py/objmap.c @@ -67,6 +67,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_map, MP_QSTR_map, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - map_make_new, + make_new, map_make_new, iter, map_iternext ); diff --git a/py/objmodule.c b/py/objmodule.c index 6fc3653e6a..d14a59b863 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -134,7 +134,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_module, MP_QSTR_module, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, module_print, attr, module_attr ); diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index 3b45d8f76f..75e21494b4 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -157,14 +157,14 @@ STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t type->base.type = &mp_type_type; type->flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE; // can match tuple type->name = name; - type->make_new = namedtuple_make_new; - MP_OBJ_TYPE_SET_SLOT(type, print, namedtuple_print, 0); - MP_OBJ_TYPE_SET_SLOT(type, unary_op, mp_obj_tuple_unary_op, 1); - MP_OBJ_TYPE_SET_SLOT(type, binary_op, mp_obj_tuple_binary_op, 2); - MP_OBJ_TYPE_SET_SLOT(type, attr, namedtuple_attr, 3); - MP_OBJ_TYPE_SET_SLOT(type, subscr, mp_obj_tuple_subscr, 4); - MP_OBJ_TYPE_SET_SLOT(type, iter, mp_obj_tuple_getiter, 5); - MP_OBJ_TYPE_SET_SLOT(type, parent, &mp_type_tuple, 6); + MP_OBJ_TYPE_SET_SLOT(type, make_new, namedtuple_make_new, 0); + MP_OBJ_TYPE_SET_SLOT(type, print, namedtuple_print, 1); + MP_OBJ_TYPE_SET_SLOT(type, unary_op, mp_obj_tuple_unary_op, 2); + MP_OBJ_TYPE_SET_SLOT(type, binary_op, mp_obj_tuple_binary_op, 3); + MP_OBJ_TYPE_SET_SLOT(type, attr, namedtuple_attr, 4); + MP_OBJ_TYPE_SET_SLOT(type, subscr, mp_obj_tuple_subscr, 5); + MP_OBJ_TYPE_SET_SLOT(type, iter, mp_obj_tuple_getiter, 6); + MP_OBJ_TYPE_SET_SLOT(type, parent, &mp_type_tuple, 7); return MP_OBJ_FROM_PTR(o); } diff --git a/py/objnamedtuple.h b/py/objnamedtuple.h index db4a3d87d8..c4f4149fd6 100644 --- a/py/objnamedtuple.h +++ b/py/objnamedtuple.h @@ -29,9 +29,9 @@ #include "py/objtuple.h" typedef struct _mp_obj_namedtuple_type_t { - // This is a mp_obj_type_t with seven slots. + // This is a mp_obj_type_t with eight slots. mp_obj_empty_type_t base; - void *slots[7]; + void *slots[8]; size_t n_fields; qstr fields[]; } mp_obj_namedtuple_type_t; diff --git a/py/objnone.c b/py/objnone.c index 4fffbc997e..4f8996e897 100644 --- a/py/objnone.c +++ b/py/objnone.c @@ -47,7 +47,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_NoneType, MP_QSTR_NoneType, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, none_print, unary_op, mp_generic_unary_op ); diff --git a/py/objobject.c b/py/objobject.c index ffad610707..1acae6d00b 100644 --- a/py/objobject.c +++ b/py/objobject.c @@ -121,6 +121,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_object, MP_QSTR_object, MP_TYPE_FLAG_NONE, - object_make_new + make_new, object_make_new OBJECT_TYPE_LOCALS_DICT ); diff --git a/py/objpolyiter.c b/py/objpolyiter.c index 7a45b6b73f..78b600abac 100644 --- a/py/objpolyiter.c +++ b/py/objpolyiter.c @@ -49,7 +49,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_polymorph_iter, MP_QSTR_iterator, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - MP_TYPE_NULL_MAKE_NEW, iter, polymorph_it_iternext ); @@ -81,7 +80,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_polymorph_iter_with_finaliser, MP_QSTR_iterator, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - MP_TYPE_NULL_MAKE_NEW, iter, polymorph_it_iternext, locals_dict, &mp_obj_polymorph_iter_locals_dict ); diff --git a/py/objproperty.c b/py/objproperty.c index ce3b572591..2d3af10e8c 100644 --- a/py/objproperty.c +++ b/py/objproperty.c @@ -94,7 +94,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_property, MP_QSTR_property, MP_TYPE_FLAG_NONE, - property_make_new, + make_new, property_make_new, locals_dict, &property_locals_dict ); diff --git a/py/objrange.c b/py/objrange.c index 1ad8f6031f..f0fe56d9db 100644 --- a/py/objrange.c +++ b/py/objrange.c @@ -54,7 +54,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_range_it, MP_QSTR_iterator, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - MP_TYPE_NULL_MAKE_NEW, iter, range_it_iternext ); @@ -225,7 +224,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_range, MP_QSTR_range, MP_TYPE_FLAG_NONE, - range_make_new, + make_new, range_make_new, RANGE_TYPE_BINOP RANGE_TYPE_ATTR print, range_print, diff --git a/py/objreversed.c b/py/objreversed.c index e265266d3f..c66698f028 100644 --- a/py/objreversed.c +++ b/py/objreversed.c @@ -72,7 +72,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_reversed, MP_QSTR_reversed, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - reversed_make_new, + make_new, reversed_make_new, iter, reversed_iternext ); diff --git a/py/objset.c b/py/objset.c index b827f49f40..906807889a 100644 --- a/py/objset.c +++ b/py/objset.c @@ -543,7 +543,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_set, MP_QSTR_set, MP_TYPE_FLAG_ITER_IS_GETITER, - set_make_new, + make_new, set_make_new, print, set_print, unary_op, set_unary_op, binary_op, set_binary_op, @@ -569,7 +569,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_frozenset, MP_QSTR_frozenset, MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER, - set_make_new, + make_new, set_make_new, print, set_print, unary_op, set_unary_op, binary_op, set_binary_op, diff --git a/py/objsingleton.c b/py/objsingleton.c index 4a099657d4..dc73d28c27 100644 --- a/py/objsingleton.c +++ b/py/objsingleton.c @@ -44,7 +44,7 @@ STATIC void singleton_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ } MP_DEFINE_CONST_OBJ_TYPE( - mp_type_singleton, MP_QSTR_, MP_TYPE_FLAG_NONE, MP_TYPE_NULL_MAKE_NEW, + mp_type_singleton, MP_QSTR_, MP_TYPE_FLAG_NONE, print, singleton_print, unary_op, mp_generic_unary_op ); diff --git a/py/objslice.c b/py/objslice.c index d1dbb24586..01d4da0dbd 100644 --- a/py/objslice.c +++ b/py/objslice.c @@ -104,7 +104,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_slice, MP_QSTR_slice, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, SLICE_TYPE_ATTR_OR_LOCALS_DICT print, slice_print ); diff --git a/py/objstr.c b/py/objstr.c index 12f6e15d04..50ab0018ed 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -482,7 +482,7 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { if (!mp_obj_is_type(arg, &mp_type_list) && !mp_obj_is_type(arg, &mp_type_tuple)) { // arg is not a list nor a tuple, try to convert it to a list // TODO: Try to optimize? - arg = mp_type_list.make_new(&mp_type_list, 1, 0, &arg); + arg = mp_obj_list_make_new(&mp_type_list, 1, 0, &arg); } mp_obj_get_array(arg, &seq_len, &seq_items); @@ -2147,7 +2147,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_str, MP_QSTR_str, MP_TYPE_FLAG_NONE, - mp_obj_str_make_new, + make_new, mp_obj_str_make_new, print, str_print, binary_op, mp_obj_str_binary_op, subscr, bytes_subscr, @@ -2162,7 +2162,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_bytes, MP_QSTR_bytes, MP_TYPE_FLAG_NONE, - bytes_make_new, + make_new, bytes_make_new, print, str_print, binary_op, mp_obj_str_binary_op, subscr, bytes_subscr, diff --git a/py/objstringio.c b/py/objstringio.c index 4e19b83999..1a083449ba 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -248,7 +248,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_stringio, MP_QSTR_StringIO, MP_TYPE_FLAG_ITER_IS_STREAM, - stringio_make_new, + make_new, stringio_make_new, print, stringio_print, protocol, &stringio_stream_p, locals_dict, &stringio_locals_dict @@ -265,7 +265,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_bytesio, MP_QSTR_BytesIO, MP_TYPE_FLAG_ITER_IS_STREAM, - stringio_make_new, + make_new, stringio_make_new, print, stringio_print, protocol, &bytesio_stream_p, locals_dict, &stringio_locals_dict diff --git a/py/objstrunicode.c b/py/objstrunicode.c index 9b28841ecd..93383b3c19 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -233,7 +233,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_str, MP_QSTR_str, MP_TYPE_FLAG_ITER_IS_GETITER, - mp_obj_str_make_new, + make_new, mp_obj_str_make_new, print, uni_print, unary_op, uni_unary_op, binary_op, mp_obj_str_binary_op, diff --git a/py/objtuple.c b/py/objtuple.c index 485d44c52a..9d6797b4ff 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -228,7 +228,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_tuple, MP_QSTR_tuple, MP_TYPE_FLAG_ITER_IS_GETITER, - mp_obj_tuple_make_new, + make_new, mp_obj_tuple_make_new, print, mp_obj_tuple_print, unary_op, mp_obj_tuple_unary_op, binary_op, mp_obj_tuple_binary_op, diff --git a/py/objtype.c b/py/objtype.c index 183dce071e..db364e0e5a 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -88,7 +88,7 @@ STATIC mp_obj_t native_base_init_wrapper(size_t n_args, const mp_obj_t *args) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(args[0]); const mp_obj_type_t *native_base = NULL; instance_count_native_bases(self->base.type, &native_base); - self->subobj[0] = native_base->make_new(native_base, n_args - 1, 0, args + 1); + self->subobj[0] = MP_OBJ_TYPE_GET_SLOT(native_base, make_new)(native_base, n_args - 1, 0, args + 1); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(native_base_init_wrapper_obj, 1, MP_OBJ_FUN_ARGS_MAX, native_base_init_wrapper); @@ -285,7 +285,7 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size struct class_lookup_data lookup = { .obj = NULL, .attr = MP_QSTR___new__, - .slot_offset = offsetof(mp_obj_type_t, make_new), + .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(make_new), .dest = init_fn, .is_type = false, }; @@ -362,7 +362,7 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size // If the type had a native base that was not explicitly initialised // (constructed) by the Python __init__() method then construct it now. if (native_base != NULL && o->subobj[0] == MP_OBJ_FROM_PTR(&native_base_init_wrapper_obj)) { - o->subobj[0] = native_base->make_new(native_base, n_args, n_kw, args); + o->subobj[0] = MP_OBJ_TYPE_GET_SLOT(native_base, make_new)(native_base, n_args, n_kw, args); } return MP_OBJ_FROM_PTR(o); @@ -998,7 +998,7 @@ STATIC mp_obj_t type_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in); - if (self->make_new == NULL) { + if (!MP_OBJ_TYPE_HAS_SLOT(self, make_new)) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE mp_raise_TypeError(MP_ERROR_TEXT("can't create instance")); #else @@ -1007,7 +1007,7 @@ STATIC mp_obj_t type_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp } // make new instance - mp_obj_t o = self->make_new(self, n_args, n_kw, args); + mp_obj_t o = MP_OBJ_TYPE_GET_SLOT(self, make_new)(self, n_args, n_kw, args); // return new instance return o; @@ -1109,7 +1109,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_type, MP_QSTR_type, MP_TYPE_FLAG_NONE, - type_make_new, + make_new, type_make_new, print, type_print, call, type_call, unary_op, mp_generic_unary_op, @@ -1141,7 +1141,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) } mp_obj_type_t *t = MP_OBJ_TO_PTR(bases_items[i]); // TODO: Verify with CPy, tested on function type - if (t->make_new == NULL) { + if (!MP_OBJ_TYPE_HAS_SLOT(t, make_new)) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE mp_raise_TypeError(MP_ERROR_TEXT("type isn't an acceptable base type")); #else @@ -1163,35 +1163,35 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) } // Allocate a variable-sized mp_obj_type_t with as many slots as we need - // (currently 9, plus 1 for base, plus 1 for base-protocol). - // Note: 11 slots pushes it from 4 to 5 GC blocks. - mp_obj_type_t *o = m_new_obj_var0(mp_obj_type_t, void *, 9 + (bases_len ? 1 : 0) + (base_protocol ? 1 : 0)); + // (currently 10, plus 1 for base, plus 1 for base-protocol). + // Note: mp_obj_type_t is (2 + 3 + #slots) words, so going from 11 to 12 slots + // moves from 4 to 5 gc blocks. + mp_obj_type_t *o = m_new_obj_var0(mp_obj_type_t, void *, 10 + (bases_len ? 1 : 0) + (base_protocol ? 1 : 0)); o->base.type = &mp_type_type; o->flags = base_flags; o->name = name; - o->make_new = mp_obj_instance_make_new; - MP_OBJ_TYPE_SET_SLOT(o, print, instance_print, 0); - MP_OBJ_TYPE_SET_SLOT(o, call, mp_obj_instance_call, 1); - MP_OBJ_TYPE_SET_SLOT(o, unary_op, instance_unary_op, 2); - MP_OBJ_TYPE_SET_SLOT(o, binary_op, instance_binary_op, 3); - MP_OBJ_TYPE_SET_SLOT(o, attr, mp_obj_instance_attr, 4); - MP_OBJ_TYPE_SET_SLOT(o, subscr, instance_subscr, 5); - MP_OBJ_TYPE_SET_SLOT(o, iter, mp_obj_instance_getiter, 6); - // MP_OBJ_TYPE_SET_SLOT(o, iternext, not implemented) - MP_OBJ_TYPE_SET_SLOT(o, buffer, instance_get_buffer, 7); + MP_OBJ_TYPE_SET_SLOT(o, make_new, mp_obj_instance_make_new, 0); + MP_OBJ_TYPE_SET_SLOT(o, print, instance_print, 1); + MP_OBJ_TYPE_SET_SLOT(o, call, mp_obj_instance_call, 2); + MP_OBJ_TYPE_SET_SLOT(o, unary_op, instance_unary_op, 3); + MP_OBJ_TYPE_SET_SLOT(o, binary_op, instance_binary_op, 4); + MP_OBJ_TYPE_SET_SLOT(o, attr, mp_obj_instance_attr, 5); + MP_OBJ_TYPE_SET_SLOT(o, subscr, instance_subscr, 6); + MP_OBJ_TYPE_SET_SLOT(o, iter, mp_obj_instance_getiter, 7); + MP_OBJ_TYPE_SET_SLOT(o, buffer, instance_get_buffer, 8); mp_obj_dict_t *locals_ptr = MP_OBJ_TO_PTR(locals_dict); - MP_OBJ_TYPE_SET_SLOT(o, locals_dict, locals_ptr, 8); + MP_OBJ_TYPE_SET_SLOT(o, locals_dict, locals_ptr, 9); if (bases_len > 0) { if (bases_len >= 2) { #if MICROPY_MULTIPLE_INHERITANCE - MP_OBJ_TYPE_SET_SLOT(o, parent, MP_OBJ_TO_PTR(bases_tuple), 9); + MP_OBJ_TYPE_SET_SLOT(o, parent, MP_OBJ_TO_PTR(bases_tuple), 10); #else mp_raise_NotImplementedError(MP_ERROR_TEXT("multiple inheritance not supported")); #endif } else { - MP_OBJ_TYPE_SET_SLOT(o, parent, MP_OBJ_TO_PTR(bases_items[0]), 9); + MP_OBJ_TYPE_SET_SLOT(o, parent, MP_OBJ_TO_PTR(bases_items[0]), 10); } // Inherit protocol from a base class. This allows to define an @@ -1199,7 +1199,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) // Python method calls, and any subclass inheriting from it will // support this feature. if (base_protocol) { - MP_OBJ_TYPE_SET_SLOT(o, protocol, base_protocol, 10); + MP_OBJ_TYPE_SET_SLOT(o, protocol, base_protocol, 11); } } @@ -1292,7 +1292,7 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { // Allow a call super().__init__() to reach any native base classes. if (attr == MP_QSTR___init__) { - lookup.slot_offset = offsetof(mp_obj_type_t, make_new); + lookup.slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(make_new); } if (!MP_OBJ_TYPE_HAS_SLOT(type, parent)) { @@ -1340,7 +1340,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_super, MP_QSTR_super, MP_TYPE_FLAG_NONE, - super_make_new, + make_new, super_make_new, print, super_print, attr, super_attr ); @@ -1463,12 +1463,12 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_staticmethod, MP_QSTR_staticmethod, MP_TYPE_FLAG_NONE, - static_class_method_make_new + make_new, static_class_method_make_new ); MP_DEFINE_CONST_OBJ_TYPE( mp_type_classmethod, MP_QSTR_classmethod, MP_TYPE_FLAG_NONE, - static_class_method_make_new + make_new, static_class_method_make_new ); diff --git a/py/objtype.h b/py/objtype.h index 2c613b9045..76a290760c 100644 --- a/py/objtype.h +++ b/py/objtype.h @@ -46,8 +46,8 @@ mp_obj_instance_t *mp_obj_new_instance(const mp_obj_type_t *cls, const mp_obj_ty bool mp_obj_instance_is_callable(mp_obj_t self_in); mp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); -#define mp_obj_is_instance_type(type) ((type)->make_new == mp_obj_instance_make_new) -#define mp_obj_is_native_type(type) ((type)->make_new != mp_obj_instance_make_new) +#define mp_obj_is_instance_type(type) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(type, make_new) == mp_obj_instance_make_new) +#define mp_obj_is_native_type(type) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(type, make_new) != mp_obj_instance_make_new) // this needs to be exposed for the above macros to work correctly mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); diff --git a/py/objzip.c b/py/objzip.c index 34d73465ef..3c3138180a 100644 --- a/py/objzip.c +++ b/py/objzip.c @@ -70,6 +70,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_zip, MP_QSTR_zip, MP_TYPE_FLAG_ITER_IS_ITERNEXT, - zip_make_new, + make_new, zip_make_new, iter, zip_iternext ); diff --git a/py/profile.c b/py/profile.c index 2b9531e245..fd2d61caa9 100644 --- a/py/profile.c +++ b/py/profile.c @@ -176,7 +176,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_settrace_codeobj, MP_QSTR_code, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, code_print, unary_op, mp_generic_unary_op, attr, code_attr @@ -247,7 +246,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_frame, MP_QSTR_frame, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, print, frame_print, unary_op, mp_generic_unary_op, attr, frame_attr diff --git a/py/runtime.c b/py/runtime.c index ec628bfe14..da6c86d971 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1076,7 +1076,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( mp_type_checked_fun, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF, - MP_TYPE_NULL_MAKE_NEW, call, checked_fun_call ); diff --git a/shared/runtime/mpirq.c b/shared/runtime/mpirq.c index 889fa7a9a8..f9a85ebbd6 100644 --- a/shared/runtime/mpirq.c +++ b/shared/runtime/mpirq.c @@ -129,7 +129,6 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_irq_type, MP_QSTR_irq, MP_TYPE_FLAG_NONE, - MP_TYPE_NULL_MAKE_NEW, call, mp_irq_call, locals_dict, &mp_irq_locals_dict ); diff --git a/shared/runtime/sys_stdio_mphal.c b/shared/runtime/sys_stdio_mphal.c index 325f93dde1..ab5bdd34e7 100644 --- a/shared/runtime/sys_stdio_mphal.c +++ b/shared/runtime/sys_stdio_mphal.c @@ -127,7 +127,6 @@ MP_DEFINE_CONST_OBJ_TYPE( stdio_obj_type, MP_QSTR_FileIO, MP_TYPE_FLAG_ITER_IS_STREAM, - MP_TYPE_NULL_MAKE_NEW, print, stdio_obj_print, protocol, &stdio_obj_stream_p, locals_dict, &stdio_locals_dict @@ -161,7 +160,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( stdio_buffer_obj_type, MP_QSTR_FileIO, MP_TYPE_FLAG_ITER_IS_STREAM, - MP_TYPE_NULL_MAKE_NEW, print, stdio_obj_print, protocol, &stdio_buffer_obj_stream_p, locals_dict, &stdio_locals_dict From b41aaaa8a918a6645ebc6bfa4483bd17286f9263 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 17 Sep 2022 22:22:32 +1000 Subject: [PATCH 0428/1041] py/obj: Optimise code size and performance for make_new as a slot. The check for make_new (i.e. used to determine something's type) is now more complicated due to the slot access. This commit changes the inlining of a few frequently-used helpers to overall improve code size and performance. --- py/obj.h | 6 ++++-- py/objdict.c | 4 ++++ py/objexcept.c | 4 ++++ py/objstr.c | 20 ++++++++++++-------- py/objtype.c | 5 +++-- py/objtype.h | 6 ++---- 6 files changed, 29 insertions(+), 16 deletions(-) diff --git a/py/obj.h b/py/obj.h index 34adfbd0f0..8aa5b0a8e6 100644 --- a/py/obj.h +++ b/py/obj.h @@ -521,6 +521,7 @@ typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *); // mp_getiter_iternext_custom_t struct instance (with both .getiter and .iternext set). // If MP_TYPE_FLAG_ITER_IS_STREAM is set then the type implicitly gets a "return self" // getiter, and mp_stream_unbuffered_iter for iternext. +// If MP_TYPE_FLAG_INSTANCE_TYPE is set then this is an instance type (i.e. defined in Python). #define MP_TYPE_FLAG_NONE (0x0000) #define MP_TYPE_FLAG_IS_SUBCLASSED (0x0001) #define MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS (0x0002) @@ -533,6 +534,7 @@ typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *); #define MP_TYPE_FLAG_ITER_IS_ITERNEXT (0x0080) #define MP_TYPE_FLAG_ITER_IS_CUSTOM (0x0100) #define MP_TYPE_FLAG_ITER_IS_STREAM (MP_TYPE_FLAG_ITER_IS_ITERNEXT | MP_TYPE_FLAG_ITER_IS_CUSTOM) +#define MP_TYPE_FLAG_INSTANCE_TYPE (0x0200) typedef enum { PRINT_STR = 0, @@ -914,7 +916,7 @@ void *mp_obj_malloc_helper(size_t num_bytes, const mp_obj_type_t *type); #define mp_obj_is_int(o) (mp_obj_is_small_int(o) || mp_obj_is_exact_type(o, &mp_type_int)) #define mp_obj_is_str(o) (mp_obj_is_qstr(o) || mp_obj_is_exact_type(o, &mp_type_str)) #define mp_obj_is_str_or_bytes(o) (mp_obj_is_qstr(o) || (mp_obj_is_obj(o) && MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type, binary_op) == mp_obj_str_binary_op)) -#define mp_obj_is_dict_or_ordereddict(o) (mp_obj_is_obj(o) && MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type, make_new) == mp_obj_dict_make_new) +bool mp_obj_is_dict_or_ordereddict(mp_obj_t o); #define mp_obj_is_fun(o) (mp_obj_is_obj(o) && (((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type->name == MP_QSTR_function)) mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict); @@ -1030,7 +1032,7 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in); mp_uint_t mp_obj_int_get_uint_checked(mp_const_obj_t self_in); // exception -#define mp_obj_is_native_exception_instance(o) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(o), make_new) == mp_obj_exception_make_new) +bool mp_obj_is_native_exception_instance(mp_obj_t self_in); bool mp_obj_is_exception_type(mp_obj_t self_in); bool mp_obj_is_exception_instance(mp_obj_t self_in); bool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type); diff --git a/py/objdict.c b/py/objdict.c index 68c33961c7..7fad5fc8f4 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -33,6 +33,10 @@ #include "py/objtype.h" #include "py/objstr.h" +bool mp_obj_is_dict_or_ordereddict(mp_obj_t o) { + return mp_obj_is_obj(o) && MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type, make_new) == mp_obj_dict_make_new; +} + const mp_obj_dict_t mp_const_empty_dict_obj = { .base = { .type = &mp_type_dict }, .map = { diff --git a/py/objexcept.c b/py/objexcept.c index 3b76ae62cc..515cbe7425 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -111,6 +111,10 @@ mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in) { #endif #endif // MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF +bool mp_obj_is_native_exception_instance(mp_obj_t self_in) { + return MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(self_in), make_new) == mp_obj_exception_make_new; +} + STATIC mp_obj_exception_t *get_native_exception(mp_obj_t self_in) { assert(mp_obj_is_exception_instance(self_in)); if (mp_obj_is_native_exception_instance(self_in)) { diff --git a/py/objstr.c b/py/objstr.c index 50ab0018ed..62d7bfb4cc 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -63,6 +63,10 @@ STATIC void str_check_arg_type(const mp_obj_type_t *self_type, const mp_obj_t ar } } +STATIC void check_is_str_or_bytes(mp_obj_t self_in) { + mp_check_self(mp_obj_is_str_or_bytes(self_in)); +} + /******************************************************************************/ /* str */ @@ -468,7 +472,7 @@ STATIC mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { - mp_check_self(mp_obj_is_str_or_bytes(self_in)); + check_is_str_or_bytes(self_in); const mp_obj_type_t *self_type = mp_obj_get_type(self_in); const mp_obj_type_t *ret_type = self_type; @@ -724,7 +728,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj, 1, 3, str_rsplit); STATIC mp_obj_t str_finder(size_t n_args, const mp_obj_t *args, int direction, bool is_index) { const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); - mp_check_self(mp_obj_is_str_or_bytes(args[0])); + check_is_str_or_bytes(args[0]); // check argument type str_check_arg_type(self_type, args[1]); @@ -820,7 +824,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 3, str_endswith); enum { LSTRIP, RSTRIP, STRIP }; STATIC mp_obj_t str_uni_strip(int type, size_t n_args, const mp_obj_t *args) { - mp_check_self(mp_obj_is_str_or_bytes(args[0])); + check_is_str_or_bytes(args[0]); const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); const byte *chars_to_del; @@ -1422,7 +1426,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar } mp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { - mp_check_self(mp_obj_is_str_or_bytes(args[0])); + check_is_str_or_bytes(args[0]); GET_STR_DATA_LEN(args[0], str, len); int arg_i = 0; @@ -1433,7 +1437,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(str_format_obj, 1, mp_obj_str_format); #if MICROPY_PY_BUILTINS_STR_OP_MODULO STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_t *args, mp_obj_t dict) { - mp_check_self(mp_obj_is_str_or_bytes(pattern)); + check_is_str_or_bytes(pattern); GET_STR_DATA_LEN(pattern, str, len); #if MICROPY_ERROR_REPORTING > MICROPY_ERROR_REPORTING_TERSE @@ -1639,7 +1643,7 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_ // The implementation is optimized, returning the original string if there's // nothing to replace. STATIC mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) { - mp_check_self(mp_obj_is_str_or_bytes(args[0])); + check_is_str_or_bytes(args[0]); mp_int_t max_rep = -1; if (n_args == 4) { @@ -1742,7 +1746,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj, 3, 4, str_replace); #if MICROPY_PY_BUILTINS_STR_COUNT STATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) { const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); - mp_check_self(mp_obj_is_str_or_bytes(args[0])); + check_is_str_or_bytes(args[0]); // check argument type str_check_arg_type(self_type, args[1]); @@ -1782,7 +1786,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj, 2, 4, str_count); #if MICROPY_PY_BUILTINS_STR_PARTITION STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, int direction) { - mp_check_self(mp_obj_is_str_or_bytes(self_in)); + check_is_str_or_bytes(self_in); const mp_obj_type_t *self_type = mp_obj_get_type(self_in); str_check_arg_type(self_type, arg); diff --git a/py/objtype.c b/py/objtype.c index db364e0e5a..909fc83393 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -277,7 +277,7 @@ STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k mp_printf(print, "<%s object at %p>", mp_obj_get_type_str(self_in), self); } -mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) { +STATIC mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_instance_type(self)); // look for __new__ function @@ -1131,7 +1131,8 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) uint16_t base_flags = MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_EQ_HAS_NEQ_TEST - | MP_TYPE_FLAG_ITER_IS_GETITER; + | MP_TYPE_FLAG_ITER_IS_GETITER + | MP_TYPE_FLAG_INSTANCE_TYPE; size_t bases_len; mp_obj_t *bases_items; mp_obj_tuple_get(bases_tuple, &bases_len, &bases_items); diff --git a/py/objtype.h b/py/objtype.h index 76a290760c..839cc6d146 100644 --- a/py/objtype.h +++ b/py/objtype.h @@ -46,10 +46,8 @@ mp_obj_instance_t *mp_obj_new_instance(const mp_obj_type_t *cls, const mp_obj_ty bool mp_obj_instance_is_callable(mp_obj_t self_in); mp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); -#define mp_obj_is_instance_type(type) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(type, make_new) == mp_obj_instance_make_new) -#define mp_obj_is_native_type(type) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(type, make_new) != mp_obj_instance_make_new) -// this needs to be exposed for the above macros to work correctly -mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); +#define mp_obj_is_instance_type(type) ((type)->flags & MP_TYPE_FLAG_INSTANCE_TYPE) +#define mp_obj_is_native_type(type) (!((type)->flags & MP_TYPE_FLAG_INSTANCE_TYPE)) // this needs to be exposed for mp_getiter mp_obj_t mp_obj_instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf); From d94141e1473aebae0d3c63aeaa8397651ad6fa01 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 17 Sep 2022 23:57:12 +1000 Subject: [PATCH 0429/1041] py/persistentcode: Introduce .mpy sub-version. The intent is to allow us to make breaking changes to the native ABI (e.g. changes to dynruntime.h) without needing the bytecode version to increment. With this commit the two bits previously used for the feature flags (but now unused as of .mpy version 6) encode a sub-version. A bytecode-only .mpy file can be loaded as long as MPY_VERSION matches, but a native .mpy (i.e. one with an arch set) must also match MPY_SUB_VERSION. This allows 3 additional updates to the native ABI per bytecode revision. The sub-version is set to 1 because the previous commits that changed the layout of mp_obj_type_t have changed the native ABI. Signed-off-by: Jim Mussared Signed-off-by: Damien George --- docs/reference/mpyfiles.rst | 6 ++++++ mpy-cross/main.c | 2 +- py/persistentcode.c | 6 +++--- py/persistentcode.h | 23 +++++++++++------------ tests/micropython/import_mpy_native.py | 7 ++++--- tests/micropython/import_mpy_native_gc.py | 12 +++++++----- tools/mpy-tool.py | 10 ++++++++-- tools/mpy_ld.py | 7 ++++++- 8 files changed, 46 insertions(+), 27 deletions(-) diff --git a/docs/reference/mpyfiles.rst b/docs/reference/mpyfiles.rst index fcb4996565..d93a86383e 100644 --- a/docs/reference/mpyfiles.rst +++ b/docs/reference/mpyfiles.rst @@ -27,6 +27,11 @@ Compatibility is based on the following: * Version of the .mpy file: the version of the file must match the version supported by the system loading it. +* Sub-version of the .mpy file: if the .mpy file contains native machine code + then the sub-version of the file must match the version support by the + system loading it. Otherwise, if there is no native machine code in the .mpy + file, then the sub-version is ignored when loading. + * Small integer bits: the .mpy file will require a minimum number of bits in a small integer and the system loading it must support at least this many bits. @@ -55,6 +60,7 @@ If importing an .mpy file fails then try the following: 'armv6', 'armv6m', 'armv7m', 'armv7em', 'armv7emsp', 'armv7emdp', 'xtensa', 'xtensawin'][sys_mpy >> 10] print('mpy version:', sys_mpy & 0xff) + print('mpy sub-version:', sys_mpy >> 8 & 3) print('mpy flags:', end='') if arch: print(' -march=' + arch, end='') diff --git a/mpy-cross/main.c b/mpy-cross/main.c index f3ffff61fd..4975c8ddb2 100644 --- a/mpy-cross/main.c +++ b/mpy-cross/main.c @@ -228,7 +228,7 @@ MP_NOINLINE int main_(int argc, char **argv) { a += 1; } else if (strcmp(argv[a], "--version") == 0) { printf("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE - "; mpy-cross emitting mpy v" MP_STRINGIFY(MPY_VERSION) "\n"); + "; mpy-cross emitting mpy v" MP_STRINGIFY(MPY_VERSION) "." MP_STRINGIFY(MPY_SUB_VERSION) "\n"); return 0; } else if (strcmp(argv[a], "-v") == 0) { mp_verbose_flag++; diff --git a/py/persistentcode.c b/py/persistentcode.c index 1b1741f261..de84c17359 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -393,14 +393,14 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, mp_module_context_t *co mp_compiled_module_t mp_raw_code_load(mp_reader_t *reader, mp_module_context_t *context) { byte header[4]; read_bytes(reader, header, sizeof(header)); + byte arch = MPY_FEATURE_DECODE_ARCH(header[2]); if (header[0] != 'M' || header[1] != MPY_VERSION - || MPY_FEATURE_DECODE_FLAGS(header[2]) != MPY_FEATURE_FLAGS + || (arch != MP_NATIVE_ARCH_NONE && MPY_FEATURE_DECODE_SUB_VERSION(header[2]) != MPY_SUB_VERSION) || header[3] > MP_SMALL_INT_BITS) { mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy file")); } if (MPY_FEATURE_DECODE_ARCH(header[2]) != MP_NATIVE_ARCH_NONE) { - byte arch = MPY_FEATURE_DECODE_ARCH(header[2]); if (!MPY_FEATURE_ARCH_TEST(arch)) { if (MPY_FEATURE_ARCH_TEST(MP_NATIVE_ARCH_NONE)) { // On supported ports this can be resolved by enabling feature, eg @@ -596,7 +596,7 @@ void mp_raw_code_save(mp_compiled_module_t *cm, mp_print_t *print) { byte header[4] = { 'M', MPY_VERSION, - MPY_FEATURE_ENCODE_FLAGS(MPY_FEATURE_FLAGS_DYNAMIC), + MPY_FEATURE_ENCODE_SUB_VERSION(MPY_SUB_VERSION), #if MICROPY_DYNAMIC_COMPILER mp_dynamic_compiler.small_int_bits, #else diff --git a/py/persistentcode.h b/py/persistentcode.h index 29ccce4a3d..e664358737 100644 --- a/py/persistentcode.h +++ b/py/persistentcode.h @@ -30,24 +30,23 @@ #include "py/reader.h" #include "py/emitglue.h" -// The current version of .mpy files +// The current version of .mpy files. A bytecode-only .mpy file can be loaded +// as long as MPY_VERSION matches, but a native .mpy (i.e. one with an arch +// set) must also match MPY_SUB_VERSION. This allows 3 additional updates to +// the native ABI per bytecode revision. #define MPY_VERSION 6 +#define MPY_SUB_VERSION 1 -// Macros to encode/decode flags to/from the feature byte -#define MPY_FEATURE_ENCODE_FLAGS(flags) (flags) -#define MPY_FEATURE_DECODE_FLAGS(feat) ((feat) & 3) +// Macros to encode/decode sub-version to/from the feature byte. This replaces +// the bits previously used to encode the flags (map caching and unicode) +// which are no longer used starting at .mpy version 6. +#define MPY_FEATURE_ENCODE_SUB_VERSION(version) (version) +#define MPY_FEATURE_DECODE_SUB_VERSION(feat) ((feat) & 3) // Macros to encode/decode native architecture to/from the feature byte #define MPY_FEATURE_ENCODE_ARCH(arch) ((arch) << 2) #define MPY_FEATURE_DECODE_ARCH(feat) ((feat) >> 2) -// The feature flag bits encode the compile-time config options that affect -// the generate bytecode. Note: no longer used. -// (formerly MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE and MICROPY_PY_BUILTINS_STR_UNICODE). -#define MPY_FEATURE_FLAGS (0) -// This is a version of the flags that can be configured at runtime. -#define MPY_FEATURE_FLAGS_DYNAMIC (0) - // Define the host architecture #if MICROPY_EMIT_X86 #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_X86) @@ -82,7 +81,7 @@ // 16-bit little-endian integer with the second and third bytes of supported .mpy files #define MPY_FILE_HEADER_INT (MPY_VERSION \ - | (MPY_FEATURE_ENCODE_FLAGS(MPY_FEATURE_FLAGS) | MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH)) << 8) + | (MPY_FEATURE_ENCODE_SUB_VERSION(MPY_SUB_VERSION) | MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH)) << 8) enum { MP_NATIVE_ARCH_NONE = 0, diff --git a/tests/micropython/import_mpy_native.py b/tests/micropython/import_mpy_native.py index 449371ddac..73e20694cc 100644 --- a/tests/micropython/import_mpy_native.py +++ b/tests/micropython/import_mpy_native.py @@ -11,7 +11,8 @@ except (ImportError, AttributeError): raise SystemExit mpy_arch = usys.implementation._mpy >> 8 -if mpy_arch == 0: +if mpy_arch >> 2 == 0: + # This system does not support .mpy files containing native code print("SKIP") raise SystemExit @@ -54,8 +55,8 @@ class UserFS: valid_header = bytes([77, 6, mpy_arch, 31]) # fmt: off user_files = { - # bad architecture - '/mod0.mpy': b'M\x06\xfc\x1f', + # bad architecture (mpy_arch needed for sub-version) + '/mod0.mpy': bytes([77, 6, 0xfc | mpy_arch, 31]), # test loading of viper and asm '/mod1.mpy': valid_header + ( diff --git a/tests/micropython/import_mpy_native_gc.py b/tests/micropython/import_mpy_native_gc.py index bc8dcafdc7..e18720fb31 100644 --- a/tests/micropython/import_mpy_native_gc.py +++ b/tests/micropython/import_mpy_native_gc.py @@ -46,24 +46,26 @@ class UserFS: # Pre-compiled examples/natmod/features0 example for various architectures, keyed -# by the required value of sys.implementation._mpy. +# by the required value of sys.implementation._mpy (without sub-version). features0_file_contents = { # -march=x64 - 0x806: b'M\x06\x08\x1f\x02\x004build/features0.native.mpy\x00\x12factorial\x00\x8a\x02\xe9/\x00\x00\x00SH\x8b\x1d\x83\x00\x00\x00\xbe\x02\x00\x00\x00\xffS\x18\xbf\x01\x00\x00\x00H\x85\xc0u\x0cH\x8bC \xbe\x02\x00\x00\x00[\xff\xe0H\x0f\xaf\xf8H\xff\xc8\xeb\xe6ATUSH\x8b\x1dQ\x00\x00\x00H\x8bG\x08L\x8bc(H\x8bx\x08A\xff\xd4H\x8d5+\x00\x00\x00H\x89\xc5H\x8b\x059\x00\x00\x00\x0f\xb7x\x02\xffShH\x89\xefA\xff\xd4H\x8b\x03[]A\\\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x11$\r&\xa3 \x01"\xff', + 0x806: b'M\x06\x09\x1f\x02\x004build/features0.native.mpy\x00\x12factorial\x00\x8a\x02\xe9/\x00\x00\x00SH\x8b\x1d\x83\x00\x00\x00\xbe\x02\x00\x00\x00\xffS\x18\xbf\x01\x00\x00\x00H\x85\xc0u\x0cH\x8bC \xbe\x02\x00\x00\x00[\xff\xe0H\x0f\xaf\xf8H\xff\xc8\xeb\xe6ATUSH\x8b\x1dQ\x00\x00\x00H\x8bG\x08L\x8bc(H\x8bx\x08A\xff\xd4H\x8d5+\x00\x00\x00H\x89\xc5H\x8b\x059\x00\x00\x00\x0f\xb7x\x02\xffShH\x89\xefA\xff\xd4H\x8b\x03[]A\\\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x11$\r&\xa3 \x01"\xff', # -march=armv6m - 0x1006: b"M\x06\x10\x1f\x02\x004build/features0.native.mpy\x00\x12factorial\x00\x88\x02\x18\xe0\x00\x00\x10\xb5\tK\tJ{D\x9cX\x02!\xe3h\x98G\x03\x00\x01 \x00+\x02\xd0XC\x01;\xfa\xe7\x02!#i\x98G\x10\xbd\xc0Fj\x00\x00\x00\x00\x00\x00\x00\xf8\xb5\nN\nK~D\xf4XChgiXh\xb8G\x05\x00\x07K\x08I\xf3XyDX\x88ck\x98G(\x00\xb8G h\xf8\xbd\xc0F:\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x11<\r>\xa38\x01:\xff", + 0x1006: b"M\x06\x11\x1f\x02\x004build/features0.native.mpy\x00\x12factorial\x00\x88\x02\x18\xe0\x00\x00\x10\xb5\tK\tJ{D\x9cX\x02!\xe3h\x98G\x03\x00\x01 \x00+\x02\xd0XC\x01;\xfa\xe7\x02!#i\x98G\x10\xbd\xc0Fj\x00\x00\x00\x00\x00\x00\x00\xf8\xb5\nN\nK~D\xf4XChgiXh\xb8G\x05\x00\x07K\x08I\xf3XyDX\x88ck\x98G(\x00\xb8G h\xf8\xbd\xc0F:\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x11<\r>\xa38\x01:\xff", } # Populate armv7m-derived archs based on armv6m. for arch in (0x1406, 0x1806, 0x1C06, 0x2006): features0_file_contents[arch] = features0_file_contents[0x1006] -if sys.implementation._mpy not in features0_file_contents: +# Check that a .mpy exists for the target (ignore sub-version in lookup). +sys_implementation_mpy = sys.implementation._mpy & ~(3 << 8) +if sys_implementation_mpy not in features0_file_contents: print("SKIP") raise SystemExit # These are the test .mpy files. -user_files = {"/features0.mpy": features0_file_contents[sys.implementation._mpy]} +user_files = {"/features0.mpy": features0_file_contents[sys_implementation_mpy]} # Create and mount a user filesystem. uos.mount(UserFS(user_files), "/userfs") diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 31212fd5bd..8b644c137f 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -88,6 +88,7 @@ class FreezeError(Exception): class Config: MPY_VERSION = 6 + MPY_SUB_VERSION = 1 MICROPY_LONGINT_IMPL_NONE = 0 MICROPY_LONGINT_IMPL_LONGLONG = 1 MICROPY_LONGINT_IMPL_MPZ = 2 @@ -1335,6 +1336,9 @@ def read_mpy(filename): feature_byte = header[2] mpy_native_arch = feature_byte >> 2 if mpy_native_arch != MP_NATIVE_ARCH_NONE: + mpy_sub_version = feature_byte & 3 + if mpy_sub_version != config.MPY_SUB_VERSION: + raise MPYReadError(filename, "incompatible .mpy sub-version") if config.native_arch == MP_NATIVE_ARCH_NONE: config.native_arch = mpy_native_arch elif config.native_arch != mpy_native_arch: @@ -1658,7 +1662,9 @@ def merge_mpy(compiled_modules, output_file): else: main_cm_idx = None for idx, cm in enumerate(compiled_modules): - if cm.header[2]: + feature_byte = cm.header[2] + mpy_native_arch = feature_byte >> 2 + if mpy_native_arch: # Must use qstr_table and obj_table from this raw_code if main_cm_idx is not None: raise Exception("can't merge files when more than one contains native code") @@ -1670,7 +1676,7 @@ def merge_mpy(compiled_modules, output_file): header = bytearray(4) header[0] = ord("M") header[1] = config.MPY_VERSION - header[2] = config.native_arch << 2 + header[2] = config.native_arch << 2 | config.MPY_SUB_VERSION header[3] = config.mp_small_int_bits merged_mpy.extend(header) diff --git a/tools/mpy_ld.py b/tools/mpy_ld.py index 09ea90dcd1..05e70709ad 100755 --- a/tools/mpy_ld.py +++ b/tools/mpy_ld.py @@ -36,6 +36,7 @@ import makeqstrdata as qstrutil # MicroPython constants MPY_VERSION = 6 +MPY_SUB_VERSION = 1 MP_CODE_BYTECODE = 2 MP_CODE_NATIVE_VIPER = 4 MP_NATIVE_ARCH_X86 = 1 @@ -917,7 +918,11 @@ def build_mpy(env, entry_offset, fmpy, native_qstr_vals, native_qstr_objs): out.open(fmpy) # MPY: header - out.write_bytes(bytearray([ord("M"), MPY_VERSION, env.arch.mpy_feature, MP_SMALL_INT_BITS])) + out.write_bytes( + bytearray( + [ord("M"), MPY_VERSION, env.arch.mpy_feature | MPY_SUB_VERSION, MP_SMALL_INT_BITS] + ) + ) # MPY: n_qstr out.write_uint(1 + len(native_qstr_vals)) From 15d0615d5cad430930d160a8ca3e809d7b82da32 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 13 Sep 2022 14:16:58 +1000 Subject: [PATCH 0430/1041] py/objmodule: Add support for __dict__. This matches class `__dict__`, and is similarly gated on MICROPY_CPYTHON_COMPAT. Unlike class though, because modules's globals are actually dict instances, the result is a mutable dictionary. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared --- py/objmodule.c | 4 ++++ tests/basics/module_dict.py | 13 +++++++++++++ tests/import/module_dict.py | 17 +++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 tests/basics/module_dict.py create mode 100644 tests/import/module_dict.py diff --git a/py/objmodule.c b/py/objmodule.c index d14a59b863..63e9fa4757 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -89,6 +89,10 @@ STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP); if (elem != NULL) { dest[0] = elem->value; + #if MICROPY_CPYTHON_COMPAT + } else if (attr == MP_QSTR___dict__) { + dest[0] = MP_OBJ_FROM_PTR(self->globals); + #endif #if MICROPY_MODULE_GETATTR } else if (attr != MP_QSTR___getattr__) { elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___getattr__), MP_MAP_LOOKUP); diff --git a/tests/basics/module_dict.py b/tests/basics/module_dict.py new file mode 100644 index 0000000000..c847294f08 --- /dev/null +++ b/tests/basics/module_dict.py @@ -0,0 +1,13 @@ +# test __dict__ attribute of a built-in module +# see import/module_dict.py for the equivalent test on user modules + +import sys + +if not hasattr(sys, "__dict__"): + print("SKIP") + raise SystemExit + + +# dict of a built-in module (read-only) +print(type(sys.__dict__)) +print(sys.__dict__["__name__"]) diff --git a/tests/import/module_dict.py b/tests/import/module_dict.py new file mode 100644 index 0000000000..431d80b3b4 --- /dev/null +++ b/tests/import/module_dict.py @@ -0,0 +1,17 @@ +# test __dict__ attribute of a user module + +import sys + +if not hasattr(sys, "__dict__"): + print("SKIP") + raise SystemExit + + +import import1b + +# dict of a user module (read/write) +print(import1b.var) +print(import1b.__dict__["var"]) +import1b.__dict__["var"] = "hello" +print(import1b.var) +print(import1b.__dict__["var"]) From cc588ac3a91a16807242347e8b182d4bc8b7f139 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 19 Sep 2022 10:35:12 +1000 Subject: [PATCH 0431/1041] py/runtime: Add mp_raise_OSError_with_filename helper function. Useful when more detail is needed for an OSError associated with a file. Signed-off-by: Damien George --- py/runtime.c | 9 +++++++++ py/runtime.h | 1 + 2 files changed, 10 insertions(+) diff --git a/py/runtime.c b/py/runtime.c index da6c86d971..23fae6041d 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1692,6 +1692,15 @@ NORETURN void mp_raise_OSError(int errno_) { mp_raise_type_arg(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno_)); } +NORETURN void mp_raise_OSError_with_filename(int errno_, const char *filename) { + vstr_t vstr; + vstr_init(&vstr, 32); + vstr_printf(&vstr, "can't open %s", filename); + mp_obj_t o_str = mp_obj_new_str_from_vstr(&vstr); + mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(errno_), MP_OBJ_FROM_PTR(o_str)}; + nlr_raise(mp_obj_exception_make_new(&mp_type_OSError, 2, 0, args)); +} + #if MICROPY_STACK_CHECK || MICROPY_ENABLE_PYSTACK NORETURN void mp_raise_recursion_depth(void) { mp_raise_type_arg(&mp_type_RuntimeError, MP_OBJ_NEW_QSTR(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded)); diff --git a/py/runtime.h b/py/runtime.h index 779b66f2bd..36b3caa6c7 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -196,6 +196,7 @@ NORETURN void mp_raise_NotImplementedError(mp_rom_error_text_t msg); NORETURN void mp_raise_type_arg(const mp_obj_type_t *exc_type, mp_obj_t arg); NORETURN void mp_raise_StopIteration(mp_obj_t arg); NORETURN void mp_raise_OSError(int errno_); +NORETURN void mp_raise_OSError_with_filename(int errno_, const char *filename); NORETURN void mp_raise_recursion_depth(void); #if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG From fb77be150636090d69460578ed8458d84db02614 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 19 Sep 2022 10:36:17 +1000 Subject: [PATCH 0432/1041] py: Include filename in errors from loading/saving files via "open". This improves error messages in mpy-cross: - When loading a .py file that doesn't exist (or can't be opened) it now includes the filename in the OSError. - When saving a .mpy file that can't be opened it now raises an exception (prior, it would silently fail), and includes the filename in the OSError. Signed-off-by: Damien George --- py/persistentcode.c | 3 +++ py/reader.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/py/persistentcode.c b/py/persistentcode.c index de84c17359..67c8f327f0 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -644,6 +644,9 @@ void mp_raw_code_save_file(mp_compiled_module_t *cm, const char *filename) { MP_THREAD_GIL_EXIT(); int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); MP_THREAD_GIL_ENTER(); + if (fd < 0) { + mp_raise_OSError_with_filename(errno, filename); + } mp_print_t fd_print = {(void *)(intptr_t)fd, fd_print_strn}; mp_raw_code_save(cm, &fd_print); MP_THREAD_GIL_EXIT(); diff --git a/py/reader.c b/py/reader.c index d68406b1c6..57b12b3b65 100644 --- a/py/reader.c +++ b/py/reader.c @@ -139,7 +139,7 @@ void mp_reader_new_file(mp_reader_t *reader, const char *filename) { int fd = open(filename, O_RDONLY, 0644); MP_THREAD_GIL_ENTER(); if (fd < 0) { - mp_raise_OSError(errno); + mp_raise_OSError_with_filename(errno, filename); } mp_reader_new_file_from_fd(reader, fd, true); } From 9ae8d3820474a9525d707b1e19f7703721aec1c8 Mon Sep 17 00:00:00 2001 From: stijn Date: Mon, 12 Sep 2022 14:45:39 +0200 Subject: [PATCH 0433/1041] extmod/vfs_posix_file: Implement finaliser for files. Prevent handle leaks when file objects aren't closed explicitly and fix some MICROPY_CPYTHON_COMPAT issues: this wasn't properly adhered to because #ifdef was used so it was always on, and closing files multiple times should be avoided unconditionally. --- extmod/vfs_posix_file.c | 15 ++++++++------- tests/extmod/vfs_posix.py | 29 +++++++++++++++++++++++++++++ tests/extmod/vfs_posix.py.exp | 1 + 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index 4a37489686..ea19de7fd0 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -46,7 +46,7 @@ typedef struct _mp_obj_vfs_posix_file_t { int fd; } mp_obj_vfs_posix_file_t; -#ifdef MICROPY_CPYTHON_COMPAT +#if MICROPY_CPYTHON_COMPAT STATIC void check_fd_is_open(const mp_obj_vfs_posix_file_t *o) { if (o->fd < 0) { mp_raise_ValueError(MP_ERROR_TEXT("I/O operation on closed file")); @@ -63,7 +63,7 @@ STATIC void vfs_posix_file_print(const mp_print_t *print, mp_obj_t self_in, mp_p } mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_obj_t mode_in) { - mp_obj_vfs_posix_file_t *o = m_new_obj(mp_obj_vfs_posix_file_t); + mp_obj_vfs_posix_file_t *o = m_new_obj_with_finaliser(mp_obj_vfs_posix_file_t); const char *mode_s = mp_obj_str_get_str(mode_in); int mode_rw = 0, mode_x = 0; @@ -185,12 +185,12 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_ return 0; } case MP_STREAM_CLOSE: - MP_THREAD_GIL_EXIT(); - close(o->fd); - MP_THREAD_GIL_ENTER(); - #ifdef MICROPY_CPYTHON_COMPAT + if (o->fd >= 0) { + MP_THREAD_GIL_EXIT(); + close(o->fd); + MP_THREAD_GIL_ENTER(); + } o->fd = -1; - #endif return 0; case MP_STREAM_GET_FILENO: return o->fd; @@ -237,6 +237,7 @@ STATIC const mp_rom_map_elem_t vfs_posix_rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) }, { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&vfs_posix_file___exit___obj) }, }; diff --git a/tests/extmod/vfs_posix.py b/tests/extmod/vfs_posix.py index d193236696..3c23140065 100644 --- a/tests/extmod/vfs_posix.py +++ b/tests/extmod/vfs_posix.py @@ -1,6 +1,7 @@ # Test for VfsPosix try: + import gc import uos uos.VfsPosix @@ -51,6 +52,34 @@ f = open(temp_dir + "/test", "r") print(f.read()) f.close() +# file finaliser, also see vfs_fat_finaliser.py +names = [temp_dir + "/x%d" % i for i in range(4)] +basefd = temp_dir + "/nextfd1" +nextfd = temp_dir + "/nextfd2" + +with open(basefd, "w") as f: + base_file_no = f.fileno() + +for i in range(1024): # move GC head forwards by allocating a lot of single blocks + [] + + +def write_files_without_closing(): + for n in names: + open(n, "w").write(n) + sorted(list(range(128)), key=lambda x: x) # use up Python and C stack so f is really gone + + +write_files_without_closing() +gc.collect() + +with open(nextfd, "w") as f: + next_file_no = f.fileno() + print("next_file_no <= base_file_no", next_file_no <= base_file_no) + +for n in names + [basefd, nextfd]: + uos.remove(n) + # rename uos.rename(temp_dir + "/test", temp_dir + "/test2") print(uos.listdir(temp_dir)) diff --git a/tests/extmod/vfs_posix.py.exp b/tests/extmod/vfs_posix.py.exp index eb9ab43106..99922e621d 100644 --- a/tests/extmod/vfs_posix.py.exp +++ b/tests/extmod/vfs_posix.py.exp @@ -4,6 +4,7 @@ True hello +next_file_no <= base_file_no True ['test2'] ['test2'] From 6ecdf1a240e43bd60c824c7efd575c0a82d02d7e Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 19 Sep 2022 12:03:38 +1000 Subject: [PATCH 0434/1041] tests/frozen: Move frozentest.mpy from ports/ to tests/. frozentest.mpy was previously duplicated in ports/minimal and ports/powerpc. This needs to be re-generated on every .mpy version increase, so might as well just have a single copy of it. Signed-off-by: Jim Mussared --- ports/minimal/Makefile | 2 +- ports/powerpc/Makefile | 2 +- ports/powerpc/frozentest.mpy | Bin 196 -> 0 bytes ports/powerpc/frozentest.py | 7 ------- tests/frozen/README.md | 2 ++ {ports/minimal => tests/frozen}/frozentest.mpy | Bin {ports/minimal => tests/frozen}/frozentest.py | 0 tools/ci.sh | 4 ++-- 8 files changed, 6 insertions(+), 11 deletions(-) delete mode 100644 ports/powerpc/frozentest.mpy delete mode 100644 ports/powerpc/frozentest.py create mode 100644 tests/frozen/README.md rename {ports/minimal => tests/frozen}/frozentest.mpy (100%) rename {ports/minimal => tests/frozen}/frozentest.py (100%) diff --git a/ports/minimal/Makefile b/ports/minimal/Makefile index 5ba6514c9e..0e875cc249 100644 --- a/ports/minimal/Makefile +++ b/ports/minimal/Makefile @@ -81,7 +81,7 @@ else all: $(BUILD)/firmware.elf endif -$(BUILD)/_frozen_mpy.c: frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h +$(BUILD)/_frozen_mpy.c: $(TOP)/tests/frozen/frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h $(ECHO) "MISC freezing bytecode" $(Q)$(TOP)/tools/mpy-tool.py -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h -mlongint-impl=none $< > $@ diff --git a/ports/powerpc/Makefile b/ports/powerpc/Makefile index 12ae485bb8..0986fd13eb 100644 --- a/ports/powerpc/Makefile +++ b/ports/powerpc/Makefile @@ -50,7 +50,7 @@ OBJ += $(BUILD)/head.o all: $(BUILD)/firmware.elf $(BUILD)/firmware.map $(BUILD)/firmware.bin -$(BUILD)/_frozen_mpy.c: frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h +$(BUILD)/_frozen_mpy.c: $(TOP)/tests/frozen/frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h $(ECHO) "MISC freezing bytecode" $(Q)$(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h -mlongint-impl=mpz $< > $@ diff --git a/ports/powerpc/frozentest.mpy b/ports/powerpc/frozentest.mpy deleted file mode 100644 index 99581617ac3d13e416722a63852da14088ff8db7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 196 zcmeZeW0GfOmP#wiuS(4;Ni8nXE2w1PZ!Bjk4X9*b%4A?wN>s?n&r4S*E-A_cQY9IQ zB?_6v3VHcJ3aFtdFExdMRV@)kJ|nSMp)@ZuIX@*;;oQb^o6c=kNX|$sDrR8gPO1c2 zqF`ubY{JOUVj#fBs15{LYJyAx%qEPHf=tQ`5Q-5(F@Y(iUGHa!0$B}CKH*|4f=q%e QKu+V+@RsY&`jLUj0I@qak^lez diff --git a/ports/powerpc/frozentest.py b/ports/powerpc/frozentest.py deleted file mode 100644 index 78cdd60bf0..0000000000 --- a/ports/powerpc/frozentest.py +++ /dev/null @@ -1,7 +0,0 @@ -print("uPy") -print("a long string that is not interned") -print("a string that has unicode αβγ chars") -print(b"bytes 1234\x01") -print(123456789) -for i in range(4): - print(i) diff --git a/tests/frozen/README.md b/tests/frozen/README.md new file mode 100644 index 0000000000..bd786d5a3c --- /dev/null +++ b/tests/frozen/README.md @@ -0,0 +1,2 @@ +This is a .mpy built against the current .mpy version that can be used to test +freezing without a dependency on mpy-cross. diff --git a/ports/minimal/frozentest.mpy b/tests/frozen/frozentest.mpy similarity index 100% rename from ports/minimal/frozentest.mpy rename to tests/frozen/frozentest.mpy diff --git a/ports/minimal/frozentest.py b/tests/frozen/frozentest.py similarity index 100% rename from ports/minimal/frozentest.py rename to tests/frozen/frozentest.py diff --git a/tools/ci.sh b/tools/ci.sh index 9c670b7be5..9963f7796c 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -75,8 +75,8 @@ function ci_mpy_format_setup { function ci_mpy_format_test { # Test mpy-tool.py dump feature on bytecode - python2 ./tools/mpy-tool.py -xd ports/minimal/frozentest.mpy - python3 ./tools/mpy-tool.py -xd ports/minimal/frozentest.mpy + python2 ./tools/mpy-tool.py -xd tests/frozen/frozentest.mpy + python3 ./tools/mpy-tool.py -xd tests/frozen/frozentest.mpy # Test mpy-tool.py dump feature on native code make -C examples/natmod/features1 From 920da9c5e30da58d5f77b2c5e28c74e3670e6a3b Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 19 Sep 2022 12:05:39 +1000 Subject: [PATCH 0435/1041] unix/variants/coverage: Add test for manifest freeze_mpy(). This uses the frozentest.mpy that is also used by ports/minimal. Also fixes two bugs that these new tests picked up: - File extension matching in manifestfile.py. - Handling of freeze_mpy results in makemanifest. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared --- ports/unix/variants/coverage/manifest.py | 1 + tests/unix/extra_coverage.py | 5 +++++ tests/unix/extra_coverage.py.exp | 10 ++++++++++ tools/makemanifest.py | 6 +++--- tools/manifestfile.py | 17 +++++++++++++---- 5 files changed, 32 insertions(+), 7 deletions(-) diff --git a/ports/unix/variants/coverage/manifest.py b/ports/unix/variants/coverage/manifest.py index 6111050884..7c3d9a6b64 100644 --- a/ports/unix/variants/coverage/manifest.py +++ b/ports/unix/variants/coverage/manifest.py @@ -1,2 +1,3 @@ freeze_as_str("frzstr") freeze_as_mpy("frzmpy") +freeze_mpy("$(MPY_DIR)/tests/frozen") diff --git a/tests/unix/extra_coverage.py b/tests/unix/extra_coverage.py index bb22485026..00226a68e6 100644 --- a/tests/unix/extra_coverage.py +++ b/tests/unix/extra_coverage.py @@ -96,3 +96,8 @@ import frzmpy3 from frzqstr import returns_NULL print(returns_NULL()) + +# test for freeze_mpy +import frozentest + +print(frozentest.__file__) diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index 4d6e1e0856..2941154556 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -199,3 +199,13 @@ X '\x1b' b'\x00\xff' NULL +uPy +a long string that is not interned +a string that has unicode αβγ chars +b'bytes 1234\x01' +123456789 +0 +1 +2 +3 +frozentest.py diff --git a/tools/makemanifest.py b/tools/makemanifest.py index 9dd8815aac..b2e4f7d844 100644 --- a/tools/makemanifest.py +++ b/tools/makemanifest.py @@ -210,9 +210,9 @@ def main(): ts_outfile = get_timestamp(outfile) mpy_files.append(outfile) else: - assert kind == manifestfile.KIND_FREEZE_MPY - mpy_files.append(full_path) - ts_outfile = timestamp + assert result.kind == manifestfile.KIND_FREEZE_MPY + mpy_files.append(result.full_path) + ts_outfile = result.timestamp ts_newest = max(ts_newest, ts_outfile) # Check if output file needs generating diff --git a/tools/manifestfile.py b/tools/manifestfile.py index 84c79ed82b..a4d056137f 100644 --- a/tools/manifestfile.py +++ b/tools/manifestfile.py @@ -394,28 +394,37 @@ class ManifestFile: `opt` is the optimisation level to pass to mpy-cross when compiling .py to .mpy. """ - self._freeze_internal(path, script, exts=(".py", ".mpy"), kind=KIND_FREEZE_AUTO, opt=opt) + self._freeze_internal( + path, + script, + exts=( + ".py", + ".mpy", + ), + kind=KIND_FREEZE_AUTO, + opt=opt, + ) def freeze_as_str(self, path): """ Freeze the given `path` and all .py scripts within it as a string, which will be compiled upon import. """ - self._search(path, None, None, exts=(".py"), kind=KIND_FREEZE_AS_STR) + self._search(path, None, None, exts=(".py",), kind=KIND_FREEZE_AS_STR) def freeze_as_mpy(self, path, script=None, opt=None): """ Freeze the input (see above) by first compiling the .py scripts to .mpy files, then freezing the resulting .mpy files. """ - self._freeze_internal(path, script, exts=(".py"), kind=KIND_FREEZE_AS_MPY, opt=opt) + self._freeze_internal(path, script, exts=(".py",), kind=KIND_FREEZE_AS_MPY, opt=opt) def freeze_mpy(self, path, script=None, opt=None): """ Freeze the input (see above), which must be .mpy files that are frozen directly. """ - self._freeze_internal(path, script, exts=(".mpy"), kind=KIND_FREEZE_MPY, opt=opt) + self._freeze_internal(path, script, exts=(".mpy",), kind=KIND_FREEZE_MPY, opt=opt) # Generate a temporary file with a line appended to the end that adds __version__. From 7589d86b6b6ea4232ff5614f3e73565529d4b3bb Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Tue, 20 Sep 2022 08:54:53 +1000 Subject: [PATCH 0436/1041] tests/run-multitests: Extend usage information. --- tests/run-multitests.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/run-multitests.py b/tests/run-multitests.py index bd6cc70f7a..b5ba83b0ad 100755 --- a/tests/run-multitests.py +++ b/tests/run-multitests.py @@ -3,6 +3,11 @@ # This file is part of the MicroPython project, http://micropython.org/ # The MIT License (MIT) # Copyright (c) 2020 Damien P. George +# +# run-multitests.py +# Runs a test suite that relies on two micropython instances/devices +# interacting in some way. Typically used to test networking / bluetooth etc. + import sys, os, time, re, select import argparse @@ -471,7 +476,10 @@ def run_tests(test_files, instances_truth, instances_test): def main(): global cmd_args - cmd_parser = argparse.ArgumentParser(description="Run network tests for MicroPython") + cmd_parser = argparse.ArgumentParser( + description="Run network tests for MicroPython", + formatter_class=argparse.RawTextHelpFormatter, + ) cmd_parser.add_argument( "-s", "--show-output", action="store_true", help="show test output after running" ) @@ -488,6 +496,14 @@ def main(): default=1, help="repeat the test with this many permutations of the instance order", ) + cmd_parser.epilog = ( + "Supported instance types:\r\n" + " -i pyb: physical device (eg. pyboard) on provided repl port.\n" + " -i micropython unix micropython instance, path customised with MICROPY_MICROPYTHON env.\n" + " -i cpython desktop python3 instance, path customised with MICROPY_CPYTHON3 env.\n" + " -i exec: custom program run on provided path.\n" + "Each instance arg can optionally have custom env provided, eg. ,ENV=VAR,ENV=VAR...\n" + ) cmd_parser.add_argument("files", nargs="+", help="input test files") cmd_args = cmd_parser.parse_args() From 13c4470fd04981fce3fd29771e1d973febbe7d60 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Tue, 20 Sep 2022 08:54:58 +1000 Subject: [PATCH 0437/1041] tests/run-multitests: Make paths more deterministic. Allows running from a different directory, etc. This work was funded by Planet Innovation. --- tests/run-multitests.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/run-multitests.py b/tests/run-multitests.py index b5ba83b0ad..70bae59474 100755 --- a/tests/run-multitests.py +++ b/tests/run-multitests.py @@ -15,15 +15,24 @@ import itertools import subprocess import tempfile -sys.path.append("../tools") +test_dir = os.path.abspath(os.path.dirname(__file__)) + +if os.path.abspath(sys.path[0]) == test_dir: + # remove the micropython/tests dir from path to avoid + # accidentally importing tests like micropython/const.py + sys.path.pop(0) + +sys.path.insert(0, test_dir + "/../tools") import pyboard if os.name == "nt": CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3.exe") - MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/windows/micropython.exe") + MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", test_dir + "/../ports/windows/micropython.exe") else: CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") - MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/build-standard/micropython") + MICROPYTHON = os.getenv( + "MICROPY_MICROPYTHON", test_dir + "/../ports/unix/build-standard/micropython" + ) # For diff'ing test output DIFF = os.getenv("MICROPY_DIFF", "diff -u") @@ -508,7 +517,7 @@ def main(): cmd_args = cmd_parser.parse_args() # clear search path to make sure tests use only builtin modules and those in extmod - os.environ["MICROPYPATH"] = os.pathsep + "../extmod" + os.environ["MICROPYPATH"] = os.pathsep.join(("", ".frozen", "../extmod")) test_files = prepare_test_file_list(cmd_args.files) max_instances = max(t[1] for t in test_files) From ed41d517466f329112529a20f9808f1c1724f759 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 22 Sep 2022 11:47:03 +1000 Subject: [PATCH 0438/1041] extmod/modbluetooth: Change data_len type from size_t to uint16_t. For consistency, and to remove the need for additional conversion of types. Signed-off-by: Damien George --- extmod/modbluetooth.c | 16 ++++++++-------- extmod/modbluetooth.h | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 9c168483ba..f021308187 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -1139,7 +1139,7 @@ STATIC mp_obj_t invoke_irq_handler_run(uint16_t event, const mp_int_t *numeric, size_t n_unsigned, size_t n_signed, const uint8_t *addr, const mp_obj_bluetooth_uuid_t *uuid, - const uint8_t **data, size_t *data_len, size_t n_data) { + const uint8_t **data, uint16_t *data_len, size_t n_data) { mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); if (o->irq_handler == mp_const_none) { return mp_const_none; @@ -1199,7 +1199,7 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event, const mp_int_t *numeric, size_t n_unsigned, size_t n_signed, const uint8_t *addr, const mp_obj_bluetooth_uuid_t *uuid, - const uint8_t **data, size_t *data_len, size_t n_data) { + const uint8_t **data, uint16_t *data_len, size_t n_data) { // This code may run on an existing MicroPython thread, or a non-MicroPython thread // that's not using the mp_thread_get_state() value. In the former case the state @@ -1249,7 +1249,7 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event, const mp_int_t *numeric, size_t n_unsigned, size_t n_signed, const uint8_t *addr, const mp_obj_bluetooth_uuid_t *uuid, - const uint8_t **data, size_t *data_len, size_t n_data) { + const uint8_t **data, uint16_t *data_len, size_t n_data) { return invoke_irq_handler_run(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data); } @@ -1277,7 +1277,7 @@ void mp_bluetooth_gatts_on_encryption_update(uint16_t conn_handle, bool encrypte invoke_irq_handler(MP_BLUETOOTH_IRQ_ENCRYPTION_UPDATE, args, 5, 0, NULL_ADDR, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0); } -bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *key, size_t key_len, const uint8_t **value, size_t *value_len) { +bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *key, uint16_t key_len, const uint8_t **value, size_t *value_len) { mp_int_t args[] = {type, index}; mp_obj_t result = invoke_irq_handler(MP_BLUETOOTH_IRQ_GET_SECRET, args, 2, 0, NULL_ADDR, NULL_UUID, &key, &key_len, 1); if (result == mp_const_none) { @@ -1293,7 +1293,7 @@ bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t * bool mp_bluetooth_gap_on_set_secret(uint8_t type, const uint8_t *key, size_t key_len, const uint8_t *value, size_t value_len) { mp_int_t args[] = { type }; const uint8_t *data[] = {key, value}; - size_t data_len[] = {key_len, value_len}; + uint16_t data_len[] = {key_len, value_len}; mp_obj_t result = invoke_irq_handler(MP_BLUETOOTH_IRQ_SET_SECRET, args, 1, 0, NULL_ADDR, NULL_UUID, data, data_len, 2); return mp_obj_is_true(result); } @@ -1364,7 +1364,7 @@ void mp_bluetooth_gap_on_scan_complete(void) { invoke_irq_handler(MP_BLUETOOTH_IRQ_SCAN_DONE, NULL_NUMERIC, 0, 0, NULL_ADDR, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0); } -void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, size_t data_len) { +void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, uint16_t data_len) { mp_int_t args[] = {addr_type, adv_type, rssi}; invoke_irq_handler(MP_BLUETOOTH_IRQ_SCAN_RESULT, args, 1, 2, addr, NULL_UUID, &data, &data_len, 1); } @@ -1394,7 +1394,7 @@ void mp_bluetooth_gattc_on_discover_complete(uint8_t event, uint16_t conn_handle void mp_bluetooth_gattc_on_data_available(uint8_t event, uint16_t conn_handle, uint16_t value_handle, const uint8_t **data, uint16_t *data_len, size_t num) { const uint8_t *combined_data; - size_t total_len; + uint16_t total_len; if (num > 1) { // Fragmented buffer, need to combine into a new heap-allocated buffer @@ -1553,7 +1553,7 @@ void mp_bluetooth_gap_on_scan_complete(void) { schedule_ringbuf(atomic_state); } -void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, size_t data_len) { +void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, uint16_t data_len) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); data_len = MIN(o->irq_data_data_alloc, data_len); diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index d490346278..ca6436b678 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -426,7 +426,7 @@ void mp_bluetooth_gatts_on_encryption_update(uint16_t conn_handle, bool encrypte // For get, if key is NULL, then the implementation must return the index'th matching key. Otherwise it should return a specific key. // For set, if value is NULL, then delete. // The "type" is stack-specific, but could also be used to implement versioning. -bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *key, size_t key_len, const uint8_t **value, size_t *value_len); +bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *key, uint16_t key_len, const uint8_t **value, size_t *value_len); bool mp_bluetooth_gap_on_set_secret(uint8_t type, const uint8_t *key, size_t key_len, const uint8_t *value, size_t value_len); // Call this when a passkey verification needs to be processed. @@ -451,7 +451,7 @@ void mp_bluetooth_gatts_on_mtu_exchanged(uint16_t conn_handle, uint16_t value); void mp_bluetooth_gap_on_scan_complete(void); // Notify modbluetooth of a scan result. -void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, size_t data_len); +void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, uint16_t data_len); #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE #if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT From db668742a5986ab1de9c0474ef268c00fb1879e7 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 21 Sep 2022 13:22:27 +1000 Subject: [PATCH 0439/1041] extmod/modbluetooth: Do GATTC reassembly in protected uPy context. The calls to m_new and m_del require an exclusive uPy (really a GC) context. In particular these functions cannot be called directly from a FreeRTOS task on esp32. Fixes issue #9369. Signed-off-by: Damien George --- extmod/modbluetooth.c | 67 +++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index f021308187..acdbf8d85d 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -52,6 +52,9 @@ #error pairing and bonding require synchronous modbluetooth events #endif +// NimBLE can have fragmented data for GATTC events, so requires reassembly. +#define MICROPY_PY_BLUETOOTH_USE_GATTC_EVENT_DATA_REASSEMBLY MICROPY_BLUETOOTH_NIMBLE + #define MP_BLUETOOTH_CONNECT_DEFAULT_SCAN_DURATION_MS 2000 #define MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN 5 @@ -1168,6 +1171,34 @@ STATIC mp_obj_t invoke_irq_handler_run(uint16_t event, data_tuple->items[data_tuple->len++] = MP_OBJ_FROM_PTR(uuid); } #endif + + #if MICROPY_PY_BLUETOOTH_USE_GATTC_EVENT_DATA_REASSEMBLY + void *buf_to_free = NULL; + uint16_t buf_to_free_len = 0; + if (event == MP_BLUETOOTH_IRQ_GATTC_NOTIFY || event == MP_BLUETOOTH_IRQ_GATTC_INDICATE || event == MP_BLUETOOTH_IRQ_GATTC_READ_RESULT) { + if (n_data > 1) { + // Fragmented buffer, need to combine into a new heap-allocated buffer + // in order to pass to Python. + // Only gattc_on_data_available calls this code, so data and data_len are writable. + uint16_t total_len = 0; + for (size_t i = 0; i < n_data; ++i) { + total_len += data_len[i]; + } + uint8_t *buf = m_new(uint8_t, total_len); + uint8_t *p = buf; + for (size_t i = 0; i < n_data; ++i) { + memcpy(p, data[i], data_len[i]); + p += data_len[i]; + } + data[0] = buf; + data_len[0] = total_len; + n_data = 1; + buf_to_free = buf; + buf_to_free_len = total_len; + } + } + #endif + for (size_t i = 0; i < n_data; ++i) { if (data[i]) { mp_obj_memoryview_init(&mv_data[i], 'B', 0, data_len[i], (void *)data[i]); @@ -1176,10 +1207,17 @@ STATIC mp_obj_t invoke_irq_handler_run(uint16_t event, data_tuple->items[data_tuple->len++] = mp_const_none; } } + assert(data_tuple->len <= MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN); mp_obj_t result = mp_call_function_2(o->irq_handler, MP_OBJ_NEW_SMALL_INT(event), MP_OBJ_FROM_PTR(data_tuple)); + #if MICROPY_PY_BLUETOOTH_USE_GATTC_EVENT_DATA_REASSEMBLY + if (buf_to_free != NULL) { + m_del(uint8_t, (uint8_t *)buf_to_free, buf_to_free_len); + } + #endif + mp_local_free(data_tuple); return result; @@ -1393,35 +1431,8 @@ void mp_bluetooth_gattc_on_discover_complete(uint8_t event, uint16_t conn_handle } void mp_bluetooth_gattc_on_data_available(uint8_t event, uint16_t conn_handle, uint16_t value_handle, const uint8_t **data, uint16_t *data_len, size_t num) { - const uint8_t *combined_data; - uint16_t total_len; - - if (num > 1) { - // Fragmented buffer, need to combine into a new heap-allocated buffer - // in order to pass to Python. - total_len = 0; - for (size_t i = 0; i < num; ++i) { - total_len += data_len[i]; - } - uint8_t *buf = m_new(uint8_t, total_len); - uint8_t *p = buf; - for (size_t i = 0; i < num; ++i) { - memcpy(p, data[i], data_len[i]); - p += data_len[i]; - } - combined_data = buf; - } else { - // Single buffer, use directly. - combined_data = *data; - total_len = *data_len; - } - mp_int_t args[] = {conn_handle, value_handle}; - invoke_irq_handler(event, args, 2, 0, NULL_ADDR, NULL_UUID, &combined_data, &total_len, 1); - - if (num > 1) { - m_del(uint8_t, (uint8_t *)combined_data, total_len); - } + invoke_irq_handler(event, args, 2, 0, NULL_ADDR, NULL_UUID, data, data_len, num); } void mp_bluetooth_gattc_on_read_write_status(uint8_t event, uint16_t conn_handle, uint16_t value_handle, uint16_t status) { From f2ad152e7e04608cbf57d756f6a4cebbf9976f6c Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 23 Sep 2022 14:20:37 +1000 Subject: [PATCH 0440/1041] extmod/modbluetooth: Run BLE IRQ callback in protected NLR context. The call to invoke_irq_handler_run() always needs to run in a protected NLR context, to catch exceptions from the Python handler, and the m_new's (and also mp_local_alloc when PYSTACK is enabled). With MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS_WITH_INTERLOCK enabled there was already an explicit nlr_push, and that is now used in all cases. Without this change, on stm32 (for example), the callbacks from the BLE stack to invoke_irq_handler() were made via static scheduled nodes which do not have any NLR protection, and hence would lead to a hard fault (uncaught NLR) if an exception was raised in the Python BLE IRQ handler. This was a regression introduced by 8045ac07f599c0ccc447c88a0b778f704b497559, which is fixed by this commit. Signed-off-by: Damien George --- extmod/modbluetooth.c | 51 ++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index acdbf8d85d..3a51fb8b23 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -1143,10 +1143,6 @@ STATIC mp_obj_t invoke_irq_handler_run(uint16_t event, const uint8_t *addr, const mp_obj_bluetooth_uuid_t *uuid, const uint8_t **data, uint16_t *data_len, size_t n_data) { - mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); - if (o->irq_handler == mp_const_none) { - return mp_const_none; - } mp_obj_array_t mv_addr; mp_obj_array_t mv_data[2]; @@ -1210,6 +1206,7 @@ STATIC mp_obj_t invoke_irq_handler_run(uint16_t event, assert(data_tuple->len <= MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN); + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); mp_obj_t result = mp_call_function_2(o->irq_handler, MP_OBJ_NEW_SMALL_INT(event), MP_OBJ_FROM_PTR(data_tuple)); #if MICROPY_PY_BLUETOOTH_USE_GATTC_EVENT_DATA_REASSEMBLY @@ -1223,6 +1220,34 @@ STATIC mp_obj_t invoke_irq_handler_run(uint16_t event, return result; } +STATIC mp_obj_t invoke_irq_handler_run_protected(uint16_t event, + const mp_int_t *numeric, size_t n_unsigned, size_t n_signed, + const uint8_t *addr, + const mp_obj_bluetooth_uuid_t *uuid, + const uint8_t **data, uint16_t *data_len, size_t n_data) { + + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + if (o->irq_handler == mp_const_none) { + return mp_const_none; + } + + mp_obj_t result = mp_const_none; + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + result = invoke_irq_handler_run(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data); + nlr_pop(); + } else { + // Uncaught exception, print it out. + mp_printf(MICROPY_ERROR_PRINTER, "Unhandled exception in IRQ callback handler\n"); + mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(nlr.ret_val)); + + // Disable the BLE IRQ handler. + o->irq_handler = mp_const_none; + } + + return result; +} + #if MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS_WITH_INTERLOCK // On some systems the BLE event callbacks may occur on a system thread which is not @@ -1256,19 +1281,9 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event, MP_THREAD_GIL_ENTER(); } - mp_obj_t result = mp_const_none; - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - mp_sched_lock(); - result = invoke_irq_handler_run(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data); - mp_sched_unlock(); - nlr_pop(); - } else { - // Uncaught exception, print it out. - mp_sched_unlock(); - mp_printf(MICROPY_ERROR_PRINTER, "Unhandled exception in IRQ callback handler\n"); - mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(nlr.ret_val)); - } + mp_sched_lock(); + mp_obj_t result = invoke_irq_handler_run_protected(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data); + mp_sched_unlock(); if (ts_orig == NULL) { MP_THREAD_GIL_EXIT(); @@ -1288,7 +1303,7 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event, const uint8_t *addr, const mp_obj_bluetooth_uuid_t *uuid, const uint8_t **data, uint16_t *data_len, size_t n_data) { - return invoke_irq_handler_run(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data); + return invoke_irq_handler_run_protected(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data); } #endif From f91ebf6fa972a593ede25d33740e693d99dbbc3f Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 15 Aug 2022 12:02:23 +1000 Subject: [PATCH 0441/1041] tests: Allow 'special' tests to output "SKIP" on a single line. --- tests/run-tests.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/run-tests.py b/tests/run-tests.py index ca7941f626..6031b35b53 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -305,6 +305,10 @@ def run_micropython(pyb, args, test_file, is_special=False): if had_crash or output_mupy in (b"SKIP\n", b"CRASH"): return output_mupy + # skipped special tests will output "SKIP" surrounded by other interpreter debug output + if is_special and not had_crash and b"\nSKIP\n" in output_mupy: + return b"SKIP\n" + if is_special or test_file in special_tests: # convert parts of the output that are not stable across runs with open(test_file + ".exp", "rb") as f: From 25ff5b52d9786beff0b90a268af813b223f31f57 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 27 Jul 2022 12:52:48 +1000 Subject: [PATCH 0442/1041] py/parse: Allow const types other than int to optimise as true/false. Allows optimisation of cases like: import micropython _DEBUG = micropython.const(False) if _DEBUG: print('Debugging info') Previously the 'if' statement was only optimised out if the type of the const() argument was integer. The change is implemented in a way that makes the compiler slightly smaller (-16 bytes on PYBV11) but compilation will also be very slightly slower. As a bonus, if const support is enabled then the compiler can now optimise const truthy/falsey expressions of other types, like: while "something": pass ... unclear if that is useful, but perhaps it could be. Signed-off-by: Angus Gratton --- py/parse.c | 28 +++-- tests/cmdline/cmd_showbc_const.py | 69 +++++++++++ tests/cmdline/cmd_showbc_const.py.exp | 160 ++++++++++++++++++++++++++ 3 files changed, 247 insertions(+), 10 deletions(-) create mode 100644 tests/cmdline/cmd_showbc_const.py create mode 100644 tests/cmdline/cmd_showbc_const.py.exp diff --git a/py/parse.c b/py/parse.c index d58098af2e..62de3282b3 100644 --- a/py/parse.c +++ b/py/parse.c @@ -334,16 +334,6 @@ STATIC uint8_t peek_rule(parser_t *parser, size_t n) { } #endif -bool mp_parse_node_is_const_false(mp_parse_node_t pn) { - return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE) - || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) == 0); -} - -bool mp_parse_node_is_const_true(mp_parse_node_t pn) { - return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_TRUE) - || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) != 0); -} - bool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o) { if (MP_PARSE_NODE_IS_SMALL_INT(pn)) { *o = MP_OBJ_NEW_SMALL_INT(MP_PARSE_NODE_LEAF_SMALL_INT(pn)); @@ -427,6 +417,24 @@ STATIC mp_obj_t mp_parse_node_convert_to_obj(mp_parse_node_t pn) { } #endif +STATIC bool parse_node_is_const_bool(mp_parse_node_t pn, bool value) { + // Returns true if 'pn' is a constant whose boolean value is equivalent to 'value' + #if MICROPY_COMP_CONST_TUPLE || MICROPY_COMP_CONST + return mp_parse_node_is_const(pn) && mp_obj_is_true(mp_parse_node_convert_to_obj(pn)) == value; + #else + return MP_PARSE_NODE_IS_TOKEN_KIND(pn, value ? MP_TOKEN_KW_TRUE : MP_TOKEN_KW_FALSE) + || (MP_PARSE_NODE_IS_SMALL_INT(pn) && !!MP_PARSE_NODE_LEAF_SMALL_INT(pn) == value); + #endif +} + +bool mp_parse_node_is_const_false(mp_parse_node_t pn) { + return parse_node_is_const_bool(pn, false); +} + +bool mp_parse_node_is_const_true(mp_parse_node_t pn) { + return parse_node_is_const_bool(pn, true); +} + size_t mp_parse_node_extract_list(mp_parse_node_t *pn, size_t pn_kind, mp_parse_node_t **nodes) { if (MP_PARSE_NODE_IS_NULL(*pn)) { *nodes = NULL; diff --git a/tests/cmdline/cmd_showbc_const.py b/tests/cmdline/cmd_showbc_const.py new file mode 100644 index 0000000000..54f9ec23cd --- /dev/null +++ b/tests/cmdline/cmd_showbc_const.py @@ -0,0 +1,69 @@ +# cmdline: -v -v +# Test constant-related bytecode optimisations +# (constant folding, compile-time if/while evaluation, etc.) +from micropython import const +import sys + +try: + sys.settrace + # if MICROPY_PY_SYS_SETTRACE is enabled, compile-time const optimizations + # are disabled so the bytecode output is very different + print("SKIP") + raise SystemExit +except AttributeError: + pass + +_STR = const("foo") +_EMPTY_TUPLE = const(()) +_TRUE = const(True) +_FALSE = const(False) +_SMALLINT = const(33) +_ZERO = const(0) + +# Bytecode generated for these if/while statements should contain no JUMP_IF +# and no instances of string 'Eliminated' + +if _STR or _EMPTY_TUPLE: + print("Kept") +if _STR and _EMPTY_TUPLE: + print("Eliminated") +if _TRUE: + print("Kept") +if _SMALLINT: + print("Kept") +if _ZERO and _SMALLINT: + print("Eliminated") +if _FALSE: + print("Eliminated") + +while _SMALLINT: + print("Kept") + break +while _ZERO: + print("Eliminated") +while _FALSE: + print("Eliminated") + +# These values are stored in variables, and therefore bytecode will contain JUMP_IF + +a = _EMPTY_TUPLE or _STR +if a == _STR: + print("Kept") + +b = _SMALLINT and _STR +if b == _STR: + print("Kept") + +# The compiler is also unable to optimise these expressions, even though the arguments are const, +# so these also contain JUMP_IF + +if (_EMPTY_TUPLE or _STR) == _STR: + print("Kept") + +if (_EMPTY_TUPLE and _STR) == _STR: + print("Not Eliminated") + +if (not _STR) == _FALSE: + print("Kept") + +assert True diff --git a/tests/cmdline/cmd_showbc_const.py.exp b/tests/cmdline/cmd_showbc_const.py.exp new file mode 100644 index 0000000000..6cdc3e9c96 --- /dev/null +++ b/tests/cmdline/cmd_showbc_const.py.exp @@ -0,0 +1,160 @@ +File cmdline/cmd_showbc_const.py, code block '' (descriptor: \.\+, bytecode @\.\+ 198 bytes) +Raw bytecode (code_info_size=40, bytecode_size=158): + 2c 4c 01 60 2c 46 22 65 27 4a 83 0c 20 27 40 20 + 27 20 27 40 60 20 27 24 40 60 40 24 27 47 24 27 + 67 40 27 47 27 47 26 47 80 10 02 2a 01 1b 03 1c + 02 16 02 59 80 51 1b 04 16 04 48 0f 11 04 13 05 + 59 11 09 10 06 34 01 59 11 0a 65 57 11 0b df 44 + 43 59 4a 01 5d 11 09 10 07 34 01 59 11 09 10 07 + 34 01 59 11 09 10 07 34 01 59 11 09 10 07 34 01 + 59 42 42 42 35 23 00 16 0c 11 0c 23 00 d9 44 47 + 11 09 10 07 34 01 59 23 00 16 0d 11 0d 23 00 d9 + 44 47 11 09 10 07 34 01 59 23 00 23 00 d9 44 47 + 11 09 10 07 34 01 59 23 01 23 00 d9 44 47 11 09 + 23 02 34 01 59 50 23 03 d9 44 47 11 09 10 07 34 + 01 59 42 40 51 63 +arg names: +(N_STATE 6) +(N_EXC_STACK 1) + bc=0 line=1 + bc=0 line=4 + bc=12 line=5 + bc=18 line=7 + bc=20 line=8 + bc=25 line=11 + bc=32 line=12 + bc=42 line=14 + bc=45 line=26 + bc=45 line=27 + bc=52 line=28 + bc=52 line=30 + bc=52 line=31 + bc=59 line=32 + bc=59 line=33 + bc=66 line=34 + bc=66 line=36 + bc=66 line=39 + bc=66 line=40 + bc=73 line=41 + bc=77 line=42 + bc=77 line=44 + bc=77 line=47 + bc=77 line=49 + bc=81 line=50 + bc=88 line=51 + bc=95 line=53 + bc=99 line=54 + bc=106 line=55 + bc=113 line=58 + bc=113 line=60 + bc=120 line=61 + bc=127 line=63 + bc=134 line=64 + bc=141 line=66 + bc=147 line=67 + bc=154 line=69 +00 LOAD_CONST_SMALL_INT 0 +01 LOAD_CONST_STRING 'const' +03 BUILD_TUPLE 1 +05 IMPORT_NAME 'micropython' +07 IMPORT_FROM 'const' +09 STORE_NAME const +11 POP_TOP +12 LOAD_CONST_SMALL_INT 0 +13 LOAD_CONST_NONE +14 IMPORT_NAME 'sys' +16 STORE_NAME sys +18 SETUP_EXCEPT 35 +20 LOAD_NAME sys +22 LOAD_ATTR settrace +24 POP_TOP +25 LOAD_NAME print +27 LOAD_CONST_STRING 'SKIP' +29 CALL_FUNCTION n=1 nkw=0 +31 POP_TOP +32 LOAD_NAME SystemExit +34 RAISE_OBJ +35 DUP_TOP +36 LOAD_NAME AttributeError +38 BINARY_OP 8 +39 POP_JUMP_IF_FALSE 44 +41 POP_TOP +42 POP_EXCEPT_JUMP 45 +44 END_FINALLY +45 LOAD_NAME print +47 LOAD_CONST_STRING 'Kept' +49 CALL_FUNCTION n=1 nkw=0 +51 POP_TOP +52 LOAD_NAME print +54 LOAD_CONST_STRING 'Kept' +56 CALL_FUNCTION n=1 nkw=0 +58 POP_TOP +59 LOAD_NAME print +61 LOAD_CONST_STRING 'Kept' +63 CALL_FUNCTION n=1 nkw=0 +65 POP_TOP +66 LOAD_NAME print +68 LOAD_CONST_STRING 'Kept' +70 CALL_FUNCTION n=1 nkw=0 +72 POP_TOP +73 JUMP 77 +75 JUMP 66 +77 LOAD_CONST_OBJ \.\+='foo' +79 STORE_NAME a +81 LOAD_NAME a +83 LOAD_CONST_OBJ \.\+='foo' +85 BINARY_OP 2 __eq__ +86 POP_JUMP_IF_FALSE 95 +88 LOAD_NAME print +90 LOAD_CONST_STRING 'Kept' +92 CALL_FUNCTION n=1 nkw=0 +94 POP_TOP +95 LOAD_CONST_OBJ \.\+='foo' +97 STORE_NAME b +99 LOAD_NAME b +101 LOAD_CONST_OBJ \.\+='foo' +103 BINARY_OP 2 __eq__ +104 POP_JUMP_IF_FALSE 113 +106 LOAD_NAME print +108 LOAD_CONST_STRING 'Kept' +110 CALL_FUNCTION n=1 nkw=0 +112 POP_TOP +113 LOAD_CONST_OBJ \.\+='foo' +115 LOAD_CONST_OBJ \.\+='foo' +117 BINARY_OP 2 __eq__ +118 POP_JUMP_IF_FALSE 127 +120 LOAD_NAME print +122 LOAD_CONST_STRING 'Kept' +124 CALL_FUNCTION n=1 nkw=0 +126 POP_TOP +127 LOAD_CONST_OBJ \.\+=() +129 LOAD_CONST_OBJ \.\+='foo' +131 BINARY_OP 2 __eq__ +132 POP_JUMP_IF_FALSE 141 +134 LOAD_NAME print +136 LOAD_CONST_OBJ \.\+='Not Eliminated' +138 CALL_FUNCTION n=1 nkw=0 +140 POP_TOP +141 LOAD_CONST_FALSE +142 LOAD_CONST_OBJ \.\+=False +144 BINARY_OP 2 __eq__ +145 POP_JUMP_IF_FALSE 154 +147 LOAD_NAME print +149 LOAD_CONST_STRING 'Kept' +151 CALL_FUNCTION n=1 nkw=0 +153 POP_TOP +154 JUMP 156 +156 LOAD_CONST_NONE +157 RETURN_VALUE +Kept +Kept +Kept +Kept +Kept +Kept +Kept +Kept +mem: total=\\d\+, current=\\d\+, peak=\\d\+ +stack: \\d\+ out of \\d\+ +GC: total: \\d\+, used: \\d\+, free: \\d\+ + No. of 1-blocks: \\d\+, 2-blocks: \\d\+, max blk sz: \\d\+, max free sz: \\d\+ From 30e50ab1951680a046c224c12f7cc29aed410e2a Mon Sep 17 00:00:00 2001 From: Jatty_ Date: Tue, 13 Sep 2022 18:38:03 +0700 Subject: [PATCH 0443/1041] stm32/make-stmconst.py: Support TypeDef's with a single char prefix. Update the regex to support parsing files from the STM32CubeU5 library. --- ports/stm32/make-stmconst.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/make-stmconst.py b/ports/stm32/make-stmconst.py index 554d662384..aab4038e61 100644 --- a/ports/stm32/make-stmconst.py +++ b/ports/stm32/make-stmconst.py @@ -72,7 +72,7 @@ class Lexer: ("}", re.compile(r"}$")), ( "} TypeDef", - re.compile(r"} *(?P[A-Z][A-Za-z0-9_]+)_(?P([A-Za-z0-9_]+)?)TypeDef;$"), + re.compile(r"} *(?P[A-Z][A-Za-z0-9_]*)_(?P([A-Za-z0-9_]+)?)TypeDef;$"), ), ( "IO reg", From ae0b0e701899297d057ab8dc578b3bdbf0144fc4 Mon Sep 17 00:00:00 2001 From: yn386 Date: Mon, 19 Sep 2022 17:55:51 +0900 Subject: [PATCH 0444/1041] lib/stm32lib: Update library to get L1 v1.10.3, and some other fixes. Changes in this new library version are: - Add L1 HAL at v1.10.3. - H7_HAL/rcc_ex: Add SPI45 to HAL_RCCEx_GetPeriphCLKFreq. - L4_HAL/gpio_ex: Add #define for GPIO_AF14_TIM2 on L4P5/L4Q5. - F4_HAL/i2c: Fix I2C frequency calculation macros. - L1_HAL/utils: Fix compile error when USE_HAL_DRIVER is defined. --- .gitmodules | 2 +- lib/stm32lib | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 3c47b5959a..992fec3d18 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,7 +13,7 @@ [submodule "lib/stm32lib"] path = lib/stm32lib url = https://github.com/micropython/stm32lib - branch = work-F0-1.9.0+F4-1.16.0+F7-1.7.0+G4-1.3.0+H7-1.6.0+L0-1.11.2+L4-1.17.0+WB-1.10.0+WL-1.1.0 + branch = work-F0-1.9.0+F4-1.16.0+F7-1.7.0+G0-1.5.1+G4-1.3.0+H7-1.6.0+L0-1.11.2+L1-1.10.3+L4-1.17.0+WB-1.10.0+WL-1.1.0 [submodule "lib/nrfx"] path = lib/nrfx url = https://github.com/NordicSemiconductor/nrfx.git diff --git a/lib/stm32lib b/lib/stm32lib index eb80f0126e..a9f8fee7bb 160000 --- a/lib/stm32lib +++ b/lib/stm32lib @@ -1 +1 @@ -Subproject commit eb80f0126e50687aac966f4c39a2b5a5deffbe78 +Subproject commit a9f8fee7bb0cb4ac1b4ff719b6b5b285f613f352 From 427d72667f23ef8758fbfd2352dd28ba5565644a Mon Sep 17 00:00:00 2001 From: yn386 Date: Mon, 19 Sep 2022 17:56:31 +0900 Subject: [PATCH 0445/1041] stm32: Add support for STM32L1 MCUs. This change adds STM32L1 support to the STM32 port. --- ports/stm32/Makefile | 7 ++ ports/stm32/adc.c | 55 ++++++++- ports/stm32/boards/stm32l152_af.csv | 117 +++++++++++++++++++ ports/stm32/boards/stm32l152xe.ld | 37 ++++++ ports/stm32/boards/stm32l1xx_hal_conf_base.h | 99 ++++++++++++++++ ports/stm32/dac.c | 2 + ports/stm32/dma.c | 66 ++++++++++- ports/stm32/dma.h | 14 +++ ports/stm32/extint.c | 4 + ports/stm32/extint.h | 2 +- ports/stm32/flash.c | 10 +- ports/stm32/machine_adc.c | 7 +- ports/stm32/modmachine.c | 4 +- ports/stm32/mpconfigboard_common.h | 10 ++ ports/stm32/mphalport.c | 2 +- ports/stm32/mphalport.h | 2 + ports/stm32/powerctrl.c | 6 +- ports/stm32/powerctrlboot.c | 68 +++++++++++ ports/stm32/resethandler_m3.s | 75 ++++++++++++ ports/stm32/rtc.c | 17 +++ ports/stm32/stm32.mk | 3 +- ports/stm32/stm32_it.c | 34 ++++++ ports/stm32/timer.c | 34 ++++-- ports/stm32/uart.c | 17 ++- ports/stm32/uart.h | 2 +- 25 files changed, 657 insertions(+), 37 deletions(-) create mode 100644 ports/stm32/boards/stm32l152_af.csv create mode 100644 ports/stm32/boards/stm32l152xe.ld create mode 100644 ports/stm32/boards/stm32l1xx_hal_conf_base.h create mode 100644 ports/stm32/resethandler_m3.s diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index ee00d77173..4b4a9f0ce3 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -347,11 +347,18 @@ SRC_O += \ resethandler_m0.o \ shared/runtime/gchelper_m0.o else +ifeq ($(MCU_SERIES),l1) +CFLAGS += -DUSE_HAL_DRIVER +SRC_O += \ + resethandler_m3.o \ + shared/runtime/gchelper_m3.o +else SRC_O += \ system_stm32.o \ resethandler.o \ shared/runtime/gchelper_m3.o endif +endif HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ hal.c \ diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index 712e9b3ade..02bbbb58db 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -118,6 +118,14 @@ #define ADC_CAL2 ((uint16_t *)(0x1FF1E840)) #define ADC_CAL_BITS (16) +#elif defined(STM32L1) + +#define ADC_SCALE_V (VREFINT_CAL_VREF / 1000.0f) +#define ADC_CAL_ADDRESS (VREFINT_CAL_ADDR) +#define ADC_CAL1 (TEMPSENSOR_CAL1_ADDR) +#define ADC_CAL2 (TEMPSENSOR_CAL2_ADDR) +#define ADC_CAL_BITS (12) + #elif defined(STM32L4) || defined(STM32WB) #define ADC_SCALE_V (VREFINT_CAL_VREF / 1000.0f) @@ -163,6 +171,8 @@ defined(STM32L476xx) || defined(STM32L496xx) || \ defined(STM32WB55xx) #define VBAT_DIV (3) +#elif defined(STM32L152xE) +// STM32L152xE does not have vbat. #else #error Unsupported processor #endif @@ -179,11 +189,17 @@ #define VREFIN_CAL ((uint16_t *)ADC_CAL_ADDRESS) #ifndef __HAL_ADC_IS_CHANNEL_INTERNAL +#if defined(STM32L1) +#define __HAL_ADC_IS_CHANNEL_INTERNAL(channel) \ + (channel == ADC_CHANNEL_VREFINT \ + || channel == ADC_CHANNEL_TEMPSENSOR) +#else #define __HAL_ADC_IS_CHANNEL_INTERNAL(channel) \ (channel == ADC_CHANNEL_VBAT \ || channel == ADC_CHANNEL_VREFINT \ || channel == ADC_CHANNEL_TEMPSENSOR) #endif +#endif typedef struct _pyb_obj_adc_t { mp_obj_base_t base; @@ -210,6 +226,10 @@ STATIC bool is_adcx_channel(int channel) { return IS_ADC_CHANNEL(channel) || channel == ADC_CHANNEL_TEMPSENSOR; #elif defined(STM32F0) || defined(STM32F4) || defined(STM32F7) return IS_ADC_CHANNEL(channel); + #elif defined(STM32L1) + // The HAL of STM32L1 defines some channels those may not be available on package + return __HAL_ADC_IS_CHANNEL_INTERNAL(channel) + || (channel < MP_ARRAY_SIZE(pin_adcall_table) && pin_adcall_table[channel]); #elif defined(STM32G0) || defined(STM32H7) return __HAL_ADC_IS_CHANNEL_INTERNAL(channel) || IS_ADC_CHANNEL(__HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel)); @@ -225,7 +245,7 @@ STATIC bool is_adcx_channel(int channel) { STATIC void adc_wait_for_eoc_or_timeout(ADC_HandleTypeDef *adcHandle, int32_t timeout) { uint32_t tickstart = HAL_GetTick(); - #if defined(STM32F4) || defined(STM32F7) + #if defined(STM32F4) || defined(STM32F7) || defined(STM32L1) while ((adcHandle->Instance->SR & ADC_FLAG_EOC) != ADC_FLAG_EOC) { #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) while (READ_BIT(adcHandle->Instance->ISR, ADC_FLAG_EOC) != ADC_FLAG_EOC) { @@ -239,7 +259,7 @@ STATIC void adc_wait_for_eoc_or_timeout(ADC_HandleTypeDef *adcHandle, int32_t ti } STATIC void adcx_clock_enable(ADC_HandleTypeDef *adch) { - #if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) + #if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32L1) ADCx_CLK_ENABLE(); #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) __HAL_RCC_ADC12_CLK_ENABLE(); @@ -299,6 +319,12 @@ STATIC void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) { adch->Init.OversamplingMode = DISABLE; adch->Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE; adch->Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; + #elif defined(STM32L1) + adch->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; + adch->Init.ScanConvMode = ADC_SCAN_DISABLE; + adch->Init.LowPowerAutoWait = DISABLE; + adch->Init.DataAlign = ADC_DATAALIGN_RIGHT; + adch->Init.DMAContinuousRequests = DISABLE; #elif defined(STM32G0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WB) adch->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; adch->Init.ScanConvMode = ADC_SCAN_DISABLE; @@ -367,6 +393,12 @@ STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.OffsetRightShift = DISABLE; sConfig.OffsetSignedSaturation = DISABLE; + #elif defined(STM32L1) + if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { + sConfig.SamplingTime = ADC_SAMPLETIME_384CYCLES; + } else { + sConfig.SamplingTime = ADC_SAMPLETIME_384CYCLES; + } #elif defined(STM32G0) if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { sConfig.SamplingTime = ADC_SAMPLETIME_160CYCLES_5; @@ -555,7 +587,7 @@ STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_ HAL_ADC_Start(&self->handle); } else { // for subsequent samples we can just set the "start sample" bit - #if defined(STM32F4) || defined(STM32F7) + #if defined(STM32F4) || defined(STM32F7) || defined(STM32L1) self->handle.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) SET_BIT(self->handle.Instance->CR, ADC_CR_ADSTART); @@ -665,7 +697,7 @@ STATIC mp_obj_t adc_read_timed_multi(mp_obj_t adc_array_in, mp_obj_t buf_array_i adc_config_channel(&adc->handle, adc->channel); // for the first sample we need to turn the ADC on // ADC is started: set the "start sample" bit - #if defined(STM32F4) || defined(STM32F7) + #if defined(STM32F4) || defined(STM32F7) || defined(STM32L1) adc->handle.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) SET_BIT(adc->handle.Instance->CR, ADC_CR_ADSTART); @@ -720,6 +752,8 @@ typedef struct _pyb_adc_all_obj_t { ADC_HandleTypeDef handle; } pyb_adc_all_obj_t; +float adc_read_core_vref(ADC_HandleTypeDef *adcHandle); + void adc_init_all(pyb_adc_all_obj_t *adc_all, uint32_t resolution, uint32_t en_mask) { switch (resolution) { @@ -762,7 +796,11 @@ void adc_init_all(pyb_adc_all_obj_t *adc_all, uint32_t resolution, uint32_t en_m } int adc_get_resolution(ADC_HandleTypeDef *adcHandle) { + #if defined(STM32L1) + uint32_t res_reg = adcHandle->Instance->CR1 & ADC_CR1_RES_Msk; + #else uint32_t res_reg = ADC_GET_RESOLUTION(adcHandle); + #endif switch (res_reg) { #if !defined(STM32H7) @@ -814,6 +852,11 @@ float adc_read_core_temp_float(ADC_HandleTypeDef *adcHandle) { return 0; } #else + #if defined(STM32L1) + // Update the reference correction factor before reading tempsensor + // because TS_CAL1 and TS_CAL2 of STM32L1 are at VDDA=3.0V + adc_read_core_vref(adcHandle); + #endif int32_t raw_value = adc_config_and_read_ref(adcHandle, ADC_CHANNEL_TEMPSENSOR); #endif float core_temp_avg_slope = (*ADC_CAL2 - *ADC_CAL1) / 80.0f; @@ -821,8 +864,12 @@ float adc_read_core_temp_float(ADC_HandleTypeDef *adcHandle) { } float adc_read_core_vbat(ADC_HandleTypeDef *adcHandle) { + #if defined(STM32L152xE) + mp_raise_NotImplementedError(MP_ERROR_TEXT("read_core_vbat not supported")); + #else uint32_t raw_value = adc_config_and_read_ref(adcHandle, ADC_CHANNEL_VBAT); return raw_value * VBAT_DIV * ADC_SCALE * adc_refcor; + #endif } float adc_read_core_vref(ADC_HandleTypeDef *adcHandle) { diff --git a/ports/stm32/boards/stm32l152_af.csv b/ports/stm32/boards/stm32l152_af.csv new file mode 100644 index 0000000000..a6f8e80c30 --- /dev/null +++ b/ports/stm32/boards/stm32l152_af.csv @@ -0,0 +1,117 @@ +Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, +,,SYS_AF,TIM2,TIM3/TIM4/TIM5,TIM9/TIM10/TIM11,I2C1/I2C2,SPI1/SPI2,SPI3,USART1/USART2/USART3,UART4/UART5,,,,,,,,ADC +PortA,PA0,,TIM2_CH1_ETR,TIM5_CH1,,,,,USART2_CTS,,,,,,,,EVENTOUT,ADC1_IN0 +PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,,,,,,,,EVENTOUT,ADC1_IN1 +PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,,,,,,,,EVENTOUT,ADC1_IN2 +PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,,,,,,EVENTOUT,ADC1_IN3 +PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,,,,EVENTOUT,ADC1_IN4 +PortA,PA5,,TIM2_CH1_ETR,,,,SPI1_SCK,,,,,,,,,,EVENTOUT,ADC1_IN5 +PortA,PA6,,,TIM3_CH1,TIM10_CH1,,SPI1_MISO,,,,,,,,,,EVENTOUT,ADC1_IN6 +PortA,PA7,,,TIM3_CH2,TIM11_CH1,,SPI1_MOSI,,,,,,,,,,EVENTOUT,ADC1_IN7 +PortA,PA8,MCO,,,,,,,USART1_CK,,,,,,,,EVENTOUT, +PortA,PA9,,,,,,,,USART1_TX,,,,,,,,EVENTOUT, +PortA,PA10,,,,,,,,USART1_RX,,,,,,,,EVENTOUT, +PortA,PA11,,,,,,SPI1_MISO,,USART1_CTS,,,,,,,,EVENTOUT, +PortA,PA12,,,,,,SPI1_MOSI,,USART1_RTS,,,,,,,,EVENTOUT, +PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT, +PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT, +PortA,PA15,JTDI,TIM2_CH1_ETR,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,,,,,,,,,EVENTOUT, +PortB,PB0,,,TIM3_CH3,,,,,,,,,,,,,EVENTOUT,ADC1_IN8 +PortB,PB1,,,TIM3_CH4,,,,,,,,,,,,,EVENTOUT,ADC1_IN9 +PortB,PB2,BOOT1,,,,,,,,,,,,,,,EVENTOUT, +PortB,PB3,JTDO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCK/I2S3_CK,,,,,,,,,EVENTOUT, +PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,,,,,,,,,EVENTOUT, +PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI,SPI3_MOSI/I2S3_SD,,,,,,,,,EVENTOUT, +PortB,PB6,,,TIM4_CH1,,I2C1_SCL,,,USART1_TX,,,,,,,,EVENTOUT, +PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,,,,,,,,EVENTOUT, +PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,,,,,,,EVENTOUT, +PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,,,,,,,,,,,EVENTOUT, +PortB,PB10,,TIM2_CH3,,,I2C2_SCL,,,USART3_TX,,,,,,,,EVENTOUT, +PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,,USART3_RX,,,,,,,,EVENTOUT, +PortB,PB12,,,,TIM10_CH1,I2C2_SMBA,SPI2_NSS/I2S2_WS,,USART3_CK,,,,,,,,EVENTOUT,ADC1_IN18 +PortB,PB13,,,,TIM9_CH1,,SPI2_SCK/I2S2_CK,,USART3_CTS,,,,,,,,EVENTOUT,ADC1_IN19 +PortB,PB14,,,,TIM9_CH2,,SPI2_MISO,,USART3_RTS,,,,,,,,EVENTOUT,ADC1_IN20 +PortB,PB15,,,,TIM11_CH1,,SPI2_MOSI/I2S2_SD,,,,,,,,,,EVENTOUT,ADC1_IN21 +PortC,PC0,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN10 +PortC,PC1,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN11 +PortC,PC2,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN12 +PortC,PC3,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN13 +PortC,PC4,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN14 +PortC,PC5,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN15 +PortC,PC6,,,TIM3_CH1,,,I2S2_MCK,,,,,,,,,,EVENTOUT, +PortC,PC7,,,TIM3_CH2,,,,I2S3_MCK,,,,,,,,,EVENTOUT, +PortC,PC8,,,TIM3_CH3,,,,,,,,,,,,,EVENTOUT, +PortC,PC9,,,TIM3_CH4,,,,,,,,,,,,,EVENTOUT, +PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,,,,,,,EVENTOUT, +PortC,PC11,,,,,,,SPI3_MISO,USART3_RX,UART4_RX,,,,,,,EVENTOUT, +PortC,PC12,,,,,,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,,,,,,EVENTOUT, +PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, +PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, +PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, +PortD,PD0,,,,TIM9_CH1,,SPI2_NSS/I2S2_WS,,,,,,,,,,EVENTOUT, +PortD,PD1,,,,,,SPI2_SCK/I2S2_CK,,,,,,,,,,EVENTOUT, +PortD,PD2,,,TIM3_ETR,,,,,,UART5_RX,,,,,,,EVENTOUT, +PortD,PD3,,,,,,SPI2_MISO,,USART2_CTS,,,,,,,,EVENTOUT, +PortD,PD4,,,,,,SPI2_MOSI/I2S2_SD,,USART2_RTS,,,,,,,,EVENTOUT, +PortD,PD5,,,,,,,,USART2_TX,,,,,,,,EVENTOUT, +PortD,PD6,,,,,,,,USART2_RX,,,,,,,,EVENTOUT, +PortD,PD7,,,,TIM9_CH2,,,,USART2_CK,,,,,,,,EVENTOUT, +PortD,PD8,,,,,,,,USART3_TX,,,,,,,,EVENTOUT, +PortD,PD9,,,,,,,,USART3_RX,,,,,,,,EVENTOUT, +PortD,PD10,,,,,,,,USART3_CK,,,,,,,,EVENTOUT, +PortD,PD11,,,,,,,,USART3_CTS,,,,,,,,EVENTOUT, +PortD,PD12,,,TIM4_CH1,,,,,USART3_RTS,,,,,,,,EVENTOUT, +PortD,PD13,,,TIM4_CH2,,,,,,,,,,,,,EVENTOUT, +PortD,PD14,,,TIM4_CH3,,,,,,,,,,,,,EVENTOUT, +PortD,PD15,,,TIM4_CH4,,,,,,,,,,,,,EVENTOUT, +PortE,PE0,,,TIM4_ETR,TIM10_CH1,,,,,,,,,,,,EVENTOUT, +PortE,PE1,,,,TIM11_CH1,,,,,,,,,,,,EVENTOUT, +PortE,PE2,TRACECK,,TIM3_ETR,,,,,,,,,,,,,EVENTOUT, +PortE,PE3,TRACED0,,TIM3_CH1,,,,,,,,,,,,,EVENTOUT, +PortE,PE4,TRACED1,,TIM3_CH2,,,,,,,,,,,,,EVENTOUT, +PortE,PE5,TRACED2,,,TIM9_CH1,,,,,,,,,,,,EVENTOUT, +PortE,PE6,TRACED3,,,TIM9_CH2,,,,,,,,,,,,EVENTOUT, +PortE,PE7,,,,,,,,,,,,,,,,EVENTOUT, +PortE,PE8,,,,,,,,,,,,,,,,EVENTOUT, +PortE,PE9,,TIM2_CH1_ETR,,,,,,,,,,,,,,EVENTOUT, +PortE,PE10,,TIM2_CH2,,,,,,,,,,,,,,EVENTOUT, +PortE,PE11,,TIM2_CH3,,,,,,,,,,,,,,EVENTOUT, +PortE,PE12,,TIM2_CH4,,,,SPI1_NSS,,,,,,,,,,EVENTOUT, +PortE,PE13,,,,,,SPI1_SCK,,,,,,,,,,EVENTOUT, +PortE,PE14,,,,,,SPI1_MISO,,,,,,,,,,EVENTOUT, +PortE,PE15,,,,,,SPI1_MOSI,,,,,,,,,,EVENTOUT, +PortF,PF0,,,,,,,,,,,,,,,,EVENTOUT, +PortF,PF1,,,,,,,,,,,,,,,,EVENTOUT, +PortF,PF2,,,,,,,,,,,,,,,,EVENTOUT, +PortF,PF3,,,,,,,,,,,,,,,,EVENTOUT, +PortF,PF4,,,,,,,,,,,,,,,,EVENTOUT, +PortF,PF5,,,,,,,,,,,,,,,,EVENTOUT, +PortF,PF6,,,TIM5_ETR,,,,,,,,,,,,,EVENTOUT, +PortF,PF7,,,TIM5_CH2,,,,,,,,,,,,,EVENTOUT, +PortF,PF8,,,TIM5_CH3,,,,,,,,,,,,,EVENTOUT, +PortF,PF9,,,TIM5_CH4,,,,,,,,,,,,,EVENTOUT, +PortF,PF10,,,,,,,,,,,,,,,,EVENTOUT, +PortF,PF11,,,,,,,,,,,,,,,,EVENTOUT, +PortF,PF12,,,,,,,,,,,,,,,,EVENTOUT, +PortF,PF13,,,,,,,,,,,,,,,,EVENTOUT, +PortF,PF14,,,,,,,,,,,,,,,,EVENTOUT, +PortF,PF15,,,,,,,,,,,,,,,,EVENTOUT, +PortG,PG0,,,,,,,,,,,,,,,,EVENTOUT, +PortG,PG1,,,,,,,,,,,,,,,,EVENTOUT, +PortG,PG2,,,,,,,,,,,,,,,,EVENTOUT, +PortG,PG3,,,,,,,,,,,,,,,,EVENTOUT, +PortG,PG4,,,,,,,,,,,,,,,,EVENTOUT, +PortG,PG5,,,,,,,,,,,,,,,,EVENTOUT, +PortG,PG6,,,,,,,,,,,,,,,,EVENTOUT, +PortG,PG7,,,,,,,,,,,,,,,,EVENTOUT, +PortG,PG8,,,,,,,,,,,,,,,,EVENTOUT, +PortG,PG9,,,,,,,,,,,,,,,,EVENTOUT, +PortG,PG10,,,,,,,,,,,,,,,,EVENTOUT, +PortG,PG11,,,,,,,,,,,,,,,,EVENTOUT, +PortG,PG12,,,,,,,,,,,,,,,,EVENTOUT, +PortG,PG13,,,,,,,,,,,,,,,,EVENTOUT, +PortG,PG14,,,,,,,,,,,,,,,,EVENTOUT, +PortG,PG15,,,,,,,,,,,,,,,,EVENTOUT, +PortH,PH0,,,,,,,,,,,,,,,,, +PortH,PH1,,,,,,,,,,,,,,,,, +PortH,PH2,,,,,,,,,,,,,,,,, diff --git a/ports/stm32/boards/stm32l152xe.ld b/ports/stm32/boards/stm32l152xe.ld new file mode 100644 index 0000000000..32f8444947 --- /dev/null +++ b/ports/stm32/boards/stm32l152xe.ld @@ -0,0 +1,37 @@ +/* + GNU linker script for STM32L152xE +*/ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* entire flash */ + FLASH_FS (rx) : ORIGIN = 0x08064000, LENGTH = 112K /* sectors 100-127 */ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 81408 + FS_CACHE (xrw) : ORIGIN = 0x20013e00, LENGTH = 512 +} + +/* produce a link error if there is not this amount of RAM for these sections */ +_minimum_stack_size = 2K; +_minimum_heap_size = 16K; + +/* RAM extents for the garbage collector */ +_ram_start = ORIGIN(RAM); +_ram_end = ORIGIN(RAM) + LENGTH(RAM); + +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; +_sstack = _estack - 16K; /* tunable */ + +/* RAM extents for the garbage collector */ +_ram_start = ORIGIN(RAM); +_ram_end = ORIGIN(RAM) + LENGTH(RAM); +_heap_start = _ebss; /* heap starts just after statically allocated memory */ +_heap_end = _sstack; + +/* Filesystem cache in RAM, and storage in flash */ +_micropy_hw_internal_flash_storage_ram_cache_start = ORIGIN(FS_CACHE); +_micropy_hw_internal_flash_storage_ram_cache_end = ORIGIN(FS_CACHE) + LENGTH(FS_CACHE); +_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); +_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); diff --git a/ports/stm32/boards/stm32l1xx_hal_conf_base.h b/ports/stm32/boards/stm32l1xx_hal_conf_base.h new file mode 100644 index 0000000000..b839fd29f0 --- /dev/null +++ b/ports/stm32/boards/stm32l1xx_hal_conf_base.h @@ -0,0 +1,99 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 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. + */ +#ifndef MICROPY_INCLUDED_STM32L1XX_HAL_CONF_BASE_H +#define MICROPY_INCLUDED_STM32L1XX_HAL_CONF_BASE_H + +// Include various HAL modules for convenience +#include "stm32l1xx_hal_rcc.h" +#include "stm32l1xx_hal_gpio.h" +#include "stm32l1xx_hal_dma.h" +#include "stm32l1xx_hal_cortex.h" +#include "stm32l1xx_hal_adc.h" +#include "stm32l1xx_hal_comp.h" +#include "stm32l1xx_hal_crc.h" +#include "stm32l1xx_hal_dac.h" +#include "stm32l1xx_hal_flash.h" +#include "stm32l1xx_hal_i2c.h" +#include "stm32l1xx_hal_iwdg.h" +#include "stm32l1xx_hal_pwr.h" +#include "stm32l1xx_hal_rtc.h" +#include "stm32l1xx_hal_spi.h" +#include "stm32l1xx_hal_tim.h" +#include "stm32l1xx_hal_uart.h" +#include "stm32l1xx_hal_usart.h" +#include "stm32l1xx_hal_wwdg.h" +#include "stm32l1xx_hal_exti.h" +#include "stm32l1xx_ll_adc.h" +#include "stm32l1xx_ll_pwr.h" +#include "stm32l1xx_ll_rtc.h" +#include "stm32l1xx_ll_usart.h" + +// Enable various HAL modules +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED + +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define HSI_VALUE (16000000) +#define HSI48_VALUE (48000000) +#define LSI_VALUE (37000) +#define LSE_VALUE (32768) +#define MSI_VALUE (2097000) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +// SysTick has the highest priority +#define TICK_INT_PRIORITY (0x00) + +// Miscellaneous HAL settings +#define DATA_CACHE_ENABLE 1 +#define INSTRUCTION_CACHE_ENABLE 1 +#define PREFETCH_ENABLE 1 +#define USE_SPI_CRC 0 +#define USE_RTOS 0 + +// HAL parameter assertions are disabled +#define assert_param(expr) ((void)0) + +#endif // MICROPY_INCLUDED_STM32L1XX_HAL_CONF_BASE_H diff --git a/ports/stm32/dac.c b/ports/stm32/dac.c index 36ef9387f8..feadbe5c58 100644 --- a/ports/stm32/dac.c +++ b/ports/stm32/dac.c @@ -261,6 +261,8 @@ STATIC mp_obj_t pyb_dac_init_helper(pyb_dac_obj_t *self, size_t n_args, const mp __HAL_RCC_DAC12_CLK_ENABLE(); #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32L4) __HAL_RCC_DAC1_CLK_ENABLE(); + #elif defined(STM32L1) + __HAL_RCC_DAC_CLK_ENABLE(); #else #error Unsupported Processor #endif diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index 2dc6e8e8b4..29306f1b27 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -80,7 +80,7 @@ typedef union { struct _dma_descr_t { #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) DMA_Stream_TypeDef *instance; - #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) DMA_Channel_TypeDef *instance; #else #error "Unsupported Processor" @@ -398,6 +398,57 @@ static const uint8_t dma_irqn[NSTREAM] = { DMA1_Channel4_5_6_7_IRQn, }; +#elif defined(STM32L1) + +#define NCONTROLLERS (2) +#define NSTREAMS_PER_CONTROLLER (7) +#define NSTREAM (NCONTROLLERS * NSTREAMS_PER_CONTROLLER) + +#define DMA_SUB_INSTANCE_AS_UINT8(dma_request) (dma_request) + +#define DMA1_ENABLE_MASK (0x007f) // Bits in dma_enable_mask corresponding to DMA1 +#define DMA2_ENABLE_MASK (0x0f80) // Bits in dma_enable_mask corresponding to DMA2 + +// These descriptors are ordered by DMAx_Channel number, and within a channel by request +// number. The duplicate streams are ok as long as they aren't used at the same time. + +// DMA1 streams +const dma_descr_t dma_SPI_1_RX = { DMA1_Channel2, 2, dma_id_1, &dma_init_struct_spi_i2c }; +#if MICROPY_HW_ENABLE_DAC +const dma_descr_t dma_DAC_1_TX = { DMA1_Channel2, 2, dma_id_1, &dma_init_struct_dac }; +#endif +const dma_descr_t dma_SPI_1_TX = { DMA1_Channel3, 3, dma_id_2, &dma_init_struct_spi_i2c }; +#if MICROPY_HW_ENABLE_DAC +const dma_descr_t dma_DAC_2_TX = { DMA1_Channel3, 3, dma_id_2, &dma_init_struct_dac }; +#endif +const dma_descr_t dma_SPI_2_RX = { DMA1_Channel4, 4, dma_id_3, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_2_TX = { DMA1_Channel4, 4, dma_id_3, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_2_TX = { DMA1_Channel5, 5, dma_id_4, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_2_RX = { DMA1_Channel5, 5, dma_id_4, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_1_TX = { DMA1_Channel6, 6, dma_id_5, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_1_RX = { DMA1_Channel7, 7, dma_id_6, &dma_init_struct_spi_i2c }; + +// DMA2 streams +const dma_descr_t dma_SPI_3_RX = { DMA2_Channel1, 3, dma_id_7, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_3_TX = { DMA2_Channel2, 3, dma_id_8, &dma_init_struct_spi_i2c }; + +static const uint8_t dma_irqn[NSTREAM] = { + DMA1_Channel1_IRQn, + DMA1_Channel2_IRQn, + DMA1_Channel3_IRQn, + DMA1_Channel4_IRQn, + DMA1_Channel5_IRQn, + DMA1_Channel6_IRQn, + DMA1_Channel7_IRQn, + DMA2_Channel1_IRQn, + DMA2_Channel2_IRQn, + DMA2_Channel3_IRQn, + DMA2_Channel4_IRQn, + DMA2_Channel5_IRQn, + 0, + 0 +}; + #elif defined(STM32L4) #define NCONTROLLERS (2) @@ -705,7 +756,7 @@ volatile dma_idle_count_t dma_idle; #define DMA_INVALID_CHANNEL 0xff // Value stored in dma_last_channel which means invalid -#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) +#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32L1) #define DMA1_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA1EN) != 0) #if defined(DMA2) #define DMA2_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA2EN) != 0) @@ -1080,7 +1131,7 @@ void DMA1_Channel4_5_6_7_IRQHandler(void) { IRQ_EXIT(DMA1_Channel4_5_6_7_IRQn); } -#elif defined(STM32L4) || defined(STM32WB) +#elif defined(STM32L1) || defined(STM32L4) || defined(STM32WB) void DMA1_Channel1_IRQHandler(void) { IRQ_ENTER(DMA1_Channel1_IRQn); @@ -1166,6 +1217,7 @@ void DMA2_Channel5_IRQHandler(void) { } IRQ_EXIT(DMA2_Channel5_IRQn); } +#if !defined(STM32L1) void DMA2_Channel6_IRQHandler(void) { IRQ_ENTER(DMA2_Channel6_IRQn); if (dma_handle[dma_id_12] != NULL) { @@ -1180,6 +1232,7 @@ void DMA2_Channel7_IRQHandler(void) { } IRQ_EXIT(DMA2_Channel7_IRQn); } +#endif #endif @@ -1260,7 +1313,7 @@ void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint3 #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) dma->Init.Request = dma_descr->sub_instance; #else - #if !defined(STM32F0) + #if !defined(STM32F0) && !defined(STM32L1) dma->Init.Channel = dma_descr->sub_instance; #endif #endif @@ -1284,7 +1337,7 @@ void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir dma_enable_clock(dma_id); - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) // Always reset and configure the H7 and G0/G4/H7/L0/L4/WB/WL DMA peripheral // (dma->State is set to HAL_DMA_STATE_RESET by memset above) // TODO: understand how L0/L4 DMA works so this is not needed @@ -1410,7 +1463,7 @@ static void dma_idle_handler(uint32_t tick) { } #endif -#if defined(STM32F0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) +#if defined(STM32F0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) void dma_nohal_init(const dma_descr_t *descr, uint32_t config) { DMA_Channel_TypeDef *dma = descr->instance; @@ -1436,6 +1489,7 @@ void dma_nohal_init(const dma_descr_t *descr, uint32_t config) { #elif defined(STM32G4) uint32_t *dmamux_ctrl = (void *)(DMAMUX1_Channel0_BASE + 0x04 * descr->id); *dmamux_ctrl = (*dmamux_ctrl & ~(0x7f)) | descr->sub_instance; + #elif defined(STM32L1) #else DMA_Request_TypeDef *dma_ctrl = (void *)(((uint32_t)dma & ~0xff) + (DMA1_CSELR_BASE - DMA1_BASE)); // DMA1_CSELR or DMA2_CSELR uint32_t channel_number = (((uint32_t)dma & 0xff) - 0x08) / 20; // 0 through 6 diff --git a/ports/stm32/dma.h b/ports/stm32/dma.h index 70c7e6a005..37b8710c21 100644 --- a/ports/stm32/dma.h +++ b/ports/stm32/dma.h @@ -100,6 +100,20 @@ extern const dma_descr_t dma_I2C_2_RX; extern const dma_descr_t dma_I2C_1_TX; extern const dma_descr_t dma_I2C_1_RX; +#elif defined(STM32L1) +extern const dma_descr_t dma_SPI_1_RX; +extern const dma_descr_t dma_SPI_3_TX; +extern const dma_descr_t dma_SPI_1_TX; +extern const dma_descr_t dma_SPI_3_RX; +extern const dma_descr_t dma_DAC_1_TX; +extern const dma_descr_t dma_SPI_2_RX; +extern const dma_descr_t dma_I2C_2_TX; +extern const dma_descr_t dma_DAC_2_TX; +extern const dma_descr_t dma_SPI_2_TX; +extern const dma_descr_t dma_I2C_2_RX; +extern const dma_descr_t dma_I2C_1_TX; +extern const dma_descr_t dma_I2C_1_RX; + #elif defined(STM32L4) || defined(STM32WB) || defined(STM32WL) extern const dma_descr_t dma_ADC_1_RX; diff --git a/ports/stm32/extint.c b/ports/stm32/extint.c index ca23261ca7..fd7950de3e 100644 --- a/ports/stm32/extint.c +++ b/ports/stm32/extint.c @@ -210,7 +210,11 @@ STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { #endif ETH_WKUP_IRQn, OTG_HS_WKUP_IRQn, + #if defined(STM32L1) + TAMPER_STAMP_IRQn, + #else TAMP_STAMP_IRQn, + #endif RTC_WKUP_IRQn, #endif diff --git a/ports/stm32/extint.h b/ports/stm32/extint.h index 95e29c97fd..fddcc2ae7a 100644 --- a/ports/stm32/extint.h +++ b/ports/stm32/extint.h @@ -43,7 +43,7 @@ #endif #define EXTI_ETH_WAKEUP (19) #define EXTI_USB_OTG_HS_WAKEUP (20) -#if defined(STM32F0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WL) +#if defined(STM32F0) || defined(STM32G4) || defined(STM32L1) || defined(STM32L4) || defined(STM32WL) #define EXTI_RTC_TIMESTAMP (19) #define EXTI_RTC_WAKEUP (20) #elif defined(STM32H7) || defined(STM32WB) diff --git a/ports/stm32/flash.c b/ports/stm32/flash.c index de537aba21..16af49c3cf 100644 --- a/ports/stm32/flash.c +++ b/ports/stm32/flash.c @@ -117,6 +117,12 @@ static const flash_layout_t flash_layout[] = { { (uint32_t)FLASH_BASE, (uint32_t)FLASH_PAGE_SIZE, 512 }, }; +#elif defined(STM32L1) + +static const flash_layout_t flash_layout[] = { + { (uint32_t)FLASH_BASE, 0x200, 1024 }, +}; + #elif defined(STM32H7) static const flash_layout_t flash_layout[] = { @@ -264,7 +270,7 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) { EraseInitStruct.Page = get_page(flash_dest); EraseInitStruct.Banks = get_bank(flash_dest); EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; - #elif defined(STM32L0) + #elif defined(STM32L0) || defined(STM32L1) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR); EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.PageAddress = flash_dest; @@ -286,6 +292,8 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) { #if defined(STM32H7) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS_BANK1 | FLASH_FLAG_ALL_ERRORS_BANK2); + #elif defined(STM32L1) + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR); #else __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); diff --git a/ports/stm32/machine_adc.c b/ports/stm32/machine_adc.c index 000b478f86..1a478cd1cf 100644 --- a/ports/stm32/machine_adc.c +++ b/ports/stm32/machine_adc.c @@ -42,7 +42,7 @@ #define ADCx_COMMON __LL_ADC_COMMON_INSTANCE(0) #endif -#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32WL) +#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32L1) || defined(STM32WL) #define ADC_STAB_DELAY_US (1) #define ADC_TEMPSENSOR_DELAY_US (10) #elif defined(STM32G4) @@ -68,6 +68,9 @@ #elif defined(STM32G0) || defined(STM32L0) || defined(STM32WL) #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_12CYCLES_5 #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_160CYCLES_5 +#elif defined(STM32L1) +#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_384CYCLES +#define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_384CYCLES #elif defined(STM32L4) || defined(STM32WB) #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_12CYCLES_5 #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_247CYCLES_5 @@ -239,7 +242,7 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { STATIC int adc_get_bits(ADC_TypeDef *adc) { #if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32WL) uint32_t res = (adc->CFGR1 & ADC_CFGR1_RES) >> ADC_CFGR1_RES_Pos; - #elif defined(STM32F4) || defined(STM32F7) + #elif defined(STM32F4) || defined(STM32F7) || defined(STM32L1) uint32_t res = (adc->CR1 & ADC_CR1_RES) >> ADC_CR1_RES_Pos; #elif defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) uint32_t res = (adc->CFGR & ADC_CFGR_RES) >> ADC_CFGR_RES_Pos; diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index acedac7a59..e1796d1cf0 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -138,7 +138,7 @@ void machine_init(void) { if (state & RCC_SR_IWDGRSTF || state & RCC_SR_WWDGRSTF) { reset_cause = PYB_RESET_WDT; } else if (state & RCC_SR_PORRSTF - #if !defined(STM32F0) && !defined(STM32F412Zx) + #if !defined(STM32F0) && !defined(STM32F412Zx) && !defined(STM32L1) || state & RCC_SR_BORRSTF #endif ) { @@ -309,7 +309,7 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple); } else { // set - #if defined(STM32F0) || defined(STM32L0) || defined(STM32L4) || defined(STM32G0) + #if defined(STM32F0) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32G0) mp_raise_NotImplementedError(MP_ERROR_TEXT("machine.freq set not supported yet")); #else mp_int_t sysclk = mp_obj_get_int(args[0]); diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 51bad18dd5..b538f78235 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -370,6 +370,16 @@ #define MICROPY_HW_MAX_UART (5) #define MICROPY_HW_MAX_LPUART (1) +// Configuration for STM32L1 series +#elif defined(STM32L1) +#define MP_HAL_UNIQUE_ID_ADDRESS (UID_BASE) +#define PYB_EXTI_NUM_VECTORS (23) +#define MICROPY_HW_MAX_I2C (2) +// TODO: L1 has 9 timers but tim0 and tim1 don't exist. +#define MICROPY_HW_MAX_TIMER (11) +#define MICROPY_HW_MAX_UART (5) +#define MICROPY_HW_MAX_LPUART (0) + // Configuration for STM32L4 series #elif defined(STM32L4) diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index 619bde69bf..092d63e1bb 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -87,7 +87,7 @@ void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) { // This logic assumes that all the GPIOx_EN bits are adjacent and ordered in one register - #if defined(STM32F0) + #if defined(STM32F0) || defined(STM32L1) #define AHBxENR AHBENR #define AHBxENR_GPIOAEN_Pos RCC_AHBENR_GPIOAEN_Pos #elif defined(STM32F4) || defined(STM32F7) diff --git a/ports/stm32/mphalport.h b/ports/stm32/mphalport.h index 358d9cd25d..5c587c016d 100644 --- a/ports/stm32/mphalport.h +++ b/ports/stm32/mphalport.h @@ -17,6 +17,8 @@ #define MICROPY_PLATFORM_VERSION "HAL1.6.0" #elif defined(STM32L0) #define MICROPY_PLATFORM_VERSION "HAL1.11.2" +#elif defined(STM32L1) +#define MICROPY_PLATFORM_VERSION "HAL1.10.3" #elif defined(STM32L4) #define MICROPY_PLATFORM_VERSION "HAL1.17.0" #elif defined(STM32WB) diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index f3f1837ece..c0a0595e5d 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -143,7 +143,7 @@ void powerctrl_check_enter_bootloader(void) { if (BL_STATE_GET_KEY(bl_state) == BL_STATE_KEY && (RCC->RCC_SR & RCC_SR_SFTRSTF)) { // Reset by NVIC_SystemReset with bootloader data set -> branch to bootloader RCC->RCC_SR = RCC_SR_RMVF; - #if defined(STM32F0) || defined(STM32F4) || defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32F0) || defined(STM32F4) || defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32WB) __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); #endif branch_to_bootloader(BL_STATE_GET_REG(bl_state), BL_STATE_GET_ADDR(bl_state)); @@ -286,7 +286,7 @@ int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk #endif -#if !defined(STM32F0) && !defined(STM32G0) && !defined(STM32L0) && !defined(STM32L4) +#if !defined(STM32F0) && !defined(STM32G0) && !defined(STM32L0) && !defined(STM32L1) && !defined(STM32L4) STATIC uint32_t calc_ahb_div(uint32_t wanted_div) { #if defined(STM32H7) @@ -708,7 +708,7 @@ void powerctrl_enter_stop_mode(void) { __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI); #endif - #if !defined(STM32F0) && !defined(STM32G0) && !defined(STM32G4) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB) && !defined(STM32WL) + #if !defined(STM32F0) && !defined(STM32G0) && !defined(STM32G4) && !defined(STM32L0) && !defined(STM32L1) && !defined(STM32L4) && !defined(STM32WB) && !defined(STM32WL) // takes longer to wake but reduces stop current HAL_PWREx_EnableFlashPowerDown(); #endif diff --git a/ports/stm32/powerctrlboot.c b/ports/stm32/powerctrlboot.c index 555457c582..61d48ffe5c 100644 --- a/ports/stm32/powerctrlboot.c +++ b/ports/stm32/powerctrlboot.c @@ -228,6 +228,74 @@ void SystemClock_Config(void) { #endif } +#elif defined(STM32L1) + +void SystemClock_Config(void) { + // Enable power control peripheral + __HAL_RCC_PWR_CLK_ENABLE(); + + // Set power voltage scaling + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); + + // Enable the FLASH 64-bit access + FLASH->ACR = FLASH_ACR_ACC64; + // Set flash latency to 1 because SYSCLK > 16MHz + FLASH->ACR |= MICROPY_HW_FLASH_LATENCY; + + #if MICROPY_HW_CLK_USE_HSI + // Enable the 16MHz internal oscillator + RCC->CR |= RCC_CR_HSION; + while (!(RCC->CR & RCC_CR_HSIRDY)) { + } + RCC->CFGR = RCC_CFGR_PLLSRC_HSI; + #else + // Enable the 8MHz external oscillator + RCC->CR |= RCC_CR_HSEBYP; + RCC->CR |= RCC_CR_HSEON; + while (!(RCC->CR & RCC_CR_HSERDY)) { + } + RCC->CFGR = RCC_CFGR_PLLSRC_HSE; + #endif + // Use HSI16 and the PLL to get a 32MHz SYSCLK + RCC->CFGR |= MICROPY_HW_CLK_PLLMUL | MICROPY_HW_CLK_PLLDIV; + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR & RCC_CR_PLLRDY)) { + // Wait for PLL to lock + } + RCC->CFGR |= RCC_CFGR_SW_PLL; + + while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL) { + // Wait for SYSCLK source to change + } + + SystemCoreClockUpdate(); + powerctrl_config_systick(); + + #if MICROPY_HW_ENABLE_USB + // Enable the 48MHz internal oscillator + RCC->CRRCR |= RCC_CRRCR_HSI48ON; + RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; + SYSCFG->CFGR3 |= SYSCFG_CFGR3_ENREF_HSI48; + while (!(RCC->CRRCR & RCC_CRRCR_HSI48RDY)) { + // Wait for HSI48 to be ready + } + + // Select RC48 as HSI48 for USB and RNG + RCC->CCIPR |= RCC_CCIPR_HSI48SEL; + + // Synchronise HSI48 with 1kHz USB SoF + __HAL_RCC_CRS_CLK_ENABLE(); + CRS->CR = 0x20 << CRS_CR_TRIM_Pos; + CRS->CFGR = 2 << CRS_CFGR_SYNCSRC_Pos | 0x22 << CRS_CFGR_FELIM_Pos + | __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000, 1000) << CRS_CFGR_RELOAD_Pos; + #endif + + // Disable the Debug Module in low-power mode due to prevent + // unexpected HardFault after __WFI(). + #if !defined(NDEBUG) + DBGMCU->CR &= ~(DBGMCU_CR_DBG_SLEEP | DBGMCU_CR_DBG_STOP | DBGMCU_CR_DBG_STANDBY); + #endif +} #elif defined(STM32WB) #include "stm32wbxx_ll_hsem.h" diff --git a/ports/stm32/resethandler_m3.s b/ports/stm32/resethandler_m3.s new file mode 100644 index 0000000000..05a44306e1 --- /dev/null +++ b/ports/stm32/resethandler_m3.s @@ -0,0 +1,75 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 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. + */ + + .syntax unified + .cpu cortex-m3 + .fpu softvfp + .thumb + + .section .text.Reset_Handler + .global Reset_Handler + .type Reset_Handler, %function + +Reset_Handler: + /* Save the first argument to pass through to stm32_main */ + mov r4, r0 + + /* Load the stack pointer */ + ldr r0, =_estack + mov sp, r0 + + /* Initialise the data section */ + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + b .data_copy_entry +.data_copy_loop: + ldr r0, [r1] + adds r1, #4 + str r0, [r2] + adds r2, #4 +.data_copy_entry: + cmp r2, r3 + bcc .data_copy_loop + + /* Zero out the BSS section */ + movs r0, #0 + ldr r1, =_sbss + ldr r2, =_ebss + b .bss_zero_entry +.bss_zero_loop: + str r0, [r1] + adds r1, #4 +.bss_zero_entry: + cmp r1, r2 + bcc .bss_zero_loop + + /* Initialise the system and jump to the main code */ + bl SystemInit + mov r0, r4 + bl stm32_main + + .size Reset_Handler, .-Reset_Handler diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index aacfc3805e..874e427cff 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -91,6 +91,15 @@ STATIC bool rtc_need_init_finalise = false; #define RCC_BDCR_LSEON RCC_CSR_LSEON #define RCC_BDCR_LSERDY RCC_CSR_LSERDY #define RCC_BDCR_LSEBYP RCC_CSR_LSEBYP +#elif defined(STM32L1) +#define BDCR CR +#define RCC_BDCR_RTCEN RCC_CSR_RTCEN +#define RCC_BDCR_RTCSEL RCC_CSR_RTCSEL +#define RCC_BDCR_RTCSEL_0 RCC_CSR_RTCSEL_0 +#define RCC_BDCR_RTCSEL_1 RCC_CSR_RTCSEL_1 +#define RCC_BDCR_LSEON RCC_CSR_LSEON +#define RCC_BDCR_LSERDY RCC_CSR_LSERDY +#define RCC_BDCR_LSEBYP RCC_CSR_LSEBYP #endif void rtc_init_start(bool force_init) { @@ -664,7 +673,15 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { wucksel -= 1; } if (div <= 16) { + #if defined(STM32L1) + if (rtc_use_lse) { + wut = LSE_VALUE / div * ms / 1000; + } else { + wut = LSI_VALUE / div * ms / 1000; + } + #else wut = 32768 / div * ms / 1000; + #endif } else { // use 1Hz clock wucksel = 4; diff --git a/ports/stm32/stm32.mk b/ports/stm32/stm32.mk index c55b243fe5..b4f73a67f3 100644 --- a/ports/stm32/stm32.mk +++ b/ports/stm32/stm32.mk @@ -48,7 +48,7 @@ CFLAGS_CORTEX_M += -mfpu=fpv5-d16 -mfloat-abi=hard SUPPORTS_HARDWARE_FP_SINGLE = 1 SUPPORTS_HARDWARE_FP_DOUBLE = 1 else -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 g0 l0 wl)) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 g0 l0 l1 wl)) CFLAGS_CORTEX_M += -msoft-float else CFLAGS_CORTEX_M += -mfpu=fpv4-sp-d16 -mfloat-abi=hard @@ -64,6 +64,7 @@ CFLAGS_MCU_f7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 CFLAGS_MCU_g0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0plus -mcpu=cortex-m0plus CFLAGS_MCU_g4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_l0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0plus -mcpu=cortex-m0plus +CFLAGS_MCU_l1 = $(CFLAGS_CORTEX_M) -mtune=cortex-m3 -mcpu=cortex-m3 CFLAGS_MCU_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_h7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 CFLAGS_MCU_wb = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index 2f89f67deb..c260499218 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -520,11 +520,19 @@ void ETH_WKUP_IRQHandler(void) { } #endif +#if defined(STM32L1) +void TAMPER_STAMP_IRQHandler(void) { + IRQ_ENTER(TAMPER_STAMP_IRQn); + Handle_EXTI_Irq(EXTI_RTC_TIMESTAMP); + IRQ_EXIT(TAMPER_STAMP_IRQn); +} +#else void TAMP_STAMP_IRQHandler(void) { IRQ_ENTER(TAMP_STAMP_IRQn); Handle_EXTI_Irq(EXTI_RTC_TIMESTAMP); IRQ_EXIT(TAMP_STAMP_IRQn); } +#endif void RTC_WKUP_IRQHandler(void) { IRQ_ENTER(RTC_WKUP_IRQn); @@ -698,6 +706,12 @@ void TIM6_DAC_LPTIM1_IRQHandler(void) { timer_irq_handler(6); IRQ_EXIT(TIM6_DAC_LPTIM1_IRQn); } +#elif defined(STM32L1) +void TIM6_IRQHandler(void) { + IRQ_ENTER(TIM6_IRQn); + timer_irq_handler(6); + IRQ_EXIT(TIM6_IRQn); +} #else void TIM6_DAC_IRQHandler(void) { IRQ_ENTER(TIM6_DAC_IRQn); @@ -764,6 +778,26 @@ void TIM8_TRG_COM_TIM14_IRQHandler(void) { } #endif +#if defined(STM32L1) +void TIM9_IRQHandler(void) { + IRQ_ENTER(TIM9_IRQn); + timer_irq_handler(9); + IRQ_EXIT(TIM9_IRQn); +} + +void TIM10_IRQHandler(void) { + IRQ_ENTER(TIM9_IRQn); + timer_irq_handler(10); + IRQ_EXIT(TIM9_IRQn); +} + +void TIM11_IRQHandler(void) { + IRQ_ENTER(TIM9_IRQn); + timer_irq_handler(11); + IRQ_EXIT(TIM9_IRQn); +} +#endif + #if defined(STM32G0) void TIM14_IRQHandler(void) { IRQ_ENTER(TIM14_IRQn); diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index 7a6ccd4dfd..8816c218f5 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -431,7 +431,7 @@ STATIC mp_obj_t compute_percent_from_pwm_value(uint32_t period, uint32_t cmp) { #endif } -#if !defined(STM32L0) +#if !defined(STM32L0) && !defined(STM32L1) // Computes the 8-bit value for the DTG field in the BDTR register. // @@ -522,7 +522,7 @@ STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV4 ? 4 : self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV2 ? 2 : 1); - #if !defined(STM32L0) + #if !defined(STM32L0) && !defined(STM32L1) #if defined(IS_TIM_ADVANCED_INSTANCE) if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance)) #elif defined(IS_TIM_BREAK_INSTANCE) @@ -640,7 +640,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons args[ARG_div].u_int == 4 ? TIM_CLOCKDIVISION_DIV4 : TIM_CLOCKDIVISION_DIV1; - #if !defined(STM32L0) + #if !defined(STM32L0) && !defined(STM32L1) init->RepetitionCounter = 0; #endif @@ -772,7 +772,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons // init TIM HAL_TIM_Base_Init(&self->tim); - #if !defined(STM32L0) + #if !defined(STM32L0) && !defined(STM32L1) #if defined(IS_TIM_ADVANCED_INSTANCE) if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance)) #elif defined(IS_TIM_BREAK_INSTANCE) @@ -833,7 +833,7 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { TIM_ENTRY(5, TIM5_IRQn), #endif #if defined(TIM6) - #if defined(STM32F412Zx) + #if defined(STM32F412Zx) || defined(STM32L1) TIM_ENTRY(6, TIM6_IRQn), #elif defined(STM32G0) TIM_ENTRY(6, TIM6_DAC_LPTIM1_IRQn), @@ -858,14 +858,26 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { #endif #endif #if defined(TIM9) + #if defined(STM32L1) + TIM_ENTRY(9, TIM9_IRQn), + #else TIM_ENTRY(9, TIM1_BRK_TIM9_IRQn), #endif + #endif #if defined(TIM10) + #if defined(STM32L1) + TIM_ENTRY(10, TIM10_IRQn), + #else TIM_ENTRY(10, TIM1_UP_TIM10_IRQn), #endif + #endif #if defined(TIM11) + #if defined(STM32L1) + TIM_ENTRY(11, TIM11_IRQn), + #else TIM_ENTRY(11, TIM1_TRG_COM_TIM11_IRQn), #endif + #endif #if defined(TIM12) TIM_ENTRY(12, TIM8_BRK_TIM12_IRQn), #endif @@ -936,7 +948,11 @@ STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, size_t n_args, siz memset(tim, 0, sizeof(*tim)); tim->base.type = &pyb_timer_type; tim->tim_id = tim_id; + #if defined(STM32L1) + tim->is_32bit = tim_id == 5; + #else tim->is_32bit = tim_id == 2 || tim_id == 5; + #endif tim->callback = mp_const_none; uint32_t ti = tim_instance_table[tim_id - 1]; tim->tim.Instance = (TIM_TypeDef *)(ti & 0xffffff00); @@ -1168,7 +1184,7 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma } oc_config.OCPolarity = TIM_OCPOLARITY_HIGH; oc_config.OCFastMode = TIM_OCFAST_DISABLE; - #if !defined(STM32L0) + #if !defined(STM32L0) && !defined(STM32L1) oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH; oc_config.OCIdleState = TIM_OCIDLESTATE_SET; oc_config.OCNIdleState = TIM_OCNIDLESTATE_SET; @@ -1180,7 +1196,7 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma } else { pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), chan->callback); } - #if !defined(STM32L0) + #if !defined(STM32L0) && !defined(STM32L1) // Start the complimentary channel too (if its supported) if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) { HAL_TIMEx_PWMN_Start(&self->tim, TIMER_CHANNEL(chan)); @@ -1203,7 +1219,7 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma oc_config.OCPolarity = TIM_OCPOLARITY_HIGH; } oc_config.OCFastMode = TIM_OCFAST_DISABLE; - #if !defined(STM32L0) + #if !defined(STM32L0) && !defined(STM32L1) if (oc_config.OCPolarity == TIM_OCPOLARITY_HIGH) { oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH; } else { @@ -1222,7 +1238,7 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma } else { pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), chan->callback); } - #if !defined(STM32L0) + #if !defined(STM32L0) && !defined(STM32L1) // Start the complimentary channel too (if its supported) if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) { HAL_TIMEx_OCN_Start(&self->tim, TIMER_CHANNEL(chan)); diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index cea49f4ba1..6d1240cf8d 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -38,7 +38,7 @@ #include "irq.h" #include "pendsv.h" -#if defined(STM32F4) +#if defined(STM32F4) || defined(STM32L1) #define UART_RXNE_IS_SET(uart) ((uart)->SR & USART_SR_RXNE) #else #if defined(STM32G0) || defined(STM32H7) || defined(STM32WL) @@ -101,6 +101,11 @@ #define USART_CR2_IE_ALL (USART_CR2_IE_BASE) #define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_WUFIE) +#elif defined(STM32L1) +#define USART_CR1_IE_ALL (USART_CR1_IE_BASE) +#define USART_CR2_IE_ALL (USART_CR2_IE_BASE) +#define USART_CR3_IE_ALL (USART_CR3_IE_BASE) + #elif defined(STM32L4) || defined(STM32WB) || defined(STM32WL) #define USART_CR1_IE_ALL (USART_CR1_IE_BASE | USART_CR1_EOBIE | USART_CR1_RTOIE | USART_CR1_CMIE) #define USART_CR2_IE_ALL (USART_CR2_IE_BASE) @@ -580,7 +585,7 @@ bool uart_init(pyb_uart_obj_t *uart_obj, huart.FifoMode = UART_FIFOMODE_ENABLE; #endif - #if !defined(STM32F4) + #if !defined(STM32F4) && !defined(STM32L1) huart.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; #endif @@ -1016,7 +1021,7 @@ STATIC bool uart_wait_flag_set(pyb_uart_obj_t *self, uint32_t flag, uint32_t tim // an interrupt and the flag can be set quickly if the baudrate is large. uint32_t start = HAL_GetTick(); for (;;) { - #if defined(STM32F4) + #if defined(STM32F4) || defined(STM32L1) if (self->uartx->SR & flag) { return true; } @@ -1071,7 +1076,7 @@ size_t uart_tx_data(pyb_uart_obj_t *self, const void *src_in, size_t num_chars, } else { data = *src++; } - #if defined(STM32F4) + #if defined(STM32F4) || defined(STM32L1) uart->DR = data; #else uart->TDR = data; @@ -1109,7 +1114,7 @@ void uart_irq_handler(mp_uint_t uart_id) { } // Capture IRQ status flags. - #if defined(STM32F4) + #if defined(STM32F4) || defined(STM32L1) self->mp_irq_flags = self->uartx->SR; bool rxne_is_set = self->mp_irq_flags & USART_SR_RXNE; bool did_clear_sr = false; @@ -1153,7 +1158,7 @@ void uart_irq_handler(mp_uint_t uart_id) { } // Clear other interrupt flags that can trigger this IRQ handler. - #if defined(STM32F4) + #if defined(STM32F4) || defined(STM32L1) if (did_clear_sr) { // SR was cleared above. Re-enable IDLE if it should be enabled. if (self->mp_irq_trigger & UART_FLAG_IDLE) { diff --git a/ports/stm32/uart.h b/ports/stm32/uart.h index ec8a27591c..61d1ac4397 100644 --- a/ports/stm32/uart.h +++ b/ports/stm32/uart.h @@ -103,7 +103,7 @@ size_t uart_tx_data(pyb_uart_obj_t *self, const void *src_in, size_t num_chars, void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len); static inline bool uart_tx_avail(pyb_uart_obj_t *self) { - #if defined(STM32F4) + #if defined(STM32F4) || defined(STM32L1) return self->uartx->SR & USART_SR_TXE; #elif defined(STM32G0) || defined(STM32H7) || defined(STM32WL) return self->uartx->ISR & USART_ISR_TXE_TXFNF; From e6d351318746495bf88d2c4bd7cbd81e94a2290e Mon Sep 17 00:00:00 2001 From: yn386 Date: Mon, 19 Sep 2022 17:57:27 +0900 Subject: [PATCH 0446/1041] stm32/boards/NUCLEO_L152RE: Add NUCLEO-L152RE board support. This change adds NUCLEO-L152RE support to the STM32 port. NUCLEO-L152RE: https://www.st.com/en/evaluation-tools/nucleo-l152re.html This board use STM32L152RE: https://www.st.com/en/microcontrollers-microprocessors/stm32l152re.html --- ports/stm32/boards/NUCLEO_L152RE/board.json | 15 ++++ ports/stm32/boards/NUCLEO_L152RE/deploy.md | 31 ++++++++ .../boards/NUCLEO_L152RE/mpconfigboard.h | 74 ++++++++++++++++++ .../boards/NUCLEO_L152RE/mpconfigboard.mk | 4 + ports/stm32/boards/NUCLEO_L152RE/pins.csv | 76 +++++++++++++++++++ .../boards/NUCLEO_L152RE/stm32l1xx_hal_conf.h | 10 +++ 6 files changed, 210 insertions(+) create mode 100644 ports/stm32/boards/NUCLEO_L152RE/board.json create mode 100644 ports/stm32/boards/NUCLEO_L152RE/deploy.md create mode 100644 ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.h create mode 100644 ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.mk create mode 100644 ports/stm32/boards/NUCLEO_L152RE/pins.csv create mode 100644 ports/stm32/boards/NUCLEO_L152RE/stm32l1xx_hal_conf.h diff --git a/ports/stm32/boards/NUCLEO_L152RE/board.json b/ports/stm32/boards/NUCLEO_L152RE/board.json new file mode 100644 index 0000000000..7b34276937 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_L152RE/board.json @@ -0,0 +1,15 @@ +{ + "deploy": [ + "./deploy.md" + ], + "docs": "", + "features": [], + "images": [ + "nucleo_l152re.jpg" + ], + "mcu": "stm32l1", + "product": "Nucleo L152RE", + "thumbnail": "", + "url": "", + "vendor": "ST Microelectronics" +} diff --git a/ports/stm32/boards/NUCLEO_L152RE/deploy.md b/ports/stm32/boards/NUCLEO_L152RE/deploy.md new file mode 100644 index 0000000000..0323981d2d --- /dev/null +++ b/ports/stm32/boards/NUCLEO_L152RE/deploy.md @@ -0,0 +1,31 @@ +### STM32 via ST-Link + +Nucleo and Discovery boards typically include a built-in ST-Link programmer. + +A `.bin` or `.hex` file can be flashed using [st-flash](https://github.com/stlink-org/stlink). + +```bash +# Optional erase to clear existing filesystem. +st-flash erase + +# Flash .bin +st-flash write firmware.bin 0x08000000 +# or, flash .hex +st-flash --format ihex write firmware.hex +``` + +A `.hex` file can be flashed using [STM32 Cube Programmer](https://www.st.com/en/development-tools/stm32cubeprog.html). + +```bash +STM32_Programmer.sh -c port=SWD mode=UR dLPM -d firmware.hex -v -hardRst +``` + +### STM32 via DFU + +Boards with USB support can also be programmed via the ST DFU bootloader, using e.g. [dfu-util](http://dfu-util.sourceforge.net/) or [pydfu.py](https://github.com/micropython/micropython/blob/master/tools/pydfu.py). + +To enter the bootloader the `BOOT0` pin can be connected to `VCC` during reset, or you can use `machine.bootloader()` from the MicroPython REPL. + +```bash +dfu-util --alt 0 -D firmware.dfu +``` diff --git a/ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.h b/ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.h new file mode 100644 index 0000000000..3609955893 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.h @@ -0,0 +1,74 @@ +#define MICROPY_HW_BOARD_NAME "NUCLEO-L152RE" +#define MICROPY_HW_MCU_NAME "STM32L152xE" + +#define MICROPY_HW_HAS_SWITCH (1) +#define MICROPY_HW_ENABLE_RTC (1) +// This board has an external 32kHz crystal +#define MICROPY_HW_RTC_USE_LSE (1) +#define MICROPY_HW_ENABLE_SERVO (1) +#define MICROPY_HW_ENABLE_DAC (1) + +// HSE is 8MHz, HSI is 16MHz CPU freq set to 32MHz +// Default source for the clock is HSI. +// For revisions of the board greater than C-01, HSE can be used as a +// clock source by removing the #define MICROPY_HW_CLK_USE_HSE line +#define MICROPY_HW_CLK_USE_HSI (1) + +#if MICROPY_HW_CLK_USE_HSI +#define MICROPY_HW_CLK_PLLMUL (RCC_CFGR_PLLMUL6) +#define MICROPY_HW_CLK_PLLDIV (RCC_CFGR_PLLDIV3) +#else +#define MICROPY_HW_CLK_PLLMUL (RCC_CFGR_PLLMUL12) +#define MICROPY_HW_CLK_PLLDIV (RCC_CFGR_PLLDIV3) +#endif + +// UART config +#define MICROPY_HW_UART1_TX (pin_A9) +#define MICROPY_HW_UART1_RX (pin_A10) +#define MICROPY_HW_UART2_TX (pin_A2) +#define MICROPY_HW_UART2_RX (pin_A3) +#define MICROPY_HW_UART3_TX (pin_B10) +#define MICROPY_HW_UART3_RX (pin_B11) +#define MICROPY_HW_UART4_TX (pin_C10) +#define MICROPY_HW_UART4_RX (pin_C11) +#define MICROPY_HW_UART5_TX (pin_C12) +#define MICROPY_HW_UART5_RX (pin_D2) +// UART 2 connects to the STM32F103 (STLINK) on the Nucleo board +// and this is exposed as a USB Serial port. +#define MICROPY_HW_UART_REPL PYB_UART_2 +#define MICROPY_HW_UART_REPL_BAUD 115200 + +// I2C buses +#define MICROPY_HW_I2C1_SCL (pin_B8) // Arduino D15, pin 3 on CN10 +#define MICROPY_HW_I2C1_SDA (pin_B9) // D14, pin 5 on CN10 +#define MICROPY_HW_I2C2_SCL (pin_B10) // Arduino D6, pin 25 on CN10 +#define MICROPY_HW_I2C2_SDA (pin_B11) // Arduino D3, pin 31 on CN10 + +// SPI buses +#define MICROPY_HW_SPI1_NSS (pin_A15) // pin 17 on CN7 +#define MICROPY_HW_SPI1_SCK (pin_A5) // Arduino D13, pin 11 on CN10 +#define MICROPY_HW_SPI1_MISO (pin_A6) // Arduino D12, pin 13 on CN10 +#define MICROPY_HW_SPI1_MOSI (pin_A7) // Arduino D11, pin 15 on CN10 + +#define MICROPY_HW_SPI2_NSS (pin_B12) // pin 16 on CN10 +#define MICROPY_HW_SPI2_SCK (pin_B13) // pin 30 on CN10 +#define MICROPY_HW_SPI2_MISO (pin_B14) // pin 28 on CN10 +#define MICROPY_HW_SPI2_MOSI (pin_B15) // pin 26 on CN10 + +#define MICROPY_HW_SPI3_NSS (pin_A4) // Arduino A2, pin 32 on CN7 +#define MICROPY_HW_SPI3_SCK (pin_C10) // Arduino D3, pin 31 on CN10 +#define MICROPY_HW_SPI3_MISO (pin_C11) // Arduino D5, pin 27 on CN10 +#define MICROPY_HW_SPI3_MOSI (pin_C12) // Arduino D4, pin 29 on CN10 + +// USRSW is pulled low. Pressing the button makes the input go high. +#define MICROPY_HW_USRSW_PIN (pin_C13) +#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) +#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) +#define MICROPY_HW_USRSW_PRESSED (0) + +// LEDs +#define MICROPY_HW_LED1 (pin_A5) // Green LD2 LED on Nucleo +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) + +#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_1 diff --git a/ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.mk new file mode 100644 index 0000000000..a62a775ac8 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.mk @@ -0,0 +1,4 @@ +MCU_SERIES = l1 +CMSIS_MCU = STM32L152xE +AF_FILE = boards/stm32l152_af.csv +LD_FILES = boards/stm32l152xe.ld boards/common_basic.ld diff --git a/ports/stm32/boards/NUCLEO_L152RE/pins.csv b/ports/stm32/boards/NUCLEO_L152RE/pins.csv new file mode 100644 index 0000000000..035d933f5d --- /dev/null +++ b/ports/stm32/boards/NUCLEO_L152RE/pins.csv @@ -0,0 +1,76 @@ +D0,PA3 +D1,PA2 +D2,PA10 +D3,PB3 +D4,PB5 +D5,PB4 +D6,PB10 +D7,PA8 +D8,PA9 +D9,PC7 +D10,PB6 +D11,PA7 +D12,PA6 +D13,PA5 +D14,PB9 +D15,PB8 +A0,PA0 +A1,PA1 +A2,PA4 +A3,PB0 +A4,PC1 +A5,PC0 +PA0,PA0 +PA1,PA1 +PA2,PA2 +PA3,PA3 +PA4,PA4 +PA5,PA5 +PA6,PA6 +PA7,PA7 +PA8,PA8 +PA9,PA9 +PA10,PA10 +PA11,PA11 +PA12,PA12 +PA15,PA15 +PB0,PB0 +PB1,PB1 +PB2,PB2 +PB3,PB3 +PB4,PB4 +PB5,PB5 +PB6,PB6 +PB7,PB7 +PB8,PB8 +PB9,PB9 +PB10,PB10 +PB11,PB11 +PB12,PB12 +PB13,PB13 +PB14,PB14 +PB15,PB15 +PC0,PC0 +PC1,PC1 +PC2,PC2 +PC3,PC3 +PC4,PC4 +PC5,PC5 +PC6,PC6 +PC7,PC7 +PC8,PC8 +PC9,PC9 +PC10,PC10 +PC11,PC11 +PC12,PC12 +PC13,PC13 +PC14,PC14 +PC15,PC15 +PD2,PD2 +PH0,PH0 +PH1,PH1 +LED_GREEN,PA5 +LED_ORANGE,PA5 +LED_RED,PA5 +LED_BLUE,PA4 +SW,PC13 diff --git a/ports/stm32/boards/NUCLEO_L152RE/stm32l1xx_hal_conf.h b/ports/stm32/boards/NUCLEO_L152RE/stm32l1xx_hal_conf.h new file mode 100644 index 0000000000..7ee8204cbf --- /dev/null +++ b/ports/stm32/boards/NUCLEO_L152RE/stm32l1xx_hal_conf.h @@ -0,0 +1,10 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32L1XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32L1XX_HAL_CONF_H + +#include "boards/stm32l1xx_hal_conf_base.h" + +#endif // MICROPY_INCLUDED_STM32L1XX_HAL_CONF_H From 3abcfb9aecd567c4c74fd3c99703f23c372b7445 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 26 Sep 2022 00:07:58 +1000 Subject: [PATCH 0447/1041] esp32/modsocket: Use mp_obj_is_integer to test port type. Because the value may be a big integer, which is still a valid type to use. Fixes issue #9410. Signed-off-by: Damien George --- ports/esp32/modsocket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/modsocket.c b/ports/esp32/modsocket.c index 334c5bae33..9812eb3476 100644 --- a/ports/esp32/modsocket.c +++ b/ports/esp32/modsocket.c @@ -214,7 +214,7 @@ static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struc }; mp_obj_t port = portx; - if (mp_obj_is_small_int(port)) { + if (mp_obj_is_integer(port)) { // This is perverse, because lwip_getaddrinfo promptly converts it back to an int, but // that's the API we have to work with ... port = mp_obj_str_binary_op(MP_BINARY_OP_MODULO, mp_obj_new_str_via_qstr("%s", 2), port); From dd9dcb594c577cb818c336db59a884fd329c3840 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 25 Sep 2022 22:12:29 +1000 Subject: [PATCH 0448/1041] esp32/machine_pwm: Don't use LEDC_USE_REF_TICK on ESP32-C3 variants. Because it's not supported by this particular MCU (since IDF v4.4.2). Signed-off-by: Damien George --- ports/esp32/machine_pwm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ports/esp32/machine_pwm.c b/ports/esp32/machine_pwm.c index 0107187a8c..2a456c71c7 100644 --- a/ports/esp32/machine_pwm.c +++ b/ports/esp32/machine_pwm.c @@ -97,8 +97,10 @@ STATIC ledc_timer_config_t timers[PWM_TIMER_MAX]; // How much to shift from the HIGHEST_PWM_RES duty resolution to the user interface duty resolution UI_RES_16_BIT #define UI_RES_SHIFT (UI_RES_16_BIT - HIGHEST_PWM_RES) // 0 for ESP32, 2 for S2, S3, C3 +#if SOC_LEDC_SUPPORT_REF_TICK // If the PWM frequency is less than EMPIRIC_FREQ, then LEDC_REF_CLK_HZ(1 MHz) source is used, else LEDC_APB_CLK_HZ(80 MHz) source is used #define EMPIRIC_FREQ (10) // Hz +#endif // Config of timer upon which we run all PWM'ed GPIO pins STATIC bool pwm_inited = false; @@ -208,9 +210,11 @@ STATIC void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_conf if (freq != timer->freq_hz) { // Find the highest bit resolution for the requested frequency unsigned int i = LEDC_APB_CLK_HZ; // 80 MHz + #if SOC_LEDC_SUPPORT_REF_TICK if (freq < EMPIRIC_FREQ) { i = LEDC_REF_CLK_HZ; // 1 MHz } + #endif #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) // original code @@ -243,9 +247,11 @@ STATIC void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_conf timer->duty_resolution = res; timer->freq_hz = freq; timer->clk_cfg = LEDC_USE_APB_CLK; + #if SOC_LEDC_SUPPORT_REF_TICK if (freq < EMPIRIC_FREQ) { timer->clk_cfg = LEDC_USE_REF_TICK; } + #endif // Set frequency esp_err_t err = ledc_timer_config(timer); From 9d6f474ea49fd89b7a1a90b830e6014ef70a89b7 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sun, 25 Sep 2022 22:15:45 +1000 Subject: [PATCH 0449/1041] py/objstr: Don't treat bytes as unicode in str.count. `b'\xaa \xaa'.count(b'\xaa')` now (correctly) returns 2 instead of 1. Fixes issue #9404. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared --- py/objstr.c | 4 +++- tests/basics/bytes_count.py | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/py/objstr.c b/py/objstr.c index 62d7bfb4cc..55e737fffc 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -1768,6 +1768,8 @@ STATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) { return MP_OBJ_NEW_SMALL_INT(utf8_charlen(start, end - start) + 1); } + bool is_str = self_type == &mp_type_str; + // count the occurrences mp_int_t num_occurrences = 0; for (const byte *haystack_ptr = start; haystack_ptr + needle_len <= end;) { @@ -1775,7 +1777,7 @@ STATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) { num_occurrences++; haystack_ptr += needle_len; } else { - haystack_ptr = utf8_next_char(haystack_ptr); + haystack_ptr = is_str ? utf8_next_char(haystack_ptr) : haystack_ptr + 1; } } diff --git a/tests/basics/bytes_count.py b/tests/basics/bytes_count.py index 5fa0730f5c..e71f09db00 100644 --- a/tests/basics/bytes_count.py +++ b/tests/basics/bytes_count.py @@ -48,6 +48,13 @@ print(b"aaaa".count(b'a', 1, 5)) print(b"aaaa".count(b'a', -1, 5)) print(b"abbabba".count(b"abba")) +print(b'\xaa \xaa'.count(b'\xaa')) +print(b'\xaa \xaa \xaa \xaa'.count(b'\xaa')) +print(b'\xaa \xaa \xaa \xaa'.count(b'\xaa'), 1) +print(b'\xaa \xaa \xaa \xaa'.count(b'\xaa'), 2) +print(b'\xaa \xaa \xaa \xaa'.count(b'\xaa'), 1, 3) +print(b'\xaa \xaa \xaa \xaa'.count(b'\xaa'), 2, 3) + def t(): return True From 0bc1d1055748dd41a2db10a4c6cab32499c488f9 Mon Sep 17 00:00:00 2001 From: Matt Trentini Date: Sun, 11 Sep 2022 11:40:59 +1000 Subject: [PATCH 0450/1041] rp2/Makefile: Add support for BOARD_VARIANTS. Following stm32. This allows a single board definition to define variants of its configuration. --- ports/rp2/Makefile | 9 +++++++++ py/mkrules.cmake | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/ports/rp2/Makefile b/ports/rp2/Makefile index c603f5403f..7057021bfc 100644 --- a/ports/rp2/Makefile +++ b/ports/rp2/Makefile @@ -22,6 +22,10 @@ ifeq ($(DEBUG),1) CMAKE_ARGS += -DCMAKE_BUILD_TYPE=Debug endif +ifdef BOARD_VARIANT +CMAKE_ARGS += -DBOARD_VARIANT=${BOARD_VARIANT} +endif + HELP_BUILD_ERROR ?= "See \033[1;31mhttps://github.com/micropython/micropython/wiki/Build-Troubleshooting\033[0m" all: @@ -38,3 +42,8 @@ submodules: GIT_SUBMODULES=$$(cmake -B $(BUILD)/submodules -DECHO_SUBMODULES=1 ${CMAKE_ARGS} -S . 2>&1 | \ grep '^GIT_SUBMODULES=' | cut -d= -f2); \ $(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="$${GIT_SUBMODULES}" submodules + +query-variants: + @BOARD_VARIANTS=$$(cmake -B $(BUILD)/variants -DECHO_BOARD_VARIANTS=1 ${CMAKE_ARGS} -S . 2>&1 | \ + grep '^BOARD_VARIANTS=' | cut -d= -f2); \ + echo "VARIANTS: $${BOARD_VARIANTS}" diff --git a/py/mkrules.cmake b/py/mkrules.cmake index e7c4101ddb..b29986585a 100644 --- a/py/mkrules.cmake +++ b/py/mkrules.cmake @@ -223,3 +223,9 @@ if(ECHO_SUBMODULES) execute_process(COMMAND ${CMAKE_COMMAND} -E echo "GIT_SUBMODULES=${GIT_SUBMODULES}") message(FATAL_ERROR "Done") endif() + +# Display BOARD_VARIANTS +if(ECHO_BOARD_VARIANTS) + execute_process(COMMAND ${CMAKE_COMMAND} -E echo "BOARD_VARIANTS=${BOARD_VARIANTS}") + message(FATAL_ERROR "Done") +endif() From bdbc44474f92db19a40b5f710a140a0bf70fb0ec Mon Sep 17 00:00:00 2001 From: Matt Trentini Date: Thu, 7 Apr 2022 23:33:36 +1000 Subject: [PATCH 0451/1041] rp2/boards/WEACTSTUDIO: Add WEACTSTUDIO with multiple variants. This supports 2, 4, 8 and 16MB flash variants. --- ports/rp2/boards/WEACTSTUDIO/README.md | 34 ++++++++++ ports/rp2/boards/WEACTSTUDIO/board.json | 23 +++++++ ports/rp2/boards/WEACTSTUDIO/deploy.md | 8 +++ ports/rp2/boards/WEACTSTUDIO/manifest.py | 2 + ports/rp2/boards/WEACTSTUDIO/modules/board.py | 4 ++ .../boards/WEACTSTUDIO/mpconfigboard.cmake | 26 ++++++++ ports/rp2/boards/WEACTSTUDIO/mpconfigboard.h | 4 ++ .../rp2/boards/WEACTSTUDIO/weactstudio_16mb.h | 18 ++++++ .../rp2/boards/WEACTSTUDIO/weactstudio_2mb.h | 18 ++++++ .../rp2/boards/WEACTSTUDIO/weactstudio_4mb.h | 18 ++++++ .../rp2/boards/WEACTSTUDIO/weactstudio_8mb.h | 18 ++++++ .../boards/WEACTSTUDIO/weactstudio_common.h | 62 +++++++++++++++++++ 12 files changed, 235 insertions(+) create mode 100644 ports/rp2/boards/WEACTSTUDIO/README.md create mode 100644 ports/rp2/boards/WEACTSTUDIO/board.json create mode 100644 ports/rp2/boards/WEACTSTUDIO/deploy.md create mode 100644 ports/rp2/boards/WEACTSTUDIO/manifest.py create mode 100644 ports/rp2/boards/WEACTSTUDIO/modules/board.py create mode 100644 ports/rp2/boards/WEACTSTUDIO/mpconfigboard.cmake create mode 100644 ports/rp2/boards/WEACTSTUDIO/mpconfigboard.h create mode 100644 ports/rp2/boards/WEACTSTUDIO/weactstudio_16mb.h create mode 100644 ports/rp2/boards/WEACTSTUDIO/weactstudio_2mb.h create mode 100644 ports/rp2/boards/WEACTSTUDIO/weactstudio_4mb.h create mode 100644 ports/rp2/boards/WEACTSTUDIO/weactstudio_8mb.h create mode 100644 ports/rp2/boards/WEACTSTUDIO/weactstudio_common.h diff --git a/ports/rp2/boards/WEACTSTUDIO/README.md b/ports/rp2/boards/WEACTSTUDIO/README.md new file mode 100644 index 0000000000..ae0acfd2c7 --- /dev/null +++ b/ports/rp2/boards/WEACTSTUDIO/README.md @@ -0,0 +1,34 @@ +# WeAct Studio RP2040 + +The WeAct Studio RP2040 Board is based on the Raspberry Pi RP2040 and can be +purchased with 2/4/8/16 MiB of flash. + +These boards are available from a number of resellers and often have the name +"Pico Board RP2040". WeAct maintain the [WeActStudio.RP2040CoreBoard](https://github.com/WeActTC/WeActStudio.RP2040CoreBoard/tree/master) +repository containing information on the board. + +## Build notes + +Builds can be configured with the `BOARD_VARIANT` parameter. Valid variants +can be displayed with the `query-variant` target. An example: + +```bash +> cd ports/rp2 +> make BOARD=WEACTSTUDIO query-variants +VARIANTS: flash_2mb flash_4mb flash_8mb flash_16mb +> make BOARD=WEACTSTUDIO BOARD_VARIANT=flash_8mb submodules all # Build the 8 MiB variant +``` + +`flash_16mb` is the default if `BOARD_VARIANT` is not supplied. + +## Board-specific modules + +The `board` module contains definitions for the onboard LED and user button. + +Example: + +```python +> import board +> board.led.toggle() # Toggles the state of the on-board LED +> board.key.value() # Returns 0 or 1 corresponding to the state of the user key +``` diff --git a/ports/rp2/boards/WEACTSTUDIO/board.json b/ports/rp2/boards/WEACTSTUDIO/board.json new file mode 100644 index 0000000000..bac5263627 --- /dev/null +++ b/ports/rp2/boards/WEACTSTUDIO/board.json @@ -0,0 +1,23 @@ +{ + "deploy": [ + "deploy.md" + ], + "docs": "", + "features": [ + "Breadboard Friendly", + "SPI Flash", + "USB-C" + ], + "images": [ + "weact_rp2040.jpg" + ], + "mcu": "rp2040", + "product": "WeAct Studio RP2040", + "url": "https://github.com/WeActTC/WeActStudio.RP2040CoreBoard", + "variants": { + "flash_2mb": "2 MiB Flash", + "flash_4mb": "4 MiB Flash", + "flash_8mb": "8 MiB Flash" + }, + "vendor": "WeAct" +} diff --git a/ports/rp2/boards/WEACTSTUDIO/deploy.md b/ports/rp2/boards/WEACTSTUDIO/deploy.md new file mode 100644 index 0000000000..b4db7675eb --- /dev/null +++ b/ports/rp2/boards/WEACTSTUDIO/deploy.md @@ -0,0 +1,8 @@ +### Flashing via UF2 bootloader + +To get the board in bootloader mode ready for the firmware update, execute +`machine.bootloader()` at the MicroPython REPL. Alternatively, hold +down the BOOTSEL button while pressing reset (NRST). The uf2 file below +should then be copied to the USB mass storage device that appears. Once +programming of the new firmware is complete the device will automatically reset +and be ready for use. diff --git a/ports/rp2/boards/WEACTSTUDIO/manifest.py b/ports/rp2/boards/WEACTSTUDIO/manifest.py new file mode 100644 index 0000000000..f993d4fa6b --- /dev/null +++ b/ports/rp2/boards/WEACTSTUDIO/manifest.py @@ -0,0 +1,2 @@ +include("$(PORT_DIR)/boards/manifest.py") +freeze("./modules") diff --git a/ports/rp2/boards/WEACTSTUDIO/modules/board.py b/ports/rp2/boards/WEACTSTUDIO/modules/board.py new file mode 100644 index 0000000000..dd3b31b805 --- /dev/null +++ b/ports/rp2/boards/WEACTSTUDIO/modules/board.py @@ -0,0 +1,4 @@ +from machine import Pin + +led = Pin(25, Pin.OUT, value=0) +key = Pin(23, Pin.IN, Pin.PULL_UP) diff --git a/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.cmake b/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.cmake new file mode 100644 index 0000000000..5fd3eec897 --- /dev/null +++ b/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.cmake @@ -0,0 +1,26 @@ +# CMake file for WeAct Studio RP2040 boards + +# The WeAct Studio boards don't have official pico-sdk support so we define it +# See also: https://github.com/raspberrypi/pico-sdk/tree/master/src/boards/include/boards +list(APPEND PICO_BOARD_HEADER_DIRS ${MICROPY_BOARD_DIR}) + +# Freeze board.py +set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py) + +# Provide different variants for the downloads page +set(BOARD_VARIANTS "flash_2mb flash_4mb flash_8mb flash_16mb") + +# Select the 16MB variant as the default +set(PICO_BOARD "weactstudio_16mb") + +if("${BOARD_VARIANT}" STREQUAL "flash_2mb") + set(PICO_BOARD "weactstudio_2mb") +endif() + +if("${BOARD_VARIANT}" STREQUAL "flash_4mb") +set(PICO_BOARD "weactstudio_4mb") +endif() + +if("${BOARD_VARIANT}" STREQUAL "flash_8mb") +set(PICO_BOARD "weactstudio_8mb") +endif() diff --git a/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.h b/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.h new file mode 100644 index 0000000000..3c72ef4fca --- /dev/null +++ b/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.h @@ -0,0 +1,4 @@ +#define MICROPY_HW_BOARD_NAME "WeAct Studio RP2040" + +// Allow 1MB for the firmware image itself, allocate the remainder to the filesystem +#define MICROPY_HW_FLASH_STORAGE_BYTES (PICO_FLASH_SIZE_BYTES - (1 * 1024 * 1024)) diff --git a/ports/rp2/boards/WEACTSTUDIO/weactstudio_16mb.h b/ports/rp2/boards/WEACTSTUDIO/weactstudio_16mb.h new file mode 100644 index 0000000000..b6208c6897 --- /dev/null +++ b/ports/rp2/boards/WEACTSTUDIO/weactstudio_16mb.h @@ -0,0 +1,18 @@ +// A pico-sdk board definition is required since the WeAct Studio boards are +// not officially supported. +// +// Officially supported boards: +// https://github.com/raspberrypi/pico-sdk/tree/master/src/boards/include/boards + +#ifndef _BOARDS_WEACTSTUDIO_16MB_H +#define _BOARDS_WEACTSTUDIO_16MB_H + +#include "weactstudio_common.h" + +#define WEACTSTUDIO_16MB + +#ifndef PICO_FLASH_SIZE_BYTES +#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024) +#endif + +#endif diff --git a/ports/rp2/boards/WEACTSTUDIO/weactstudio_2mb.h b/ports/rp2/boards/WEACTSTUDIO/weactstudio_2mb.h new file mode 100644 index 0000000000..e6a21ea3bc --- /dev/null +++ b/ports/rp2/boards/WEACTSTUDIO/weactstudio_2mb.h @@ -0,0 +1,18 @@ +// A pico-sdk board definition is required since the WeAct Studio boards are +// not officially supported. +// +// Officially supported boards: +// https://github.com/raspberrypi/pico-sdk/tree/master/src/boards/include/boards + +#ifndef _BOARDS_WEACTSTUDIO_2MB_H +#define _BOARDS_WEACTSTUDIO_2MB_H + +#include "weactstudio_common.h" + +#define WEACTSTUDIO_2MB + +#ifndef PICO_FLASH_SIZE_BYTES +#define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024) +#endif + +#endif diff --git a/ports/rp2/boards/WEACTSTUDIO/weactstudio_4mb.h b/ports/rp2/boards/WEACTSTUDIO/weactstudio_4mb.h new file mode 100644 index 0000000000..7a2836ab4a --- /dev/null +++ b/ports/rp2/boards/WEACTSTUDIO/weactstudio_4mb.h @@ -0,0 +1,18 @@ +// A pico-sdk board definition is required since the WeAct Studio boards are +// not officially supported. +// +// Officially supported boards: +// https://github.com/raspberrypi/pico-sdk/tree/master/src/boards/include/boards + +#ifndef _BOARDS_WEACTSTUDIO_4MB_H +#define _BOARDS_WEACTSTUDIO_4MB_H + +#include "weactstudio_common.h" + +#define WEACTSTUDIO_4MB + +#ifndef PICO_FLASH_SIZE_BYTES +#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024) +#endif + +#endif diff --git a/ports/rp2/boards/WEACTSTUDIO/weactstudio_8mb.h b/ports/rp2/boards/WEACTSTUDIO/weactstudio_8mb.h new file mode 100644 index 0000000000..82baf6688e --- /dev/null +++ b/ports/rp2/boards/WEACTSTUDIO/weactstudio_8mb.h @@ -0,0 +1,18 @@ +// A pico-sdk board definition is required since the WeAct Studio boards are +// not officially supported. +// +// Officially supported boards: +// https://github.com/raspberrypi/pico-sdk/tree/master/src/boards/include/boards + +#ifndef _BOARDS_WEACTSTUDIO_8MB_H +#define _BOARDS_WEACTSTUDIO_8MB_H + +#include "weactstudio_common.h" + +#define WEACTSTUDIO_8MB + +#ifndef PICO_FLASH_SIZE_BYTES +#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024) +#endif + +#endif diff --git a/ports/rp2/boards/WEACTSTUDIO/weactstudio_common.h b/ports/rp2/boards/WEACTSTUDIO/weactstudio_common.h new file mode 100644 index 0000000000..f1c6903601 --- /dev/null +++ b/ports/rp2/boards/WEACTSTUDIO/weactstudio_common.h @@ -0,0 +1,62 @@ +// Common configuration to all WeAct Studio boards (only flash size differs) + +#ifndef _BOARDS_WEACTSTUDIO_COMMON_H +#define _BOARDS_WEACTSTUDIO_COMMON_H + +// --- UART --- +#ifndef PICO_DEFAULT_UART +#define PICO_DEFAULT_UART 0 +#endif +#ifndef PICO_DEFAULT_UART_TX_PIN +#define PICO_DEFAULT_UART_TX_PIN 0 +#endif +#ifndef PICO_DEFAULT_UART_RX_PIN +#define PICO_DEFAULT_UART_RX_PIN 1 +#endif + +// --- LED --- +#ifndef PICO_DEFAULT_LED_PIN +#define PICO_DEFAULT_LED_PIN 25 +#endif + +// --- I2C --- +#ifndef PICO_DEFAULT_I2C +#define PICO_DEFAULT_I2C 0 +#endif +#ifndef PICO_DEFAULT_I2C_SDA_PIN +#define PICO_DEFAULT_I2C_SDA_PIN 4 +#endif +#ifndef PICO_DEFAULT_I2C_SCL_PIN +#define PICO_DEFAULT_I2C_SCL_PIN 5 +#endif + +// --- SPI --- +#ifndef PICO_DEFAULT_SPI +#define PICO_DEFAULT_SPI 0 +#endif +#ifndef PICO_DEFAULT_SPI_SCK_PIN +#define PICO_DEFAULT_SPI_SCK_PIN 18 +#endif +#ifndef PICO_DEFAULT_SPI_TX_PIN +#define PICO_DEFAULT_SPI_TX_PIN 19 +#endif +#ifndef PICO_DEFAULT_SPI_RX_PIN +#define PICO_DEFAULT_SPI_RX_PIN 16 +#endif +#ifndef PICO_DEFAULT_SPI_CSN_PIN +#define PICO_DEFAULT_SPI_CSN_PIN 17 +#endif + +// --- FLASH --- +#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1 + +#ifndef PICO_FLASH_SPI_CLKDIV +#define PICO_FLASH_SPI_CLKDIV 2 +#endif + +// All boards have B1 RP2040 +#ifndef PICO_RP2040_B0_SUPPORTED +#define PICO_RP2040_B0_SUPPORTED 0 +#endif + +#endif From 71050870b81a8dbf3c3fac93bd2d86f0ff9a37d2 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 28 Sep 2022 01:04:05 +1000 Subject: [PATCH 0452/1041] mpy-cross/mpy_cross: Fix default path to mpy-cross binary. Needed to be updated to use build/mpy-cross. Also fixes some other issues in the Python wrapper: - Rename find_mpy_cross_binary to _find_mpy_cross_binary - Fix passing of -march arg. - Decode stdout from subprocess. - Print stdout from mpy-cross in __main__.py. Signed-off-by: Jim Mussared --- mpy-cross/mpy_cross/__init__.py | 12 +++++++----- mpy-cross/mpy_cross/__main__.py | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/mpy-cross/mpy_cross/__init__.py b/mpy-cross/mpy_cross/__init__.py index d4c0930bb9..235271d2ce 100644 --- a/mpy-cross/mpy_cross/__init__.py +++ b/mpy-cross/mpy_cross/__init__.py @@ -62,9 +62,11 @@ class CrossCompileError(Exception): def find_mpy_cross_binary(mpy_cross): + +def _find_mpy_cross_binary(mpy_cross): if mpy_cross: return mpy_cross - return os.path.abspath(os.path.join(os.path.dirname(__file__), "../mpy-cross")) + return os.path.abspath(os.path.join(os.path.dirname(__file__), "../build/mpy-cross")) def compile(src, dest=None, src_path=None, opt=None, march=None, mpy_cross=None, extra_args=None): @@ -82,7 +84,7 @@ def compile(src, dest=None, src_path=None, opt=None, march=None, mpy_cross=None, args += ["-o", dest] if march: - args += ["-march", march] + args += ["-march=" + march] if opt is not None: args += ["-O{}".format(opt)] @@ -96,7 +98,7 @@ def compile(src, dest=None, src_path=None, opt=None, march=None, mpy_cross=None, def run(args, mpy_cross=None): - mpy_cross = find_mpy_cross_binary(mpy_cross) + mpy_cross = _find_mpy_cross_binary(mpy_cross) if not os.path.exists(mpy_cross): raise CrossCompileError("mpy-cross binary not found at {}.".format(mpy_cross)) @@ -108,6 +110,6 @@ def run(args, mpy_cross=None): pass try: - subprocess.check_output([mpy_cross] + args, stderr=subprocess.STDOUT) + return subprocess.check_output([mpy_cross] + args, stderr=subprocess.STDOUT).decode() except subprocess.CalledProcessError as er: - raise CrossCompileError(er.output) + raise CrossCompileError(er.output.decode()) diff --git a/mpy-cross/mpy_cross/__main__.py b/mpy-cross/mpy_cross/__main__.py index 9d957bca02..2b6b81c333 100644 --- a/mpy-cross/mpy_cross/__main__.py +++ b/mpy-cross/mpy_cross/__main__.py @@ -32,7 +32,7 @@ import sys from . import run, CrossCompileError try: - run(sys.argv[1:]) + print(run(sys.argv[1:])) except CrossCompileError as er: print(er.args[0], file=sys.stderr) raise SystemExit(1) From ee1b4a2026e79b662142f0d985643dadf7fff87b Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 28 Sep 2022 01:05:09 +1000 Subject: [PATCH 0453/1041] mpy-cross/mpy_cross: Add a way to query the mpy version. This returns the mpy version and sub-version for files compiled with this mpy-cross binary. Signed-off-by: Jim Mussared --- mpy-cross/mpy_cross/__init__.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/mpy-cross/mpy_cross/__init__.py b/mpy-cross/mpy_cross/__init__.py index 235271d2ce..01fe550a93 100644 --- a/mpy-cross/mpy_cross/__init__.py +++ b/mpy-cross/mpy_cross/__init__.py @@ -27,6 +27,7 @@ from __future__ import print_function import os +import re import stat import subprocess @@ -54,14 +55,15 @@ NATIVE_ARCHS = [ NATIVE_ARCH_XTENSAWIN, ] -__all__ = ["compile", "run", "CrossCompileError"] +__all__ = ["version", "compile", "run", "CrossCompileError"] class CrossCompileError(Exception): pass -def find_mpy_cross_binary(mpy_cross): +_VERSION_RE = re.compile("mpy-cross emitting mpy v([0-9]+)(?:.([0-9]+))?") + def _find_mpy_cross_binary(mpy_cross): if mpy_cross: @@ -69,6 +71,16 @@ def _find_mpy_cross_binary(mpy_cross): return os.path.abspath(os.path.join(os.path.dirname(__file__), "../build/mpy-cross")) +def mpy_version(mpy_cross=None): + version_info = run(["--version"], mpy_cross=mpy_cross) + match = re.search(_VERSION_RE, version_info) + mpy_version, mpy_sub_version = int(match.group(1)), int(match.group(2) or "0") + return ( + mpy_version, + mpy_sub_version, + ) + + def compile(src, dest=None, src_path=None, opt=None, march=None, mpy_cross=None, extra_args=None): if not src: raise ValueError("src is required") From 370a87dd12b92722ba8fac5f3562384d31a864ce Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 28 Sep 2022 11:33:24 +1000 Subject: [PATCH 0454/1041] mpy-cross/mpy_cross: Add list of architectures to `__all__`. Signed-off-by: Jim Mussared --- mpy-cross/mpy_cross/__init__.py | 38 +++++++++++++-------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/mpy-cross/mpy_cross/__init__.py b/mpy-cross/mpy_cross/__init__.py index 01fe550a93..22d175c89c 100644 --- a/mpy-cross/mpy_cross/__init__.py +++ b/mpy-cross/mpy_cross/__init__.py @@ -31,31 +31,23 @@ import re import stat import subprocess -NATIVE_ARCH_X86 = "x86" -NATIVE_ARCH_X64 = "x64" -NATIVE_ARCH_ARMV6 = "armv6" -NATIVE_ARCH_ARMV6M = "armv6m" -NATIVE_ARCH_ARMV7M = "armv7m" -NATIVE_ARCH_ARMV7EM = "armv7em" -NATIVE_ARCH_ARMV7EMSP = "armv7emsp" -NATIVE_ARCH_ARMV7EMDP = "armv7emdp" -NATIVE_ARCH_XTENSA = "xtensa" -NATIVE_ARCH_XTENSAWIN = "xtensawin" +NATIVE_ARCHS = { + "NATIVE_ARCH_NONE": "", + "NATIVE_ARCH_X86": "x86", + "NATIVE_ARCH_X64": "x64", + "NATIVE_ARCH_ARMV6": "armv6", + "NATIVE_ARCH_ARMV6M": "armv6m", + "NATIVE_ARCH_ARMV7M": "armv7m", + "NATIVE_ARCH_ARMV7EM": "armv7em", + "NATIVE_ARCH_ARMV7EMSP": "armv7emsp", + "NATIVE_ARCH_ARMV7EMDP": "armv7emdp", + "NATIVE_ARCH_XTENSA": "xtensa", + "NATIVE_ARCH_XTENSAWIN": "xtensawin", +} -NATIVE_ARCHS = [ - NATIVE_ARCH_X86, - NATIVE_ARCH_X64, - NATIVE_ARCH_ARMV6, - NATIVE_ARCH_ARMV6M, - NATIVE_ARCH_ARMV7M, - NATIVE_ARCH_ARMV7EM, - NATIVE_ARCH_ARMV7EMSP, - NATIVE_ARCH_ARMV7EMDP, - NATIVE_ARCH_XTENSA, - NATIVE_ARCH_XTENSAWIN, -] +globals().update(NATIVE_ARCHS) -__all__ = ["version", "compile", "run", "CrossCompileError"] +__all__ = ["version", "compile", "run", "CrossCompileError"] + list(NATIVE_ARCHS.keys()) class CrossCompileError(Exception): From e4d90be680b0a8933daf1bad03a1fa2632e0136e Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 28 Sep 2022 11:46:45 +1000 Subject: [PATCH 0455/1041] mpy-cross/mpy_cross: Add docstrings to public methods. --- mpy-cross/mpy_cross/__init__.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/mpy-cross/mpy_cross/__init__.py b/mpy-cross/mpy_cross/__init__.py index 22d175c89c..8eadbc8352 100644 --- a/mpy-cross/mpy_cross/__init__.py +++ b/mpy-cross/mpy_cross/__init__.py @@ -64,6 +64,13 @@ def _find_mpy_cross_binary(mpy_cross): def mpy_version(mpy_cross=None): + """ + Get the version and sub-version of the .mpy file format generated by this version of mpy-cross. + + Returns: A tuple of `(mpy_version, mpy_sub_version)` + Optional keyword arguments: + - mpy_cross: Specific mpy-cross binary to use + """ version_info = run(["--version"], mpy_cross=mpy_cross) match = re.search(_VERSION_RE, version_info) mpy_version, mpy_sub_version = int(match.group(1)), int(match.group(2) or "0") @@ -74,6 +81,22 @@ def mpy_version(mpy_cross=None): def compile(src, dest=None, src_path=None, opt=None, march=None, mpy_cross=None, extra_args=None): + """ + Compile the specified .py file with mpy-cross. + + Returns: Standard output from mpy-cross as a string. + + Required arguments: + - src: The path to the .py file + + Optional keyword arguments: + - dest: The output .mpy file. Defaults to `src` (with .mpy extension) + - src_path: The path to embed in the .mpy file (defaults to `src`) + - opt: Optimisation level (0-3, default 0) + - march: One of the `NATIVE_ARCH_*` constants (defaults to NATIVE_ARCH_NONE) + - mpy_cross: Specific mpy-cross binary to use + - extra_args: Additional arguments to pass to mpy-cross (e.g. `["-X", "emit=native"]`) + """ if not src: raise ValueError("src is required") if not os.path.exists(src): @@ -102,6 +125,15 @@ def compile(src, dest=None, src_path=None, opt=None, march=None, mpy_cross=None, def run(args, mpy_cross=None): + """ + Run mpy-cross with the specified command line arguments. + Prefer to use `compile()` instead. + + Returns: Standard output from mpy-cross as a string. + + Optional keyword arguments: + - mpy_cross: Specific mpy-cross binary to use + """ mpy_cross = _find_mpy_cross_binary(mpy_cross) if not os.path.exists(mpy_cross): From fecfbc3f678c8f2f6c450abf840bbefca48a57d0 Mon Sep 17 00:00:00 2001 From: stijn Date: Thu, 29 Sep 2022 14:17:37 +0200 Subject: [PATCH 0456/1041] py/mkenv.mk: Make CPP definition explicit for consistency. --- py/mkenv.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/py/mkenv.mk b/py/mkenv.mk index ea2e34f3b6..5368279e29 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -45,6 +45,7 @@ PYTHON = python3 AS = $(CROSS_COMPILE)as CC = $(CROSS_COMPILE)gcc +CPP = $(CC) -E CXX = $(CROSS_COMPILE)g++ GDB = $(CROSS_COMPILE)gdb LD = $(CROSS_COMPILE)ld From b76ddcbc83b7235ab373e764ae033c1e5cecddd1 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 29 Sep 2022 22:31:35 +1000 Subject: [PATCH 0457/1041] docs/Makefile: Enable parallel compilation for Sphinx. This has a fairly dramatic (nearly 3x on a 6-core machine) speedup for docs compilation, with no impact on correctness. Signed-off-by: Jim Mussared --- docs/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Makefile b/docs/Makefile index 05709617c3..766a669a50 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -3,7 +3,7 @@ # You can set these variables from the command line. PYTHON = python3 -SPHINXOPTS = -W --keep-going +SPHINXOPTS = -W --keep-going -j auto SPHINXBUILD = sphinx-build PAPER = BUILDDIR = build/$(MICROPY_PORT) From 65ab0ec91cffe5d39ff2e253ac5cc898ecc3c5ce Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 29 Sep 2022 23:13:52 +1000 Subject: [PATCH 0458/1041] tools/manifestfile.py: Add `author` kwarg to metadata(). This allows future micropython-lib packages to specify an author. Signed-off-by: Jim Mussared --- tools/manifestfile.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/manifestfile.py b/tools/manifestfile.py index a4d056137f..f7966ccb80 100644 --- a/tools/manifestfile.py +++ b/tools/manifestfile.py @@ -87,14 +87,17 @@ class ManifestMetadata: self.version = None self.description = None self.license = None + self.author = None - def update(self, description=None, version=None, license=None): + def update(self, description=None, version=None, license=None, author=None): if description: self.description = description if version: self.version = version if license: self.license = version + if author: + self.author = author # Turns a dict of options into a object with attributes used to turn the @@ -228,7 +231,7 @@ class ManifestFile: if base_path: os.chdir(prev_cwd) - def metadata(self, description=None, version=None, license=None): + def metadata(self, description=None, version=None, license=None, author=None): """ From within a manifest file, use this to set the metadata for the package described by current manifest. @@ -237,7 +240,7 @@ class ManifestFile: to obtain the metadata for the top-level manifest file. """ - self._metadata[-1].update(description, version, license) + self._metadata[-1].update(description, version, license, author) return self._metadata[-1] def include(self, manifest_path, top_level=False, **kwargs): From ba3652f15d96d9dca0f84522639ea2005b07fcb4 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 30 Sep 2022 00:46:16 +1000 Subject: [PATCH 0459/1041] lib/micropython-lib: Update submodule to latest. This brings in the `mip` tool for installing packages. Signed-off-by: Jim Mussared --- lib/micropython-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/micropython-lib b/lib/micropython-lib index 58f8bec54d..d0f97fc218 160000 --- a/lib/micropython-lib +++ b/lib/micropython-lib @@ -1 +1 @@ -Subproject commit 58f8bec54d5b3b959247b73a6e8f28e8493bd30b +Subproject commit d0f97fc218f07c381c835d9f632904c1ae1c9d6b From 924a3e03ec167c4417d89b531794c75ce5a631a3 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 29 Sep 2022 17:49:58 +1000 Subject: [PATCH 0460/1041] top: Replace upip with mip everywhere. Updates all README.md and docs, and manifests to `require("mip")`. Also extend and improve the documentation on freezing and packaging. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared --- docs/develop/gettingstarted.rst | 3 +- docs/develop/optimizations.rst | 2 + docs/esp8266/tutorial/intro.rst | 2 +- docs/pyboard/tutorial/lcd160cr_skin.rst | 2 +- docs/reference/glossary.rst | 30 +- docs/reference/manifest.rst | 271 ++++++++++---- docs/reference/packages.rst | 463 ++++++++---------------- examples/hwapi/README.md | 2 +- ports/esp32/boards/manifest.py | 3 +- ports/esp8266/README.md | 18 +- ports/esp8266/boards/manifest.py | 7 +- ports/rp2/boards/PICO_W/manifest.py | 4 +- ports/unix/README.md | 26 +- ports/unix/variants/manifest.py | 3 +- tools/upip.py | 351 ------------------ tools/upip_utarfile.py | 95 ----- 16 files changed, 404 insertions(+), 878 deletions(-) delete mode 100644 tools/upip.py delete mode 100644 tools/upip_utarfile.py diff --git a/docs/develop/gettingstarted.rst b/docs/develop/gettingstarted.rst index 000b7d6139..c2d3816d42 100644 --- a/docs/develop/gettingstarted.rst +++ b/docs/develop/gettingstarted.rst @@ -322,7 +322,8 @@ tests tools - Contains helper tools including the ``upip`` and the ``pyboard.py`` module. + Contains scripts used by the build and CI process, as well as user tools such + as ``pyboard.py`` and ``mpremote``. examples diff --git a/docs/develop/optimizations.rst b/docs/develop/optimizations.rst index d972cde666..7f2c8cbe72 100644 --- a/docs/develop/optimizations.rst +++ b/docs/develop/optimizations.rst @@ -25,6 +25,8 @@ into the firmware image as part of the main firmware compilation process, which the bytecode will be executed from ROM. This can lead to a significant memory saving, and reduce heap fragmentation. +See :ref:`manifest` for more information. + Variables --------- diff --git a/docs/esp8266/tutorial/intro.rst b/docs/esp8266/tutorial/intro.rst index ac46e68b5a..75739bd6f9 100644 --- a/docs/esp8266/tutorial/intro.rst +++ b/docs/esp8266/tutorial/intro.rst @@ -23,7 +23,7 @@ convertor to make the UART available to your PC. The minimum requirement for flash size is 1Mbyte. There is also a special build for boards with 512KB, but it is highly limited comparing to the normal build: there is no support for filesystem, and thus features which -depend on it won't work (WebREPL, upip, etc.). As such, 512KB build will +depend on it won't work (WebREPL, mip, etc.). As such, 512KB build will be more interesting for users who build from source and fine-tune parameters for their particular application. diff --git a/docs/pyboard/tutorial/lcd160cr_skin.rst b/docs/pyboard/tutorial/lcd160cr_skin.rst index fa0debcb1c..a0fe88a2e6 100644 --- a/docs/pyboard/tutorial/lcd160cr_skin.rst +++ b/docs/pyboard/tutorial/lcd160cr_skin.rst @@ -42,7 +42,7 @@ There is a test program which you can use to test the features of the display, and which also serves as a basis to start creating your own code that uses the LCD. This test program is available on GitHub `here `__. -Copy it to the board over USB mass storage, or by using `mpremote`. +Copy it to the board over USB mass storage, or by using :ref:`mpremote`. To run the test from the MicroPython prompt do:: diff --git a/docs/reference/glossary.rst b/docs/reference/glossary.rst index da951189e2..4c66f70319 100644 --- a/docs/reference/glossary.rst +++ b/docs/reference/glossary.rst @@ -52,7 +52,7 @@ Glossary cross-compiler Also known as ``mpy-cross``. This tool runs on your PC and converts a :term:`.py file` containing MicroPython code into a :term:`.mpy file` - containing MicroPython bytecode. This means it loads faster (the board + containing MicroPython :term:`bytecode`. This means it loads faster (the board doesn't have to compile the code), and uses less space on flash (the bytecode is more space efficient). @@ -128,7 +128,7 @@ Glossary Unlike the :term:`CPython` stdlib, micropython-lib modules are intended to be installed individually - either using manual copying or - using :term:`upip`. + using :term:`mip`. MicroPython port MicroPython supports different :term:`boards `, RTOSes, and @@ -151,16 +151,26 @@ Glossary machine-independent features. It can also function in a similar way to :term:`CPython`'s ``python`` executable. + mip + A package installer for MicroPython (mip - "mip installs packages"). It + installs MicroPython packages either from :term:`micropython-lib`, + GitHub, or arbitrary URLs. mip can be used on-device on + network-capable boards, and internally by tools such + as :term:`mpremote`. + + mpremote + A tool for interacting with a MicroPython device. See :ref:`mpremote`. + .mpy file The output of the :term:`cross-compiler`. A compiled form of a - :term:`.py file` that contains MicroPython bytecode instead of Python - source code. + :term:`.py file` that contains MicroPython :term:`bytecode` instead of + Python source code. native Usually refers to "native code", i.e. machine code for the target microcontroller (such as ARM Thumb, Xtensa, x86/x64). The ``@native`` decorator can be applied to a MicroPython function to generate native - code instead of bytecode for that function, which will likely be + code instead of :term:`bytecode` for that function, which will likely be faster but use more RAM. port @@ -193,8 +203,10 @@ Glossary as a serial port over USB. upip - (Literally, "micro pip"). A package manager for MicroPython, inspired + A now-obsolete package manager for MicroPython, inspired by :term:`CPython`'s pip, but much smaller and with reduced - functionality. - upip runs both on the :term:`Unix port ` and on - :term:`baremetal` ports which offer filesystem and networking support. + functionality. See its replacement, :term:`mip`. + + webrepl + A way of connecting to the REPL (and transferring files) on a device + over the internet from a browser. See https://micropython.org/webrepl diff --git a/docs/reference/manifest.rst b/docs/reference/manifest.rst index b756de47ed..9bcafd5839 100644 --- a/docs/reference/manifest.rst +++ b/docs/reference/manifest.rst @@ -1,35 +1,177 @@ +.. _manifest: + MicroPython manifest files ========================== -When building firmware for a device the following components are included in -the compilation process: +Summary +------- -- the core MicroPython virtual machine and runtime -- port-specific system code and drivers to interface with the - microcontroller/device that the firmware is targeting -- standard built-in modules, like ``sys`` -- extended built-in modules, like ``json`` and ``machine`` -- extra modules written in C/C++ -- extra modules written in Python +MicroPython has a feature that allows Python code to be "frozen" into the +firmware, as an alternative to loading code from the filesystem. -All the modules included in the firmware are available via ``import`` from -Python code. The extra modules written in Python that are included in a build -(the last point above) are called *frozen modules*, and are specified by a -``manifest.py`` file. Changing this manifest requires rebuilding the firmware. +This has the following benefits: -It's also possible to add additional modules to the filesystem of the device -once it is up and running. Adding and removing modules to/from the filesystem -does not require rebuilding the firmware so is a simpler process than rebuilding -firmware. The benefit of using a manifest is that frozen modules are more -efficient: they are faster to import and take up less RAM once imported. +- the code is pre-compiled to bytecode, avoiding the need for the Python + source to be compiled at load-time. +- the bytecode can be executed directly from ROM (i.e. flash memory) rather than + being copied into RAM. Similarly any constant objects (strings, tuples, etc) + are loaded from ROM also. This can lead to significantly more memory being + available for your application. +- on devices that do not have a filesystem, this is the only way to + load Python code. -MicroPython manifest files are Python files and can contain arbitrary Python -code. There are also a set of commands (predefined functions) which are used -to specify the Python source files to include. These commands are described -below. +During development, freezing is generally not recommended as it will +significantly slow down your development cycle, as each update will require +re-flashing the entire firmware. However, it can still be useful to +selectively freeze some rarely-changing dependencies (such as third-party +libraries). -Freezing source code --------------------- +The way to list the Python files to be be frozen into the firmware is via +a "manifest", which is a Python file that will be interpreted by the build +process. Typically you would write a manifest file as part of a board +definition, but you can also write a stand-alone manifest file and use it with +an existing board definition. + +Manifest files can define dependencies on libraries from :term:`micropython-lib` +as well as Python files on the filesystem, and also on other manifest files. + +Writing manifest files +---------------------- + +A manifest file is a Python file containing a series of function calls. See the +available functions defined below. + +Any paths used in manifest files can include the following variables. These all +resolve to absolute paths. + +- ``$(MPY_DIR)`` -- path to the micropython repo. +- ``$(MPY_LIB_DIR)`` -- path to the micropython-lib submodule. Prefer to use + ``require()``. +- ``$(PORT_DIR)`` -- path to the current port (e.g. ``ports/stm32``) +- ``$(BOARD_DIR)`` -- path to the current board + (e.g. ``ports/stm32/boards/PYBV11``) + +Custom manifest files should not live in the main MicroPython repository. You +should keep them in version control with the rest of your project. + +Typically a manifest used for compiling firmware will need to include the port +manifest, which might include frozen modules that are required for the board to +function. If you just want to add additional modules to an existing board, then +include the board manifest (which will in turn include the port manifest). + +Building with a custom manifest +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Your manifest can be specified on the ``make`` command line with: + +.. code-block:: bash + + $ make BOARD=MYBOARD FROZEN_MANIFEST=/path/to/my/project/manifest.py + +This applies to all ports, including CMake-based ones (e.g. esp32, rp2), as the +Makefile wrapper that will pass this into the CMake build. + +Adding a manifest to a board definition +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you have a custom board definition, you can make it include your custom +manifest automatically. On make-based ports (most ports), in your +``mpconfigboard.mk`` set the ``FROZEN_MANIFEST`` variable. + +.. code-block:: makefile + + FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py + +On CMake-based ports (e.g. esp32, rp2), instead use ``mpconfigboard.cmake`` + +.. code-block:: cmake + + set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py) + +High-level functions +~~~~~~~~~~~~~~~~~~~~ + +Note: The ``opt`` keyword argument can be set on the various functions, this controls +the optimisation level used by the cross-compiler. +See :func:`micropython.opt_level`. + +.. function:: package(package_path, files=None, base_path=".", opt=None) + + This is equivalent to copying the "package_path" directory to the device + (except as frozen code). + + In the simplest case, to freeze a package "foo" in the current directory: + + .. code-block:: python3 + + package("foo") + + will recursively include all .py files in foo, and will be frozen as + ``foo/**/*.py``. + + If the package isn't in the same directory as the manifest file, use ``base_path``: + + .. code-block:: python3 + + package("foo", base_path="path/to/libraries") + + You can use the variables above, such as ``$(PORT_DIR)`` in ``base_path``. + + To restrict to certain files in the package use ``files`` (note: paths + should be relative to the package): ``package("foo", files=["bar/baz.py"])``. + +.. function:: module(module_path, base_path=".", opt=None) + + Include a single Python file as a module. + + If the file is in the current directory: + + .. code-block:: python3 + + module("foo.py") + + Otherwise use base_path to locate the file: + + .. code-block:: python3 + + module("foo.py", base_path="src/drivers") + + You can use the variables above, such as ``$(PORT_DIR)`` in ``base_path``. + +.. function:: require(name, unix_ffi=False) + + Require a package by name (and its dependencies) from :term:`micropython-lib`. + + Optionally specify unix_ffi=True to use a module from the unix-ffi directory. + +.. function:: include(manifest_path) + + Include another manifest. + + Typically a manifest used for compiling firmware will need to include the + port manifest, which might include frozen modules that are required for + the board to function. + + The *manifest* argument can be a string (filename) or an iterable of + strings. + + Relative paths are resolved with respect to the current manifest file. + + If the path is to a directory, then it implicitly includes the + manifest.py file inside that directory. + + You can use the variables above, such as ``$(PORT_DIR)`` in ``manifest_path``. + +.. function:: metadata(description=None, version=None, license=None, author=None) + + Define metadata for this manifest file. This is useful for manifests for + micropython-lib packages. + +Low-level functions +~~~~~~~~~~~~~~~~~~~ + +These functions are documented for completeness, but with the exception of +``freeze_as_str`` all functionality can be accessed via the high-level functions. .. function:: freeze(path, script=None, opt=0) @@ -42,9 +184,7 @@ Freezing source code module will start after *path*, i.e. *path* is excluded from the module name. - If *path* is relative, it is resolved to the current ``manifest.py``. Use - ``$(MPY_DIR)``, ``$(MPY_LIB_DIR)``, ``$(PORT_DIR)``, ``$(BOARD_DIR)`` if you - need to access specific paths. + If *path* is relative, it is resolved to the current ``manifest.py``. If *script* is None, all files in *path* will be frozen. @@ -75,71 +215,48 @@ Freezing source code Freeze the input, which must be ``.mpy`` files that are frozen directly. See ``freeze()`` for further details on the arguments. - -Including other manifest files ------------------------------- - -.. function:: include(manifest, **kwargs) - - Include another manifest. - - The *manifest* argument can be a string (filename) or an iterable of - strings. - - Relative paths are resolved with respect to the current manifest file. - - Optional *kwargs* can be provided which will be available to the included - script via the *options* variable. - - For example: - - .. code-block:: python3 - - include("path.py", extra_features=True) - - then in path.py: - - .. code-block:: python3 - - options.defaults(standard_features=True) - # freeze minimal modules. - if options.standard_features: - # freeze standard modules. - if options.extra_features: - # freeze extra modules. - - Examples -------- -To freeze a single file which is available as ``import mydriver``, use: +To freeze a single file from the current directory which will be available as +``import mydriver``, use: .. code-block:: python3 - freeze(".", "mydriver.py") + module("mydriver.py") -To freeze a set of files which are available as ``import test1`` and -``import test2``, and which are compiled with optimisation level 3, use: +To freeze a directory of files in a subdirectory "mydriver" of the current +directory which will be available as ``import mydriver``, use: .. code-block:: python3 - freeze("/path/to/tests", ("test1.py", "test2.py"), opt=3) + package("mydriver") -To freeze a module which can be imported as ``import mymodule``, use: +To freeze the "hmac" library from :term:`micropython-lib`, use: .. code-block:: python3 - freeze( - "../relative/path", - ( - "mymodule/__init__.py", - "mymodule/core.py", - "mymodule/extra.py", - ), - ) + require("hmac") -To include a manifest from the MicroPython repository, use: +A more complete example of a custom ``manifest.py`` file for the ``PYBD_SF2`` +board is: .. code-block:: python3 - include("$(MPY_DIR)/extmod/uasyncio/manifest.py") + # Include the board's default manifest. + include("$(BOARD_DIR)/manifest.py") + # Add a custom driver + module("mydriver.py") + # Add aiorepl from micropython-lib + require("aiorepl") + +Then the board can be compiled with + +.. code-block:: bash + + $ cd ports/stm32 + $ make BOARD=PYBD_SF2 FROZEN_MANIFEST=~/src/myproject/manifest.py + +Note that most boards do not have their own ``manifest.py``, rather they use the +port one directly, in which case your manifest should just +``include("$(PORT_DIR)/boards/manifest.py")`` instead. diff --git a/docs/reference/packages.rst b/docs/reference/packages.rst index eb44992ed6..0c049d1fb2 100644 --- a/docs/reference/packages.rst +++ b/docs/reference/packages.rst @@ -1,314 +1,153 @@ .. _packages: -Distribution packages, package management, and deploying applications -===================================================================== - -Just as the "big" Python, MicroPython supports creation of "third party" -packages, distributing them, and easily installing them in each user's -environment. This chapter discusses how these actions are achieved. -Some familiarity with Python packaging is recommended. - -Overview --------- - -Steps below represent a high-level workflow when creating and consuming -packages: - -1. Python modules and packages are turned into distribution package - archives, and published at the Python Package Index (PyPI). -2. :term:`upip` package manager can be used to install a distribution package - on a :term:`MicroPython port` with networking capabilities (for example, - on the Unix port). -3. For ports without networking capabilities, an "installation image" - can be prepared on the Unix port, and transferred to a device by - suitable means. -4. For low-memory ports, the installation image can be frozen as the - bytecode into MicroPython executable, thus minimizing the memory - storage overheads. - -The sections below describe this process in details. - -Distribution packages ---------------------- - -Python modules and packages can be packaged into archives suitable for -transfer between systems, storing at the well-known location (PyPI), -and downloading on demand for deployment. These archives are known as -*distribution packages* (to differentiate them from Python packages -(means to organize Python source code)). - -The MicroPython distribution package format is a well-known tar.gz -format, with some adaptations however. The Gzip compressor, used as -an external wrapper for TAR archives, by default uses 32KB dictionary -size, which means that to uncompress a compressed stream, 32KB of -contiguous memory needs to be allocated. This requirement may be not -satisfiable on low-memory devices, which may have total memory available -less than that amount, and even if not, a contiguous block like that -may be hard to allocate due to memory fragmentation. To accommodate -these constraints, MicroPython distribution packages use Gzip compression -with the dictionary size of 4K, which should be a suitable compromise -with still achieving some compression while being able to uncompressed -even by the smallest devices. - -Besides the small compression dictionary size, MicroPython distribution -packages also have other optimizations, like removing any files from -the archive which aren't used by the installation process. In particular, -:term:`upip` package manager doesn't execute ``setup.py`` during installation -(see below), and thus that file is not included in the archive. - -At the same time, these optimizations make MicroPython distribution -packages not compatible with :term:`CPython`'s package manager, ``pip``. -This isn't considered a big problem, because: - -1. Packages can be installed with :term:`upip`, and then can be used with - CPython (if they are compatible with it). -2. In the other direction, majority of CPython packages would be - incompatible with MicroPython by various reasons, first of all, - the reliance on features not implemented by MicroPython. - -Summing up, the MicroPython distribution package archives are highly -optimized for MicroPython's target environments, which are highly -resource constrained devices. - - -``upip`` package manager ------------------------- - -MicroPython distribution packages are intended to be installed using -the :term:`upip` package manager. :term:`upip` is a Python application which is -usually distributed (as frozen bytecode) with network-enabled -:term:`MicroPython ports `. At the very least, -:term:`upip` is available in the :term:`MicroPython Unix port`. - -On any :term:`MicroPython port` providing :term:`upip`, it can be accessed as -following:: - - import upip - upip.help() - upip.install(package_or_package_list, [path]) - -Where *package_or_package_list* is the name of a distribution -package to install, or a list of such names to install multiple -packages. Optional *path* parameter specifies filesystem -location to install under and defaults to the standard library -location (see below). - -An example of installing a specific package and then using it:: - - >>> import upip - >>> upip.install("micropython-pystone_lowmem") - [...] - >>> import pystone_lowmem - >>> pystone_lowmem.main() - -Note that the name of Python package and the name of distribution -package for it in general don't have to match, and oftentimes they -don't. This is because PyPI provides a central package repository -for all different Python implementations and versions, and thus -distribution package names may need to be namespaced for a particular -implementation. For example, all packages from `micropython-lib` -follow this naming convention: for a Python module or package named -``foo``, the distribution package name is ``micropython-foo``. - -For the ports which run MicroPython executable from the OS command -prompts (like the Unix port), `upip` can be (and indeed, usually is) -run from the command line instead of MicroPython's own REPL. The -commands which corresponds to the example above are:: - - micropython -m upip -h - micropython -m upip install [-p ] ... - micropython -m upip install micropython-pystone_lowmem - -[TODO: Describe installation path.] - - -Cross-installing packages -------------------------- - -For :term:`MicroPython ports ` without native networking -capabilities, the recommend process is "cross-installing" them into a -"directory image" using the :term:`MicroPython Unix port`, and then -transferring this image to a device by suitable means. - -Installing to a directory image involves using ``-p`` switch to :term:`upip`:: - - micropython -m upip install -p install_dir micropython-pystone_lowmem - -After this command, the package content (and contents of every dependency -packages) will be available in the ``install_dir/`` subdirectory. You -would need to transfer contents of this directory (without the -``install_dir/`` prefix) to the device, at the suitable location, where -it can be found by the Python ``import`` statement (see discussion of -the :term:`upip` installation path above). - - -Cross-installing packages with freezing ---------------------------------------- - -For the low-memory :term:`MicroPython ports `, the process -described in the previous section does not provide the most efficient -resource usage,because the packages are installed in the source form, -so need to be compiled to the bytecome on each import. This compilation -requires RAM, and the resulting bytecode is also stored in RAM, reducing -its amount available for storing application data. Moreover, the process -above requires presence of the filesystem on a device, and the most -resource-constrained devices may not even have it. - -The bytecode freezing is a process which resolves all the issues -mentioned above: - -* The source code is pre-compiled into bytecode and store as such. -* The bytecode is stored in ROM, not RAM. -* Filesystem is not required for frozen packages. - -Using frozen bytecode requires building the executable (firmware) -for a given :term:`MicroPython port` from the C source code. Consequently, -the process is: - -1. Follow the instructions for a particular port on setting up a - toolchain and building the port. For example, for ESP8266 port, - study instructions in ``ports/esp8266/README.md`` and follow them. - Make sure you can build the port and deploy the resulting - executable/firmware successfully before proceeding to the next steps. -2. Build :term:`MicroPython Unix port` and make sure it is in your PATH and - you can execute ``micropython``. -3. Change to port's directory (e.g. ``ports/esp8266/`` for ESP8266). -4. Run ``make clean-frozen``. This step cleans up any previous - modules which were installed for freezing (consequently, you need - to skip this step to add additional modules, instead of starting - from scratch). -5. Run ``micropython -m upip install -p modules ...`` to - install packages you want to freeze. -6. Run ``make clean``. -7. Run ``make``. - -After this, you should have the executable/firmware with modules as -the bytecode inside, which you can deploy the usual way. - -Few notes: - -1. Step 5 in the sequence above assumes that the distribution package - is available from PyPI. If that is not the case, you would need - to copy Python source files manually to ``modules/`` subdirectory - of the port directory. (Note that upip does not support - installing from e.g. version control repositories). -2. The firmware for baremetal devices usually has size restrictions, - so adding too many frozen modules may overflow it. Usually, you - would get a linking error if this happens. However, in some cases, - an image may be produced, which is not runnable on a device. Such - cases are in general bugs, and should be reported and further - investigated. If you face such a situation, as an initial step, - you may want to decrease the amount of frozen modules included. - - -Creating distribution packages ------------------------------- - -Distribution packages for MicroPython are created in the same manner -as for CPython or any other Python implementation, see references at -the end of chapter. Setuptools (instead of distutils) should be used, -because distutils do not support dependencies and other features. "Source -distribution" (``sdist``) format is used for packaging. The post-processing -discussed above, (and pre-processing discussed in the following section) -is achieved by using custom ``sdist`` command for setuptools. Thus, packaging -steps remain the same as for the standard setuptools, the user just -needs to override ``sdist`` command implementation by passing the -appropriate argument to ``setup()`` call:: - - from setuptools import setup - import sdist_upip - - setup( - ..., - cmdclass={'sdist': sdist_upip.sdist} - ) - -The sdist_upip.py module as referenced above can be found in -`micropython-lib`: -https://github.com/micropython/micropython-lib/blob/master/sdist_upip.py - - -Application resources ---------------------- - -A complete application, besides the source code, oftentimes also consists -of data files, e.g. web page templates, game images, etc. It's clear how -to deal with those when application is installed manually - you just put -those data files in the filesystem at some location and use the normal -file access functions. - -The situation is different when deploying applications from packages - this -is more advanced, streamlined and flexible way, but also requires more -advanced approach to accessing data files. This approach is treating -the data files as "resources", and abstracting away access to them. - -Python supports resource access using its "setuptools" library, using -``pkg_resources`` module. MicroPython, following its usual approach, -implements subset of the functionality of that module, specifically -``pkg_resources.resource_stream(package, resource)`` function. -The idea is that an application calls this function, passing a -resource identifier, which is a relative path to data file within -the specified package (usually top-level application package). It -returns a stream object which can be used to access resource contents. -Thus, the ``resource_stream()`` emulates interface of the standard -`open()` function. - -Implementation-wise, ``resource_stream()`` uses file operations -underlyingly, if distribution package is install in the filesystem. -However, it also supports functioning without the underlying filesystem, -e.g. if the package is frozen as the bytecode. This however requires -an extra intermediate step when packaging application - creation of -"Python resource module". - -The idea of this module is to convert binary data to a Python bytes -object, and put it into the dictionary, indexed by the resource name. -This conversion is done automatically using overridden ``sdist`` command -described in the previous section. - -Let's trace the complete process using the following example. Suppose -your application has the following structure:: - - my_app/ - __main__.py - utils.py - data/ - page.html - image.png - -``__main__.py`` and ``utils.py`` should access resources using the -following calls:: - - import pkg_resources - - pkg_resources.resource_stream(__name__, "data/page.html") - pkg_resources.resource_stream(__name__, "data/image.png") - -You can develop and debug using the :term:`MicroPython Unix port` as usual. -When time comes to make a distribution package out of it, just use -overridden "sdist" command from sdist_upip.py module as described in -the previous section. - -This will create a Python resource module named ``R.py``, based on the -files declared in ``MANIFEST`` or ``MANIFEST.in`` files (any non-``.py`` -file will be considered a resource and added to ``R.py``) - before -proceeding with the normal packaging steps. - -Prepared like this, your application will work both when deployed to -filesystem and as frozen bytecode. - -If you would like to debug ``R.py`` creation, you can run:: - - python3 setup.py sdist --manifest-only - -Alternatively, you can use tools/mpy_bin2res.py script from the -MicroPython distribution, in which can you will need to pass paths -to all resource files:: - - mpy_bin2res.py data/page.html data/image.png - -References ----------- - -* Python Packaging User Guide: https://packaging.python.org/ -* Setuptools documentation: https://setuptools.readthedocs.io/ -* Distutils documentation: https://docs.python.org/3/library/distutils.html +Package management +================== + +Installing packages with ``mip`` +-------------------------------- + +Network-capable boards include the ``mip`` module, which can install packages +from :term:`micropython-lib` and from third-party sites (including GitHub). + +``mip`` ("mip installs packages") is similar in concept to Python's ``pip`` tool, +however it does not use the PyPI index, rather it uses :term:`micropython-lib` +as its index by default. ``mip`` will automatically fetch compiled +:term:`.mpy file` when downloading from micropython-lib. + +The most common way to use ``mip`` is from the REPL:: + + >>> import mip + >>> mip.install("pkgname") # Installs the latest version of "pkgname" (and dependencies) + >>> mip.install("pkgname", version="x.y") # Installs version x.y of "pkgname" + >>> mip.install("pkgname", mpy=False) # Installs the source version (i.e. .py rather than .mpy files) + +``mip`` will detect an appropriate location on the filesystem by searching +``sys.path`` for the first entry ending in ``/lib``. You can override the +destination using ``target``, but note that this path must be in ``sys.path`` to be +able to subsequently import it.:: + + >>> mip.install("pkgname", target="third-party") + >>> sys.path.append("third-party") + +As well as downloading packages from the micropython-lib index, ``mip`` can also +install third-party libraries. The simplest way is to download a file directly:: + + >>> mip.install("http://example.com/x/y/foo.py") + >>> mip.install("http://example.com/x/y/foo.mpy") + +When installing a file directly, the ``target`` argument is still supported to set +the destination path, but ``mpy`` and ``version`` are ignored. + +The URL can also start with ``github:`` as a simple way of pointing to content +hosted on GitHub:: + + >>> mip.install("github:org/repo/path/foo.py") # Uses default branch + >>> mip.install("github:org/repo/path/foo.py", version="branch-or-tag") # Optionally specify the branch or tag + +More sophisticated packages (i.e. with more than one file, or with dependencies) +can be downloaded by specifying the path to their ``package.json``. + + >>> mip.install("http://example.com/x/package.json") + >>> mip.install("github:org/user/path/package.json") + +If no json file is specified, then "package.json" is implicitly added:: + + >>> mip.install("http://example.com/x/") + >>> mip.install("github:org/repo") + >>> mip.install("github:org/repo", version="branch-or-tag") + + +Using ``mip`` on the Unix port +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +On the Unix port, ``mip`` can be used at the REPL as above, and also by using ``-m``:: + + $ ./micropython -m mip install pkgname-or-url + $ ./micropython -m mip install pkgname-or-url@version + +The ``--target=path``, ``--no-mpy``, and ``--index`` arguments can be set:: + + $ ./micropython -m mip install --target=third-party pkgname + $ ./micropython -m mip install --no-mpy pkgname + $ ./micropython -m mip install --index https://host/pi pkgname + +Installing packages with ``mpremote`` +------------------------------------- + +The :term:`mpremote` tool also includes the same functionality as ``mip`` and +can be used from a host PC to install packages to a locally connected device +(e.g. via USB or UART):: + + $ mpremote install pkgname + $ mpremote install pkgname@x.y + $ mpremote install http://example.com/x/y/foo.py + $ mpremote install github:org/repo + $ mpremote install github:org/repo@branch-or-tag + +The ``--target=path``, ``--no-mpy``, and ``--index`` arguments can be set:: + + $ mpremote install --target=/flash/third-party pkgname + $ mpremote install --no-mpy pkgname + $ mpremote install --index https://host/pi pkgname + +Installing packages manually +---------------------------- + +Packages can also be installed (in either .py or .mpy form) by manually copying +the files to the device. Depending on the board this might be via USB Mass Storage, +the :term:`mpremote` tool (e.g. ``mpremote fs cp path/to/package.py :package.py``), +:term:`webrepl`, etc. + +Writing & publishing packages +----------------------------- + +Publishing to :term:`micropython-lib` is the easiest way to make your package +broadly accessible to MicroPython users, and automatically available via +``mip`` and ``mpremote`` and compiled to bytecode. See +https://github.com/micropython/micropython-lib for more information. + +To write a "self-hosted" package that can be downloaded by ``mip`` or +``mpremote``, you need a static webserver (or GitHub) to host either a +single .py file, or a package.json file alongside your .py files. + +A typical package.json for an example ``mlx90640`` library looks like:: + + { + "urls": [ + ["mlx90640/__init__.py", "github:org/micropython-mlx90640/mlx90640/__init__.py"], + ["mlx90640/utils.py", "github:org/micropython-mlx90640/mlx90640/utils.py"] + ], + "deps": [ + ["collections-defaultdict", "latest"], + ["os-path", "latest"] + ], + "version": "0.2" + } + +This includes two files, hosted at a GitHub repo named +``org/micropython-mlx90640``, which install into the ``mlx90640`` directory on +the device. It depends on ``collections-defaultdict`` and ``os-path`` which will +be installed automatically. + +Freezing packages +----------------- + +When a Python module or package is imported from the device filesystem, it is +compiled into :term:`bytecode` in RAM, ready to be executed by the VM. For +a :term:`.mpy file`, this conversion has been done already, but the bytecode +still ends up in RAM. + +For low-memory devices, or for large applications, it can be advantageous to +instead run the bytecode from ROM (i.e. flash memory). This can be done +by "freezing" the bytecode into the MicroPython firmware, which is then flashed +to the device. The runtime performance is the same (although importing is +faster), but it can free up significant amounts of RAM for your program to +use. + +The downside of this approach is that it's much slower to develop, because you +have to flash the firmware each time, but it can be still useful to freeze +dependencies that don't change often. + +Freezing is done by writing a manifest file and using it in the build, often as +part of a custom board definition. See the :ref:`manifest` guide for more +information. diff --git a/examples/hwapi/README.md b/examples/hwapi/README.md index 1992eb6609..df16b4c86b 100644 --- a/examples/hwapi/README.md +++ b/examples/hwapi/README.md @@ -116,7 +116,7 @@ For example, one may invent a "configuration manager" helper module which will try to detect current board (among well-known ones), and load appropriate `hwconfig_*.py` - this assumes that a user would lazily deploy them all (or that application will be automatically installed, e.g. using MicroPython's -`upip` package manager). The key point in this case remains the same as +`mip` package manager). The key point in this case remains the same as elaborated above - always assume there can, and will be a custom configuration, and it should be well supported. So, any automatic detection should be overridable by a user, and instructions how to do so are among the most diff --git a/ports/esp32/boards/manifest.py b/ports/esp32/boards/manifest.py index fcc48d7218..3f6c8cfde5 100644 --- a/ports/esp32/boards/manifest.py +++ b/ports/esp32/boards/manifest.py @@ -1,11 +1,10 @@ freeze("$(PORT_DIR)/modules") -module("upip.py", base_path="$(MPY_DIR)/tools", opt=3) -module("upip_utarfile.py", base_path="$(MPY_DIR)/tools", opt=3) include("$(MPY_DIR)/extmod/uasyncio") # Require some micropython-lib modules. require("dht") require("ds18x20") +require("mip") require("neopixel") require("ntptime") require("onewire") diff --git a/ports/esp8266/README.md b/ports/esp8266/README.md index dd50fc1af9..b54d8958d7 100644 --- a/ports/esp8266/README.md +++ b/ports/esp8266/README.md @@ -200,20 +200,22 @@ Python prompt over WiFi, connecting through a browser. - GitHub repository https://github.com/micropython/webrepl. Please follow the instructions there. -__upip__ +__mip__ -The ESP8266 port comes with builtin `upip` package manager, which can -be used to install additional modules (see the main README for more -information): +The ESP8266 port comes with the built-in `mip` package manager, which can +be used to install additional modules: ``` ->>> import upip ->>> upip.install("micropython-pystone_lowmem") +>>> import mip +>>> mip.install("hmac") [...] ->>> import pystone_lowmem ->>> pystone_lowmem.main() +>>> import hmac +>>> hmac.new(b"1234567890", msg="hello world").hexdigest() ``` +See [Package management](https://docs.micropython.org/en/latest/reference/packages.html) for more +information about `mip`. + Downloading and installing packages may requite a lot of free memory, if you get an error, retry immediately after the hard reset. diff --git a/ports/esp8266/boards/manifest.py b/ports/esp8266/boards/manifest.py index e7defd0bb7..53975f6a6b 100644 --- a/ports/esp8266/boards/manifest.py +++ b/ports/esp8266/boards/manifest.py @@ -1,9 +1,8 @@ freeze("$(PORT_DIR)/modules") -module("upip.py", base_path="$(MPY_DIR)/tools", opt=3) -module("upip_utarfile.py", base_path="$(MPY_DIR)/tools", opt=3) -require("ntptime") require("dht") -require("onewire") require("ds18x20") +require("mip") require("neopixel") +require("ntptime") +require("onewire") require("webrepl") diff --git a/ports/rp2/boards/PICO_W/manifest.py b/ports/rp2/boards/PICO_W/manifest.py index 4d9eb87f20..8a74006c64 100644 --- a/ports/rp2/boards/PICO_W/manifest.py +++ b/ports/rp2/boards/PICO_W/manifest.py @@ -1,7 +1,5 @@ include("../manifest.py") -module("upip.py", base_path="$(MPY_DIR)/tools", opt=3) -module("upip_utarfile.py", base_path="$(MPY_DIR)/tools", opt=3) - +require("mip") require("ntptime") require("urequests") diff --git a/ports/unix/README.md b/ports/unix/README.md index efc68b2455..a3a0dba75a 100644 --- a/ports/unix/README.md +++ b/ports/unix/README.md @@ -24,21 +24,26 @@ Use `CTRL-D` (i.e. EOF) to exit the shell. Learn about command-line options (in particular, how to increase heap size which may be needed for larger applications): - $ ./micropython -h + $ ./build-standard/micropython -h To run the complete testsuite, use: $ make test -The Unix port comes with a builtin package manager called upip, e.g.: +The Unix port comes with a built-in package manager called `mip`, e.g.: - $ ./micropython -m upip install micropython-pystone - $ ./micropython -m pystone + $ ./build-standard/micropython -m mip install hmac -Browse available modules on -[PyPI](https://pypi.python.org/pypi?%3Aaction=search&term=micropython). -Standard library modules come from the -[micropython-lib](https://github.com/micropython/micropython-lib) project. +or + + $ ./build-standard/micropython + >>> import mip + >>> mip.install("hmac") + +Browse available modules at [micropython-lib] +(https://github.com/micropython/micropython-lib). See +[Package management](https://docs.micropython.org/en/latest/reference/packages.html) +for more information about `mip`. External dependencies --------------------- @@ -65,6 +70,5 @@ or not). If you intend to build MicroPython with additional options (like cross-compiling), the same set of options should be passed to `make deplibs`. To actually enable/disable use of dependencies, edit the `ports/unix/mpconfigport.mk` file, which has inline descriptions of the -options. For example, to build SSL module (required for the `upip` tool -described above, and so enabled by default), `MICROPY_PY_USSL` should be set -to 1. +options. For example, to build the SSL module, `MICROPY_PY_USSL` should be +set to 1. diff --git a/ports/unix/variants/manifest.py b/ports/unix/variants/manifest.py index bf7ce992ad..e7fe747cb7 100644 --- a/ports/unix/variants/manifest.py +++ b/ports/unix/variants/manifest.py @@ -1,2 +1 @@ -module("upip.py", base_path="$(MPY_DIR)/tools", opt=3) -module("upip_utarfile.py", base_path="$(MPY_DIR)/tools", opt=3) +require("mip") diff --git a/tools/upip.py b/tools/upip.py deleted file mode 100644 index 2932cca50c..0000000000 --- a/tools/upip.py +++ /dev/null @@ -1,351 +0,0 @@ -# -# upip - Package manager for MicroPython -# -# Copyright (c) 2015-2018 Paul Sokolovsky -# -# Licensed under the MIT license. -# -import sys -import gc -import uos as os -import uerrno as errno -import ujson as json -import uzlib -import upip_utarfile as tarfile - -gc.collect() - - -debug = False -index_urls = ["https://micropython.org/pi", "https://pypi.org/pypi"] -install_path = None -cleanup_files = [] -gzdict_sz = 16 + 15 - -file_buf = bytearray(512) - - -class NotFoundError(Exception): - pass - - -def op_split(path): - if path == "": - return ("", "") - r = path.rsplit("/", 1) - if len(r) == 1: - return ("", path) - head = r[0] - if not head: - head = "/" - return (head, r[1]) - - -# Expects *file* name -def _makedirs(name, mode=0o777): - ret = False - s = "" - comps = name.rstrip("/").split("/")[:-1] - if comps[0] == "": - s = "/" - for c in comps: - if s and s[-1] != "/": - s += "/" - s += c - try: - os.mkdir(s) - ret = True - except OSError as e: - if e.errno != errno.EEXIST and e.errno != errno.EISDIR: - raise e - ret = False - return ret - - -def save_file(fname, subf): - global file_buf - with open(fname, "wb") as outf: - while True: - sz = subf.readinto(file_buf) - if not sz: - break - outf.write(file_buf, sz) - - -def install_tar(f, prefix): - meta = {} - for info in f: - # print(info) - fname = info.name - try: - fname = fname[fname.index("/") + 1 :] - except ValueError: - fname = "" - - save = True - for p in ("setup.", "PKG-INFO", "README"): - # print(fname, p) - if fname.startswith(p) or ".egg-info" in fname: - if fname.endswith("/requires.txt"): - meta["deps"] = f.extractfile(info).read() - save = False - if debug: - print("Skipping", fname) - break - - if save: - outfname = prefix + fname - if info.type != tarfile.DIRTYPE: - if debug: - print("Extracting " + outfname) - _makedirs(outfname) - subf = f.extractfile(info) - save_file(outfname, subf) - return meta - - -def expandhome(s): - if "~/" in s: - h = os.getenv("HOME") - s = s.replace("~/", h + "/") - return s - - -import ussl -import usocket - -warn_ussl = True - - -def url_open(url): - global warn_ussl - - if debug: - print(url) - - proto, _, host, urlpath = url.split("/", 3) - try: - port = 443 - if ":" in host: - host, port = host.split(":") - port = int(port) - ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM) - except OSError as e: - fatal("Unable to resolve %s (no Internet?)" % host, e) - # print("Address infos:", ai) - ai = ai[0] - - s = usocket.socket(ai[0], ai[1], ai[2]) - try: - # print("Connect address:", addr) - s.connect(ai[-1]) - - if proto == "https:": - s = ussl.wrap_socket(s, server_hostname=host) - if warn_ussl: - print("Warning: %s SSL certificate is not validated" % host) - warn_ussl = False - - # MicroPython rawsocket module supports file interface directly - s.write("GET /%s HTTP/1.0\r\nHost: %s:%s\r\n\r\n" % (urlpath, host, port)) - l = s.readline() - protover, status, msg = l.split(None, 2) - if status != b"200": - if status == b"404" or status == b"301": - raise NotFoundError("Package not found") - raise ValueError(status) - while 1: - l = s.readline() - if not l: - raise ValueError("Unexpected EOF in HTTP headers") - if l == b"\r\n": - break - except Exception as e: - s.close() - raise e - - return s - - -def get_pkg_metadata(name): - for url in index_urls: - try: - f = url_open("%s/%s/json" % (url, name)) - except NotFoundError: - continue - try: - return json.load(f) - finally: - f.close() - raise NotFoundError("Package not found") - - -def fatal(msg, exc=None): - print("Error:", msg) - if exc and debug: - raise exc - sys.exit(1) - - -def install_pkg(pkg_spec, install_path): - package = pkg_spec.split("==") - data = get_pkg_metadata(package[0]) - - if len(package) == 1: - latest_ver = data["info"]["version"] - else: - latest_ver = package[1] - packages = data["releases"][latest_ver] - del data - gc.collect() - assert len(packages) == 1 - package_url = packages[0]["url"] - print("Installing %s %s from %s" % (pkg_spec, latest_ver, package_url)) - f1 = url_open(package_url) - try: - f2 = uzlib.DecompIO(f1, gzdict_sz) - f3 = tarfile.TarFile(fileobj=f2) - meta = install_tar(f3, install_path) - finally: - f1.close() - del f3 - del f2 - gc.collect() - return meta - - -def install(to_install, install_path=None): - # Calculate gzip dictionary size to use - global gzdict_sz - sz = gc.mem_free() + gc.mem_alloc() - if sz <= 65536: - gzdict_sz = 16 + 12 - - if install_path is None: - install_path = get_install_path() - if install_path[-1] != "/": - install_path += "/" - if not isinstance(to_install, list): - to_install = [to_install] - print("Installing to: " + install_path) - # sets would be perfect here, but don't depend on them - installed = [] - try: - while to_install: - if debug: - print("Queue:", to_install) - pkg_spec = to_install.pop(0) - if pkg_spec in installed: - continue - meta = install_pkg(pkg_spec, install_path) - installed.append(pkg_spec) - if debug: - print(meta) - deps = meta.get("deps", "").rstrip() - if deps: - deps = deps.decode("utf-8").split("\n") - to_install.extend(deps) - except Exception as e: - print( - "Error installing '{}': {}, packages may be partially installed".format(pkg_spec, e), - file=sys.stderr, - ) - - -def get_install_path(): - global install_path - if install_path is None: - # sys.path[0] is current module's path - install_path = sys.path[1] - if install_path == ".frozen": - install_path = sys.path[2] - install_path = expandhome(install_path) - return install_path - - -def cleanup(): - for fname in cleanup_files: - try: - os.unlink(fname) - except OSError: - print("Warning: Cannot delete " + fname) - - -def help(): - print( - """\ -upip - Simple PyPI package manager for MicroPython -Usage: micropython -m upip install [-p ] ... | -r -import upip; upip.install(package_or_list, []) - -If isn't given, packages will be installed to sys.path[1], or -sys.path[2] if the former is .frozen (path can be set from MICROPYPATH -environment variable if supported).""" - ) - print("Default install path:", get_install_path()) - print( - """\ - -Note: only MicroPython packages (usually, named micropython-*) are supported -for installation, upip does not support arbitrary code in setup.py. -""" - ) - - -def main(): - global debug - global index_urls - global install_path - install_path = None - - if len(sys.argv) < 2 or sys.argv[1] == "-h" or sys.argv[1] == "--help": - help() - return - - if sys.argv[1] != "install": - fatal("Only 'install' command supported") - - to_install = [] - - i = 2 - while i < len(sys.argv) and sys.argv[i][0] == "-": - opt = sys.argv[i] - i += 1 - if opt == "-h" or opt == "--help": - help() - return - elif opt == "-p": - install_path = sys.argv[i] - i += 1 - elif opt == "-r": - list_file = sys.argv[i] - i += 1 - with open(list_file) as f: - while True: - l = f.readline() - if not l: - break - if l[0] == "#": - continue - to_install.append(l.rstrip()) - elif opt == "-i": - index_urls = [sys.argv[i]] - i += 1 - elif opt == "--debug": - debug = True - else: - fatal("Unknown/unsupported option: " + opt) - - to_install.extend(sys.argv[i:]) - if not to_install: - help() - return - - install(to_install) - - if not debug: - cleanup() - - -if __name__ == "__main__": - main() diff --git a/tools/upip_utarfile.py b/tools/upip_utarfile.py deleted file mode 100644 index 21b899f020..0000000000 --- a/tools/upip_utarfile.py +++ /dev/null @@ -1,95 +0,0 @@ -import uctypes - -# http://www.gnu.org/software/tar/manual/html_node/Standard.html -TAR_HEADER = { - "name": (uctypes.ARRAY | 0, uctypes.UINT8 | 100), - "size": (uctypes.ARRAY | 124, uctypes.UINT8 | 11), -} - -DIRTYPE = "dir" -REGTYPE = "file" - - -def roundup(val, align): - return (val + align - 1) & ~(align - 1) - - -class FileSection: - def __init__(self, f, content_len, aligned_len): - self.f = f - self.content_len = content_len - self.align = aligned_len - content_len - - def read(self, sz=65536): - if self.content_len == 0: - return b"" - if sz > self.content_len: - sz = self.content_len - data = self.f.read(sz) - sz = len(data) - self.content_len -= sz - return data - - def readinto(self, buf): - if self.content_len == 0: - return 0 - if len(buf) > self.content_len: - buf = memoryview(buf)[: self.content_len] - sz = self.f.readinto(buf) - self.content_len -= sz - return sz - - def skip(self): - sz = self.content_len + self.align - if sz: - buf = bytearray(16) - while sz: - s = min(sz, 16) - self.f.readinto(buf, s) - sz -= s - - -class TarInfo: - def __str__(self): - return "TarInfo(%r, %s, %d)" % (self.name, self.type, self.size) - - -class TarFile: - def __init__(self, name=None, fileobj=None): - if fileobj: - self.f = fileobj - else: - self.f = open(name, "rb") - self.subf = None - - def next(self): - if self.subf: - self.subf.skip() - buf = self.f.read(512) - if not buf: - return None - - h = uctypes.struct(uctypes.addressof(buf), TAR_HEADER, uctypes.LITTLE_ENDIAN) - - # Empty block means end of archive - if h.name[0] == 0: - return None - - d = TarInfo() - d.name = str(h.name, "utf-8").rstrip("\0") - d.size = int(bytes(h.size), 8) - d.type = [REGTYPE, DIRTYPE][d.name[-1] == "/"] - self.subf = d.subf = FileSection(self.f, d.size, roundup(d.size, 512)) - return d - - def __iter__(self): - return self - - def __next__(self): - v = self.next() - if v is None: - raise StopIteration - return v - - def extractfile(self, tarinfo): - return tarinfo.subf From 282401da5c6e689e63af7b9858cf9b0d23a24b2b Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 30 Sep 2022 15:33:43 +1000 Subject: [PATCH 0461/1041] tools/manifestfile.py: Replace recursive glob with os.walk. Recursive glob isn't supported before Python 3.5. Signed-off-by: Jim Mussared --- tools/manifestfile.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/manifestfile.py b/tools/manifestfile.py index f7966ccb80..fb9691d293 100644 --- a/tools/manifestfile.py +++ b/tools/manifestfile.py @@ -311,14 +311,14 @@ class ManifestFile: lib_dirs = ["unix-ffi"] + lib_dirs for lib_dir in lib_dirs: - for manifest_path in glob.glob( - os.path.join( - self._path_vars["MPY_LIB_DIR"], lib_dir, "**", name, "manifest.py" - ), - recursive=True, + # Search for {lib_dir}/**/{name}/manifest.py. + for root, dirnames, filenames in os.walk( + os.path.join(self._path_vars["MPY_LIB_DIR"], lib_dir) ): - self.include(manifest_path, **kwargs) - return + if os.path.basename(root) == name and "manifest.py" in filenames: + self.include(root, **kwargs) + return + raise ValueError("Library not found in local micropython-lib: {}".format(name)) else: # TODO: HTTP request to obtain URLs from manifest.json. From 413a69b94b92d1ae1cdd132e41d460259d22b9b8 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 30 Sep 2022 11:46:23 +1000 Subject: [PATCH 0462/1041] tools/mpremote: Simplify dispatch of commands. No functional change. This makes each built-in command defined by just a handler method and simplifies a lot of the logic around tracking the board state. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared --- tools/mpremote/mpremote/commands.py | 261 +++++++++++++ tools/mpremote/mpremote/main.py | 551 ++++++++-------------------- tools/mpremote/mpremote/repl.py | 101 +++++ 3 files changed, 507 insertions(+), 406 deletions(-) create mode 100644 tools/mpremote/mpremote/commands.py create mode 100644 tools/mpremote/mpremote/repl.py diff --git a/tools/mpremote/mpremote/commands.py b/tools/mpremote/mpremote/commands.py new file mode 100644 index 0000000000..60a625d5e8 --- /dev/null +++ b/tools/mpremote/mpremote/commands.py @@ -0,0 +1,261 @@ +import os +import sys +import tempfile + +import serial.tools.list_ports + +from . import pyboardextended as pyboard + + +class CommandError(Exception): + pass + + do_disconnect(state) + + try: + if dev == "list": + # List attached devices. + for p in sorted(serial.tools.list_ports.comports()): + print( + "{} {} {:04x}:{:04x} {} {}".format( + p.device, + p.serial_number, + p.vid if isinstance(p.vid, int) else 0, + p.pid if isinstance(p.pid, int) else 0, + p.manufacturer, + p.product, + ) + ) + # Don't do implicit REPL command. + state.did_action() + elif dev == "auto": + # Auto-detect and auto-connect to the first available device. + for p in sorted(serial.tools.list_ports.comports()): + try: + state.pyb = pyboard.PyboardExtended(p.device, baudrate=115200) + return + except pyboard.PyboardError as er: + if not er.args[0].startswith("failed to access"): + raise er + raise pyboard.PyboardError("no device found") + elif dev.startswith("id:"): + # Search for a device with the given serial number. + serial_number = dev[len("id:") :] + dev = None + for p in serial.tools.list_ports.comports(): + if p.serial_number == serial_number: + state.pyb = pyboard.PyboardExtended(p.device, baudrate=115200) + return + raise pyboard.PyboardError("no device with serial number {}".format(serial_number)) + else: + # Connect to the given device. + if dev.startswith("port:"): + dev = dev[len("port:") :] + state.pyb = pyboard.PyboardExtended(dev, baudrate=115200) + return + except pyboard.PyboardError as er: + msg = er.args[0] + if msg.startswith("failed to access"): + msg += " (it may be in use by another program)" + print(msg) + sys.exit(1) + + +def do_disconnect(state, _args=None): + if not state.pyb: + return + + try: + if state.pyb.mounted: + if not state.pyb.in_raw_repl: + state.pyb.enter_raw_repl(soft_reset=False) + state.pyb.umount_local() + if state.pyb.in_raw_repl: + state.pyb.exit_raw_repl() + except OSError: + # Ignore any OSError exceptions when shutting down, eg: + # - pyboard.filesystem_command will close the connecton if it had an error + # - umounting will fail if serial port disappeared + pass + state.pyb.close() + state.pyb = None + state._auto_soft_reset = True + + +def show_progress_bar(size, total_size, op="copying"): + if not sys.stdout.isatty(): + return + verbose_size = 2048 + bar_length = 20 + if total_size < verbose_size: + return + elif size >= total_size: + # Clear progress bar when copy completes + print("\r" + " " * (13 + len(op) + bar_length) + "\r", end="") + else: + bar = size * bar_length // total_size + progress = size * 100 // total_size + print( + "\r ... {} {:3d}% [{}{}]".format(op, progress, "#" * bar, "-" * (bar_length - bar)), + end="", + ) + + +# Get all args up to the terminator ("+"). +# The passed args will be updated with these ones removed. +def _get_fs_args(args): + n = 0 + for src in args: + if src == "+": + break + n += 1 + fs_args = args[:n] + args[:] = args[n + 1 :] + return fs_args + + +def do_filesystem(state, args): + state.ensure_raw_repl() + state.did_action() + + def _list_recursive(files, path): + if os.path.isdir(path): + for entry in os.listdir(path): + _list_recursive(files, "/".join((path, entry))) + else: + files.append(os.path.split(path)) + + fs_args = _get_fs_args(args) + + # Don't be verbose when using cat, so output can be redirected to something. + verbose = fs_args[0] != "cat" + + if fs_args[0] == "cp" and fs_args[1] == "-r": + fs_args.pop(0) + fs_args.pop(0) + if fs_args[-1] != ":": + print(f"{_PROG}: 'cp -r' destination must be ':'") + sys.exit(1) + fs_args.pop() + src_files = [] + for path in fs_args: + if path.startswith(":"): + raise CommandError("'cp -r' source files must be local") + _list_recursive(src_files, path) + known_dirs = {""} + state.pyb.exec_("import uos") + for dir, file in src_files: + dir_parts = dir.split("/") + for i in range(len(dir_parts)): + d = "/".join(dir_parts[: i + 1]) + if d not in known_dirs: + state.pyb.exec_("try:\n uos.mkdir('%s')\nexcept OSError as e:\n print(e)" % d) + known_dirs.add(d) + pyboard.filesystem_command( + state.pyb, + ["cp", "/".join((dir, file)), ":" + dir + "/"], + progress_callback=show_progress_bar, + verbose=verbose, + ) + else: + try: + pyboard.filesystem_command( + state.pyb, fs_args, progress_callback=show_progress_bar, verbose=verbose + ) + except OSError as er: + raise CommandError(er) + + +def do_edit(state, args): + state.ensure_raw_repl() + state.did_action() + + if not os.getenv("EDITOR"): + raise pyboard.PyboardError("edit: $EDITOR not set") + for src in _get_fs_args(args): + src = src.lstrip(":") + dest_fd, dest = tempfile.mkstemp(suffix=os.path.basename(src)) + try: + print("edit :%s" % (src,)) + os.close(dest_fd) + state.pyb.fs_touch(src) + state.pyb.fs_get(src, dest, progress_callback=show_progress_bar) + if os.system("$EDITOR '%s'" % (dest,)) == 0: + state.pyb.fs_put(dest, src, progress_callback=show_progress_bar) + finally: + os.unlink(dest) + + +def _get_follow_arg(args): + if args[0] == "--no-follow": + args.pop(0) + return False + else: + return True + + +def _do_execbuffer(state, buf, follow): + state.ensure_raw_repl() + state.did_action() + + try: + state.pyb.exec_raw_no_follow(buf) + if follow: + ret, ret_err = state.pyb.follow(timeout=None, data_consumer=pyboard.stdout_write_bytes) + if ret_err: + pyboard.stdout_write_bytes(ret_err) + sys.exit(1) + except pyboard.PyboardError as er: + print(er) + sys.exit(1) + except KeyboardInterrupt: + sys.exit(1) + + +def do_exec(state, args): + follow = _get_follow_arg(args) + buf = args.pop(0) + _do_execbuffer(state, buf, follow) + + +def do_eval(state, args): + follow = _get_follow_arg(args) + buf = "print(" + args.pop(0) + ")" + _do_execbuffer(state, buf, follow) + + +def do_run(state, args): + follow = _get_follow_arg(args) + filename = args.pop(0) + try: + with open(filename, "rb") as f: + buf = f.read() + except OSError: + raise CommandError(f"could not read file '{filename}'") + sys.exit(1) + _do_execbuffer(state, buf, follow) + + +def do_mount(state, args): + state.ensure_raw_repl() + + unsafe_links = False + if args[0] == "--unsafe-links" or args[0] == "-l": + args.pop(0) + unsafe_links = True + path = args.pop(0) + state.pyb.mount_local(path, unsafe_links=unsafe_links) + print(f"Local directory {path} is mounted at /remote") + + +def do_umount(state, path): + state.ensure_raw_repl() + state.pyb.umount_local() + + +def do_resume(state, _args=None): + state._auto_soft_reset = False + + +def do_soft_reset(state, _args=None): + state.ensure_raw_repl(soft_reset=True) diff --git a/tools/mpremote/mpremote/main.py b/tools/mpremote/mpremote/main.py index bd98da8824..b96e3f46b1 100644 --- a/tools/mpremote/mpremote/main.py +++ b/tools/mpremote/mpremote/main.py @@ -19,45 +19,101 @@ MicroPython device over a serial connection. Commands supported are: import os, sys from collections.abc import Mapping -import tempfile from textwrap import dedent -import serial.tools.list_ports - -from . import pyboardextended as pyboard -from .console import Console, ConsolePosix +from .commands import ( + CommandError, + do_connect, + do_disconnect, + do_edit, + do_filesystem, + do_mount, + do_umount, + do_exec, + do_eval, + do_run, + do_resume, + do_soft_reset, +) +from .repl import do_repl _PROG = "mpremote" -# (need_raw_repl, is_action, num_args_min, help_text) + +def do_help(state, _args=None): + def print_commands_help(cmds, help_idx): + max_command_len = max(len(cmd) for cmd in cmds.keys()) + for cmd in sorted(cmds.keys()): + help_message_lines = dedent(cmds[cmd][help_idx]).split("\n") + help_message = help_message_lines[0] + for line in help_message_lines[1:]: + help_message = "{}\n{}{}".format(help_message, " " * (max_command_len + 4), line) + print(" ", cmd, " " * (max_command_len - len(cmd) + 2), help_message, sep="") + + print(_PROG, "-- MicroPython remote control") + print("See https://docs.micropython.org/en/latest/reference/mpremote.html") + + print("\nList of commands:") + print_commands_help(_COMMANDS, 1) + + print("\nList of shortcuts:") + print_commands_help(_command_expansions, 2) + + sys.exit(0) + + +def do_version(state, _args=None): + from . import __version__ + + print(f"{_PROG} {__version__}") + sys.exit(0) + + +# Map of "command" to tuple of (num_args_min, help_text, handler). _COMMANDS = { "connect": ( - False, - False, 1, """\ connect to given device device may be: list, auto, id:x, port:x or any valid device name/path""", + do_connect, + ), + "disconnect": ( + 0, + "disconnect current device", + do_disconnect, + ), + "edit": ( + 1, + "edit files on the device", + do_edit, + ), + "resume": ( + 0, + "resume a previous mpremote session (will not auto soft-reset)", + do_resume, + ), + "soft-reset": ( + 0, + "perform a soft-reset of the device", + do_soft_reset, ), - "disconnect": (False, False, 0, "disconnect current device"), - "edit": (True, True, 1, "edit files on the device"), - "resume": (False, False, 0, "resume a previous mpremote session (will not auto soft-reset)"), - "soft-reset": (False, True, 0, "perform a soft-reset of the device"), "mount": ( - True, - False, 1, """\ mount local directory on device options: --unsafe-links, -l follow symbolic links pointing outside of local directory""", + do_mount, + ), + "umount": ( + 0, + "unmount the local directory", + do_umount, ), - "umount": (True, False, 0, "unmount the local directory"), "repl": ( - False, - True, 0, """\ enter REPL @@ -65,15 +121,45 @@ _COMMANDS = { --capture --inject-code --inject-file """, + do_repl, + ), + "eval": ( + 1, + "evaluate and print the string", + do_eval, + ), + "exec": ( + 1, + "execute the string", + do_exec, + ), + "run": ( + 1, + "run the given local script", + do_run, + ), + "fs": ( + 1, + "execute filesystem commands on the device", + do_filesystem, + ), + "help": ( + 0, + "print help and exit", + do_help, + ), + "version": ( + 0, + "print version and exit", + do_version, ), - "eval": (True, True, 1, "evaluate and print the string"), - "exec": (True, True, 1, "execute the string"), - "run": (True, True, 1, "run the given local script"), - "fs": (True, True, 1, "execute filesystem commands on the device"), - "help": (False, False, 0, "print help and exit"), - "version": (False, False, 0, "print version and exit"), } +# Additional commands aliases. +# The value can either be: +# - A command string. +# - A list of command strings, each command will be executed sequentially. +# - A dict of command: { [], help: ""} _BUILTIN_COMMAND_EXPANSIONS = { # Device connection shortcuts. "devs": { @@ -117,6 +203,8 @@ _BUILTIN_COMMAND_EXPANSIONS = { "--version": "version", } +# Add "a0", "a1", ..., "u0", "u1", ..., "c0", "c1", ... as aliases +# for "connect /dev/ttyACMn" (and /dev/ttyUSBn, COMn) etc. for port_num in range(4): for prefix, port in [("a", "/dev/ttyACM"), ("u", "/dev/ttyUSB"), ("c", "COM")]: _BUILTIN_COMMAND_EXPANSIONS["{}{}".format(prefix, port_num)] = { @@ -220,307 +308,33 @@ def do_command_expansion(args): args[0:0] = ["exec", ";".join(pre)] -def do_connect(args): - dev = args.pop(0) - try: - if dev == "list": - # List attached devices. - for p in sorted(serial.tools.list_ports.comports()): - print( - "{} {} {:04x}:{:04x} {} {}".format( - p.device, - p.serial_number, - p.vid if isinstance(p.vid, int) else 0, - p.pid if isinstance(p.pid, int) else 0, - p.manufacturer, - p.product, - ) - ) - return None - elif dev == "auto": - # Auto-detect and auto-connect to the first available device. - for p in sorted(serial.tools.list_ports.comports()): - try: - return pyboard.PyboardExtended(p.device, baudrate=115200) - except pyboard.PyboardError as er: - if not er.args[0].startswith("failed to access"): - raise er - raise pyboard.PyboardError("no device found") - elif dev.startswith("id:"): - # Search for a device with the given serial number. - serial_number = dev[len("id:") :] - dev = None - for p in serial.tools.list_ports.comports(): - if p.serial_number == serial_number: - return pyboard.PyboardExtended(p.device, baudrate=115200) - raise pyboard.PyboardError("no device with serial number {}".format(serial_number)) - else: - # Connect to the given device. - if dev.startswith("port:"): - dev = dev[len("port:") :] - return pyboard.PyboardExtended(dev, baudrate=115200) - except pyboard.PyboardError as er: - msg = er.args[0] - if msg.startswith("failed to access"): - msg += " (it may be in use by another program)" - print(msg) - sys.exit(1) +class State: + def __init__(self): + self.pyb = None + self._did_action = False + self._auto_soft_reset = True + def did_action(self): + self._did_action = True -def do_disconnect(pyb): - try: - if pyb.mounted: - if not pyb.in_raw_repl: - pyb.enter_raw_repl(soft_reset=False) - pyb.umount_local() - if pyb.in_raw_repl: - pyb.exit_raw_repl() - except OSError: - # Ignore any OSError exceptions when shutting down, eg: - # - pyboard.filesystem_command will close the connecton if it had an error - # - umounting will fail if serial port disappeared - pass - pyb.close() + def run_repl_on_completion(self): + return not self._did_action + def ensure_connected(self): + if self.pyb is None: + do_connect(self, ["auto"]) -def show_progress_bar(size, total_size): - if not sys.stdout.isatty(): - return - verbose_size = 2048 - bar_length = 20 - if total_size < verbose_size: - return - elif size >= total_size: - # Clear progress bar when copy completes - print("\r" + " " * (20 + bar_length) + "\r", end="") - else: - progress = size / total_size - bar = round(progress * bar_length) - print( - "\r ... copying {:3.0f}% [{}{}]".format( - progress * 100, "#" * bar, "-" * (bar_length - bar) - ), - end="", - ) + def ensure_raw_repl(self, soft_reset=None): + self.ensure_connected() + soft_reset = self._auto_soft_reset if soft_reset is None else soft_reset + if soft_reset or not self.pyb.in_raw_repl: + self.pyb.enter_raw_repl(soft_reset=soft_reset) + self._auto_soft_reset = False - -# Get all args up to the terminator ("+"). -# The passed args will be updated with these ones removed. -def get_fs_args(args): - n = 0 - for src in args: - if src == "+": - break - n += 1 - fs_args = args[:n] - args[:] = args[n + 1 :] - return fs_args - - -def do_filesystem(pyb, args): - def _list_recursive(files, path): - if os.path.isdir(path): - for entry in os.listdir(path): - _list_recursive(files, "/".join((path, entry))) - else: - files.append(os.path.split(path)) - - fs_args = get_fs_args(args) - - # Don't be verbose when using cat, so output can be redirected to something. - verbose = fs_args[0] != "cat" - - if fs_args[0] == "cp" and fs_args[1] == "-r": - fs_args.pop(0) - fs_args.pop(0) - if fs_args[-1] != ":": - print(f"{_PROG}: 'cp -r' destination must be ':'") - sys.exit(1) - fs_args.pop() - src_files = [] - for path in fs_args: - if path.startswith(":"): - print(f"{_PROG}: 'cp -r' source files must be local") - sys.exit(1) - _list_recursive(src_files, path) - known_dirs = {""} - pyb.exec_("import uos") - for dir, file in src_files: - dir_parts = dir.split("/") - for i in range(len(dir_parts)): - d = "/".join(dir_parts[: i + 1]) - if d not in known_dirs: - pyb.exec_("try:\n uos.mkdir('%s')\nexcept OSError as e:\n print(e)" % d) - known_dirs.add(d) - pyboard.filesystem_command( - pyb, - ["cp", "/".join((dir, file)), ":" + dir + "/"], - progress_callback=show_progress_bar, - verbose=verbose, - ) - else: - try: - pyboard.filesystem_command( - pyb, fs_args, progress_callback=show_progress_bar, verbose=verbose - ) - except OSError as er: - print(f"{_PROG}: {er}") - sys.exit(1) - - -def do_edit(pyb, args): - if not os.getenv("EDITOR"): - raise pyboard.PyboardError("edit: $EDITOR not set") - for src in get_fs_args(args): - src = src.lstrip(":") - dest_fd, dest = tempfile.mkstemp(suffix=os.path.basename(src)) - try: - print("edit :%s" % (src,)) - os.close(dest_fd) - pyb.fs_touch(src) - pyb.fs_get(src, dest, progress_callback=show_progress_bar) - if os.system("$EDITOR '%s'" % (dest,)) == 0: - pyb.fs_put(dest, src, progress_callback=show_progress_bar) - finally: - os.unlink(dest) - - -def do_repl_main_loop(pyb, console_in, console_out_write, *, code_to_inject, file_to_inject): - while True: - console_in.waitchar(pyb.serial) - c = console_in.readchar() - if c: - if c == b"\x1d": # ctrl-], quit - break - elif c == b"\x04": # ctrl-D - # special handling needed for ctrl-D if filesystem is mounted - pyb.write_ctrl_d(console_out_write) - elif c == b"\x0a" and code_to_inject is not None: # ctrl-j, inject code - pyb.serial.write(code_to_inject) - elif c == b"\x0b" and file_to_inject is not None: # ctrl-k, inject script - console_out_write(bytes("Injecting %s\r\n" % file_to_inject, "utf8")) - pyb.enter_raw_repl(soft_reset=False) - with open(file_to_inject, "rb") as f: - pyfile = f.read() - try: - pyb.exec_raw_no_follow(pyfile) - except pyboard.PyboardError as er: - console_out_write(b"Error:\r\n") - console_out_write(er) - pyb.exit_raw_repl() - else: - pyb.serial.write(c) - - try: - n = pyb.serial.inWaiting() - except OSError as er: - if er.args[0] == 5: # IO error, device disappeared - print("device disconnected") - break - - if n > 0: - c = pyb.serial.read(1) - if c is not None: - # pass character through to the console - oc = ord(c) - if oc in (8, 9, 10, 13, 27) or 32 <= oc <= 126: - console_out_write(c) - else: - console_out_write(b"[%02x]" % ord(c)) - - -def do_repl(pyb, args): - capture_file = None - code_to_inject = None - file_to_inject = None - - while len(args): - if args[0] == "--capture": - args.pop(0) - capture_file = args.pop(0) - elif args[0] == "--inject-code": - args.pop(0) - code_to_inject = bytes(args.pop(0).replace("\\n", "\r\n"), "utf8") - elif args[0] == "--inject-file": - args.pop(0) - file_to_inject = args.pop(0) - else: - break - - print("Connected to MicroPython at %s" % pyb.device_name) - print("Use Ctrl-] to exit this shell") - if capture_file is not None: - print('Capturing session to file "%s"' % capture_file) - capture_file = open(capture_file, "wb") - if code_to_inject is not None: - print("Use Ctrl-J to inject", code_to_inject) - if file_to_inject is not None: - print('Use Ctrl-K to inject file "%s"' % file_to_inject) - - console = Console() - console.enter() - - def console_out_write(b): - console.write(b) - if capture_file is not None: - capture_file.write(b) - capture_file.flush() - - try: - do_repl_main_loop( - pyb, - console, - console_out_write, - code_to_inject=code_to_inject, - file_to_inject=file_to_inject, - ) - finally: - console.exit() - if capture_file is not None: - capture_file.close() - - -def execbuffer(pyb, buf, follow): - ret_val = 0 - try: - pyb.exec_raw_no_follow(buf) - if follow: - ret, ret_err = pyb.follow(timeout=None, data_consumer=pyboard.stdout_write_bytes) - if ret_err: - pyboard.stdout_write_bytes(ret_err) - ret_val = 1 - except pyboard.PyboardError as er: - print(er) - ret_val = 1 - except KeyboardInterrupt: - ret_val = 1 - return ret_val - - -def print_help(): - def print_commands_help(cmds, help_idx): - max_command_len = max(len(cmd) for cmd in cmds.keys()) - for cmd in sorted(cmds.keys()): - help_message_lines = dedent(cmds[cmd][help_idx]).split("\n") - help_message = help_message_lines[0] - for line in help_message_lines[1:]: - help_message = "{}\n{}{}".format(help_message, " " * (max_command_len + 4), line) - print(" ", cmd, " " * (max_command_len - len(cmd) + 2), help_message, sep="") - - print(_PROG, "-- MicroPython remote control") - print("See https://docs.micropython.org/en/latest/reference/mpremote.html") - - print("\nList of commands:") - print_commands_help(_COMMANDS, 3) - - print("\nList of shortcuts:") - print_commands_help(_command_expansions, 2) - - -def print_version(): - from . import __version__ - - print(f"{_PROG} {__version__}") + def ensure_friendly_repl(self): + self.ensure_connected() + if self.pyb.in_raw_repl: + self.pyb.exit_raw_repl() def main(): @@ -528,106 +342,31 @@ def main(): prepare_command_expansions(config) args = sys.argv[1:] - pyb = None - auto_soft_reset = True - did_action = False + state = State() try: while args: do_command_expansion(args) cmd = args.pop(0) try: - need_raw_repl, is_action, num_args_min, _ = _COMMANDS[cmd] + num_args_min, _help, handler = _COMMANDS[cmd] except KeyError: - print(f"{_PROG}: '{cmd}' is not a command") - return 1 + raise CommandError(f"'{cmd}' is not a command") if len(args) < num_args_min: print(f"{_PROG}: '{cmd}' neads at least {num_args_min} argument(s)") return 1 - if cmd == "connect": - if pyb is not None: - do_disconnect(pyb) - pyb = do_connect(args) - if pyb is None: - did_action = True - continue - elif cmd == "help": - print_help() - sys.exit(0) - elif cmd == "version": - print_version() - sys.exit(0) - elif cmd == "resume": - auto_soft_reset = False - continue + handler(state, args) - # The following commands need a connection, and either a raw or friendly REPL. - if pyb is None: - pyb = do_connect(["auto"]) + # If no commands were "actions" then implicitly finish with the REPL. + if state.run_repl_on_completion(): + do_repl(state, args) - if need_raw_repl: - if not pyb.in_raw_repl: - pyb.enter_raw_repl(soft_reset=auto_soft_reset) - auto_soft_reset = False - else: - if pyb.in_raw_repl: - pyb.exit_raw_repl() - if is_action: - did_action = True - - if cmd == "disconnect": - do_disconnect(pyb) - pyb = None - auto_soft_reset = True - elif cmd == "soft-reset": - pyb.enter_raw_repl(soft_reset=True) - auto_soft_reset = False - elif cmd == "mount": - unsafe_links = False - if args[0] == "--unsafe-links" or args[0] == "-l": - args.pop(0) - unsafe_links = True - path = args.pop(0) - pyb.mount_local(path, unsafe_links=unsafe_links) - print(f"Local directory {path} is mounted at /remote") - elif cmd == "umount": - pyb.umount_local() - elif cmd in ("exec", "eval", "run"): - follow = True - if args[0] == "--no-follow": - args.pop(0) - follow = False - if cmd == "exec": - buf = args.pop(0) - elif cmd == "eval": - buf = "print(" + args.pop(0) + ")" - else: - filename = args.pop(0) - try: - with open(filename, "rb") as f: - buf = f.read() - except OSError: - print(f"{_PROG}: could not read file '{filename}'") - return 1 - ret = execbuffer(pyb, buf, follow) - if ret: - return ret - elif cmd == "fs": - do_filesystem(pyb, args) - elif cmd == "edit": - do_edit(pyb, args) - elif cmd == "repl": - do_repl(pyb, args) - - if not did_action: - if pyb is None: - pyb = do_connect(["auto"]) - if pyb.in_raw_repl: - pyb.exit_raw_repl() - do_repl(pyb, args) + return 0 + except CommandError as e: + print(f"{_PROG}: {e}", file=sys.stderr) + return 1 finally: - if pyb is not None: - do_disconnect(pyb) + do_disconnect(state) diff --git a/tools/mpremote/mpremote/repl.py b/tools/mpremote/mpremote/repl.py new file mode 100644 index 0000000000..f92d20ae79 --- /dev/null +++ b/tools/mpremote/mpremote/repl.py @@ -0,0 +1,101 @@ +from .console import Console, ConsolePosix + +from . import pyboardextended as pyboard + + +def do_repl_main_loop(state, console_in, console_out_write, *, code_to_inject, file_to_inject): + while True: + console_in.waitchar(state.pyb.serial) + c = console_in.readchar() + if c: + if c == b"\x1d": # ctrl-], quit + break + elif c == b"\x04": # ctrl-D + # special handling needed for ctrl-D if filesystem is mounted + state.pyb.write_ctrl_d(console_out_write) + elif c == b"\x0a" and code_to_inject is not None: # ctrl-j, inject code + state.pyb.serial.write(code_to_inject) + elif c == b"\x0b" and file_to_inject is not None: # ctrl-k, inject script + console_out_write(bytes("Injecting %s\r\n" % file_to_inject, "utf8")) + state.pyb.enter_raw_repl(soft_reset=False) + with open(file_to_inject, "rb") as f: + pyfile = f.read() + try: + state.pyb.exec_raw_no_follow(pyfile) + except pyboard.PyboardError as er: + console_out_write(b"Error:\r\n") + console_out_write(er) + state.pyb.exit_raw_repl() + else: + state.pyb.serial.write(c) + + try: + n = state.pyb.serial.inWaiting() + except OSError as er: + if er.args[0] == 5: # IO error, device disappeared + print("device disconnected") + break + + if n > 0: + c = state.pyb.serial.read(1) + if c is not None: + # pass character through to the console + oc = ord(c) + if oc in (8, 9, 10, 13, 27) or 32 <= oc <= 126: + console_out_write(c) + else: + console_out_write(b"[%02x]" % ord(c)) + + +def do_repl(state, args): + state.ensure_friendly_repl() + state.did_action() + + capture_file = None + code_to_inject = None + file_to_inject = None + + while len(args): + if args[0] == "--capture": + args.pop(0) + capture_file = args.pop(0) + elif args[0] == "--inject-code": + args.pop(0) + code_to_inject = bytes(args.pop(0).replace("\\n", "\r\n"), "utf8") + elif args[0] == "--inject-file": + args.pop(0) + file_to_inject = args.pop(0) + else: + break + + print("Connected to MicroPython at %s" % state.pyb.device_name) + print("Use Ctrl-] to exit this shell") + if capture_file is not None: + print('Capturing session to file "%s"' % capture_file) + capture_file = open(capture_file, "wb") + if code_to_inject is not None: + print("Use Ctrl-J to inject", code_to_inject) + if file_to_inject is not None: + print('Use Ctrl-K to inject file "%s"' % file_to_inject) + + console = Console() + console.enter() + + def console_out_write(b): + console.write(b) + if capture_file is not None: + capture_file.write(b) + capture_file.flush() + + try: + do_repl_main_loop( + state, + console, + console_out_write, + code_to_inject=code_to_inject, + file_to_inject=file_to_inject, + ) + finally: + console.exit() + if capture_file is not None: + capture_file.close() From 68d094358ec71aa8cdec97e9e6fc3c6d46dedfbf Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 30 Sep 2022 14:36:39 +1000 Subject: [PATCH 0463/1041] tools/mpremote: Use argparse for command line parsing. No functional change other than to allow slightly more flexibility in how --foo arguments are specified. This removes all custom handling for --foo args in all commands and replaces it with per-command argparse configs. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared --- tools/mpremote/mpremote/commands.py | 78 ++++------ tools/mpremote/mpremote/main.py | 218 ++++++++++++++++++++-------- tools/mpremote/mpremote/repl.py | 19 +-- 3 files changed, 190 insertions(+), 125 deletions(-) diff --git a/tools/mpremote/mpremote/commands.py b/tools/mpremote/mpremote/commands.py index 60a625d5e8..bf56df6999 100644 --- a/tools/mpremote/mpremote/commands.py +++ b/tools/mpremote/mpremote/commands.py @@ -10,6 +10,9 @@ from . import pyboardextended as pyboard class CommandError(Exception): pass + +def do_connect(state, args=None): + dev = args.device[0] if args else "auto" do_disconnect(state) try: @@ -101,19 +104,6 @@ def show_progress_bar(size, total_size, op="copying"): ) -# Get all args up to the terminator ("+"). -# The passed args will be updated with these ones removed. -def _get_fs_args(args): - n = 0 - for src in args: - if src == "+": - break - n += 1 - fs_args = args[:n] - args[:] = args[n + 1 :] - return fs_args - - def do_filesystem(state, args): state.ensure_raw_repl() state.did_action() @@ -125,20 +115,22 @@ def do_filesystem(state, args): else: files.append(os.path.split(path)) - fs_args = _get_fs_args(args) + command = args.command[0] + paths = args.path - # Don't be verbose when using cat, so output can be redirected to something. - verbose = fs_args[0] != "cat" + if command == "cat": + # Don't be verbose by default when using cat, so output can be + # redirected to something. + verbose = args.verbose == True + else: + verbose = args.verbose != False - if fs_args[0] == "cp" and fs_args[1] == "-r": - fs_args.pop(0) - fs_args.pop(0) - if fs_args[-1] != ":": - print(f"{_PROG}: 'cp -r' destination must be ':'") - sys.exit(1) - fs_args.pop() + if command == "cp" and args.recursive: + if paths[-1] != ":": + raise CommandError("'cp -r' destination must be ':'") + paths.pop() src_files = [] - for path in fs_args: + for path in paths: if path.startswith(":"): raise CommandError("'cp -r' source files must be local") _list_recursive(src_files, path) @@ -158,9 +150,11 @@ def do_filesystem(state, args): verbose=verbose, ) else: + if args.recursive: + raise CommandError("'-r' only supported for 'cp'") try: pyboard.filesystem_command( - state.pyb, fs_args, progress_callback=show_progress_bar, verbose=verbose + state.pyb, [command] + paths, progress_callback=show_progress_bar, verbose=verbose ) except OSError as er: raise CommandError(er) @@ -172,7 +166,7 @@ def do_edit(state, args): if not os.getenv("EDITOR"): raise pyboard.PyboardError("edit: $EDITOR not set") - for src in _get_fs_args(args): + for src in args.files: src = src.lstrip(":") dest_fd, dest = tempfile.mkstemp(suffix=os.path.basename(src)) try: @@ -186,14 +180,6 @@ def do_edit(state, args): os.unlink(dest) -def _get_follow_arg(args): - if args[0] == "--no-follow": - args.pop(0) - return False - else: - return True - - def _do_execbuffer(state, buf, follow): state.ensure_raw_repl() state.did_action() @@ -213,38 +199,28 @@ def _do_execbuffer(state, buf, follow): def do_exec(state, args): - follow = _get_follow_arg(args) - buf = args.pop(0) - _do_execbuffer(state, buf, follow) + _do_execbuffer(state, args.expr[0], args.follow) def do_eval(state, args): - follow = _get_follow_arg(args) - buf = "print(" + args.pop(0) + ")" - _do_execbuffer(state, buf, follow) + buf = "print(" + args.expr[0] + ")" + _do_execbuffer(state, buf, args.follow) def do_run(state, args): - follow = _get_follow_arg(args) - filename = args.pop(0) + filename = args.path[0] try: with open(filename, "rb") as f: buf = f.read() except OSError: raise CommandError(f"could not read file '{filename}'") - sys.exit(1) - _do_execbuffer(state, buf, follow) + _do_execbuffer(state, buf, args.follow) def do_mount(state, args): state.ensure_raw_repl() - - unsafe_links = False - if args[0] == "--unsafe-links" or args[0] == "-l": - args.pop(0) - unsafe_links = True - path = args.pop(0) - state.pyb.mount_local(path, unsafe_links=unsafe_links) + path = args.path[0] + state.pyb.mount_local(path, unsafe_links=args.unsafe_links) print(f"Local directory {path} is mounted at /remote") diff --git a/tools/mpremote/mpremote/main.py b/tools/mpremote/mpremote/main.py index b96e3f46b1..17d2b33738 100644 --- a/tools/mpremote/mpremote/main.py +++ b/tools/mpremote/mpremote/main.py @@ -17,6 +17,7 @@ MicroPython device over a serial connection. Commands supported are: mpremote repl -- enter REPL """ +import argparse import os, sys from collections.abc import Mapping from textwrap import dedent @@ -41,10 +42,10 @@ _PROG = "mpremote" def do_help(state, _args=None): - def print_commands_help(cmds, help_idx): + def print_commands_help(cmds, help_key): max_command_len = max(len(cmd) for cmd in cmds.keys()) for cmd in sorted(cmds.keys()): - help_message_lines = dedent(cmds[cmd][help_idx]).split("\n") + help_message_lines = dedent(help_key(cmds[cmd])).split("\n") help_message = help_message_lines[0] for line in help_message_lines[1:]: help_message = "{}\n{}{}".format(help_message, " " * (max_command_len + 4), line) @@ -54,10 +55,12 @@ def do_help(state, _args=None): print("See https://docs.micropython.org/en/latest/reference/mpremote.html") print("\nList of commands:") - print_commands_help(_COMMANDS, 1) + print_commands_help( + _COMMANDS, lambda x: x[1]().description + ) # extract description from argparse print("\nList of shortcuts:") - print_commands_help(_command_expansions, 2) + print_commands_help(_command_expansions, lambda x: x[2]) # (args, sub, help_message) sys.exit(0) @@ -69,89 +72,157 @@ def do_version(state, _args=None): sys.exit(0) -# Map of "command" to tuple of (num_args_min, help_text, handler). +def _bool_flag(cmd_parser, name, short_name, default, description): + # In Python 3.9+ this can be replaced with argparse.BooleanOptionalAction. + group = cmd_parser.add_mutually_exclusive_group() + group.add_argument( + "--" + name, + "-" + short_name, + action="store_true", + default=default, + help=description, + ) + group.add_argument( + "--no-" + name, + action="store_false", + dest=name, + ) + + +def argparse_connect(): + cmd_parser = argparse.ArgumentParser(description="connect to given device") + cmd_parser.add_argument( + "device", nargs=1, help="Either list, auto, id:x, port:x, or any valid device name/path" + ) + return cmd_parser + + +def argparse_edit(): + cmd_parser = argparse.ArgumentParser(description="edit files on the device") + cmd_parser.add_argument("files", nargs="+", help="list of remote paths") + return cmd_parser + + +def argparse_mount(): + cmd_parser = argparse.ArgumentParser(description="mount local directory on device") + _bool_flag( + cmd_parser, + "unsafe-links", + "l", + False, + "follow symbolic links pointing outside of local directory", + ) + cmd_parser.add_argument("path", nargs=1, help="local path to mount") + return cmd_parser + + +def argparse_repl(): + cmd_parser = argparse.ArgumentParser(description="connect to given device") + cmd_parser.add_argument("--capture", type=str, required=False, help="TODO") + cmd_parser.add_argument("--inject-code", type=str, required=False, help="TODO") + cmd_parser.add_argument("--inject-file", type=str, required=False, help="TODO") + return cmd_parser + + +def argparse_eval(): + cmd_parser = argparse.ArgumentParser(description="evaluate and print the string") + _bool_flag(cmd_parser, "follow", "f", True, "TODO") + cmd_parser.add_argument("expr", nargs=1, help="expression to execute") + return cmd_parser + + +def argparse_exec(): + cmd_parser = argparse.ArgumentParser(description="execute the string") + _bool_flag(cmd_parser, "follow", "f", True, "TODO") + cmd_parser.add_argument("expr", nargs=1, help="expression to execute") + return cmd_parser + + +def argparse_run(): + cmd_parser = argparse.ArgumentParser(description="run the given local script") + _bool_flag(cmd_parser, "follow", "f", False, "TODO") + cmd_parser.add_argument("path", nargs=1, help="expression to execute") + return cmd_parser + + +def argparse_filesystem(): + cmd_parser = argparse.ArgumentParser(description="execute filesystem commands on the device") + _bool_flag(cmd_parser, "recursive", "r", False, "recursive copy (for cp command only)") + _bool_flag( + cmd_parser, + "verbose", + "v", + None, + "enable verbose output (defaults to True for all commands except cat)", + ) + cmd_parser.add_argument( + "command", nargs=1, help="filesystem command (e.g. cat, cp, ls, rm, touch)" + ) + cmd_parser.add_argument("path", nargs="+", help="local and remote paths") + return cmd_parser + + +def argparse_none(description): + return lambda: argparse.ArgumentParser(description=description) + + +# Map of "command" to tuple of (handler_func, argparse_func). _COMMANDS = { "connect": ( - 1, - """\ - connect to given device - device may be: list, auto, id:x, port:x - or any valid device name/path""", do_connect, + argparse_connect, ), "disconnect": ( - 0, - "disconnect current device", do_disconnect, + argparse_none("disconnect current device"), ), "edit": ( - 1, - "edit files on the device", do_edit, + argparse_edit, ), "resume": ( - 0, - "resume a previous mpremote session (will not auto soft-reset)", do_resume, + argparse_none("resume a previous mpremote session (will not auto soft-reset)"), ), "soft-reset": ( - 0, - "perform a soft-reset of the device", do_soft_reset, + argparse_none("perform a soft-reset of the device"), ), "mount": ( - 1, - """\ - mount local directory on device - options: - --unsafe-links, -l - follow symbolic links pointing outside of local directory""", do_mount, + argparse_mount, ), "umount": ( - 0, - "unmount the local directory", do_umount, + argparse_none("unmount the local directory"), ), "repl": ( - 0, - """\ - enter REPL - options: - --capture - --inject-code - --inject-file """, do_repl, + argparse_repl, ), "eval": ( - 1, - "evaluate and print the string", do_eval, + argparse_eval, ), "exec": ( - 1, - "execute the string", do_exec, + argparse_exec, ), "run": ( - 1, - "run the given local script", do_run, + argparse_run, ), "fs": ( - 1, - "execute filesystem commands on the device", do_filesystem, + argparse_filesystem, ), "help": ( - 0, - "print help and exit", do_help, + argparse_none("print help and exit"), ), "version": ( - 0, - "print version and exit", do_version, + argparse_none("print version and exit"), ), } @@ -301,7 +372,6 @@ def do_command_expansion(args): # Extra unknown arguments given. arg = args[last_arg_idx].split("=", 1)[0] usage_error(cmd, exp_args, f"given unexpected argument {arg}") - sys.exit(1) # Insert expansion with optional setting of arguments. if pre: @@ -322,7 +392,7 @@ class State: def ensure_connected(self): if self.pyb is None: - do_connect(self, ["auto"]) + do_connect(self) def ensure_raw_repl(self, soft_reset=None): self.ensure_connected() @@ -341,28 +411,60 @@ def main(): config = load_user_config() prepare_command_expansions(config) - args = sys.argv[1:] + remaining_args = sys.argv[1:] state = State() try: - while args: - do_command_expansion(args) - cmd = args.pop(0) + while remaining_args: + # Skip the terminator. + if remaining_args[0] == "+": + remaining_args.pop(0) + continue + + # Rewrite the front of the list with any matching expansion. + do_command_expansion(remaining_args) + + # The (potentially rewritten) command must now be a base command. + cmd = remaining_args.pop(0) try: - num_args_min, _help, handler = _COMMANDS[cmd] + handler_func, parser_func = _COMMANDS[cmd] except KeyError: raise CommandError(f"'{cmd}' is not a command") - if len(args) < num_args_min: - print(f"{_PROG}: '{cmd}' neads at least {num_args_min} argument(s)") - return 1 + # If this command (or any down the chain) has a terminator, then + # limit the arguments passed for this command. They will be added + # back after processing this command. + try: + terminator = remaining_args.index("+") + command_args = remaining_args[:terminator] + extra_args = remaining_args[terminator:] + except ValueError: + command_args = remaining_args + extra_args = [] - handler(state, args) + # Special case: "fs ls" allowed have no path specified. + if cmd == "fs" and len(command_args) == 1 and command_args[0] == "ls": + command_args.append("") + # Use the command-specific argument parser. + cmd_parser = parser_func() + cmd_parser.prog = cmd + # Catch all for unhandled positional arguments (this is the next command). + cmd_parser.add_argument( + "next_command", nargs=argparse.REMAINDER, help=f"Next {_PROG} command" + ) + args = cmd_parser.parse_args(command_args) - # If no commands were "actions" then implicitly finish with the REPL. + # Execute command. + handler_func(state, args) + + # Get any leftover unprocessed args. + remaining_args = args.next_command + extra_args + + # If no commands were "actions" then implicitly finish with the REPL + # using default args. if state.run_repl_on_completion(): - do_repl(state, args) + do_repl(state, argparse_repl().parse_args([])) return 0 except CommandError as e: diff --git a/tools/mpremote/mpremote/repl.py b/tools/mpremote/mpremote/repl.py index f92d20ae79..7da00c0fde 100644 --- a/tools/mpremote/mpremote/repl.py +++ b/tools/mpremote/mpremote/repl.py @@ -51,22 +51,9 @@ def do_repl(state, args): state.ensure_friendly_repl() state.did_action() - capture_file = None - code_to_inject = None - file_to_inject = None - - while len(args): - if args[0] == "--capture": - args.pop(0) - capture_file = args.pop(0) - elif args[0] == "--inject-code": - args.pop(0) - code_to_inject = bytes(args.pop(0).replace("\\n", "\r\n"), "utf8") - elif args[0] == "--inject-file": - args.pop(0) - file_to_inject = args.pop(0) - else: - break + capture_file = args.capture + code_to_inject = args.inject_code + file_to_inject = args.inject_file print("Connected to MicroPython at %s" % state.pyb.device_name) print("Use Ctrl-] to exit this shell") From 12ca918eb2ac062f6e6df0772e528eef9d050cb7 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 29 Sep 2022 00:45:34 +1000 Subject: [PATCH 0464/1041] tools/mpremote: Add `mpremote mip install` to install packages. This supports the same package sources as the new `mip` tool. - micropython-lib (by name) - http(s) & github packages with json description - directly downloading a .py/.mpy file The version is specified with an optional `@version` on the end of the package name. The target dir, index, and mpy/no-mpy can be set through command line args. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared --- docs/reference/mpremote.rst | 14 +++ docs/reference/packages.rst | 16 +-- tools/mpremote/README.md | 41 ++++--- tools/mpremote/mpremote/main.py | 28 +++++ tools/mpremote/mpremote/mip.py | 191 ++++++++++++++++++++++++++++++++ tools/pyboard.py | 7 ++ 6 files changed, 272 insertions(+), 25 deletions(-) create mode 100644 tools/mpremote/mpremote/mip.py diff --git a/docs/reference/mpremote.rst b/docs/reference/mpremote.rst index e3902f8e5d..bb0686237a 100644 --- a/docs/reference/mpremote.rst +++ b/docs/reference/mpremote.rst @@ -146,6 +146,14 @@ The full list of supported commands are: variable ``$EDITOR``). If the editor exits successfully, the updated file will be copied back to the device. +- install packages from :term:`micropython-lib` (or GitHub) using the ``mip`` tool: + + .. code-block:: bash + + $ mpremote mip install + + See :ref:`packages` for more information. + - mount the local directory on the remote device: .. code-block:: bash @@ -269,3 +277,9 @@ Examples mpremote cp -r dir/ : mpremote cp a.py b.py : + repl + + mpremote mip install aioble + + mpremote mip install github:org/repo@branch + + mpremote mip install --target /flash/third-party functools diff --git a/docs/reference/packages.rst b/docs/reference/packages.rst index 0c049d1fb2..1ddbecb582 100644 --- a/docs/reference/packages.rst +++ b/docs/reference/packages.rst @@ -78,17 +78,17 @@ The :term:`mpremote` tool also includes the same functionality as ``mip`` and can be used from a host PC to install packages to a locally connected device (e.g. via USB or UART):: - $ mpremote install pkgname - $ mpremote install pkgname@x.y - $ mpremote install http://example.com/x/y/foo.py - $ mpremote install github:org/repo - $ mpremote install github:org/repo@branch-or-tag + $ mpremote mip install pkgname + $ mpremote mip install pkgname@x.y + $ mpremote mip install http://example.com/x/y/foo.py + $ mpremote mip install github:org/repo + $ mpremote mip install github:org/repo@branch-or-tag The ``--target=path``, ``--no-mpy``, and ``--index`` arguments can be set:: - $ mpremote install --target=/flash/third-party pkgname - $ mpremote install --no-mpy pkgname - $ mpremote install --index https://host/pi pkgname + $ mpremote mip install --target=/flash/third-party pkgname + $ mpremote mip install --no-mpy pkgname + $ mpremote mip install --index https://host/pi pkgname Installing packages manually ---------------------------- diff --git a/tools/mpremote/README.md b/tools/mpremote/README.md index c294b20811..7f58788fbe 100644 --- a/tools/mpremote/README.md +++ b/tools/mpremote/README.md @@ -11,23 +11,28 @@ This will automatically connect to the device and provide an interactive REPL. The full list of supported commands are: - mpremote connect -- connect to given device - device may be: list, auto, id:x, port:x - or any valid device name/path - mpremote disconnect -- disconnect current device - mpremote mount -- mount local directory on device - mpremote eval -- evaluate and print the string - mpremote exec -- execute the string - mpremote run -- run the given local script - mpremote fs -- execute filesystem commands on the device - command may be: cat, ls, cp, rm, mkdir, rmdir - use ":" as a prefix to specify a file on the device - mpremote repl -- enter REPL - options: - --capture - --inject-code - --inject-file - mpremote help -- print list of commands and exit + mpremote connect -- connect to given device + device may be: list, auto, id:x, port:x + or any valid device name/path + mpremote disconnect -- disconnect current device + mpremote mount -- mount local directory on device + mpremote eval -- evaluate and print the string + mpremote exec -- execute the string + mpremote run -- run the given local script + mpremote fs -- execute filesystem commands on the device + command may be: cat, ls, cp, rm, mkdir, rmdir + use ":" as a prefix to specify a file on the device + mpremote repl -- enter REPL + options: + --capture + --inject-code + --inject-file + mpremote mip install -- Install packages (from micropython-lib or third-party sources) + options: + --target + --index + --no-mpy + mpremote help -- print list of commands and exit Multiple commands can be specified and they will be run sequentially. Connection and disconnection will be done automatically at the start and end of the execution @@ -73,3 +78,5 @@ Examples: mpremote cp :main.py . mpremote cp main.py : mpremote cp -r dir/ : + mpremote mip install aioble + mpremote mip install github:org/repo@branch diff --git a/tools/mpremote/mpremote/main.py b/tools/mpremote/mpremote/main.py index 17d2b33738..4f541685a0 100644 --- a/tools/mpremote/mpremote/main.py +++ b/tools/mpremote/mpremote/main.py @@ -36,6 +36,7 @@ from .commands import ( do_resume, do_soft_reset, ) +from .mip import do_mip from .repl import do_repl _PROG = "mpremote" @@ -162,6 +163,29 @@ def argparse_filesystem(): return cmd_parser +def argparse_mip(): + cmd_parser = argparse.ArgumentParser( + description="install packages from micropython-lib or third-party sources" + ) + _bool_flag(cmd_parser, "mpy", "m", True, "download as compiled .mpy files (default)") + cmd_parser.add_argument( + "--target", type=str, required=False, help="destination direction on the device" + ) + cmd_parser.add_argument( + "--index", + type=str, + required=False, + help="package index to use (defaults to micropython-lib)", + ) + cmd_parser.add_argument("command", nargs=1, help="mip command (e.g. install)") + cmd_parser.add_argument( + "packages", + nargs="+", + help="list package specifications, e.g. name, name@version, github:org/repo, github:org/repo@branch", + ) + return cmd_parser + + def argparse_none(description): return lambda: argparse.ArgumentParser(description=description) @@ -216,6 +240,10 @@ _COMMANDS = { do_filesystem, argparse_filesystem, ), + "mip": ( + do_mip, + argparse_mip, + ), "help": ( do_help, argparse_none("print help and exit"), diff --git a/tools/mpremote/mpremote/mip.py b/tools/mpremote/mpremote/mip.py new file mode 100644 index 0000000000..99ca9ff7e3 --- /dev/null +++ b/tools/mpremote/mpremote/mip.py @@ -0,0 +1,191 @@ +# Micropython package installer +# Ported from micropython-lib/micropython/mip/mip.py. +# MIT license; Copyright (c) 2022 Jim Mussared + +import urllib.error +import urllib.request +import json +import tempfile +import os + +from .commands import CommandError, show_progress_bar + + +_PACKAGE_INDEX = "https://micropython.org/pi/v2" +_CHUNK_SIZE = 128 + + +# This implements os.makedirs(os.dirname(path)) +def _ensure_path_exists(pyb, path): + import os + + split = path.split("/") + + # Handle paths starting with "/". + if not split[0]: + split.pop(0) + split[0] = "/" + split[0] + + prefix = "" + for i in range(len(split) - 1): + prefix += split[i] + if not pyb.fs_exists(prefix): + pyb.fs_mkdir(prefix) + prefix += "/" + + +# Copy from src (stream) to dest (function-taking-bytes) +def _chunk(src, dest, length=None, op="downloading"): + buf = memoryview(bytearray(_CHUNK_SIZE)) + total = 0 + if length: + show_progress_bar(0, length, op) + while True: + n = src.readinto(buf) + if n == 0: + break + dest(buf if n == _CHUNK_SIZE else buf[:n]) + total += n + if length: + show_progress_bar(total, length, op) + + +def _rewrite_url(url, branch=None): + if not branch: + branch = "HEAD" + if url.startswith("github:"): + url = url[7:].split("/") + url = ( + "https://raw.githubusercontent.com/" + + url[0] + + "/" + + url[1] + + "/" + + branch + + "/" + + "/".join(url[2:]) + ) + return url + + +def _download_file(pyb, url, dest): + try: + with urllib.request.urlopen(url) as src: + fd, path = tempfile.mkstemp() + try: + print("Installing:", dest) + with os.fdopen(fd, "wb") as f: + _chunk(src, f.write, src.length) + _ensure_path_exists(pyb, dest) + pyb.fs_put(path, dest, progress_callback=show_progress_bar) + finally: + os.unlink(path) + except urllib.error.HTTPError as e: + if e.status == 404: + raise CommandError(f"File not found: {url}") + else: + raise CommandError(f"Error {e.status} requesting {url}") + except urllib.error.URLError as e: + raise CommandError(f"{e.reason} requesting {url}") + + +def _install_json(pyb, package_json_url, index, target, version, mpy): + try: + with urllib.request.urlopen(_rewrite_url(package_json_url, version)) as response: + package_json = json.load(response) + except urllib.error.HTTPError as e: + if e.status == 404: + raise CommandError(f"Package not found: {package_json_url}") + else: + raise CommandError(f"Error {e.status} requesting {package_json_url}") + except urllib.error.URLError as e: + raise CommandError(f"{e.reason} requesting {package_json_url}") + for target_path, short_hash in package_json.get("hashes", ()): + fs_target_path = target + "/" + target_path + file_url = f"{index}/file/{short_hash[:2]}/{short_hash}" + _download_file(pyb, file_url, fs_target_path) + for target_path, url in package_json.get("urls", ()): + fs_target_path = target + "/" + target_path + _download_file(pyb, _rewrite_url(url, version), fs_target_path) + for dep, dep_version in package_json.get("deps", ()): + _install_package(pyb, dep, index, target, dep_version, mpy) + + +def _install_package(pyb, package, index, target, version, mpy): + if ( + package.startswith("http://") + or package.startswith("https://") + or package.startswith("github:") + ): + if package.endswith(".py") or package.endswith(".mpy"): + print(f"Downloading {package} to {target}") + _download_file( + pyb, _rewrite_url(package, version), target + "/" + package.rsplit("/")[-1] + ) + return + else: + if not package.endswith(".json"): + if not package.endswith("/"): + package += "/" + package += "package.json" + print(f"Installing {package} to {target}") + else: + if not version: + version = "latest" + print(f"Installing {package} ({version}) from {index} to {target}") + + mpy_version = "py" + if mpy: + pyb.exec("import sys") + mpy_version = ( + int(pyb.eval("getattr(sys.implementation, '_mpy', 0) & 0xFF").decode()) or "py" + ) + + package = f"{index}/package/{mpy_version}/{package}/{version}.json" + + _install_json(pyb, package, index, target, version, mpy) + + +def do_mip(state, args): + state.did_action() + + if args.command[0] == "install": + state.ensure_raw_repl() + + for package in args.packages: + version = None + if "@" in package: + package, version = package.split("@") + + print("Install", package) + + if args.index is None: + args.index = _PACKAGE_INDEX + + if args.target is None: + state.pyb.exec("import sys") + lib_paths = ( + state.pyb.eval("'\\n'.join(p for p in sys.path if p.endswith('/lib'))") + .decode() + .split("\n") + ) + if lib_paths and lib_paths[0]: + args.target = lib_paths[0] + else: + raise CommandError( + "Unable to find lib dir in sys.path, use --target to override" + ) + + if args.mpy is None: + args.mpy = True + + try: + _install_package( + state.pyb, package, args.index.rstrip("/"), args.target, version, args.mpy + ) + except CommandError: + print("Package may be partially installed") + raise + print("Done") + else: + raise CommandError(f"mip: '{args.command[0]}' is not a command") diff --git a/tools/pyboard.py b/tools/pyboard.py index 60cc06508e..043f4f06fb 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -476,6 +476,13 @@ class Pyboard: t = str(self.eval("pyb.RTC().datetime()"), encoding="utf8")[1:-1].split(", ") return int(t[4]) * 3600 + int(t[5]) * 60 + int(t[6]) + def fs_exists(self, src): + try: + self.exec_("import uos\nuos.stat(%s)" % (("'%s'" % src) if src else "")) + return True + except PyboardError: + return False + def fs_ls(self, src): cmd = ( "import uos\nfor f in uos.ilistdir(%s):\n" From 7705b9b9d50b3665de135f314fd1f8cb5d0641f0 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 30 Sep 2022 23:43:23 +1000 Subject: [PATCH 0465/1041] tools/pyboard.py: Handle unsupported fs command. Signed-off-by: Jim Mussared --- tools/pyboard.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tools/pyboard.py b/tools/pyboard.py index 043f4f06fb..55c00fbca1 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -621,23 +621,28 @@ def filesystem_command(pyb, args, progress_callback=None, verbose=False): dest2 = fname_cp_dest(src2, fname_remote(dest)) op(src2, dest2, progress_callback=progress_callback) else: - op = { + ops = { "cat": pyb.fs_cat, "ls": pyb.fs_ls, "mkdir": pyb.fs_mkdir, "rm": pyb.fs_rm, "rmdir": pyb.fs_rmdir, "touch": pyb.fs_touch, - }[cmd] + } + if cmd not in ops: + raise PyboardError("'{}' is not a filesystem command".format(cmd)) if cmd == "ls" and not args: args = [""] for src in args: src = fname_remote(src) if verbose: print("%s :%s" % (cmd, src)) - op(src) + ops[cmd](src) except PyboardError as er: - print(str(er.args[2], "ascii")) + if len(er.args) > 1: + print(str(er.args[2], "ascii")) + else: + print(er) pyb.exit_raw_repl() pyb.close() sys.exit(1) From 0ee877a20732039e603b41c63a221bfc2c8fbde9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 4 Oct 2022 11:47:06 +1100 Subject: [PATCH 0466/1041] esp32/machine_i2s: Add I2S finaliser which calls deinit(). So that the FreeRTOS resources can be freed, eg on soft reset. Fixes issue #9366. Signed-off-by: Damien George --- ports/esp32/machine_i2s.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ports/esp32/machine_i2s.c b/ports/esp32/machine_i2s.c index eecf715498..ce1cb59849 100644 --- a/ports/esp32/machine_i2s.c +++ b/ports/esp32/machine_i2s.c @@ -533,7 +533,8 @@ STATIC mp_obj_t machine_i2s_make_new(const mp_obj_type_t *type, size_t n_pos_arg machine_i2s_obj_t *self; if (MP_STATE_PORT(machine_i2s_obj)[port] == NULL) { - self = mp_obj_malloc(machine_i2s_obj_t, &machine_i2s_type); + self = m_new_obj_with_finaliser(machine_i2s_obj_t); + self->base.type = &machine_i2s_type; MP_STATE_PORT(machine_i2s_obj)[port] = self; self->port = port; } else { @@ -688,6 +689,7 @@ STATIC const mp_rom_map_elem_t machine_i2s_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_i2s_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_i2s_irq_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_i2s_deinit_obj) }, // Static method { MP_ROM_QSTR(MP_QSTR_shift), MP_ROM_PTR(&machine_i2s_shift_obj) }, From bdac8272d8b1a726012bec897dc51dacbe70b295 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 29 Aug 2022 16:50:49 +1000 Subject: [PATCH 0467/1041] tools: Add note about uncrustify versions. Uncrustify versions are not mutually compatible: 1. Version 0.73 or newer produce slightly different formatting. It may be possible to tweak these by adding more config items, but this will cause older versions to error out with 'Unknown option'. 2. Version 0.75 prints a range of deprecation warnings due to config file changes, and returns a non-zero exit code. These are actually fixable as most are the default value, and pp_indent has changed from 'true' to '1' which is backwards compatible. However issue 1 remains, so probably better to have it fail explicitly. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton --- CODECONVENTIONS.md | 4 ++++ tools/uncrustify.cfg | 3 +++ 2 files changed, 7 insertions(+) diff --git a/CODECONVENTIONS.md b/CODECONVENTIONS.md index 78fb912a6a..bceab74618 100644 --- a/CODECONVENTIONS.md +++ b/CODECONVENTIONS.md @@ -65,6 +65,10 @@ changes to the correct style. Without arguments this tool will reformat all source code (and may take some time to run). Otherwise pass as arguments to the tool the files that changed and it will only reformat those. +**Important**: Use only [uncrustify](https://github.com/uncrustify/uncrustify) +v0.71 or v0.72 for MicroPython. Different uncrustify versions produce slightly +different formatting, and the configuration file formats are often incompatible. + Python code conventions ======================= diff --git a/tools/uncrustify.cfg b/tools/uncrustify.cfg index 221fb458e9..28eb49faf7 100644 --- a/tools/uncrustify.cfg +++ b/tools/uncrustify.cfg @@ -1,5 +1,8 @@ # Uncrustify-0.71.0_f +# IMPORTANT: Output is different if using Uncrustify 0.73 or newer, and config file format has changed in newer versions. +# Use version 0.71 or 0.72 to get matching code formatting. + # # General options # From 0e35c4de9b9d55f9288eeb908efd2f7f577dc13b Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 29 Aug 2022 17:30:14 +1000 Subject: [PATCH 0468/1041] tools: Add pre-commit support. Tweak the existing codeformat.py and verifygitlog.py to allow them to be easily called by pre-commit. (This turned out to be easier than using any existing pre-commit hooks, without making subtle changes in the formatting.) This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton --- .pre-commit-config.yaml | 13 ++++++ CODECONVENTIONS.md | 32 ++++++++++++++ tools/codeformat.py | 15 +++++++ tools/verifygitlog.py | 97 ++++++++++++++++++++++++++--------------- 4 files changed, 122 insertions(+), 35 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000..12f3d79c93 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,13 @@ +repos: + - repo: local + hooks: + - id: codeformat + name: MicroPython codeformat.py for changed files + entry: tools/codeformat.py -v -f + language: python + - id: verifygitlog + name: MicroPython git commit message format checker + entry: tools/verifygitlog.py --check-file --ignore-rebase + language: python + verbose: true + stages: [commit-msg] diff --git a/CODECONVENTIONS.md b/CODECONVENTIONS.md index bceab74618..2daea8431f 100644 --- a/CODECONVENTIONS.md +++ b/CODECONVENTIONS.md @@ -69,6 +69,38 @@ the tool the files that changed and it will only reformat those. v0.71 or v0.72 for MicroPython. Different uncrustify versions produce slightly different formatting, and the configuration file formats are often incompatible. +Automatic Pre-Commit Hooks +========================== + +To have code formatting and commit message conventions automatically checked +using [pre-commit](https://pre-commit.com/), run the following commands in your +local MicroPython directory: + +``` +$ pip install pre-commit + +$ pre-commit install + +$ pre-commit install --hook-type commit-msg +``` + +pre-commit will now automatically run during `git commit` for both code and +commit message formatting. + +The same formatting checks will be run by CI for any Pull Request submitted to +MicroPython. Pre-commit allows you to see any failure more quickly, and in many +cases will automatically correct it in your local working copy. + +Tips: + +* To skip pre-commit checks on a single commit, use `git commit -n` (for + `--no-verify`). +* To ignore the pre-commit message format check temporarily, start the commit + message subject line with "WIP" (for "Work In Progress"). + +(It is also possible to install pre-commit using Brew or other sources, see +[the docs](https://pre-commit.com/index.html#install) for details.) + Python code conventions ======================= diff --git a/tools/codeformat.py b/tools/codeformat.py index 1c865663a4..13a699065e 100755 --- a/tools/codeformat.py +++ b/tools/codeformat.py @@ -151,6 +151,11 @@ def main(): cmd_parser.add_argument("-c", action="store_true", help="Format C code only") cmd_parser.add_argument("-p", action="store_true", help="Format Python code only") cmd_parser.add_argument("-v", action="store_true", help="Enable verbose output") + cmd_parser.add_argument( + "-f", + action="store_true", + help="Filter files provided on the command line against the default list of files to check.", + ) cmd_parser.add_argument("files", nargs="*", help="Run on specific globs") args = cmd_parser.parse_args() @@ -162,6 +167,16 @@ def main(): files = [] if args.files: files = list_files(args.files) + if args.f: + # Filter against the default list of files. This is a little fiddly + # because we need to apply both the inclusion globs given in PATHS + # as well as the EXCLUSIONS, and use absolute paths + files = set(os.path.abspath(f) for f in files) + all_files = set(list_files(PATHS, EXCLUSIONS, TOP)) + if args.v: # In verbose mode, log any files we're skipping + for f in files - all_files: + print("Not checking: {}".format(f)) + files = list(files & all_files) else: files = list_files(PATHS, EXCLUSIONS, TOP) diff --git a/tools/verifygitlog.py b/tools/verifygitlog.py index ce36791256..f9d98106d6 100755 --- a/tools/verifygitlog.py +++ b/tools/verifygitlog.py @@ -7,6 +7,8 @@ import sys verbosity = 0 # Show what's going on, 0 1 or 2. suggestions = 1 # Set to 0 to not include lengthy suggestions in error messages. +ignore_prefixes = [] + def verbose(*args): if verbosity: @@ -18,6 +20,22 @@ def very_verbose(*args): print(*args) +class ErrorCollection: + # Track errors and warnings as the program runs + def __init__(self): + self.has_errors = False + self.has_warnings = False + self.prefix = "" + + def error(self, text): + print("error: {}{}".format(self.prefix, text)) + self.has_errors = True + + def warning(self, text): + print("warning: {}{}".format(self.prefix, text)) + self.has_warnings = True + + def git_log(pretty_format, *args): # Delete pretty argument from user args so it doesn't interfere with what we do. args = ["git", "log"] + [arg for arg in args if "--pretty" not in args] @@ -28,83 +46,88 @@ def git_log(pretty_format, *args): yield line.decode().rstrip("\r\n") -def verify(sha): +def verify(sha, err): verbose("verify", sha) - errors = [] - warnings = [] - - def error_text(err): - return "commit " + sha + ": " + err - - def error(err): - errors.append(error_text(err)) - - def warning(err): - warnings.append(error_text(err)) + err.prefix = "commit " + sha + ": " # Author and committer email. for line in git_log("%ae%n%ce", sha, "-n1"): very_verbose("email", line) if "noreply" in line: - error("Unwanted email address: " + line) + err.error("Unwanted email address: " + line) # Message body. raw_body = list(git_log("%B", sha, "-n1")) + verify_message_body(raw_body, err) + + +def verify_message_body(raw_body, err): if not raw_body: - error("Message is empty") - return errors, warnings + err.error("Message is empty") + return # Subject line. subject_line = raw_body[0] + for prefix in ignore_prefixes: + if subject_line.startswith(prefix): + verbose("Skipping ignored commit message") + return very_verbose("subject_line", subject_line) subject_line_format = r"^[^!]+: [A-Z]+.+ .+\.$" if not re.match(subject_line_format, subject_line): - error("Subject line should match " + repr(subject_line_format) + ": " + subject_line) + err.error("Subject line should match " + repr(subject_line_format) + ": " + subject_line) if len(subject_line) >= 73: - error("Subject line should be 72 or less characters: " + subject_line) + err.error("Subject line should be 72 or less characters: " + subject_line) # Second one divides subject and body. if len(raw_body) > 1 and raw_body[1]: - error("Second message line should be empty: " + raw_body[1]) + err.error("Second message line should be empty: " + raw_body[1]) # Message body lines. for line in raw_body[2:]: # Long lines with URLs are exempt from the line length rule. if len(line) >= 76 and "://" not in line: - error("Message lines should be 75 or less characters: " + line) + err.error("Message lines should be 75 or less characters: " + line) if not raw_body[-1].startswith("Signed-off-by: ") or "@" not in raw_body[-1]: - warning("Message should be signed-off") - - return errors, warnings + err.warning("Message should be signed-off") def run(args): verbose("run", *args) - has_errors = False - has_warnings = False - for sha in git_log("%h", *args): - errors, warnings = verify(sha) - has_errors |= any(errors) - has_warnings |= any(warnings) - for err in errors: - print("error:", err) - for err in warnings: - print("warning:", err) - if has_errors or has_warnings: + + err = ErrorCollection() + + if "--check-file" in args: + filename = args[-1] + verbose("checking commit message from", filename) + with open(args[-1]) as f: + lines = [line.rstrip("\r\n") for line in f] + verify_message_body(lines, err) + else: # Normal operation, pass arguments to git log + for sha in git_log("%h", *args): + verify(sha, err) + + if err.has_errors or err.has_warnings: if suggestions: print("See https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md") else: print("ok") - if has_errors: + if err.has_errors: sys.exit(1) def show_help(): - print("usage: verifygitlog.py [-v -n -h] ...") + print("usage: verifygitlog.py [-v -n -h --check-file] ...") print("-v : increase verbosity, can be speficied multiple times") print("-n : do not print multi-line suggestions") print("-h : print this help message and exit") + print( + "--check-file : Pass a single argument which is a file containing a candidate commit message" + ) + print( + "--ignore-rebase : Skip checking commits with git rebase autosquash prefixes or WIP as a prefix" + ) print("... : arguments passed to git log to retrieve commits to verify") print(" see https://www.git-scm.com/docs/git-log") print(" passing no arguments at all will verify all commits") @@ -117,6 +140,10 @@ if __name__ == "__main__": args = sys.argv[1:] verbosity = args.count("-v") suggestions = args.count("-n") == 0 + if "--ignore-rebase" in args: + args.remove("--ignore-rebase") + ignore_prefixes = ["squash!", "fixup!", "amend!", "WIP"] + if "-h" in args: show_help() else: From 95c614e2b60b5c1c83c85aefe88a2aadbf43b9ed Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 4 Oct 2022 17:43:04 +1100 Subject: [PATCH 0469/1041] esp32/machine_hw_spi: Use auto DMA channel on S2, S3, C3 chips. Auto DMA channel is supported in IDF v4.4, and is required to be used on S3 chips, so use this simpler configuration option where possible. Fixes issue #8634. Signed-off-by: Damien George --- ports/esp32/machine_hw_spi.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/ports/esp32/machine_hw_spi.c b/ports/esp32/machine_hw_spi.c index 05b1c871cb..647874e17f 100644 --- a/ports/esp32/machine_hw_spi.c +++ b/ports/esp32/machine_hw_spi.c @@ -267,21 +267,15 @@ STATIC void machine_hw_spi_init_internal( // Select DMA channel based on the hardware SPI host int dma_chan = 0; + #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 + dma_chan = SPI_DMA_CH_AUTO; + #else if (self->host == HSPI_HOST) { - #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 - dma_chan = 3; - #else dma_chan = 1; - #endif - #ifdef FSPI_HOST - } else if (self->host == FSPI_HOST) { - dma_chan = 1; - #endif - #ifdef VSPI_HOST - } else if (self->host == VSPI_HOST) { + } else { dma_chan = 2; - #endif } + #endif ret = spi_bus_initialize(self->host, &buscfg, dma_chan); switch (ret) { From f13134e40308c24bcb2c09084f17fc9d54efe5db Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 5 Oct 2022 22:30:29 +1100 Subject: [PATCH 0470/1041] tools/mpremote: Fix argument handling for follow and add help strings. Fixes in this commit are: - Make --follow the default for "run" (accidentally changed in 68d094358). - Add help strings for "repl": --capture --inject-file --inject-code - Update help strings for "run". - Fix encoding for --inject-code (accidentally broken in 68d094358). - Remove ability to --no-follow for "eval". It was there previously because it shared the same code path with "exec" and "run", but makes no sense for "eval", so might as well remove. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared --- tools/mpremote/mpremote/commands.py | 2 +- tools/mpremote/mpremote/main.py | 29 ++++++++++++++++++++++------- tools/mpremote/mpremote/repl.py | 1 + 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/tools/mpremote/mpremote/commands.py b/tools/mpremote/mpremote/commands.py index bf56df6999..558cd82f10 100644 --- a/tools/mpremote/mpremote/commands.py +++ b/tools/mpremote/mpremote/commands.py @@ -204,7 +204,7 @@ def do_exec(state, args): def do_eval(state, args): buf = "print(" + args.expr[0] + ")" - _do_execbuffer(state, buf, args.follow) + _do_execbuffer(state, buf, True) def do_run(state, args): diff --git a/tools/mpremote/mpremote/main.py b/tools/mpremote/mpremote/main.py index 4f541685a0..988ffe8f60 100644 --- a/tools/mpremote/mpremote/main.py +++ b/tools/mpremote/mpremote/main.py @@ -119,30 +119,45 @@ def argparse_mount(): def argparse_repl(): cmd_parser = argparse.ArgumentParser(description="connect to given device") - cmd_parser.add_argument("--capture", type=str, required=False, help="TODO") - cmd_parser.add_argument("--inject-code", type=str, required=False, help="TODO") - cmd_parser.add_argument("--inject-file", type=str, required=False, help="TODO") + cmd_parser.add_argument( + "--capture", + type=str, + required=False, + help="saves a copy of the REPL session to the specified path", + ) + cmd_parser.add_argument( + "--inject-code", type=str, required=False, help="code to be run when Ctrl-J is pressed" + ) + cmd_parser.add_argument( + "--inject-file", + type=str, + required=False, + help="path to file to be run when Ctrl-K is pressed", + ) return cmd_parser def argparse_eval(): cmd_parser = argparse.ArgumentParser(description="evaluate and print the string") - _bool_flag(cmd_parser, "follow", "f", True, "TODO") cmd_parser.add_argument("expr", nargs=1, help="expression to execute") return cmd_parser def argparse_exec(): cmd_parser = argparse.ArgumentParser(description="execute the string") - _bool_flag(cmd_parser, "follow", "f", True, "TODO") + _bool_flag( + cmd_parser, "follow", "f", True, "follow output until the expression completes (default)" + ) cmd_parser.add_argument("expr", nargs=1, help="expression to execute") return cmd_parser def argparse_run(): cmd_parser = argparse.ArgumentParser(description="run the given local script") - _bool_flag(cmd_parser, "follow", "f", False, "TODO") - cmd_parser.add_argument("path", nargs=1, help="expression to execute") + _bool_flag( + cmd_parser, "follow", "f", True, "follow output until the script completes (default)" + ) + cmd_parser.add_argument("path", nargs=1, help="path to script to execute") return cmd_parser diff --git a/tools/mpremote/mpremote/repl.py b/tools/mpremote/mpremote/repl.py index 7da00c0fde..3d6ca1881b 100644 --- a/tools/mpremote/mpremote/repl.py +++ b/tools/mpremote/mpremote/repl.py @@ -61,6 +61,7 @@ def do_repl(state, args): print('Capturing session to file "%s"' % capture_file) capture_file = open(capture_file, "wb") if code_to_inject is not None: + code_to_inject = bytes(code_to_inject.replace("\\n", "\r\n"), "utf8") print("Use Ctrl-J to inject", code_to_inject) if file_to_inject is not None: print('Use Ctrl-K to inject file "%s"' % file_to_inject) From 46d02c2469ec7947fe3aae2d68e07236baf5c72e Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 6 Oct 2022 01:02:39 +1100 Subject: [PATCH 0471/1041] tools/mpremote: Bump version to 0.4.0. Signed-off-by: Damien George --- tools/mpremote/mpremote/__init__.py | 2 +- tools/mpremote/setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/mpremote/mpremote/__init__.py b/tools/mpremote/mpremote/__init__.py index 493f7415d7..6a9beea82f 100644 --- a/tools/mpremote/mpremote/__init__.py +++ b/tools/mpremote/mpremote/__init__.py @@ -1 +1 @@ -__version__ = "0.3.0" +__version__ = "0.4.0" diff --git a/tools/mpremote/setup.cfg b/tools/mpremote/setup.cfg index 16880d77f8..7fae3cbcb3 100644 --- a/tools/mpremote/setup.cfg +++ b/tools/mpremote/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = mpremote -version = 0.3.0 +version = 0.4.0 author = Damien George author_email = damien@micropython.org description = Tool for interacting remotely with MicroPython From 85afed569d3d435b2611856356ff9c78d244f25c Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 27 May 2022 15:43:48 +0200 Subject: [PATCH 0472/1041] samd: Remove the existing provisional support for REPL on UART. It was only partially working and will be rpelaced later by a full machine.UART class implementation. --- .../mpconfigboard.h | 16 ----- .../boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.c | 1 + .../mpconfigboard.h | 15 ---- .../ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.c | 1 + .../ADAFRUIT_TRINKET_M0/mpconfigboard.h | 15 ---- ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.c | 1 + ports/samd/boards/MINISAM_M4/mpconfigboard.h | 15 ---- ports/samd/boards/MINISAM_M4/pins.c | 1 + .../SAMD21_XPLAINED_PRO/mpconfigboard.h | 16 ----- ports/samd/boards/SAMD21_XPLAINED_PRO/pins.c | 1 + .../boards/SEEED_WIO_TERMINAL/mpconfigboard.h | 15 ---- ports/samd/boards/SEEED_WIO_TERMINAL/pins.c | 1 + ports/samd/boards/SEEED_XIAO/mpconfigboard.h | 15 ---- ports/samd/boards/SEEED_XIAO/pins.c | 1 + ports/samd/modmachine.c | 5 -- ports/samd/modmachine.h | 3 - ports/samd/mphalport.c | 8 --- ports/samd/samd_soc.c | 70 ------------------- 18 files changed, 7 insertions(+), 193 deletions(-) diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h index 6d3b7987e3..bdb22d2e0a 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h @@ -9,20 +9,4 @@ #define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF) #define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; -// ASF4 MCU package specific Pin definitions -#include "samd21g18a.h" - -// Please consult the SAM_D21 Datasheet, I/O Multiplexing and Considerations. -// On this board (see https://learn.adafruit.com/assets/40553) TX is D1 (PA10) and RX is D0 (PA11) -// USART pin assignments: Tx=PA10=SERCOM0/PAD[2], Rx=PA11==SERCOM0/PAD[3] #define CPU_FREQ (48000000) // For selecting Baud from clock. -#define MP_PIN_GRP 0 // A=0, B=1 -#define MP_TX_PIN 10 // 'n' -#define MP_RX_PIN 11 -#define MP_PERIPHERAL_MUX 5 // 'n'th group of 2 pins -#define USARTx SERCOM0 // SERCOM0: tx/rx -#define MP_PORT_FUNC 0x22 // Sets PMUXE & PMUXO to the Alternative Function.(A-H=0-7) -#define MP_RXPO_PAD 3 // RXPO- Receive Data Pinout -#define MP_TXPO_PAD 1 // TXPO- Transmit Data Pinout -#define MP_SERCOMx SERCOM0_ // APBCMASK -#define MP_SERCOM_GCLK_ID_x_CORE GCLK_CLKCTRL_ID_SERCOM0_CORE // Generic Clock Control diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.c b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.c index e0dd752ec9..fbb5032a40 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.c +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.c @@ -27,6 +27,7 @@ */ #include "modmachine.h" +#include "sam.h" #include "pins.h" // Ensure Declaration in 'pins.h' reflects # of Pins defined here. diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h index c1c4fd8cad..80baf39e5d 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h @@ -14,19 +14,4 @@ #define MICROPY_HW_FLASH_STORAGE_BYTES (0x1FFFF) #define VFS_BLOCK_SIZE_BYTES (1536) // -// ASF4 MCU package specific Pin definitions -#include "samd51g19a.h" - -// Please consult the SAM_D51 Datasheet, I/O Multiplexing and Considerations. -// USART pin assignments: Tx=TX_D1=PA17=SERCOM3/PAD[0], Rx=RX_D0=PA16=SERCOM3/PAD[1] #define CPU_FREQ (48000000) // For selecting Baud from clock. -#define MP_PIN_GRP 1 // A-D=0-3 -#define MP_TX_PIN 17 -#define MP_RX_PIN 16 // 'n' -#define MP_PERIPHERAL_MUX 8 // 'n'th group of 2 pins -#define USARTx SERCOM3 // -#define MP_PORT_FUNC 0x33 // Sets PMUXE & PMUXO to the Alternative Function.A-N=0-13 -#define MP_RXPO_PAD 1 // RXPO- Receive Data Pinout -#define MP_TXPO_PAD 0 // TXPO- Tranmit Data Pinout -#define MP_SERCOMx SERCOM3_ // APBCMASK -#define MP_SERCOM_GCLK_ID_x_CORE SERCOM3_GCLK_ID_CORE diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.c b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.c index 82948ccbc4..0342b0d00c 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.c +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.c @@ -27,6 +27,7 @@ */ #include "modmachine.h" +#include "sam.h" #include "pins.h" // Ensure Declaration in 'pins.h' reflects # of Pins defined here. diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h index 128689f4f7..066c7ee142 100644 --- a/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h @@ -9,19 +9,4 @@ #define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF) #define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; -// ASF4 MCU package specific Pin definitions -#include "samd21e18a.h" - -// Please consult the SAM_D21 Datasheet, I/O Multiplexing and Considerations. -// USART pin assignments: Tx=D4=PA06=SERCOM0/PAD[2], Rx=D3=PA07=SERCOM0/PAD[3] #define CPU_FREQ (48000000) // For selecting Baud from clock. -#define MP_PIN_GRP 1 // A=0, B=1 -#define MP_TX_PIN 6 // 'n' -#define MP_RX_PIN 7 -#define MP_PERIPHERAL_MUX 3 // 'n'th group of 2 pins -#define USARTx SERCOM0 // SERCOM0: tx/rx -#define MP_PORT_FUNC 0x33 // Sets PMUXE & PMUXO to the Alternative Function.A-H=0-7 -#define MP_RXPO_PAD 3 // RXPO- Receive Data Pinout -#define MP_TXPO_PAD 2 // TXPO- Tranmit Data Pinout -#define MP_SERCOMx SERCOM0_ // APBCMASK -#define MP_SERCOM_GCLK_ID_x_CORE GCLK_CLKCTRL_ID_SERCOM0_CORE // Generic Clock Control diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.c b/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.c index 9fecddb6cd..676b4794e8 100644 --- a/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.c +++ b/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.c @@ -27,6 +27,7 @@ */ #include "modmachine.h" +#include "sam.h" #include "pins.h" // Ensure Declaration in 'pins.h' reflects # of Pins defined here. diff --git a/ports/samd/boards/MINISAM_M4/mpconfigboard.h b/ports/samd/boards/MINISAM_M4/mpconfigboard.h index a65eb54b49..a8f1f96242 100644 --- a/ports/samd/boards/MINISAM_M4/mpconfigboard.h +++ b/ports/samd/boards/MINISAM_M4/mpconfigboard.h @@ -14,19 +14,4 @@ #define MICROPY_HW_FLASH_STORAGE_BYTES (0x1FFFF) #define VFS_BLOCK_SIZE_BYTES (1536) // -// ASF4 MCU package specific Pin definitions -#include "samd51g19a.h" - -// Please consult the SAM_D51 Datasheet, I/O Multiplexing and Considerations. -// USART pin assignments: Tx=TX_D1=PA17=SERCOM3/PAD[0], Rx=RX_D0=PA16=SERCOM3/PAD[1] #define CPU_FREQ (48000000) // For selecting Baud from clock. -#define MP_PIN_GRP 0 // A-D=0-3 -#define MP_TX_PIN 17 -#define MP_RX_PIN 16 // 'n' -#define MP_PERIPHERAL_MUX 8 // 'n'th group of 2 pins -#define USARTx SERCOM3 // -#define MP_PORT_FUNC 0x33 // Sets PMUXE & PMUXO to the Alternative Function.A-N=0-13 -#define MP_RXPO_PAD 1 // RXPO- Receive Data Pinout -#define MP_TXPO_PAD 0 // TXPO- Tranmit Data Pinout -#define MP_SERCOMx SERCOM3_ // APBCMASK -#define MP_SERCOM_GCLK_ID_x_CORE SERCOM3_GCLK_ID_CORE diff --git a/ports/samd/boards/MINISAM_M4/pins.c b/ports/samd/boards/MINISAM_M4/pins.c index 6cdd840b6b..17ed58d3c4 100644 --- a/ports/samd/boards/MINISAM_M4/pins.c +++ b/ports/samd/boards/MINISAM_M4/pins.c @@ -27,6 +27,7 @@ */ #include "modmachine.h" +#include "sam.h" #include "pins.h" // Ensure Declaration in 'pins.h' reflects # of Pins defined here. diff --git a/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h b/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h index a7dbf76144..860cb6b977 100644 --- a/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h +++ b/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h @@ -9,20 +9,4 @@ #define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF) #define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; -// ASF4 MCU package specific Pin definitions -#include "samd21j18a.h" - -// Please consult the SAM_D21 Datasheet, I/O Multiplexing and Considerations. -// USART pin assignments: (This board has 3 USARTS brought out to the pins. See https://docs.zephyrproject.org/1.14.1/boards/arm/atsamd21_xpro/doc/index.html#serial-port ) -// Tx=PA10=SERCOM0/PAD[2], Rx=PA11=SERCOM0/PAD[3] #define CPU_FREQ (48000000) // For selecting Baud from clock. -#define MP_PIN_GRP 1 // A=0, B=1 -#define MP_TX_PIN 10 // 'n' -#define MP_RX_PIN 11 -#define MP_PERIPHERAL_MUX 5 // 'n'th group of 2 pins -#define USARTx SERCOM0 // SERCOM0: tx/rx -#define MP_PORT_FUNC 0x22 // Sets PMUXE & PMUXO to the Alternative Function.(A-H=0-7) -#define MP_RXPO_PAD 3 // RXPO- Receive Data Pinout -#define MP_TXPO_PAD 2 // TXPO- Tranmit Data Pinout -#define MP_SERCOMx SERCOM0_ // APBCMASK -#define MP_SERCOM_GCLK_ID_x_CORE GCLK_CLKCTRL_ID_SERCOM0_CORE // Generic Clock Control diff --git a/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.c b/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.c index 2a2d50eb48..35718ea7f3 100644 --- a/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.c +++ b/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.c @@ -27,6 +27,7 @@ */ #include "modmachine.h" +#include "sam.h" #include "pins.h" // Ensure Declaration in 'pins.h' reflects # of Pins defined here. diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h b/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h index 290bd802b8..bb0f1c828e 100644 --- a/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h +++ b/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h @@ -14,19 +14,4 @@ #define MICROPY_HW_FLASH_STORAGE_BYTES (0x1FFFF) #define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; -// ASF4 MCU package specific Pin definitions -#include "samd51p19a.h" - -// Please consult the SAM_D51 Datasheet, I/O Multiplexing and Considerations. -// WIO_Terminal USART pin assignments: Tx=BCM14=PB27=SERCOM2/PAD[0], Rx=BCM15=PB26=SERCOM2/PAD[1] #define CPU_FREQ (48000000) // For selecting Baud from clock. -#define MP_PIN_GRP 1 // A-D=0-3 -#define MP_TX_PIN 27 -#define MP_RX_PIN 26 // 'n' -#define MP_PERIPHERAL_MUX 13 // 'n'th group of 2 pins -#define USARTx SERCOM2 // -#define MP_PORT_FUNC 0x22 // Sets PMUXE & PMUXO to the Alternative Function.A-N=0-13 -#define MP_RXPO_PAD 1 // RXPO- Receive Data Pinout -#define MP_TXPO_PAD 0 // TXPO- Tranmit Data Pinout -#define MP_SERCOMx SERCOM2_ // APBCMASK -#define MP_SERCOM_GCLK_ID_x_CORE SERCOM2_GCLK_ID_CORE diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.c b/ports/samd/boards/SEEED_WIO_TERMINAL/pins.c index 9862552fa3..d7833416d3 100644 --- a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.c +++ b/ports/samd/boards/SEEED_WIO_TERMINAL/pins.c @@ -27,6 +27,7 @@ */ #include "modmachine.h" +#include "sam.h" #include "pins.h" // Ensure Declaration in "pins.h" reflects # of Pins defined here. diff --git a/ports/samd/boards/SEEED_XIAO/mpconfigboard.h b/ports/samd/boards/SEEED_XIAO/mpconfigboard.h index 6422d7ea02..a2f2a9fb0b 100644 --- a/ports/samd/boards/SEEED_XIAO/mpconfigboard.h +++ b/ports/samd/boards/SEEED_XIAO/mpconfigboard.h @@ -9,19 +9,4 @@ #define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF) #define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; -// ASF4 MCU package specific Pin definitions -#include "samd21g18a.h" - -// Please consult the SAM_D21 Datasheet, I/O Multiplexing and Considerations. -// XIAO_M0 USART pin assignments: Tx=A6=PB8=SERCOM4/PAD[0], Rx=PB9=A7=SERCOM4/PAD[1] #define CPU_FREQ (48000000) // For selecting Baud from clock. -#define MP_PIN_GRP 1 // A=0, B=1 -#define MP_TX_PIN 8 // 'n' -#define MP_RX_PIN 9 -#define MP_PERIPHERAL_MUX 4 // 'n'th group of 2 pins -#define USARTx SERCOM4 // SERCOM4:XIAO_M0 tx/rx -#define MP_PORT_FUNC 0x33 // Sets PMUXE & PMUXO to the Alternative Function.A-H=0-7 -#define MP_RXPO_PAD 1 // RXPO- Receive Data Pinout -#define MP_TXPO_PAD 0 // TXPO- Tranmit Data Pinout -#define MP_SERCOMx SERCOM4_ // APBCMASK -#define MP_SERCOM_GCLK_ID_x_CORE GCLK_CLKCTRL_ID_SERCOM4_CORE // Generic Clock Control diff --git a/ports/samd/boards/SEEED_XIAO/pins.c b/ports/samd/boards/SEEED_XIAO/pins.c index 6043913d2b..e2f7c264b4 100644 --- a/ports/samd/boards/SEEED_XIAO/pins.c +++ b/ports/samd/boards/SEEED_XIAO/pins.c @@ -27,6 +27,7 @@ */ #include "modmachine.h" +#include "sam.h" #include "pins.h" // Ensure Declaration in 'pins.h' reflects # of Pins defined here. diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index 74e3571759..1b78b687e1 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -45,9 +45,6 @@ #define DBL_TAP_MAGIC_LOADER 0xf01669ef #define DBL_TAP_MAGIC_RESET 0xf02669ef -MP_DEFINE_CONST_FUN_OBJ_0(machine_uart_init_obj, machine_uart_init); -MP_DEFINE_CONST_FUN_OBJ_0(machine_uart_deinit_obj, machine_uart_deinit); - STATIC mp_obj_t machine_reset(void) { *DBL_TAP_ADDR = DBL_TAP_MAGIC_RESET; NVIC_SystemReset(); @@ -119,8 +116,6 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, - { MP_ROM_QSTR(MP_QSTR_uart_init), MP_ROM_PTR(&machine_uart_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_uart_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&machine_led_type) }, }; diff --git a/ports/samd/modmachine.h b/ports/samd/modmachine.h index 61bd2f4d29..f7ad2b5e5c 100644 --- a/ports/samd/modmachine.h +++ b/ports/samd/modmachine.h @@ -31,7 +31,4 @@ extern const mp_obj_type_t machine_pin_type; extern const mp_obj_type_t machine_led_type; -mp_obj_t machine_uart_init(void); -mp_obj_t machine_uart_deinit(void); - #endif // MICROPY_INCLUDED_SAMD_MODMACHINE_H diff --git a/ports/samd/mphalport.c b/ports/samd/mphalport.c index c19d542a85..beade14a6e 100644 --- a/ports/samd/mphalport.c +++ b/ports/samd/mphalport.c @@ -71,9 +71,6 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { int mp_hal_stdin_rx_chr(void) { for (;;) { - if (USARTx->USART.INTFLAG.bit.RXC) { - return USARTx->USART.DATA.bit.DATA; - } if (tud_cdc_connected() && tud_cdc_available()) { uint8_t buf[1]; uint32_t count = tud_cdc_read(buf, sizeof(buf)); @@ -100,9 +97,4 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { i += n2; } } - while (len--) { - while (!(USARTx->USART.INTFLAG.bit.DRE)) { - } - USARTx->USART.DATA.bit.DATA = *str++; - } } diff --git a/ports/samd/samd_soc.c b/ports/samd/samd_soc.c index 7f4df1bb1c..7a96cbb480 100644 --- a/ports/samd/samd_soc.c +++ b/ports/samd/samd_soc.c @@ -35,75 +35,6 @@ #include "samd_soc.h" #include "tusb.h" -// "MP" macros defined in "boards/$(BOARD)/mpconfigboard.h" -mp_obj_t machine_uart_init(void) { - // Firstly, assign alternate function SERCOM PADs to GPIO pins. - PORT->Group[MP_PIN_GRP].PINCFG[MP_TX_PIN].bit.PMUXEN = 1; // Enable - PORT->Group[MP_PIN_GRP].PINCFG[MP_RX_PIN].bit.PMUXEN = 1; // Enable - PORT->Group[MP_PIN_GRP].PMUX[MP_PERIPHERAL_MUX].reg = MP_PORT_FUNC; // Sets PMUXE & PMUXO in 1 hit. - uint32_t rxpo = MP_RXPO_PAD; // 1=Pad1,3=Pad3 Rx data - uint32_t txpo = MP_TXPO_PAD; // 0=pad0,1=Pad2 Tx data - - // Initialise the clocks - #if defined(MCU_SAMD21) - PM->APBCMASK.bit.MP_SERCOMx = 1; // Enable synchronous clock - GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | MP_SERCOM_GCLK_ID_x_CORE; // Select multiplexer generic clock source and enable. - // Wait while it updates synchronously. - while (GCLK->STATUS.bit.SYNCBUSY) { - } - #elif defined(MCU_SAMD51) - GCLK->PCHCTRL[MP_SERCOM_GCLK_ID_x_CORE].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK0; - MCLK->APBBMASK.bit.MP_SERCOMx = 1; - #endif - - // Setup the Peripheral. - // Reset (clear) the peripheral registers. - while (USARTx->USART.SYNCBUSY.bit.SWRST) { - } - USARTx->USART.CTRLA.bit.SWRST = 1; // Reset all Registers, disable peripheral - while (USARTx->USART.SYNCBUSY.bit.SWRST) { - } - - // Set the register bits as needed - // (CMODE (async),CHSIZE (8),FORM (no parity),SBMODE (1 stop) already 0). - USARTx->USART.CTRLA.reg = // USARTx = SERCOMx set in "boards/$(BOARD)/mpconfigboard.h" - SERCOM_USART_CTRLA_DORD // Data order - | SERCOM_USART_CTRLA_RXPO(rxpo) // Set Pad# - | SERCOM_USART_CTRLA_TXPO(txpo) // Set Pad# - | SERCOM_USART_CTRLA_MODE(1) // USART with internal clock - ; - USARTx->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN; // Enable Rx & Tx - while (USARTx->USART.SYNCBUSY.bit.CTRLB) { - } - - // Baud rate is clock dependant. - #if CPU_FREQ == 8000000 - uint32_t baud = 50437; // 115200 baud; 65536*(1 - 16 * 115200/8e6) - #elif CPU_FREQ == 48000000 - uint32_t baud = 63019; // 115200 baud; 65536*(1 - 16 * 115200/48e6) - #elif CPU_FREQ == 120000000 - uint32_t baud = 64529; // 115200 baud; 65536*(1 - 16 * 115200/120e6) - #endif - USARTx->USART.BAUD.bit.BAUD = baud; // Set Baud - USARTx->USART.CTRLA.bit.ENABLE = 1; // Enable the peripheral - // Wait for the Registers to update. - while (USARTx->USART.SYNCBUSY.bit.ENABLE) { - } - - return mp_const_none; -} - -// Disconnect SERCOM from GPIO pins. (Can't SWRST, as that will totally kill USART). -mp_obj_t machine_uart_deinit(void) { - // Reset - printf("Disabling the Alt-Funct, releasing the USART pins for GPIO... \n"); - PORT->Group[MP_PIN_GRP].PINCFG[MP_TX_PIN].bit.PMUXEN = 0; // Disable - PORT->Group[MP_PIN_GRP].PINCFG[MP_RX_PIN].bit.PMUXEN = 0; // Disable - - return mp_const_none; -} - - static void usb_init(void) { // Init USB clock #if defined(MCU_SAMD21) @@ -168,6 +99,5 @@ void samd_init(void) { #endif SysTick_Config(CPU_FREQ / 1000); - machine_uart_init(); usb_init(); } From 0420799a847d4bb74c9a92666e2cd35c23b1c12c Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 27 May 2022 21:19:47 +0200 Subject: [PATCH 0473/1041] samd/boards: Replace pins.c and pins.h by pins.csv. The files pins.c and pins.h are generated during the build process from pins.csv, using a make-pins.py script. --- ports/samd/Makefile | 11 +- .../boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.c | 59 -------- .../ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv | 37 +++++ .../boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.h | 42 ------ .../ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.c | 59 -------- .../ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv | 36 +++++ .../ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.h | 42 ------ ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.c | 44 ------ .../samd/boards/ADAFRUIT_TRINKET_M0/pins.csv | 16 +++ ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.h | 42 ------ ports/samd/boards/MINISAM_M4/pins.c | 52 -------- ports/samd/boards/MINISAM_M4/pins.csv | 27 ++++ ports/samd/boards/MINISAM_M4/pins.h | 42 ------ ports/samd/boards/SAMD21_XPLAINED_PRO/pins.c | 92 ------------- .../samd/boards/SAMD21_XPLAINED_PRO/pins.csv | 63 +++++++++ ports/samd/boards/SAMD21_XPLAINED_PRO/pins.h | 42 ------ ports/samd/boards/SEEED_WIO_TERMINAL/pins.c | 61 --------- ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv | 30 +++++ ports/samd/boards/SEEED_WIO_TERMINAL/pins.h | 42 ------ ports/samd/boards/SEEED_XIAO/pins.c | 53 -------- ports/samd/boards/SEEED_XIAO/pins.csv | 22 +++ ports/samd/boards/SEEED_XIAO/pins.h | 42 ------ ports/samd/boards/make-pins.py | 126 ++++++++++++++++++ 23 files changed, 367 insertions(+), 715 deletions(-) delete mode 100644 ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.c create mode 100644 ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv delete mode 100644 ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.h delete mode 100644 ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.c create mode 100644 ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv delete mode 100644 ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.h delete mode 100644 ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.c create mode 100644 ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.csv delete mode 100644 ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.h delete mode 100644 ports/samd/boards/MINISAM_M4/pins.c create mode 100644 ports/samd/boards/MINISAM_M4/pins.csv delete mode 100644 ports/samd/boards/MINISAM_M4/pins.h delete mode 100644 ports/samd/boards/SAMD21_XPLAINED_PRO/pins.c create mode 100644 ports/samd/boards/SAMD21_XPLAINED_PRO/pins.csv delete mode 100644 ports/samd/boards/SAMD21_XPLAINED_PRO/pins.h delete mode 100644 ports/samd/boards/SEEED_WIO_TERMINAL/pins.c create mode 100644 ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv delete mode 100644 ports/samd/boards/SEEED_WIO_TERMINAL/pins.h delete mode 100644 ports/samd/boards/SEEED_XIAO/pins.c create mode 100644 ports/samd/boards/SEEED_XIAO/pins.csv delete mode 100644 ports/samd/boards/SEEED_XIAO/pins.h create mode 100644 ports/samd/boards/make-pins.py diff --git a/ports/samd/Makefile b/ports/samd/Makefile index aed8637abc..1ef35c1a02 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -56,6 +56,11 @@ LDFLAGS += $(LDFLAGS_MOD) LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) +MAKE_PINS = boards/make-pins.py +BOARD_PINS = $(BOARD_DIR)/pins.csv +GEN_PINS_SRC = $(BUILD)/pins.c +GEN_PINS_HDR = $(BUILD)/pins.h + # Tune for Debugging or Optimization CFLAGS += -g # always include debug info in the ELF ifeq ($(DEBUG),1) @@ -79,7 +84,7 @@ SRC_C = \ help.c \ modutime.c \ modmachine.c \ - $(BOARD_DIR)/pins.c \ + $(BUILD)/pins.c \ machine_pin.c \ machine_led.c \ modsamd.c \ @@ -160,4 +165,8 @@ $(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(BUILD)/firmware.uf2: $(BUILD)/firmware.bin $(Q)$(PYTHON) $(UF2CONV) -b $(TEXT0) -c -o $@ $< +$(GEN_PINS_SRC): $(BOARD_PINS) + $(ECHO) "Create $@" + $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --pins $(GEN_PINS_SRC) --inc $(GEN_PINS_HDR) + include $(TOP)/py/mkrules.mk diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.c b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.c deleted file mode 100644 index fbb5032a40..0000000000 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Peter van der Burg - * - * 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. - * - * Used by machine_pin.c. Holds Board/MCU specific Pin allocations. - */ - -#include "modmachine.h" -#include "sam.h" -#include "pins.h" - -// Ensure Declaration in 'pins.h' reflects # of Pins defined here. -const machine_pin_obj_t machine_pin_obj[] = { - {{&machine_pin_type}, PIN_PA11}, // D0 - {{&machine_pin_type}, PIN_PA10}, // D1 - {{&machine_pin_type}, PIN_PA14}, // D2 - {{&machine_pin_type}, PIN_PA09}, // D3/ - {{&machine_pin_type}, PIN_PA08}, // D4/ - {{&machine_pin_type}, PIN_PA15}, // D5 - {{&machine_pin_type}, PIN_PA20}, // D6 - {{&machine_pin_type}, PIN_PA21}, // D7 - {{&machine_pin_type}, PIN_PA06}, // D8/ - {{&machine_pin_type}, PIN_PA07}, // D9/ - {{&machine_pin_type}, PIN_PA18}, // D10 - {{&machine_pin_type}, PIN_PA16}, // D11 - {{&machine_pin_type}, PIN_PA19}, // D12 - {{&machine_pin_type}, PIN_PA17}, // D13/ - {{&machine_pin_type}, PIN_PA02}, // A0 - {{&machine_pin_type}, PIN_PB08}, // A1 - {{&machine_pin_type}, PIN_PB09}, // A2 - {{&machine_pin_type}, PIN_PA04}, // A3/ - {{&machine_pin_type}, PIN_PA05}, // A4/ - {{&machine_pin_type}, PIN_PB02}, // A5 -}; - -const machine_led_obj_t machine_led_obj[] = { - {{&machine_led_type}, PIN_PA17}, // D13/ user LED -}; diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv new file mode 100644 index 0000000000..84e68157ac --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv @@ -0,0 +1,37 @@ +# Pin rows contain Pin number and pin name. +# Pin rows start with PIN_ +# LED rows start with LED_ +# If the pin name is omitted, the pin number is added as name. +# Rows for empty entries have to start with '-' +# Empty lines and lines starting with # are ignored + +PIN_PA11,D0 +PIN_PA10,D1 +PIN_PA14,D2 +PIN_PA09,D3 +PIN_PA08,D4 +PIN_PA15,D5 +PIN_PA20,D6 +PIN_PA21,D7 +PIN_PA06,D8 +PIN_PA07,D9 +PIN_PA18,D10 +PIN_PA16,D11 +PIN_PA19,D12 +PIN_PA17,D13 +PIN_PA02,A0 +PIN_PB08,A1 +PIN_PB09,A2 +PIN_PA04,A3 +PIN_PA05,A4 +PIN_PB02,A5 +PIN_PB22,TX +PIN_PB23,RX +PIN_PA23,SCL +PIN_PA22,SDA +PIN_PA06,NEOPIXEL +PIN_PA13,FLASH_CS + +LED_PA17,LED +LED_PA27,LED_TX +LED_PB03,LED_RX diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.h b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.h deleted file mode 100644 index 45bee61678..0000000000 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Peter van der Burg - * - * 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. - * - * Used by machine_pin.c & board specific pins.c. Holds Board/MCU specific Pin - * allocations. - */ - -typedef struct _machine_pin_obj_t { - mp_obj_base_t base; - uint32_t id; -} machine_pin_obj_t; - -typedef struct _machine_led_obj_t { - mp_obj_base_t base; - uint32_t id; -} machine_led_obj_t; - -// MUST explicitly hold array # of rows, else machine_pin.c wont compile. -extern const machine_pin_obj_t machine_pin_obj[20]; -extern const machine_led_obj_t machine_led_obj[1]; diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.c b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.c deleted file mode 100644 index 0342b0d00c..0000000000 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Peter van der Burg - * - * 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. - * - * Used by machine_pin.c. Holds Board/MCU specific Pin allocations. - */ - -#include "modmachine.h" -#include "sam.h" -#include "pins.h" - -// Ensure Declaration in 'pins.h' reflects # of Pins defined here. -const machine_pin_obj_t machine_pin_obj[] = { - {{&machine_pin_type}, PIN_PA16}, // RX_D0 - {{&machine_pin_type}, PIN_PA17}, // TX_D1 - {{&machine_pin_type}, PIN_PA07}, // D2 - {{&machine_pin_type}, PIN_PB22}, // D3 - {{&machine_pin_type}, PIN_PA14}, // D4 - {{&machine_pin_type}, PIN_PA15}, // D5 - {{NULL}, -1}, // D6- not terminated on breakout. - {{&machine_pin_type}, PIN_PA18}, // D7 - {{NULL}, -1}, // D8- not terminated on breakout. - {{&machine_pin_type}, PIN_PA19}, // D9 - {{&machine_pin_type}, PIN_PA20}, // D10 - {{&machine_pin_type}, PIN_PA21}, // D11 - {{&machine_pin_type}, PIN_PA23}, // D12 - {{&machine_pin_type}, PIN_PA22}, // D13 - {{&machine_pin_type}, PIN_PA02}, // A0 - {{&machine_pin_type}, PIN_PA05}, // A1 - {{&machine_pin_type}, PIN_PB08}, // A2 - {{&machine_pin_type}, PIN_PB09}, // A3 - {{&machine_pin_type}, PIN_PA04}, // A4 - {{&machine_pin_type}, PIN_PA06}, // A5 -}; - -const machine_led_obj_t machine_led_obj[] = { - {{&machine_led_type}, PIN_PA22}, // D13 -}; diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv new file mode 100644 index 0000000000..90e38761a1 --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv @@ -0,0 +1,36 @@ +# Pin rows contain Pin number and pin name. +# Pin rows start with PIN_ +# LED rows start with LED_ +# If the pin name is omitted, the pin number is added as name. +# Rows for empty entries have to start with '-' +# Empty lines and lines starting with # are ignored + +PIN_PA16,D0 +PIN_PA17,D1 +PIN_PA07,D2 +PIN_PB22,D3 +PIN_PA14,D4 +PIN_PA15,D5 +- +PIN_PA18,D7 +- +PIN_PA19,D9 +PIN_PA20,D10 +PIN_PA21,D11 +PIN_PA23,D12 +PIN_PA22,D13 +PIN_PA02,A0 +PIN_PA05,A1 +PIN_PB08,A2 +PIN_PB09,A3 +PIN_PA04,A4 +PIN_PA06,A5 +PIN_PA12,SDA +PIN_PA13,SCL +PIN_PA00,MO +PIN_PB23,MI +PIN_PA01,SCK +PIN_PB02,DOTSTAR_CLK +PIN_PB03,DOTSTAR_DATA + +LED_PA22,LED diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.h b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.h deleted file mode 100644 index 45bee61678..0000000000 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Peter van der Burg - * - * 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. - * - * Used by machine_pin.c & board specific pins.c. Holds Board/MCU specific Pin - * allocations. - */ - -typedef struct _machine_pin_obj_t { - mp_obj_base_t base; - uint32_t id; -} machine_pin_obj_t; - -typedef struct _machine_led_obj_t { - mp_obj_base_t base; - uint32_t id; -} machine_led_obj_t; - -// MUST explicitly hold array # of rows, else machine_pin.c wont compile. -extern const machine_pin_obj_t machine_pin_obj[20]; -extern const machine_led_obj_t machine_led_obj[1]; diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.c b/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.c deleted file mode 100644 index 676b4794e8..0000000000 --- a/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Peter van der Burg - * - * 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. - * - * Used by machine_pin.c. Holds Board/MCU specific Pin allocations. - */ - -#include "modmachine.h" -#include "sam.h" -#include "pins.h" - -// Ensure Declaration in 'pins.h' reflects # of Pins defined here. -const machine_pin_obj_t machine_pin_obj[] = { - {{&machine_pin_type}, PIN_PA08}, // D0 - {{&machine_pin_type}, PIN_PA02}, // D1 - {{&machine_pin_type}, PIN_PA09}, // D2 - {{&machine_pin_type}, PIN_PA07}, // D3/ RxD - {{&machine_pin_type}, PIN_PA06}, // D4/ TxD -}; - -const machine_led_obj_t machine_led_obj[] = { - {{&machine_led_type}, PIN_PA10}, // user LED -}; diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.csv b/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.csv new file mode 100644 index 0000000000..797b3f70bb --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.csv @@ -0,0 +1,16 @@ +# Pin rows contain Pin number and pin name. +# Pin rows start with PIN_ +# LED rows start with LED_ +# If the pin name is omitted, the pin number is added as name. +# Rows for empty entries have to start with '-' +# Empty lines and lines starting with # are ignored + +PIN_PA08,D0 +PIN_PA02,D1 +PIN_PA09,D2 +PIN_PA07,D3 +PIN_PA06,D4 +PIN_PA00,DOTSTAR_DATA +PIN_PA01,DOTSTAR_CLK + +LED_PA10,LED diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.h b/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.h deleted file mode 100644 index 843d69addc..0000000000 --- a/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Peter van der Burg - * - * 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. - * - * Used by machine_pin.c & board specific pins.c. Holds Board/MCU specific Pin - * allocations. - */ - -typedef struct _machine_pin_obj_t { - mp_obj_base_t base; - uint32_t id; -} machine_pin_obj_t; - -typedef struct _machine_led_obj_t { - mp_obj_base_t base; - uint32_t id; -} machine_led_obj_t; - -// MUST explicitly hold array # of rows, else machine_pin.c wont compile. -extern const machine_pin_obj_t machine_pin_obj[5]; -extern const machine_led_obj_t machine_led_obj[1]; diff --git a/ports/samd/boards/MINISAM_M4/pins.c b/ports/samd/boards/MINISAM_M4/pins.c deleted file mode 100644 index 17ed58d3c4..0000000000 --- a/ports/samd/boards/MINISAM_M4/pins.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Peter van der Burg - * - * 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. - * - * Used by machine_pin.c. Holds Board/MCU specific Pin allocations. - */ - -#include "modmachine.h" -#include "sam.h" -#include "pins.h" - -// Ensure Declaration in 'pins.h' reflects # of Pins defined here. -const machine_pin_obj_t machine_pin_obj[] = { - {{&machine_pin_type}, PIN_PA02}, // A0,D9 - {{&machine_pin_type}, PIN_PB08}, // A1,D10 - {{&machine_pin_type}, PIN_PB09}, // A2,D11 - {{&machine_pin_type}, PIN_PA04}, // A3,D12 - {{&machine_pin_type}, PIN_PA05}, // A4,D13 - {{&machine_pin_type}, PIN_PA06}, // A5 - {{&machine_pin_type}, PIN_PA16}, // RX_D0 - {{&machine_pin_type}, PIN_PA17}, // TX_D1 - {{&machine_pin_type}, PIN_PA07}, // D2,A6 - {{&machine_pin_type}, PIN_PA19}, // D3 - {{&machine_pin_type}, PIN_PA20}, // D4 - {{&machine_pin_type}, PIN_PA21}, // D5 - {{&machine_pin_type}, PIN_PA00}, // BUTTON -}; - -const machine_led_obj_t machine_led_obj[] = { - {{&machine_led_type}, PIN_PA15}, // LED -}; diff --git a/ports/samd/boards/MINISAM_M4/pins.csv b/ports/samd/boards/MINISAM_M4/pins.csv new file mode 100644 index 0000000000..7442a028d1 --- /dev/null +++ b/ports/samd/boards/MINISAM_M4/pins.csv @@ -0,0 +1,27 @@ +# Pin rows contain Pin number and pin name. +# Pin rows start with PIN_ +# LED rows start with LED_ +# If the pin name is omitted, the pin number is added as name. +# Rows for empty entries have to start with '-' +# Empty lines and lines starting with # are ignored + +PIN_PA02,A0_D9 +PIN_PB08,A1_D10 +PIN_PB09,A2_D11 +PIN_PA04,A3_D12 +PIN_PA05,A4_D13 +PIN_PA06,A5 +PIN_PA16,D0 +PIN_PA17,D1 +PIN_PA07,A6_D2 +PIN_PA19,D3 +PIN_PA20,D4 +PIN_PA21,D5 +PIN_PA00,BUTTON +PIN_PA03,AREF +PIN_PA12,SDA +PIN_PA13,SCL +PIN_PB03,DOTSTAR_DATA +PIN_PB02,DOTSTAR_CLK + +LED_PA15,LED diff --git a/ports/samd/boards/MINISAM_M4/pins.h b/ports/samd/boards/MINISAM_M4/pins.h deleted file mode 100644 index 892b0e7b97..0000000000 --- a/ports/samd/boards/MINISAM_M4/pins.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Peter van der Burg - * - * 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. - * - * Used by machine_pin.c & board specific pins.c. Holds Board/MCU specific Pin - * allocations. - */ - -typedef struct _machine_pin_obj_t { - mp_obj_base_t base; - uint32_t id; -} machine_pin_obj_t; - -typedef struct _machine_led_obj_t { - mp_obj_base_t base; - uint32_t id; -} machine_led_obj_t; - -// MUST explicitly hold array # of rows, else machine_pin.c wont compile. -extern const machine_pin_obj_t machine_pin_obj[13]; -extern const machine_led_obj_t machine_led_obj[1]; diff --git a/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.c b/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.c deleted file mode 100644 index 35718ea7f3..0000000000 --- a/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Peter van der Burg - * - * 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. - * - * Used by machine_pin.c. Holds Board/MCU specific Pin allocations. - */ - -#include "modmachine.h" -#include "sam.h" -#include "pins.h" - -// Ensure Declaration in 'pins.h' reflects # of Pins defined here. -const machine_pin_obj_t machine_pin_obj[] = { - // EXT1 - {{&machine_pin_type}, PIN_PB00}, // PIN3_ADC(+) - {{&machine_pin_type}, PIN_PB01}, // PIN4_ADC(-) - {{&machine_pin_type}, PIN_PB06}, // PIN5_GPIO - {{&machine_pin_type}, PIN_PB07}, // PIN6_GPIO - {{&machine_pin_type}, PIN_PB02}, // PIN7_PWM(+) - {{&machine_pin_type}, PIN_PB03}, // PIN8_PWM(-) - {{&machine_pin_type}, PIN_PB04}, // PIN9_IRQ/GPIO - {{&machine_pin_type}, PIN_PB05}, // PIN10_SPI_SS_B/GPIO - {{&machine_pin_type}, PIN_PA08}, // PIN11_TWI_SDA - {{&machine_pin_type}, PIN_PA09}, // PIN12_TWI_SCL - {{&machine_pin_type}, PIN_PB09}, // PIN13_UART_RX - {{&machine_pin_type}, PIN_PB08}, // PIN14_UART_TX - {{&machine_pin_type}, PIN_PA05}, // PIN15_SPI_SS_A - {{&machine_pin_type}, PIN_PA06}, // PIN16_SPI_MOSI - {{&machine_pin_type}, PIN_PA04}, // PIN17_SPI_MISO - {{&machine_pin_type}, PIN_PA07}, // PIN18_SPI_SCK - - // EXT2 - {{&machine_pin_type}, PIN_PA10}, // PIN3_ADC(+) - {{&machine_pin_type}, PIN_PA11}, // PIN4_ADC(-) - {{&machine_pin_type}, PIN_PA20}, // PIN5_GPIO - {{&machine_pin_type}, PIN_PA21}, // PIN6_GPIO - {{&machine_pin_type}, PIN_PB12}, // PIN7_PWM(+) - {{&machine_pin_type}, PIN_PB13}, // PIN8_PWM(-) - {{&machine_pin_type}, PIN_PB14}, // PIN9_IRQ/GPIO - {{&machine_pin_type}, PIN_PB15}, // PIN10_SPI_SS_B/GPIO - {{NULL}, -1}, // PIN_PA08/ PIN11_TWI_SDA already defined - {{NULL}, -1}, // PIN_PA09/ PIN12_TWI_SCL already defined - {{&machine_pin_type}, PIN_PB11}, // PIN13_UART_RX - {{&machine_pin_type}, PIN_PB10}, // PIN14_UART_TX - {{&machine_pin_type}, PIN_PA17}, // PIN15_SPI_SS_A - {{&machine_pin_type}, PIN_PA18}, // PIN16_SPI_MOSI - {{&machine_pin_type}, PIN_PA16}, // PIN17_SPI_MISO - {{&machine_pin_type}, PIN_PA19}, // PIN18_SPI_SCK - - // EXT3 - {{&machine_pin_type}, PIN_PA02}, // PIN3_ADC(+) - {{&machine_pin_type}, PIN_PA03}, // PIN4_ADC(-) - {{NULL}, -1}, // PIN_PB30/ PIN5_GPIO already defined - {{&machine_pin_type}, PIN_PA15}, // PIN6_GPIO; USER_BUTTON - {{&machine_pin_type}, PIN_PA12}, // PIN7_PWM(+) - {{&machine_pin_type}, PIN_PA13}, // PIN8_PWM(-) - {{&machine_pin_type}, PIN_PA28}, // PIN9_IRQ/GPIO - {{&machine_pin_type}, PIN_PA27}, // PIN10_SPI_SS_B/GPIO - {{NULL}, -1}, // PIN_PA08/ PIN11_TWI_SDA already defined - {{NULL}, -1}, // PIN_PA09/ PIN12_TWI_SCL already defined - {{NULL}, -1}, // PIN_PB11/ PIN13_UART_RX already defined - {{NULL}, -1}, // PIN_PB10/ PIN14_UART_TX already defined - {{&machine_pin_type}, PIN_PB17}, // PIN15_SPI_SS_A - {{&machine_pin_type}, PIN_PB22}, // PIN16_SPI_MOSI - {{&machine_pin_type}, PIN_PB16}, // PIN17_SPI_MISO - {{&machine_pin_type}, PIN_PB23}, // PIN18_SPI_SCK -}; - -const machine_led_obj_t machine_led_obj[] = { - {{&machine_led_type}, PIN_PB30}, // USER_LED -}; diff --git a/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.csv b/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.csv new file mode 100644 index 0000000000..438119d90c --- /dev/null +++ b/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.csv @@ -0,0 +1,63 @@ +# Pin rows contain Pin number and pin name. +# Pin rows start with PIN_ +# LED rows start with LED_ +# If the pin name is omitted, the pin number is added as name. +# Rows for empty entries have to start with '-' +# Empty lines and lines starting with # are ignored + +# EXT1 +PIN_PB00,EXT1_PIN3 +PIN_PB01,EXT1_PIN4 +PIN_PB06,EXT1_PIN5 +PIN_PB07,EXT1_PIN6 +PIN_PB02,EXT1_PIN7 +PIN_PB03,EXT1_PIN8 +PIN_PB04,EXT1_PIN9 +PIN_PB05,EXT1_PIN10 +PIN_PA08,EXT1_PIN11 +PIN_PA09,EXT1_PIN12 +PIN_PB09,EXT1_PIN13 +PIN_PB08,EXT1_PIN14 +PIN_PA05,EXT1_PIN15 +PIN_PA06,EXT1_PIN16 +PIN_PA04,EXT1_PIN17 +PIN_PA07,EXT1_PIN18 + +# EXT2 +PIN_PA10,EXT2_PIN3 +PIN_PA11,EXT2_PIN4 +PIN_PA20,EXT2_PIN5 +PIN_PA21,EXT2_PIN6 +PIN_PB12,EXT2_PIN7 +PIN_PB13,EXT2_PIN8 +PIN_PB14,EXT2_PIN9 +PIN_PB15,EXT2_PIN10 +- +- +PIN_PB11,EXT2_PIN13 +PIN_PB10,EXT2_PIN14 +PIN_PA17,EXT2_PIN15 +PIN_PA18,EXT2_PIN16 +PIN_PA16,EXT2_PIN17 +PIN_PA19,EXT2_PIN18 + +# EXT3 +PIN_PA02,EXT3_PIN3 +PIN_PA03,EXT3_PIN4 +- +PIN_PA15,EXT3_PIN6 +PIN_PA12,EXT3_PIN7 +PIN_PA13,EXT3_PIN8 +PIN_PA28,EXT3_PIN9 +PIN_PA27,EXT3_PIN10 +- +- +- +- +PIN_PB17,EXT3_PIN15 +PIN_PB22,EXT3_PIN16 +PIN_PB16,EXT3_PIN17 +PIN_PB23,EXT3_PIN18 + +LED_PB30,LED + diff --git a/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.h b/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.h deleted file mode 100644 index 0b0e878b43..0000000000 --- a/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Peter van der Burg - * - * 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. - * - * Used by machine_pin.c & board specific pins.c. Holds Board/MCU specific Pin - * allocations. - */ - -typedef struct _machine_pin_obj_t { - mp_obj_base_t base; - uint32_t id; -} machine_pin_obj_t; - -typedef struct _machine_led_obj_t { - mp_obj_base_t base; - uint32_t id; -} machine_led_obj_t; - -// MUST explicitly hold array # of rows, else machine_pin.c wont compile. -extern const machine_pin_obj_t machine_pin_obj[48]; -extern const machine_led_obj_t machine_led_obj[1]; diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.c b/ports/samd/boards/SEEED_WIO_TERMINAL/pins.c deleted file mode 100644 index d7833416d3..0000000000 --- a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Peter van der Burg - * - * 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. - * - * Used by machine_pin.c. Holds Board/MCU specific Pin allocations. - */ - -#include "modmachine.h" -#include "sam.h" -#include "pins.h" - -// Ensure Declaration in "pins.h" reflects # of Pins defined here. -const machine_pin_obj_t machine_pin_obj[] = { - {{&machine_pin_type}, PIN_PB08}, // A0/D0 - {{&machine_pin_type}, PIN_PB09}, // A1/D1 - {{&machine_pin_type}, PIN_PA07}, // A2/D2 - {{&machine_pin_type}, PIN_PB04}, // A3/D3 - {{&machine_pin_type}, PIN_PB05}, // A4/D4 - {{&machine_pin_type}, PIN_PB06}, // A5/D5 - {{&machine_pin_type}, PIN_PA04}, // A6/D6 - {{&machine_pin_type}, PIN_PB07}, // A7/D7 - {{&machine_pin_type}, PIN_PA06}, // A8/D8 - {{&machine_pin_type}, PIN_PD08}, // SWITCH_X - {{&machine_pin_type}, PIN_PD09}, // SWITCH_Y - {{&machine_pin_type}, PIN_PD10}, // SWITCH_Z - {{&machine_pin_type}, PIN_PD12}, // SWITCH_B - {{&machine_pin_type}, PIN_PD20}, // SWITCH_U - {{&machine_pin_type}, PIN_PC26}, // BUTTON_1 - {{&machine_pin_type}, PIN_PC27}, // BUTTON_2 - {{&machine_pin_type}, PIN_PC28}, // BUTTON_3 - {{&machine_pin_type}, PIN_PD11}, // BUZZER_CTR - {{&machine_pin_type}, PIN_PC14}, // 5V_OUTPUT_CTR- enable 5V on hdr - {{&machine_pin_type}, PIN_PC15}, // 3V3_OUTPUT_CTR- enable 3V3 on hdr -}; - -// Ensure Declaration in 'pins.h' reflects # of Pins defined here. -const machine_led_obj_t machine_led_obj[] = { - {{&machine_led_type}, PIN_PA15}, // USER_LED (Blue) - {{&machine_led_type}, PIN_PC05}, // LCD_BACKLIGHT_CTR -}; diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv b/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv new file mode 100644 index 0000000000..72da71224a --- /dev/null +++ b/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv @@ -0,0 +1,30 @@ +# Pin rows contain Pin number and pin name. +# Pin rows start with PIN_ +# LED rows start with LED_ +# If the pin name is omitted, the pin number is added as name. +# Rows for empty entries have to start with '-' +# Empty lines and lines starting with # are ignored + +PIN_PB08,A0_D0 +PIN_PB09,A1_D1 +PIN_PA07,A2_D2 +PIN_PB04,A3_D3 +PIN_PB05,A4_D4 +PIN_PB06,A5_D5 +PIN_PA04,A6_D6 +PIN_PB07,A7_D7 +PIN_PA06,A8_D8 +PIN_PD08,SWITCH_X +PIN_PD09,SWITCH_Y +PIN_PD10,SWITCH_Z +PIN_PD12,SWITCH_B +PIN_PD20,SWITCH_U +PIN_PC26,BUTTON_1 +PIN_PC27,BUTTON_2 +PIN_PC28,BUTTON_3 +PIN_PD11,BUZZER_CTR +PIN_PC14,5V_ENABLE +PIN_PC15,3V3_ENABLE + +LED_PA15,LED_BLUE +LED_PC05,LED_LCD diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.h b/ports/samd/boards/SEEED_WIO_TERMINAL/pins.h deleted file mode 100644 index 45ecc254f1..0000000000 --- a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Peter van der Burg - * - * 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. - * - * Used by machine_pin.c & board specific pins.c. Holds Board/MCU specific Pin - * allocations. - */ - -typedef struct _machine_pin_obj_t { - mp_obj_base_t base; - uint32_t id; -} machine_pin_obj_t; - -typedef struct _machine_led_obj_t { - mp_obj_base_t base; - uint32_t id; -} machine_led_obj_t; - -// MUST explicitly hold array # of rows, else machine_pin.c wont compile. -extern const machine_pin_obj_t machine_pin_obj[20]; -extern const machine_led_obj_t machine_led_obj[2]; diff --git a/ports/samd/boards/SEEED_XIAO/pins.c b/ports/samd/boards/SEEED_XIAO/pins.c deleted file mode 100644 index e2f7c264b4..0000000000 --- a/ports/samd/boards/SEEED_XIAO/pins.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Peter van der Burg - * - * 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. - * - * Used by machine_pin.c. Holds Board/MCU specific Pin allocations. - */ - -#include "modmachine.h" -#include "sam.h" -#include "pins.h" - -// Ensure Declaration in 'pins.h' reflects # of Pins defined here. -const machine_pin_obj_t machine_pin_obj[] = { - {{&machine_pin_type}, PIN_PA02}, // A0/D0 - {{&machine_pin_type}, PIN_PA04}, // A1/D1 - {{&machine_pin_type}, PIN_PA10}, // A2/D2 - {{&machine_pin_type}, PIN_PA11}, // A3/D3 - {{&machine_pin_type}, PIN_PA08}, // A4/D4 - {{&machine_pin_type}, PIN_PA09}, // A5/D5 - {{&machine_pin_type}, PIN_PB08}, // A6/D6 - {{&machine_pin_type}, PIN_PB09}, // A7/D7 - {{&machine_pin_type}, PIN_PA07}, // A8/D8 - {{&machine_pin_type}, PIN_PA05}, // A9/D9 - {{&machine_pin_type}, PIN_PA06}, // A10/D10 -}; - -const machine_led_obj_t machine_led_obj[] = { -// XIAO: Just the available LED Pins: User LED (PA17), Rx & Tx. - {{&machine_led_type}, PIN_PA17}, // W13 - {{&machine_led_type}, PIN_PA18}, // RX_LED - {{&machine_led_type}, PIN_PA19}, // TX_LED -}; diff --git a/ports/samd/boards/SEEED_XIAO/pins.csv b/ports/samd/boards/SEEED_XIAO/pins.csv new file mode 100644 index 0000000000..8a70a77145 --- /dev/null +++ b/ports/samd/boards/SEEED_XIAO/pins.csv @@ -0,0 +1,22 @@ +# Pin rows contain Pin number and pin name. +# Pin rows start with PIN_ +# LED rows start with LED_ +# If the pin name is omitted, the pin number is added as name. +# Rows for empty entries have to start with '-' +# Empty lines and lines starting with # are ignored + +PIN_PA02,A0_D0 +PIN_PA04,A1_D1 +PIN_PA10,A2_D2 +PIN_PA11,A3_D3 +PIN_PA08,A4_D4 +PIN_PA09,A5_D5 +PIN_PB08,A6_D6 +PIN_PB09,A7_D7 +PIN_PA07,A8_D8 +PIN_PA05,A9_D9 +PIN_PA06,A10_D10 + +LED_PA17,USER_LED +LED_PA18,RX_LED +LED_PA19,TX_LED diff --git a/ports/samd/boards/SEEED_XIAO/pins.h b/ports/samd/boards/SEEED_XIAO/pins.h deleted file mode 100644 index 226b3f1d7b..0000000000 --- a/ports/samd/boards/SEEED_XIAO/pins.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Peter van der Burg - * - * 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. - * - * Used by machine_pin.c & board specific pins.c. Holds Board/MCU specific Pin - * allocations. - */ - -typedef struct _machine_pin_obj_t { - mp_obj_base_t base; - uint32_t id; -} machine_pin_obj_t; - -typedef struct _machine_led_obj_t { - mp_obj_base_t base; - uint32_t id; -} machine_led_obj_t; - -// MUST explicitly hold array # of rows, else machine_pin.c wont compile. -extern const machine_pin_obj_t machine_pin_obj[11]; -extern const machine_led_obj_t machine_led_obj[3]; diff --git a/ports/samd/boards/make-pins.py b/ports/samd/boards/make-pins.py new file mode 100644 index 0000000000..400a9c9b88 --- /dev/null +++ b/ports/samd/boards/make-pins.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python +"""Generates the pins file for the SAMD port.""" + +from __future__ import print_function + +import argparse +import sys +import csv + +pins_header_prefix = """// This file was automatically generated by make-pins.py +// +typedef struct _machine_pin_obj_t { + mp_obj_base_t base; + uint32_t id; + char *name; +} machine_pin_obj_t; + +""" + +led_header_prefix = """typedef struct _machine_led_obj_t { + mp_obj_base_t base; + uint32_t id; + char *name; +} machine_led_obj_t; + +""" + + +class Pins: + def __init__(self): + self.board_pins = [] # list of pin objects + self.board_leds = [] # list of led objects + + def parse_csv_file(self, filename): + with open(filename, "r") as csvfile: + rows = csv.reader(csvfile) + for row in rows: + # Pin numbers must start with "PIN_" + # LED numbers must start with "LED_" + if len(row) > 0: + if row[0].strip().startswith("PIN_"): + if len(row) == 1: + self.board_pins.append([row[0], row[0][4:]]) + else: + self.board_pins.append([row[0], row[1]]) + elif row[0].strip().startswith("LED_"): + self.board_leds.append(["PIN_" + row[0][4:], row[1]]) + elif row[0].strip().startswith("-"): + self.board_pins.append(["-1", ""]) + + def print_pins(self, pins_filename): + with open(pins_filename, "wt") as pins_file: + pins_file.write("// This file was automatically generated by make-pins.py\n") + pins_file.write("//\n") + pins_file.write('#include "modmachine.h"\n') + pins_file.write('#include "sam.h"\n') + pins_file.write('#include "pins.h"\n\n') + + pins_file.write("const machine_pin_obj_t machine_pin_obj[] = {\n") + for pin in self.board_pins: + pins_file.write(" {{&machine_pin_type}, ") + pins_file.write(pin[0] + ', "' + pin[1]) + pins_file.write('"},\n') + pins_file.write("};\n") + + if self.board_leds: + pins_file.write("\nconst machine_led_obj_t machine_led_obj[] = {\n") + for pin in self.board_leds: + pins_file.write(" {{&machine_pin_type}, ") + pins_file.write(pin[0] + ', "' + pin[1]) + pins_file.write('"},\n') + pins_file.write("};\n") + + def print_header(self, hdr_filename): + with open(hdr_filename, "wt") as hdr_file: + hdr_file.write(pins_header_prefix) + if self.board_leds: + hdr_file.write(led_header_prefix) + hdr_file.write( + "extern const machine_pin_obj_t machine_pin_obj[%d];\n" % len(self.board_pins) + ) + if self.board_leds: + hdr_file.write( + "extern const machine_led_obj_t machine_led_obj[%d];\n" % len(self.board_leds) + ) + + +def main(): + parser = argparse.ArgumentParser( + prog="make-pins.py", + usage="%(prog)s [options] [command]", + description="Generate board specific pin file", + ) + parser.add_argument( + "-b", + "--board", + dest="csv_filename", + help="Specifies the pins.csv filename", + ) + parser.add_argument( + "-p", + "--pins", + dest="pins_filename", + help="Specifies the name of the generated pins.c file", + ) + parser.add_argument( + "-i", + "--inc", + dest="hdr_filename", + help="Specifies name of generated pin header file", + ) + args = parser.parse_args(sys.argv[1:]) + + pins = Pins() + + if args.csv_filename: + pins.parse_csv_file(args.csv_filename) + + if args.pins_filename: + pins.print_pins(args.pins_filename) + + pins.print_header(args.hdr_filename) + + +if __name__ == "__main__": + main() From a5d5ecbf8434e480b42a8a477ef9ba7979bba927 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 4 Jun 2022 13:27:12 +0200 Subject: [PATCH 0474/1041] samd/boards: Move mcu-specific settings into a mpconfig_samdXX.h file. Located at the boards directory. That way, the mpconfigboard.h files are almost empty, just setting the board name and the MCU name. --- ports/samd/Makefile | 3 +++ .../mpconfigboard.h | 10 --------- .../mpconfigboard.h | 15 ------------- .../ADAFRUIT_TRINKET_M0/mpconfigboard.h | 10 --------- ports/samd/boards/MINISAM_M4/mpconfigboard.h | 15 ------------- .../SAMD21_XPLAINED_PRO/mpconfigboard.h | 10 --------- .../boards/SEEED_WIO_TERMINAL/mpconfigboard.h | 15 ------------- ports/samd/boards/SEEED_XIAO/mpconfigboard.h | 10 --------- ports/samd/boards/mpconfig_samd21.h | 9 ++++++++ ports/samd/boards/mpconfig_samd51.h | 21 +++++++++++++++++++ ports/samd/mpconfigport.h | 2 ++ 11 files changed, 35 insertions(+), 85 deletions(-) create mode 100644 ports/samd/boards/mpconfig_samd21.h create mode 100644 ports/samd/boards/mpconfig_samd51.h diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 1ef35c1a02..4dd6356c1e 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -50,6 +50,9 @@ CFLAGS_MCU_SAMD51 = -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-a CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib -mthumb $(CFLAGS_MCU_$(MCU_SERIES)) -fsingle-precision-constant -Wdouble-promotion CFLAGS += -DMCU_$(MCU_SERIES) -D__$(CMSIS_MCU)__ CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) +CFLAGS += -DMPCONFIG_MCU_H='' + +QSTR_GLOBAL_DEPENDENCIES += boards/mpconfig_$(MCU_SERIES_LOWER).h LDFLAGS = -nostdlib $(addprefix -T,$(LD_FILES)) -Map=$@.map --cref LDFLAGS += $(LDFLAGS_MOD) diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h index bdb22d2e0a..cec9e9ccdd 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h @@ -1,12 +1,2 @@ #define MICROPY_HW_BOARD_NAME "Feather M0 Express" #define MICROPY_HW_MCU_NAME "SAMD21G18A" - -// MicroPython configs -// samd_flash.c flash parameters -// Build a 64k Flash storage at top. 256k-64k=196k -// 256*1024=262144 minus 64*1024=65536 = 196608 = 0x30000 -#define MICROPY_HW_FLASH_STORAGE_BASE (0x30000) -#define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF) -#define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; - -#define CPU_FREQ (48000000) // For selecting Baud from clock. diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h index 80baf39e5d..2fffc9c7de 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h @@ -1,17 +1,2 @@ #define MICROPY_HW_BOARD_NAME "ItsyBitsy M4 Express" #define MICROPY_HW_MCU_NAME "SAMD51G19A" - -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) -#define MICROPY_PY_BUILTINS_COMPLEX (0) -#define MICROPY_PY_MATH (0) -#define MICROPY_PY_CMATH (0) - -// MicroPython configs -// samd_flash.c flash parameters -// Build a 128k Flash storage at top. 512k-128k=384k=0x60000 -// 512*1024= 0x80000 minus 128*1024= 0x20000 = 0x60000 -#define MICROPY_HW_FLASH_STORAGE_BASE (0x60000) -#define MICROPY_HW_FLASH_STORAGE_BYTES (0x1FFFF) -#define VFS_BLOCK_SIZE_BYTES (1536) // - -#define CPU_FREQ (48000000) // For selecting Baud from clock. diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h index 066c7ee142..d3a6ba2d86 100644 --- a/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h @@ -1,12 +1,2 @@ #define MICROPY_HW_BOARD_NAME "Trinket M0" #define MICROPY_HW_MCU_NAME "SAMD21E18A" - -// MicroPython configs -// samd_flash.c flash parameters -// Build a 64k Flash storage at top. 256k-64k=196k -// 256*1024=262144 minus 64*1024=65536 = 196608 = 0x30000 -#define MICROPY_HW_FLASH_STORAGE_BASE (0x30000) -#define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF) -#define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; - -#define CPU_FREQ (48000000) // For selecting Baud from clock. diff --git a/ports/samd/boards/MINISAM_M4/mpconfigboard.h b/ports/samd/boards/MINISAM_M4/mpconfigboard.h index a8f1f96242..6715a16f01 100644 --- a/ports/samd/boards/MINISAM_M4/mpconfigboard.h +++ b/ports/samd/boards/MINISAM_M4/mpconfigboard.h @@ -1,17 +1,2 @@ #define MICROPY_HW_BOARD_NAME "Mini SAM M4" #define MICROPY_HW_MCU_NAME "SAMD51G19A" - -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) -#define MICROPY_PY_BUILTINS_COMPLEX (0) -#define MICROPY_PY_MATH (0) -#define MICROPY_PY_CMATH (0) - -// MicroPython configs -// samd_flash.c flash parameters -// Build a 128k Flash storage at top. 512k-128k=384k=0x60000 -// 512*1024= 0x80000 minus 128*1024= 0x20000 = 0x60000 -#define MICROPY_HW_FLASH_STORAGE_BASE (0x60000) -#define MICROPY_HW_FLASH_STORAGE_BYTES (0x1FFFF) -#define VFS_BLOCK_SIZE_BYTES (1536) // - -#define CPU_FREQ (48000000) // For selecting Baud from clock. diff --git a/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h b/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h index 860cb6b977..c69b5b4c14 100644 --- a/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h +++ b/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h @@ -1,12 +1,2 @@ #define MICROPY_HW_BOARD_NAME "SAMD21-XPLAINED-PRO" #define MICROPY_HW_MCU_NAME "SAMD21J18A" - -// MicroPython configs -// samd_flash.c flash parameters -// Build a 64k Flash storage at top. 256k-64k=196k -// 256*1024=262144 minus 64*1024=65536 = 196608 = 0x30000 -#define MICROPY_HW_FLASH_STORAGE_BASE (0x30000) -#define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF) -#define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; - -#define CPU_FREQ (48000000) // For selecting Baud from clock. diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h b/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h index bb0f1c828e..cfda18d11c 100644 --- a/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h +++ b/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h @@ -1,17 +1,2 @@ #define MICROPY_HW_BOARD_NAME "Wio Terminal D51R" #define MICROPY_HW_MCU_NAME "SAMD51P19A" - -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) -#define MICROPY_PY_BUILTINS_COMPLEX (0) -#define MICROPY_PY_MATH (0) -#define MICROPY_PY_CMATH (0) - -// MicroPython configs -// samd_flash.c flash parameters -// Build a 128k Flash storage at top. 512k-128k=384k=0x60000 -// 512*1024= 0x80000 minus 128*1024= 0x20000 = 0x60000 -#define MICROPY_HW_FLASH_STORAGE_BASE (0x60000) -#define MICROPY_HW_FLASH_STORAGE_BYTES (0x1FFFF) -#define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; - -#define CPU_FREQ (48000000) // For selecting Baud from clock. diff --git a/ports/samd/boards/SEEED_XIAO/mpconfigboard.h b/ports/samd/boards/SEEED_XIAO/mpconfigboard.h index a2f2a9fb0b..2026efc6b1 100644 --- a/ports/samd/boards/SEEED_XIAO/mpconfigboard.h +++ b/ports/samd/boards/SEEED_XIAO/mpconfigboard.h @@ -1,12 +1,2 @@ #define MICROPY_HW_BOARD_NAME "Seeed Xiao" #define MICROPY_HW_MCU_NAME "SAMD21G18A" - -// MicroPython configs -// samd_flash.c flash parameters -// Build a 64k Flash storage at top. 256k-64k=196k -// 256*1024=262144 minus 64*1024=65536 = 196608 = 0x30000 -#define MICROPY_HW_FLASH_STORAGE_BASE (0x30000) -#define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF) -#define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; - -#define CPU_FREQ (48000000) // For selecting Baud from clock. diff --git a/ports/samd/boards/mpconfig_samd21.h b/ports/samd/boards/mpconfig_samd21.h new file mode 100644 index 0000000000..1924f66f06 --- /dev/null +++ b/ports/samd/boards/mpconfig_samd21.h @@ -0,0 +1,9 @@ +// Deinitions common to all SAMD21 boards +#include "samd21.h" + +#define MICROPY_HW_FLASH_STORAGE_BASE (0x30000) +#define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF) +#define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; + +#define CPU_FREQ (48000000) +#define APB_FREQ (48000000) diff --git a/ports/samd/boards/mpconfig_samd51.h b/ports/samd/boards/mpconfig_samd51.h new file mode 100644 index 0000000000..1b67b1d02d --- /dev/null +++ b/ports/samd/boards/mpconfig_samd51.h @@ -0,0 +1,21 @@ +// Deinitions common to all SAMD51 boards +#include "samd51.h" + +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) +#define MICROPY_PY_BUILTINS_COMPLEX (0) +#define MICROPY_PY_MATH (0) +#define MICROPY_PY_CMATH (0) + +// Due to a limitation in the TC counter for us, the ticks period is 2**29 +#define MICROPY_PY_UTIME_TICKS_PERIOD (0x20000000) +// MicroPython configs +// samd_flash.c flash parameters +// Build a 128k Flash storage at top. 512k-128k=384k=0x60000 +// 512*1024= 0x80000 minus 128*1024= 0x20000 = 0x60000 +#define MICROPY_HW_FLASH_STORAGE_BASE (0x60000) +#define MICROPY_HW_FLASH_STORAGE_BYTES (0x1FFFF) +#define VFS_BLOCK_SIZE_BYTES (1536) // + +#define CPU_FREQ (120000000) +#define APB_FREQ (48000000) +#define DPLLx_REF_FREQ (32768) diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 2c6052149b..c29043c5d0 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -28,6 +28,8 @@ // Board specific definitions #include "mpconfigboard.h" +// MCU-Specific definitions +#include MPCONFIG_MCU_H // Memory allocation policies #define MICROPY_GC_STACK_ENTRY_TYPE uint16_t From c4f7c0b8a2504e8a13644ea692c4a66d6f124871 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 4 Jun 2022 16:16:22 +0200 Subject: [PATCH 0475/1041] samd/Makefile: Alphabetically sort the source code files in Makefile. --- ports/samd/Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 4dd6356c1e..66e23bae69 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -83,16 +83,16 @@ LDFLAGS += -L"$(shell dirname $(LIBSTDCPP_FILE_NAME))" endif SRC_C = \ - main.c \ help.c \ + machine_led.c \ + machine_pin.c \ + main.c \ modutime.c \ modmachine.c \ - $(BUILD)/pins.c \ - machine_pin.c \ - machine_led.c \ modsamd.c \ - samd_flash.c \ mphalport.c \ + $(BUILD)/pins.c \ + samd_flash.c \ samd_isr.c \ samd_soc.c \ tusb_port.c \ @@ -130,10 +130,10 @@ endif # List of sources for qstr extraction SRC_QSTR += \ + machine_led.c \ + machine_pin.c \ modutime.c \ modmachine.c \ - machine_pin.c \ - machine_led.c \ modsamd.c \ samd_flash.c \ shared/readline/readline.c \ From 949a808076f10f9f7e25fd9ebe4a03b8cc397e1f Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 4 Jun 2022 15:42:56 +0200 Subject: [PATCH 0476/1041] samd/boards: Add ADAFRUIT_FEATHER_M4_EXPRESS and _ITSYBITSY_M0_EXPRESS. These two boards are used for testing, so it is favorable to have them added early. The full test set is: - ADAFRUIT_FEATHER_M4_EXPRESS: SAMD51 with 32kHz crystal. - ADAFRUIT_ITSYBITSY_M0_EXPRESS: SAMD21 without crystal. - ADAFRUIT_ITSYBITSY_M4_EXPRESS: SAMD51 without crystal. - SEEED_XIAO: SAM21 with 32kHz crystal. --- .../ADAFRUIT_FEATHER_M4_EXPRESS/board.json | 22 ++++++++++ .../mpconfigboard.h | 2 + .../mpconfigboard.mk | 8 ++++ .../ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv | 34 ++++++++++++++++ .../ADAFRUIT_ITSYBITSY_M0_EXPRESS/board.json | 20 ++++++++++ .../mpconfigboard.h | 2 + .../mpconfigboard.mk | 8 ++++ .../ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv | 40 +++++++++++++++++++ ports/samd/boards/samd51j19a.ld | 17 ++++++++ 9 files changed, 153 insertions(+) create mode 100644 ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json create mode 100644 ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h create mode 100644 ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk create mode 100644 ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv create mode 100644 ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/board.json create mode 100644 ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h create mode 100644 ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.mk create mode 100644 ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv create mode 100644 ports/samd/boards/samd51j19a.ld diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json new file mode 100644 index 0000000000..c8042aa254 --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json @@ -0,0 +1,22 @@ +{ + "deploy": [ + "../deploy.md" + ], + "docs": "", + "features": [ + "Battery Charging", + "Breadboard Friendly", + "Feather", + "Micro USB", + "RGB LED", + "SPI Flash" + ], + "images": [ + "feather_m4_express.jpg" + ], + "mcu": "samd51", + "product": "Feather M4 Express", + "thumbnail": "", + "url": "https://www.adafruit.com/product/3857", + "vendor": "Adafruit" +} diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h new file mode 100644 index 0000000000..48599eec47 --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h @@ -0,0 +1,2 @@ +#define MICROPY_HW_BOARD_NAME "Feather M4 Express" +#define MICROPY_HW_MCU_NAME "SAMD51J19A" diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk new file mode 100644 index 0000000000..d29e2b1097 --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk @@ -0,0 +1,8 @@ +MCU_SERIES = SAMD51 +CMSIS_MCU = SAMD51J19A +LD_FILES = boards/samd51j19a.ld sections.ld +TEXT0 = 0x4000 + +# The ?='s allow overriding in mpconfigboard.mk. +# MicroPython settings +MICROPY_VFS_LFS1 ?= 1 diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv new file mode 100644 index 0000000000..5b999c39e0 --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv @@ -0,0 +1,34 @@ +# Pin rows contain Pin number and pin name. +# Pin rows start with PIN_ +# LED rows start with LED_ +# If the pin name is omitted, the pin number is added as name. +# Rows for empty entries have to start with '-' +# Empty lines and lines starting with PIN_ or LED_ are ignored + +PIN_PB17,D0 +PIN_PB16,D1 +PIN_PA14,D4 +PIN_PA16,D5 +PIN_PA18,D6 +- +PIN_PB03,D8 +PIN_PA19,D9 +PIN_PA20,D10 +PIN_PA21,D11 +PIN_PA22,D12 +PIN_PA23,D13 +PIN_PA02,A0 +PIN_PA05,A1 +PIN_PB08,A2 +PIN_PB09,A3 +PIN_PA04,A4 +PIN_PB06,A5 +PIN_PA13,SCL +PIN_PA12,SDA +PIN_PB23,MOSI +PIN_PB22,MISO +PIN_PA17,SCK +PIN_PB01,VDIV +PIN_PA03,AREF + +LED_PA17,LED diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/board.json new file mode 100644 index 0000000000..f99d19ca87 --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/board.json @@ -0,0 +1,20 @@ +{ + "deploy": [ + "../deploy.md" + ], + "docs": "", + "features": [ + "Breadboard Friendly", + "Micro USB", + "RGB LED", + "SPI Flash" + ], + "images": [ + "itsybitsy_m0_express.jpg" + ], + "mcu": "samd21", + "product": "ItsyBitsy M0 Express", + "thumbnail": "", + "url": "https://www.adafruit.com/product/3727", + "vendor": "Adafruit" +} diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h new file mode 100644 index 0000000000..d647af9312 --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h @@ -0,0 +1,2 @@ +#define MICROPY_HW_BOARD_NAME "ItsyBitsy M0 Express" +#define MICROPY_HW_MCU_NAME "SAMD21G18A" diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.mk new file mode 100644 index 0000000000..a760cf047e --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.mk @@ -0,0 +1,8 @@ +MCU_SERIES = SAMD21 +CMSIS_MCU = SAMD21G18A +LD_FILES = boards/samd21x18a.ld sections.ld +TEXT0 = 0x2000 + +# The ?='s allow overriding in mpconfigboard.mk. +# MicroPython settings +MICROPY_VFS_LFS1 ?= 1 diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv new file mode 100644 index 0000000000..50c3c1cf68 --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv @@ -0,0 +1,40 @@ +# Pin rows contain Pin number and pin name. +# Pin rows start with PIN_ +# LED rows start with LED_ +# If the pin name is omitted, the pin number is added as name. +# Rows for empty entries have to start with '-' +# Empty lines and lines not starting with PIN_ or LED_ are ignored + +PIN_PA11,D0 +PIN_PA10,D1 +PIN_PA14,D2 +PIN_PB09,D3 +PIN_PA08,D4 +PIN_PA15,D5 +- +PIN_PA21,D7 +- +PIN_PA07,D9 +PIN_PA18,D10 +PIN_PA16,D11 +PIN_PA19,D12 +PIN_PA17,D13 +PIN_PA02,A0 +PIN_PB08,A1 +PIN_PB09,A2 +PIN_PA04,A3 +PIN_PA05,A4 +PIN_PB02,A5 +PIN_PA22,SDA +PIN_PA23,SCL +PIN_PB10,MO +PIN_PA12,MI +PIN_PB11,SCK +PIN_PA00,DOTSTAR_CLK +PIN_PA01,DOTSTAR_DATA +PIN_PB22,FLASH_MOSI +PIN_PB03,FLASH_MISO +PIN_PB23,FLASH_SCK +PIN_PA27,FLASH_CS + +LED_PA17,LED diff --git a/ports/samd/boards/samd51j19a.ld b/ports/samd/boards/samd51j19a.ld new file mode 100644 index 0000000000..e0baa9bba0 --- /dev/null +++ b/ports/samd/boards/samd51j19a.ld @@ -0,0 +1,17 @@ +/* + GNU linker script for SAMD51 +*/ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00004000, LENGTH = 512K - 16K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K +} + +/* Top end of the stack, with room for double-tap variable */ +_estack = ORIGIN(RAM) + LENGTH(RAM) - 8; +_sstack = _estack - 16K; + +_sheap = _ebss; +_eheap = _sstack; From b4d29fd47a52526bc9626e5dc28794fa1d95dcf2 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 4 Jun 2022 16:31:46 +0200 Subject: [PATCH 0477/1041] samd/clock_config: Set up the clock configuration. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clock settings: - GCLK0: 48 MHz (SAMD21) or 120 MHz(SAMD51). - GCLK1: 32768 Hz for driving the PLL. - GCLK2: 48 MHz for tzhe peripheral clock. - GCLK3: 1 MHz (SAMD21) or 8 MHz (SAMD51) for the µs ticks timer. - GCLK8: 1 kHz for WDT (SAMD21 only). If a 32 kHz crystal is present, it will be used as clock source. Otherwise the DFLL48M in open-loop mode is used. GCLK0 for SAM51 can be changed between 48 MHz and 200 MHz. The specified range is 96 MHz - 120 MHz. --- ports/samd/Makefile | 1 + ports/samd/clock_config.c | 348 ++++++++++++++++++++++++++++++++++++++ ports/samd/clock_config.h | 33 ++++ ports/samd/samd_soc.c | 66 +++++--- ports/samd/samd_soc.h | 11 ++ 5 files changed, 431 insertions(+), 28 deletions(-) create mode 100644 ports/samd/clock_config.c create mode 100644 ports/samd/clock_config.h diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 66e23bae69..e3316a9d6c 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -83,6 +83,7 @@ LDFLAGS += -L"$(shell dirname $(LIBSTDCPP_FILE_NAME))" endif SRC_C = \ + clock_config.c \ help.c \ machine_led.c \ machine_pin.c \ diff --git a/ports/samd/clock_config.c b/ports/samd/clock_config.c new file mode 100644 index 0000000000..0f5634fdb7 --- /dev/null +++ b/ports/samd/clock_config.c @@ -0,0 +1,348 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * This file provides functions for configuring the clocks. + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Robert Hammelrath + * + * 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 + +#include "py/runtime.h" +#include "samd_soc.h" + +static uint32_t cpu_freq = CPU_FREQ; +static uint32_t apb_freq = APB_FREQ; + +#if defined(MCU_SAMD21) +int sercom_gclk_id[] = { + GCLK_CLKCTRL_ID_SERCOM0_CORE, GCLK_CLKCTRL_ID_SERCOM1_CORE, + GCLK_CLKCTRL_ID_SERCOM2_CORE, GCLK_CLKCTRL_ID_SERCOM3_CORE, + GCLK_CLKCTRL_ID_SERCOM4_CORE, GCLK_CLKCTRL_ID_SERCOM5_CORE +}; +#elif defined(MCU_SAMD51) +int sercom_gclk_id[] = { + SERCOM0_GCLK_ID_CORE, SERCOM1_GCLK_ID_CORE, + SERCOM2_GCLK_ID_CORE, SERCOM3_GCLK_ID_CORE, + SERCOM4_GCLK_ID_CORE, SERCOM5_GCLK_ID_CORE, + #if defined(SERCOM7_GCLK_ID_CORE) + SERCOM6_GCLK_ID_CORE, SERCOM7_GCLK_ID_CORE, + #endif +}; +#endif + +uint32_t get_cpu_freq(void) { + return cpu_freq; +} + +uint32_t get_apb_freq(void) { + return apb_freq; +} + +#if defined(MCU_SAMD21) +void set_cpu_freq(uint32_t cpu_freq_arg) { + cpu_freq = cpu_freq_arg; +} + +#elif defined(MCU_SAMD51) +void set_cpu_freq(uint32_t cpu_freq_arg) { + cpu_freq = cpu_freq_arg; + + // Setup GCLK0 for 48MHz as default state to keep the MCU running during config change. + GCLK->GENCTRL[0].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; + while (GCLK->SYNCBUSY.bit.GENCTRL0) { + } + + // Setup DPLL0 for 120 MHz + // first: disable DPLL0 in case it is running + OSCCTRL->Dpll[0].DPLLCTRLA.bit.ENABLE = 0; + while (OSCCTRL->Dpll[0].DPLLSYNCBUSY.bit.ENABLE == 1) { + } + // Now configure the registers + OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(1) | OSCCTRL_DPLLCTRLB_LBYPASS | + OSCCTRL_DPLLCTRLB_REFCLK(0) | OSCCTRL_DPLLCTRLB_WUF | OSCCTRL_DPLLCTRLB_FILTER(0x01); + + uint32_t div = cpu_freq / DPLLx_REF_FREQ; + uint32_t frac = (cpu_freq - div * DPLLx_REF_FREQ) / (DPLLx_REF_FREQ / 32); + OSCCTRL->Dpll[0].DPLLRATIO.reg = (frac << 16) + div - 1; + // enable it again + OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE | OSCCTRL_DPLLCTRLA_RUNSTDBY; + + // Per errata 2.13.1 + while (!(OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY == 1)) { + } + + // Setup GCLK0 for DPLL0 output (48 or 48-200MHz) + GCLK->GENCTRL[0].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DPLL0; + while (GCLK->SYNCBUSY.bit.GENCTRL0) { + } +} +#endif + +void init_clocks(uint32_t cpu_freq) { + #if defined(MCU_SAMD21) + + // SAMD21 Clock settings + // GCLK0: 48MHz from DFLL open loop mode or closed loop mode from 32k Crystal + // GCLK1: 32768 Hz from 32K ULP or 32k Crystal + // GCLK2: 48MHz from DFLL for Peripherals + // GCLK3: 1Mhz for the us-counter (TC3/TC4) + // GCLK8: 1kHz clock for WDT + + NVMCTRL->CTRLB.bit.MANW = 1; // errata "Spurious Writes" + NVMCTRL->CTRLB.bit.RWS = 1; // 1 read wait state for 48MHz + + #if MICROPY_HW_XOSC32K + // Set up OSC32K according datasheet 17.6.3 + SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP(0x3) | SYSCTRL_XOSC32K_EN32K | + SYSCTRL_XOSC32K_XTALEN; + SYSCTRL->XOSC32K.bit.ENABLE = 1; + while (SYSCTRL->PCLKSR.bit.XOSC32KRDY == 0) { + } + // Set up the DFLL48 according to the data sheet 17.6.7.1.2 + // Step 1: Set up the reference clock + // Connect the OSC32K via GCLK1 to the DFLL input and for further use. + GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) | GCLK_GENDIV_DIV(1); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_ID(1); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_DFLL48 | GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_CLKEN; + // Enable access to the DFLLCTRL reg acc. to Errata 1.2.1 + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE; + while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { + } + // Step 2: Set the coarse and fine values. + // The coarse setting will be taken from the calibration data. So the value used here + // does not matter. Get the coarse value from the calib data. In case it is not set, + // set a midrange value. + uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) + >> FUSES_DFLL48M_COARSE_CAL_Pos; + if (coarse == 0x3f) { + coarse = 0x1f; + } + SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(512); + while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { + } + // Step 3: Set the multiplication values. The offset of 16384 to the freq is for rounding. + SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_MUL((CPU_FREQ + 16384) / 32768) | + SYSCTRL_DFLLMUL_FSTEP(1) | SYSCTRL_DFLLMUL_CSTEP(1); + while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { + } + // Step 4: Start the DFLL and wait for the PLL lock. We just wait for the fine lock, since + // coarse adjusting is bypassed. + SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_WAITLOCK | + SYSCTRL_DFLLCTRL_BPLCKC | SYSCTRL_DFLLCTRL_ENABLE; + while (SYSCTRL->PCLKSR.bit.DFLLLCKF == 0) { + } + + #else // MICROPY_HW_XOSC32K + + // Enable DFLL48M + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE; + while (!SYSCTRL->PCLKSR.bit.DFLLRDY) { + } + SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(1) | SYSCTRL_DFLLMUL_FSTEP(1) + | SYSCTRL_DFLLMUL_MUL(48000); + uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) + >> FUSES_DFLL48M_COARSE_CAL_Pos; + if (coarse == 0x3f) { + coarse = 0x1f; + } + SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(512); + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_USBCRM + | SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_ENABLE; + while (!SYSCTRL->PCLKSR.bit.DFLLRDY) { + } + // Enable 32768 Hz on GCLK1 for consistency + GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) | GCLK_GENDIV_DIV(48016384 / 32768); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(1); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + + #endif // MICROPY_HW_XOSC32K + + // Enable GCLK output: 48M on both CCLK0 and GCLK2 + GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) | GCLK_GENDIV_DIV(1); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(0); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + GCLK->GENDIV.reg = GCLK_GENDIV_ID(2) | GCLK_GENDIV_DIV(1); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(2); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + + // Enable GCLK output: 1MHz on GCLK3 for TC3 + GCLK->GENDIV.reg = GCLK_GENDIV_ID(3) | GCLK_GENDIV_DIV(48); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(3); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + // Set GCLK8 to 1 kHz. + GCLK->GENDIV.reg = GCLK_GENDIV_ID(8) | GCLK_GENDIV_DIV(32); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(8); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + + #elif defined(MCU_SAMD51) + + // SAMD51 clock settings + // GCLK0: 48MHz from DFLL48M or 48 - 200 MHz from DPLL0 (SAMD51) + // GCLK1: DPLLx_REF_FREQ 32768 Hz from 32KULP or 32k Crystal + // GCLK2: 48MHz from DFLL48M for Peripheral devices + // GCLK3: 16Mhz for the us-counter (TC0/TC1) + // DPLL0: 48 - 200 MHz + + // Steps to set up clocks: + // Reset Clocks + // Switch GCLK0 to DFLL 48MHz + // Setup 32768 Hz source and DFLL48M in closed loop mode, if a crystal is present. + // Setup GCLK1 to the DPLL0 Reference freq. of 32768 Hz + // Setup GCLK1 to drive peripheral channel 1 + // Setup DPLL0 to 120MHz + // Setup GCLK0 to 120MHz + // Setup GCLK2 to 48MHz for Peripherals + // Setup GCLK3 to 8MHz for TC0/TC1 + + // Setup GCLK0 for 48MHz as default state to keep the MCU running during config change. + GCLK->GENCTRL[0].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; + while (GCLK->SYNCBUSY.bit.GENCTRL0) { + } + + #if MICROPY_HW_XOSC32K + // OSCILLATOR CONTROL + // Setup XOSC32K + OSC32KCTRL->INTFLAG.reg = OSC32KCTRL_INTFLAG_XOSC32KRDY | OSC32KCTRL_INTFLAG_XOSC32KFAIL; + OSC32KCTRL->XOSC32K.bit.CGM = OSC32KCTRL_XOSC32K_CGM_HS_Val; + OSC32KCTRL->XOSC32K.bit.XTALEN = 1; // 0: Generator 1: Crystal + OSC32KCTRL->XOSC32K.bit.EN32K = 1; + OSC32KCTRL->XOSC32K.bit.ONDEMAND = 0; + OSC32KCTRL->XOSC32K.bit.RUNSTDBY = 1; + OSC32KCTRL->XOSC32K.bit.STARTUP = 4; + OSC32KCTRL->CFDCTRL.bit.CFDEN = 1; // Fall back to internal Osc on crystal fail + OSC32KCTRL->XOSC32K.bit.ENABLE = 1; + // make sure osc32kcrtl is ready + while (OSC32KCTRL->STATUS.bit.XOSC32KRDY == 0) { + } + + // Setup GCLK1 for 32kHz crystal + GCLK->GENCTRL[1].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K; + while (GCLK->SYNCBUSY.bit.GENCTRL1) { + } + + // Set-up the DFLL48M in closed loop mode with input from the 32kHz crystal + + // Step 1: Peripheral channel 0 is driven by GCLK1 and it feeds DFLL48M + GCLK->PCHCTRL[0].reg = GCLK_PCHCTRL_GEN_GCLK1 | GCLK_PCHCTRL_CHEN; + while (GCLK->PCHCTRL[0].bit.CHEN == 0) { + } + // Step 2: Set the multiplication values. The offset of 16384 to the freq is for rounding. + OSCCTRL->DFLLMUL.reg = OSCCTRL_DFLLMUL_MUL((APB_FREQ + DPLLx_REF_FREQ / 2) / DPLLx_REF_FREQ) | + OSCCTRL_DFLLMUL_FSTEP(1) | OSCCTRL_DFLLMUL_CSTEP(1); + while (OSCCTRL->DFLLSYNC.bit.DFLLMUL == 1) { + } + // Step 3: Set the mode to closed loop + OSCCTRL->DFLLCTRLB.reg = OSCCTRL_DFLLCTRLB_BPLCKC | OSCCTRL_DFLLCTRLB_MODE; + while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) { + } + // Wait for lock fine + while (OSCCTRL->STATUS.bit.DFLLLCKF == 0) { + } + // Step 4: Start the DFLL. + OSCCTRL->DFLLCTRLA.reg = OSCCTRL_DFLLCTRLA_RUNSTDBY | OSCCTRL_DFLLCTRLA_ENABLE; + while (OSCCTRL->DFLLSYNC.bit.ENABLE == 1) { + } + + #else // MICROPY_HW_XOSC32K + + // Set GCLK1 to DPLL0_REF_FREQ as defined in mpconfigboard.h (e.g. 32768 Hz) + GCLK->GENCTRL[1].reg = ((APB_FREQ + DPLLx_REF_FREQ / 2) / DPLLx_REF_FREQ) << GCLK_GENCTRL_DIV_Pos + | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; + while (GCLK->SYNCBUSY.bit.GENCTRL1) { + } + + #endif // MICROPY_HW_XOSC32K + + // Peripheral channel 1 is driven by GCLK1 and it feeds DPLL0 + GCLK->PCHCTRL[1].reg = GCLK_PCHCTRL_GEN_GCLK1 | GCLK_PCHCTRL_CHEN; + while (GCLK->PCHCTRL[1].bit.CHEN == 0) { + } + + set_cpu_freq(cpu_freq); + + apb_freq = APB_FREQ; // To be changed if CPU_FREQ < 48M + + // Setup GCLK2 for DPLL1 output (48 MHz) + GCLK->GENCTRL[2].reg = GCLK_GENCTRL_DIV(1) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; + while (GCLK->SYNCBUSY.bit.GENCTRL2) { + } + + // Setup GCLK3 for 8MHz, Used for TC0/1 counter + GCLK->GENCTRL[3].reg = GCLK_GENCTRL_DIV(6) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; + while (GCLK->SYNCBUSY.bit.GENCTRL3) { + } + + #endif // defined(MCU_SAMD51) +} + +void enable_sercom_clock(int id) { + // Next: Set up the clocks + #if defined(MCU_SAMD21) + // Enable synchronous clock. The bits are nicely arranged + PM->APBCMASK.reg |= 0x04 << id; + // Select multiplexer generic clock source and enable. + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | sercom_gclk_id[id]; + // Wait while it updates synchronously. + while (GCLK->STATUS.bit.SYNCBUSY) { + } + #elif defined(MCU_SAMD51) + GCLK->PCHCTRL[sercom_gclk_id[id]].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK2; + // no easy way to set the clocks, except enabling all of them + switch (id) { + case 0: + MCLK->APBAMASK.bit.SERCOM0_ = 1; + break; + case 1: + MCLK->APBAMASK.bit.SERCOM1_ = 1; + break; + case 2: + MCLK->APBBMASK.bit.SERCOM2_ = 1; + break; + case 3: + MCLK->APBBMASK.bit.SERCOM3_ = 1; + break; + case 4: + MCLK->APBDMASK.bit.SERCOM4_ = 1; + break; + case 5: + MCLK->APBDMASK.bit.SERCOM5_ = 1; + break; + #ifdef SERCOM7_GCLK_ID_CORE + case 6: + MCLK->APBDMASK.bit.SERCOM6_ = 1; + break; + case 7: + MCLK->APBDMASK.bit.SERCOM7_ = 1; + break; + #endif + } + #endif +} diff --git a/ports/samd/clock_config.h b/ports/samd/clock_config.h new file mode 100644 index 0000000000..0e7a9e3280 --- /dev/null +++ b/ports/samd/clock_config.h @@ -0,0 +1,33 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * This file provides functions for configuring the clocks. + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Robert Hammelrath + * + * 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. + */ + +void init_clocks(uint32_t cpu_freq); +void set_cpu_freq(uint32_t cpu_freq); +uint32_t get_cpu_freq(void); +uint32_t get_apb_freq(void); +void enable_sercom_clock(int id); diff --git a/ports/samd/samd_soc.c b/ports/samd/samd_soc.c index 7a96cbb480..8d6e808f63 100644 --- a/ports/samd/samd_soc.c +++ b/ports/samd/samd_soc.c @@ -10,6 +10,7 @@ * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George + * Copyright (c) 2022 Robert Hammelrath * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,6 +34,7 @@ #include "py/runtime.h" #include "modmachine.h" #include "samd_soc.h" +#include "sam.h" #include "tusb.h" static void usb_init(void) { @@ -43,7 +45,7 @@ static void usb_init(void) { PM->APBBMASK.bit.USB_ = 1; uint8_t alt = 6; // alt G, USB #elif defined(MCU_SAMD51) - GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK1; + GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK2; while (GCLK->PCHCTRL[USB_GCLK_ID].bit.CHEN == 0) { } MCLK->AHBMASK.bit.USB_ = 1; @@ -61,43 +63,51 @@ static void usb_init(void) { tusb_init(); } -void samd_init(void) { +// Initialize the microsecond counter on TC 0/1 +void init_us_counter(void) { #if defined(MCU_SAMD21) - NVMCTRL->CTRLB.bit.MANW = 1; // errata "Spurious Writes" - NVMCTRL->CTRLB.bit.RWS = 1; // 1 read wait state for 48MHz - - // Enable DFLL48M - SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE; - while (!SYSCTRL->PCLKSR.bit.DFLLRDY) { - } - SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(1) | SYSCTRL_DFLLMUL_FSTEP(1) - | SYSCTRL_DFLLMUL_MUL(48000); - uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) - >> FUSES_DFLL48M_COARSE_CAL_Pos; - if (coarse == 0x3f) { - coarse = 0x1f; - } - uint32_t fine = 512; - SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(fine); - SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_USBCRM - | SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_ENABLE; - while (!SYSCTRL->PCLKSR.bit.DFLLRDY) { - } - - GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) | GCLK_GENDIV_DIV(1); - GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(0); + PM->APBCMASK.bit.TC3_ = 1; // Enable TC3 clock + PM->APBCMASK.bit.TC4_ = 1; // Enable TC4 clock + // Select multiplexer generic clock source and enable. + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK3 | GCLK_CLKCTRL_ID_TC4_TC5; + // Wait while it updates synchronously. while (GCLK->STATUS.bit.SYNCBUSY) { } + // configure the timer + TC4->COUNT32.CTRLA.bit.MODE = TC_CTRLA_MODE_COUNT32_Val; + TC4->COUNT32.CTRLA.bit.RUNSTDBY = 1; + TC4->COUNT32.CTRLA.bit.ENABLE = 1; + while (TC4->COUNT32.STATUS.bit.SYNCBUSY) { + } + TC4->COUNT32.READREQ.reg = TC_READREQ_RREQ | TC_READREQ_RCONT | 0x10; + while (TC4->COUNT32.STATUS.bit.SYNCBUSY) { + } + #elif defined(MCU_SAMD51) - GCLK->GENCTRL[1].reg = 1 << GCLK_GENCTRL_DIV_Pos | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; - while (GCLK->SYNCBUSY.bit.GENCTRL1) { + MCLK->APBAMASK.bit.TC0_ = 1; // Enable TC0 clock + MCLK->APBAMASK.bit.TC1_ = 1; // Enable TC1 clock + // Peripheral channel 9 is driven by GCLK3, 8 MHz. + GCLK->PCHCTRL[TC0_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK3 | GCLK_PCHCTRL_CHEN; + while (GCLK->PCHCTRL[TC0_GCLK_ID].bit.CHEN == 0) { + } + + // configure the timer + TC0->COUNT32.CTRLA.bit.PRESCALER = 0; + TC0->COUNT32.CTRLA.bit.MODE = TC_CTRLA_MODE_COUNT32_Val; + TC0->COUNT32.CTRLA.bit.RUNSTDBY = 1; + TC0->COUNT32.CTRLA.bit.ENABLE = 1; + while (TC0->COUNT32.SYNCBUSY.bit.ENABLE) { } #endif +} - SysTick_Config(CPU_FREQ / 1000); +void samd_init(void) { + init_clocks(get_cpu_freq()); + SysTick_Config(get_cpu_freq() / 1000); + init_us_counter(); usb_init(); } diff --git a/ports/samd/samd_soc.h b/ports/samd/samd_soc.h index a07e68dbed..b97159dc7f 100644 --- a/ports/samd/samd_soc.h +++ b/ports/samd/samd_soc.h @@ -28,6 +28,7 @@ #include #include "sam.h" +#include "clock_config.h" void samd_init(void); void samd_main(void); @@ -38,4 +39,14 @@ void USB_1_Handler_wrapper(void); void USB_2_Handler_wrapper(void); void USB_3_Handler_wrapper(void); +void common_uart_irq_handler(int uart_nr); +void common_spi_irq_handler(int spi_nr); +void common_i2c_irq_handler(int i2c_nr); +void sercom_enable(Sercom *spi, int state); +void sercom_register_irq(int sercom_id, int mode); + +#define SERCOM_IRQ_TYPE_UART (0) +#define SERCOM_IRQ_TYPE_SPI (1) +#define SERCOM_IRQ_TYPE_I2C (2) + #endif // MICROPY_INCLUDED_SAMD_SAMD_SOC_H From 5af54ad61feb52f4c1367d6f9a8a60d972f02419 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 4 Jun 2022 17:00:32 +0200 Subject: [PATCH 0478/1041] samd/modmachine: Allow changing the CPU freq with machine.freq(f). SAMD51 only. Accepted values are 48_000_000 to 200_000_000. The range specified by Atmel is 96_000_000 to 120_000_000. --- ports/samd/modmachine.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index 1b78b687e1..99fccf5bf0 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -59,10 +59,21 @@ STATIC mp_obj_t machine_bootloader(void) { } MP_DEFINE_CONST_FUN_OBJ_0(machine_bootloader_obj, machine_bootloader); -STATIC mp_obj_t machine_freq(void) { - return MP_OBJ_NEW_SMALL_INT(CPU_FREQ); +STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { + if (n_args == 0) { + return MP_OBJ_NEW_SMALL_INT(get_cpu_freq()); + } else { + #if defined(MCU_SAMD51) + uint32_t freq = mp_obj_get_int(args[0]); + if (freq >= 48000000 && freq <= 200000000) { + set_cpu_freq(freq); + SysTick_Config(freq / 1000); + } + #endif + return mp_const_none; + } } -MP_DEFINE_CONST_FUN_OBJ_0(machine_freq_obj, machine_freq); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 1, machine_freq); STATIC mp_obj_t machine_unique_id(void) { // Each device has a unique 128-bit serial number which is a concatenation of four 32-bit From 3d9940bc28e66464e22386916cb71100d6b24f1d Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 4 Jun 2022 18:09:11 +0200 Subject: [PATCH 0479/1041] samd/mphalport: Add pin open-drain funcs, and improve delay and ticks. The changes in this commit are: - Add an interface for pin open-drain mode. - Improve ticks_us() by using the us-counter. - Improve ticks_cpu() by using the CPU's SysTick. --- ports/samd/mphalport.c | 47 ++++++++++++++++++++++++++++-------- ports/samd/mphalport.h | 54 +++++++++++++++++++++++++++++++++++------- 2 files changed, 82 insertions(+), 19 deletions(-) diff --git a/ports/samd/mphalport.c b/ports/samd/mphalport.c index beade14a6e..e51f13ab7e 100644 --- a/ports/samd/mphalport.c +++ b/ports/samd/mphalport.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George + * Copyright (c) 2022 Robert Hammelrath * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,10 +28,13 @@ #include "py/runtime.h" #include "py/mphal.h" #include "py/stream.h" +#include "shared/runtime/interrupt_char.h" +#include "extmod/misc.h" #include "samd_soc.h" #include "tusb.h" #if MICROPY_KBD_EXCEPTION +int mp_interrupt_char = -1; void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { (void)itf; @@ -40,24 +44,47 @@ void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { } void mp_hal_set_interrupt_char(int c) { + mp_interrupt_char = c; tud_cdc_set_wanted_char(c); } #endif +void mp_hal_set_pin_mux(mp_hal_pin_obj_t pin, uint8_t mux) { + int pin_grp = pin / 32; + int port_grp = (pin % 32) / 2; + PORT->Group[pin_grp].PINCFG[pin % 32].bit.PMUXEN = 1; // Enable Mux + if (pin & 1) { + PORT->Group[pin_grp].PMUX[port_grp].bit.PMUXO = mux; + } else { + PORT->Group[pin_grp].PMUX[port_grp].bit.PMUXE = mux; + } +} + + void mp_hal_delay_ms(mp_uint_t ms) { - ms += 1; - uint32_t t0 = systick_ms; - while (systick_ms - t0 < ms) { - MICROPY_EVENT_POLL_HOOK + if (ms > 10) { + uint32_t t0 = systick_ms; + while (systick_ms - t0 < ms) { + MICROPY_EVENT_POLL_HOOK + } + } else { + mp_hal_delay_us(ms * 1000); } } void mp_hal_delay_us(mp_uint_t us) { - uint32_t ms = us / 1000 + 1; - uint32_t t0 = systick_ms; - while (systick_ms - t0 < ms) { - __WFI(); + if (us > 0) { + uint32_t start = mp_hal_ticks_us(); + #if defined(MCU_SAMD21) + // SAMD21 counter has effective 32 bit width + while ((mp_hal_ticks_us() - start) < us) { + } + #elif defined(MCU_SAMD51) + // SAMD51 counter has effective 29 bit width + while (((mp_hal_ticks_us() - start) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1)) < us) { + } + #endif } } @@ -78,7 +105,7 @@ int mp_hal_stdin_rx_chr(void) { return buf[0]; } } - __WFI(); + MICROPY_EVENT_POLL_HOOK } } @@ -90,7 +117,7 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { n = CFG_TUD_CDC_EP_BUFSIZE; } while (n > tud_cdc_write_available()) { - __WFI(); + MICROPY_EVENT_POLL_HOOK } uint32_t n2 = tud_cdc_write(str + i, n); tud_cdc_write_flush(); diff --git a/ports/samd/mphalport.h b/ports/samd/mphalport.h index 2bbde4390e..b18aa2f9b4 100644 --- a/ports/samd/mphalport.h +++ b/ports/samd/mphalport.h @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2019-2021 Damien P. George + * Copyright (c) 2022 Robert Hammelrath * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,25 +28,49 @@ #define MICROPY_INCLUDED_SAMD_MPHALPORT_H #include "py/mpconfig.h" -#include "py/ringbuf.h" // ASF4 #include "hal_gpio.h" +#include "hpl_time_measure.h" +#include "sam.h" extern int mp_interrupt_char; -extern ringbuf_t stdin_ringbuf; extern volatile uint32_t systick_ms; +extern volatile uint32_t systick_ms_upper; void mp_hal_set_interrupt_char(int c); +#define mp_hal_delay_us_fast mp_hal_delay_us + static inline mp_uint_t mp_hal_ticks_ms(void) { return systick_ms; } + static inline mp_uint_t mp_hal_ticks_us(void) { + #if defined(MCU_SAMD21) + + return REG_TC4_COUNT32_COUNT; + + #elif defined(MCU_SAMD51) + + TC0->COUNT32.CTRLBSET.reg = TC_CTRLBSET_CMD_READSYNC; + while (TC0->COUNT32.CTRLBSET.reg != 0) { + } + return REG_TC0_COUNT32_COUNT >> 3; + + #else return systick_ms * 1000; + #endif } + +// ticks_cpu is limited to a 1 ms period, since the CPU SysTick counter +// is used for the 1 ms SysTick_Handler interrupt. static inline mp_uint_t mp_hal_ticks_cpu(void) { - return 0; + return (system_time_t)SysTick->VAL; +} + +static inline uint64_t mp_hal_time_ns(void) { + return ((uint64_t)systick_ms + (uint64_t)systick_ms_upper * 0x100000000) * 1000000; } // C-level pin HAL @@ -55,9 +80,10 @@ static inline mp_uint_t mp_hal_ticks_cpu(void) { #define MP_HAL_PIN_FMT "%u" #define mp_hal_pin_obj_t uint -extern uint32_t machine_pin_open_drain_mask; +extern uint32_t machine_pin_open_drain_mask[]; mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t pin_in); +void mp_hal_set_pin_mux(mp_hal_pin_obj_t pin, uint8_t mux); static inline unsigned int mp_hal_pin_name(mp_hal_pin_obj_t pin) { return pin; @@ -65,18 +91,22 @@ static inline unsigned int mp_hal_pin_name(mp_hal_pin_obj_t pin) { static inline void mp_hal_pin_input(mp_hal_pin_obj_t pin) { gpio_set_pin_direction(pin, GPIO_DIRECTION_IN); - machine_pin_open_drain_mask &= ~(1 << pin); + machine_pin_open_drain_mask[pin / 32] &= ~(1 << (pin % 32)); } static inline void mp_hal_pin_output(mp_hal_pin_obj_t pin) { gpio_set_pin_direction(pin, GPIO_DIRECTION_OUT); - machine_pin_open_drain_mask &= ~(1 << pin); + machine_pin_open_drain_mask[pin / 32] &= ~(1 << (pin % 32)); } static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) { gpio_set_pin_direction(pin, GPIO_DIRECTION_IN); gpio_set_pin_level(pin, 0); - machine_pin_open_drain_mask |= 1 << pin; + machine_pin_open_drain_mask[pin / 32] |= 1 << (pin % 32); +} + +static inline unsigned int mp_hal_get_pin_direction(mp_hal_pin_obj_t pin) { + return (PORT->Group[pin / 32].DIR.reg & (1 << (pin % 32))) >> (pin % 32); } static inline int mp_hal_pin_read(mp_hal_pin_obj_t pin) { @@ -87,7 +117,14 @@ static inline void mp_hal_pin_write(mp_hal_pin_obj_t pin, int v) { gpio_set_pin_level(pin, v); } -/* +static inline void mp_hal_pin_low(mp_hal_pin_obj_t pin) { + gpio_set_pin_level(pin, 0); +} + +static inline void mp_hal_pin_high(mp_hal_pin_obj_t pin) { + gpio_set_pin_level(pin, 1); +} + static inline void mp_hal_pin_od_low(mp_hal_pin_obj_t pin) { gpio_set_pin_direction(pin, GPIO_DIRECTION_OUT); } @@ -95,6 +132,5 @@ static inline void mp_hal_pin_od_low(mp_hal_pin_obj_t pin) { static inline void mp_hal_pin_od_high(mp_hal_pin_obj_t pin) { gpio_set_pin_direction(pin, GPIO_DIRECTION_IN); } -*/ #endif // MICROPY_INCLUDED_SAMD_MPHALPORT_H From 98ae3126402260eab306e846d01d12af317d96a2 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 4 Jun 2022 20:23:56 +0200 Subject: [PATCH 0480/1041] samd/samd_isr: Extend systick_ms to 64 bit. By adding a 32 bit overflow counter. This allows it to be used for the time functions. --- ports/samd/samd_isr.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ports/samd/samd_isr.c b/ports/samd/samd_isr.c index dcf80d28ca..a7956c4930 100644 --- a/ports/samd/samd_isr.c +++ b/ports/samd/samd_isr.c @@ -32,6 +32,7 @@ extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss; const ISR isr_vector[]; uint32_t systick_ms; +volatile uint32_t systick_ms_upper; void Reset_Handler(void) __attribute__((naked)); void Reset_Handler(void) { @@ -81,7 +82,11 @@ void Default_Handler(void) { } void SysTick_Handler(void) { - systick_ms += 1; + uint32_t next_tick = systick_ms + 1; + systick_ms = next_tick; + if (systick_ms == 0) { + systick_ms_upper += 1; + } } const ISR isr_vector[] __attribute__((section(".isr_vector"))) = { From 33eaf739d2e0502ec77bdd212dfb6a3106db30b8 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 4 Jun 2022 20:33:48 +0200 Subject: [PATCH 0481/1041] samd/machine_pin: Add OPEN_DRAIN mode for pins. Changes in this commit are: - Use mphal_xx functions whenever possible. - Remove obsolete includes. - Clean up traces of a non-functional pin.irq() from earlier builds. Pin.irq() will be added in further commits in a working manner. --- ports/samd/machine_pin.c | 124 +++++++++++++++------------------------ ports/samd/mphalport.h | 4 +- 2 files changed, 50 insertions(+), 78 deletions(-) diff --git a/ports/samd/machine_pin.c b/ports/samd/machine_pin.c index 5f9cbfb99b..49aecba011 100644 --- a/ports/samd/machine_pin.c +++ b/ports/samd/machine_pin.c @@ -31,35 +31,25 @@ #include "extmod/virtpin.h" #include "modmachine.h" #include "samd_soc.h" -#include "pins.h" // boards// +#include "pins.h" -// ASF4 (MCU package specific pin defs in 'boards') #include "hal_gpio.h" -#include "hpl_gpio.h" -#include "hal_atomic.h" #define GPIO_MODE_IN (0) #define GPIO_MODE_OUT (1) -// #define GPIO_MODE_ALT (3) +#define GPIO_MODE_OPEN_DRAIN (2) #define GPIO_STRENGTH_2MA (0) #define GPIO_STRENGTH_8MA (1) -// asf4 hpl_gpio.h gpio_pull_mode +uint32_t machine_pin_open_drain_mask[4]; -/* -typedef struct _machine_pin_irq_obj_t { - mp_irq_obj_t base; - uint32_t flags; - uint32_t trigger; -} machine_pin_irq_obj_t; - -STATIC const mp_irq_methods_t machine_pin_irq_methods; -*/ +// Open drain behaviour is simulated. +#define GPIO_IS_OPEN_DRAIN(id) (machine_pin_open_drain_mask[id / 32] & (1 << (id % 32))) STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_pin_obj_t *self = self_in; - mp_printf(print, "Pin(%u)", self->id); + mp_printf(print, "GPIO P%c%02u", "ABCD"[self->id / 32], self->id % 32); } STATIC void pin_validate_drive(bool strength) { @@ -84,24 +74,26 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_ // set initial value (do this before configuring mode/pull) if (args[ARG_value].u_obj != mp_const_none) { - gpio_set_pin_level(self->id, mp_obj_is_true(args[ARG_value].u_obj)); + mp_hal_pin_write(self->id, mp_obj_is_true(args[ARG_value].u_obj)); } // configure mode if (args[ARG_mode].u_obj != mp_const_none) { mp_int_t mode = mp_obj_get_int(args[ARG_mode].u_obj); if (mode == GPIO_MODE_IN) { - gpio_set_pin_direction(self->id, GPIO_DIRECTION_IN); + mp_hal_pin_input(self->id); } else if (mode == GPIO_MODE_OUT) { - gpio_set_pin_direction(self->id, GPIO_DIRECTION_OUT); + mp_hal_pin_output(self->id); + } else if (mode == GPIO_MODE_OPEN_DRAIN) { + mp_hal_pin_open_drain(self->id); } else { - gpio_set_pin_direction(self->id, GPIO_DIRECTION_IN); // If no args are given, the Pin is 'input'. + mp_hal_pin_input(self->id); // If no args are given, the Pin is 'input'. } } // configure pull. Only to be used with IN mode. The function sets the pin to INPUT. uint32_t pull = 0; - mp_int_t mode = mp_obj_get_int(args[ARG_mode].u_obj); - if (mode == GPIO_MODE_OUT && args[ARG_pull].u_obj != mp_const_none) { + mp_int_t dir = mp_hal_get_pin_direction(self->id); + if (dir == GPIO_DIRECTION_OUT && args[ARG_pull].u_obj != mp_const_none) { mp_raise_ValueError(MP_ERROR_TEXT("OUT incompatible with pull")); } else if (args[ARG_pull].u_obj != mp_const_none) { pull = mp_obj_get_int(args[ARG_pull].u_obj); @@ -143,17 +135,24 @@ mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, } // fast method for getting/setting pin value -STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); machine_pin_obj_t *self = self_in; if (n_args == 0) { // get pin - return MP_OBJ_NEW_SMALL_INT(gpio_get_pin_level(self->id)); + return MP_OBJ_NEW_SMALL_INT(mp_hal_pin_read(self->id)); } else { // set pin bool value = mp_obj_is_true(args[0]); - gpio_set_pin_level(self->id, value); - + if (GPIO_IS_OPEN_DRAIN(self->id)) { + if (value == 0) { + mp_hal_pin_od_low(self->id); + } else { + mp_hal_pin_od_high(self->id); + } + } else { + mp_hal_pin_write(self->id, value); + } return mp_const_none; } } @@ -165,7 +164,7 @@ STATIC mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init); // Pin.value([value]) -STATIC mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) { +mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) { return machine_pin_call(args[0], n_args - 1, 0, args + 1); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value); @@ -181,9 +180,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_disable_obj, machine_pin_disable); // Pin.low() Totem-pole (push-pull) STATIC mp_obj_t machine_pin_low(mp_obj_t self_in) { machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); - gpio_set_pin_direction(self->id, GPIO_DIRECTION_OUT); - gpio_set_pin_level(self->id, false); - + if (GPIO_IS_OPEN_DRAIN(self->id)) { + mp_hal_pin_od_low(self->id); + } else { + mp_hal_pin_low(self->id); + } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_low_obj, machine_pin_low); @@ -191,9 +192,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_low_obj, machine_pin_low); // Pin.high() Totem-pole (push-pull) STATIC mp_obj_t machine_pin_high(mp_obj_t self_in) { machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); - gpio_set_pin_direction(self->id, GPIO_DIRECTION_OUT); - gpio_set_pin_level(self->id, true); - + if (GPIO_IS_OPEN_DRAIN(self->id)) { + mp_hal_pin_od_high(self->id); + } else { + mp_hal_pin_high(self->id); + } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_high_obj, machine_pin_high); @@ -205,18 +208,18 @@ STATIC mp_obj_t machine_pin_toggle(mp_obj_t self_in) { // Determine DIRECTION of PIN. bool pin_dir; - pin_dir = (PORT->Group[(enum gpio_port)GPIO_PORT(self->id)].DIR.reg // Get PORT# - & (1 << GPIO_PIN(self->id))) // Isolate the Pin in question - >> GPIO_PIN(self->id); // Shift to LSB for binary result. - - if (pin_dir) { - // Pin is OUTPUT - gpio_set_pin_direction(self->id, GPIO_DIRECTION_OUT); - gpio_toggle_pin_level(self->id); + if (GPIO_IS_OPEN_DRAIN(self->id)) { + pin_dir = mp_hal_get_pin_direction(self->id); + if (pin_dir) { + // Pin is output, thus low, switch to high + mp_hal_pin_od_high(self->id); + } else { + mp_hal_pin_od_low(self->id); + } } else { - mp_raise_ValueError(MP_ERROR_TEXT("Cannot TOGGLE INPUT pin!\n")); + gpio_toggle_pin_level(self->id); } - return mp_const_true; + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_toggle_obj, machine_pin_toggle); @@ -250,20 +253,15 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&machine_pin_disable_obj) }, { MP_ROM_QSTR(MP_QSTR_drive), MP_ROM_PTR(&machine_pin_drive_obj) }, - - // { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_pin_irq_obj) }, - // class constants { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_IN) }, { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_OUT) }, - // { MP_ROM_QSTR(MP_QSTR_ALT), MP_ROM_INT(GPIO_MODE_ALT) }, + { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_OPEN_DRAIN) }, { MP_ROM_QSTR(MP_QSTR_PULL_OFF), MP_ROM_INT(GPIO_PULL_OFF) }, { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULL_UP) }, { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULL_DOWN) }, { MP_ROM_QSTR(MP_QSTR_LOW_POWER), MP_ROM_INT(GPIO_STRENGTH_2MA) }, { MP_ROM_QSTR(MP_QSTR_HIGH_POWER), MP_ROM_INT(GPIO_STRENGTH_8MA) }, - // { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_IRQ_EDGE_RISE) }, - // { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_IRQ_EDGE_FALL) }, }; STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table); @@ -298,34 +296,6 @@ MP_DEFINE_CONST_OBJ_TYPE( locals_dict, &machine_pin_locals_dict ); -/* -STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { - machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); - machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_obj[self->id]); - gpio_set_irq_enabled(self->id, GPIO_IRQ_ALL, false); - irq->flags = 0; - irq->trigger = new_trigger; - gpio_set_irq_enabled(self->id, new_trigger, true); - return 0; -} - -STATIC mp_uint_t machine_pin_irq_info(mp_obj_t self_in, mp_uint_t info_type) { - machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); - machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_obj[self->id]); - if (info_type == MP_IRQ_INFO_FLAGS) { - return irq->flags; - } else if (info_type == MP_IRQ_INFO_TRIGGERS) { - return irq->trigger; - } - return 0; -} - -STATIC const mp_irq_methods_t machine_pin_irq_methods = { - .trigger = machine_pin_irq_trigger, - .info = machine_pin_irq_info, -}; -*/ - mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t obj) { if (!mp_obj_is_type(obj, &machine_pin_type)) { mp_raise_ValueError(MP_ERROR_TEXT("expecting a Pin")); diff --git a/ports/samd/mphalport.h b/ports/samd/mphalport.h index b18aa2f9b4..0a1db7df0c 100644 --- a/ports/samd/mphalport.h +++ b/ports/samd/mphalport.h @@ -101,7 +101,7 @@ static inline void mp_hal_pin_output(mp_hal_pin_obj_t pin) { static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) { gpio_set_pin_direction(pin, GPIO_DIRECTION_IN); - gpio_set_pin_level(pin, 0); + gpio_set_pin_pull_mode(pin, GPIO_PULL_UP); machine_pin_open_drain_mask[pin / 32] |= 1 << (pin % 32); } @@ -127,10 +127,12 @@ static inline void mp_hal_pin_high(mp_hal_pin_obj_t pin) { static inline void mp_hal_pin_od_low(mp_hal_pin_obj_t pin) { gpio_set_pin_direction(pin, GPIO_DIRECTION_OUT); + gpio_set_pin_level(pin, 0); } static inline void mp_hal_pin_od_high(mp_hal_pin_obj_t pin) { gpio_set_pin_direction(pin, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(pin, GPIO_PULL_UP); } #endif // MICROPY_INCLUDED_SAMD_MPHALPORT_H From e8615f5813855a3f839714fb62c7d8a5e0082072 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 4 Jun 2022 20:56:18 +0200 Subject: [PATCH 0482/1041] samd/machine_pin: Allow specifying a pin or LED by its name as a string. The names are defined in pins.csv. --- ports/samd/boards/make-pins.py | 10 ++++++---- ports/samd/machine_led.c | 6 ++---- ports/samd/machine_pin.c | 23 ++++++++++++++++++++++- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/ports/samd/boards/make-pins.py b/ports/samd/boards/make-pins.py index 400a9c9b88..2b62ba7c59 100644 --- a/ports/samd/boards/make-pins.py +++ b/ports/samd/boards/make-pins.py @@ -15,6 +15,8 @@ typedef struct _machine_pin_obj_t { char *name; } machine_pin_obj_t; +int pin_find(mp_obj_t pin, const machine_pin_obj_t machine_pin_obj[], int table_size); + """ led_header_prefix = """typedef struct _machine_led_obj_t { @@ -33,19 +35,19 @@ class Pins: def parse_csv_file(self, filename): with open(filename, "r") as csvfile: - rows = csv.reader(csvfile) + rows = csv.reader(csvfile, skipinitialspace=True) for row in rows: # Pin numbers must start with "PIN_" # LED numbers must start with "LED_" if len(row) > 0: - if row[0].strip().startswith("PIN_"): + if row[0].startswith("PIN_"): if len(row) == 1: self.board_pins.append([row[0], row[0][4:]]) else: self.board_pins.append([row[0], row[1]]) - elif row[0].strip().startswith("LED_"): + elif row[0].startswith("LED_"): self.board_leds.append(["PIN_" + row[0][4:], row[1]]) - elif row[0].strip().startswith("-"): + elif row[0].startswith("-"): self.board_pins.append(["-1", ""]) def print_pins(self, pins_filename): diff --git a/ports/samd/machine_led.c b/ports/samd/machine_led.c index 03b47e7cf2..9c15769581 100644 --- a/ports/samd/machine_led.c +++ b/ports/samd/machine_led.c @@ -30,12 +30,10 @@ #include "py/mphal.h" #include "extmod/virtpin.h" #include "modmachine.h" -#include "pins.h" // boards// +#include "pins.h" // ASF4 (MCU package specific pin defs in 'boards') #include "hal_gpio.h" -#include "hpl_gpio.h" -#include "hal_atomic.h" STATIC void machine_led_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_led_obj_t *self = self_in; @@ -70,7 +68,7 @@ mp_obj_t mp_led_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // get the wanted LED object - int wanted_led = mp_obj_get_int(args[0]); + int wanted_led = pin_find(args[0], (const machine_pin_obj_t *)machine_led_obj, MP_ARRAY_SIZE(machine_led_obj)); const machine_led_obj_t *self = NULL; if (0 <= wanted_led && wanted_led < MP_ARRAY_SIZE(machine_led_obj)) { self = (machine_led_obj_t *)&machine_led_obj[wanted_led]; diff --git a/ports/samd/machine_pin.c b/ports/samd/machine_pin.c index 49aecba011..98317abbf2 100644 --- a/ports/samd/machine_pin.c +++ b/ports/samd/machine_pin.c @@ -26,6 +26,7 @@ * Uses pins.h & pins.c to create board (MCU package) specific 'machine_pin_obj' array. */ +#include "string.h" #include "py/runtime.h" #include "py/mphal.h" #include "extmod/virtpin.h" @@ -58,6 +59,26 @@ STATIC void pin_validate_drive(bool strength) { } } +int pin_find(mp_obj_t pin, const machine_pin_obj_t machine_pin_obj[], int table_size) { + int wanted_pin = -1; + if (mp_obj_is_small_int(pin)) { + // Pin defined by the index of pin table + wanted_pin = mp_obj_get_int(pin); + } else if (mp_obj_is_str(pin)) { + // Search by name + size_t slen; + const char *s = mp_obj_str_get_data(pin, &slen); + for (wanted_pin = 0; wanted_pin < table_size; wanted_pin++) { + if (slen == strlen(machine_pin_obj[wanted_pin].name) && + strncmp(s, machine_pin_obj[wanted_pin].name, slen) == 0) { + break; + } + } + } + return wanted_pin; +} + + // Pin.init(mode, pull=None, *, value=None, drive=0). No 'alt' yet. STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_pull, ARG_value, ARG_drive, ARG_alt }; @@ -112,7 +133,7 @@ mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // get the wanted pin object - int wanted_pin = mp_obj_get_int(args[0]); + int wanted_pin = pin_find(args[0], machine_pin_obj, MP_ARRAY_SIZE(machine_pin_obj)); const machine_pin_obj_t *self = NULL; if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj)) { From 4013577af2f530599db80a6696c23be2ed335bee Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 4 Jun 2022 21:26:45 +0200 Subject: [PATCH 0483/1041] samd/modmachine: Enable SoftSPI and SoftI2C. --- ports/samd/Makefile | 1 + ports/samd/modmachine.c | 4 ++++ ports/samd/mpconfigport.h | 2 ++ 3 files changed, 7 insertions(+) diff --git a/ports/samd/Makefile b/ports/samd/Makefile index e3316a9d6c..ea71973bd7 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -110,6 +110,7 @@ SRC_C = \ lib/tinyusb/src/device/usbd_control.c \ lib/tinyusb/src/portable/microchip/samd/dcd_samd.c \ lib/tinyusb/src/tusb.c \ + drivers/bus/softspi.c \ shared/libc/printf.c \ shared/libc/string0.c \ shared/readline/readline.c \ diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index 99fccf5bf0..b095a6b39d 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -28,6 +28,8 @@ #include "extmod/machine_mem.h" #include "samd_soc.h" #include "modmachine.h" +#include "extmod/machine_i2c.h" +#include "extmod/machine_spi.h" // ASF 4 #include "hal_flash.h" @@ -129,6 +131,8 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&machine_led_type) }, + { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index c29043c5d0..6441818ba2 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -97,6 +97,8 @@ #define MICROPY_PY_URANDOM (1) #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_UASYNCIO (1) +#define MICROPY_PY_MACHINE_SOFTI2C (1) +#define MICROPY_PY_MACHINE_SOFTSPI (1) #define MP_STATE_PORT MP_STATE_VM From 6c037af086acd90755f93cd323a5114984885449 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 5 Jun 2022 08:55:27 +0200 Subject: [PATCH 0484/1041] samd/boards: Create pin_af_table.c from pin_af_table_SAMDxx.csv files. This step just creates the table. The firmware cannot be built at this commit. The next commit will complete the pin-af mechanism. --- ports/samd/Makefile | 23 ++++- ports/samd/boards/make-pin-af.py | 104 ++++++++++++++++++++ ports/samd/boards/pin-af-table-SAMD21.csv | 65 +++++++++++++ ports/samd/boards/pin-af-table-SAMD51.csv | 113 ++++++++++++++++++++++ 4 files changed, 300 insertions(+), 5 deletions(-) create mode 100644 ports/samd/boards/make-pin-af.py create mode 100644 ports/samd/boards/pin-af-table-SAMD21.csv create mode 100644 ports/samd/boards/pin-af-table-SAMD51.csv diff --git a/ports/samd/Makefile b/ports/samd/Makefile index ea71973bd7..1556d81617 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -45,12 +45,22 @@ INC += -I$(TOP)/lib/asf4/$(MCU_SERIES_LOWER)/include INC += -I$(TOP)/lib/asf4/$(MCU_SERIES_LOWER)/include/pio INC += -I$(TOP)/lib/tinyusb/src +MAKE_PIN_AF = boards/make-pin-af.py +PIN_AF_TABLE_CSV = boards/pin-af-table-$(MCU_SERIES).csv +GEN_PIN_AF = pin_af_table.c + +MAKE_PINS = boards/make-pins.py +BOARD_PINS = $(BOARD_DIR)/pins.csv +GEN_PINS_SRC = $(BUILD)/pins.c +GEN_PINS_HDR = $(BUILD)/pins.h + CFLAGS_MCU_SAMD21 = -mtune=cortex-m0plus -mcpu=cortex-m0plus -msoft-float CFLAGS_MCU_SAMD51 = -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib -mthumb $(CFLAGS_MCU_$(MCU_SERIES)) -fsingle-precision-constant -Wdouble-promotion CFLAGS += -DMCU_$(MCU_SERIES) -D__$(CMSIS_MCU)__ CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) CFLAGS += -DMPCONFIG_MCU_H='' +CFLAGS += -DPIN_AF_TABLE_C='<$(BUILD)/$(GEN_PIN_AF)>' QSTR_GLOBAL_DEPENDENCIES += boards/mpconfig_$(MCU_SERIES_LOWER).h @@ -59,11 +69,6 @@ LDFLAGS += $(LDFLAGS_MOD) LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) -MAKE_PINS = boards/make-pins.py -BOARD_PINS = $(BOARD_DIR)/pins.csv -GEN_PINS_SRC = $(BUILD)/pins.c -GEN_PINS_HDR = $(BUILD)/pins.h - # Tune for Debugging or Optimization CFLAGS += -g # always include debug info in the ELF ifeq ($(DEBUG),1) @@ -92,6 +97,7 @@ SRC_C = \ modmachine.c \ modsamd.c \ mphalport.c \ + pin_af.c \ $(BUILD)/pins.c \ samd_flash.c \ samd_isr.c \ @@ -170,6 +176,13 @@ $(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(BUILD)/firmware.uf2: $(BUILD)/firmware.bin $(Q)$(PYTHON) $(UF2CONV) -b $(TEXT0) -c -o $@ $< +pin_af.c: $(BUILD)/$(GEN_PIN_AF) + +$(BUILD)/$(GEN_PIN_AF): $(PIN_AF_TABLE_CSV) + $(ECHO) "Create $@" + $(Q)$(PYTHON) $(MAKE_PIN_AF) --csv $(PIN_AF_TABLE_CSV) --table $(BUILD)/$(GEN_PIN_AF) --mcu $(MCU_SERIES) + + $(GEN_PINS_SRC): $(BOARD_PINS) $(ECHO) "Create $@" $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --pins $(GEN_PINS_SRC) --inc $(GEN_PINS_HDR) diff --git a/ports/samd/boards/make-pin-af.py b/ports/samd/boards/make-pin-af.py new file mode 100644 index 0000000000..d895ef9dd9 --- /dev/null +++ b/ports/samd/boards/make-pin-af.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python +"""Generates the pin_cap table file for the SAMD port.""" + +from __future__ import print_function + +import argparse +import sys +import csv + +table_header = """// This file was automatically generated by make-pin-cap.py +// + +""" + + +class Pins: + def __init__(self): + self.board_pins = [] # list of pin objects + + def parse_csv_file(self, filename): + with open(filename, "r") as csvfile: + rows = csv.reader(csvfile) + for row in rows: + # Pin numbers must start with "PA", "PB", "PC" or "PD" + if len(row) > 0 and row[0].strip().upper()[:2] in ("PA", "PB", "PC", "PD"): + self.board_pins.append(row) + + def print_table(self, table_filename, mcu_name): + with open(table_filename, "wt") as table_file: + table_file.write(table_header) + table_file.write("const pin_af_t pin_af_table[] = {\n") + if mcu_name == "SAMD21": + for row in self.board_pins: + pin = "PIN_" + row[0].upper() + table_file.write(" #ifdef " + pin + "\n") + eic = row[1] if row[1] else "0xff" + adc = row[2] if row[2] else "0xff" + table_file.write(" {%s, %s, %s" % (pin, eic, adc)) + for cell in row[3:]: + if cell: + table_file.write( + ", 0x%s" % cell if len(cell) == 2 else ", 0x0%s" % cell + ) + else: + table_file.write(", 0xff") + table_file.write("},\n") + table_file.write(" #endif\n") + else: + for row in self.board_pins: + pin = "PIN_" + row[0].upper() + table_file.write(" #ifdef " + pin + "\n") + eic = row[1] if row[1] else "0xff" + adc0 = row[2] if row[2] else "0xff" + adc1 = row[3] if row[3] else "0xff" + table_file.write(" {%s, %s, %s, %s" % (pin, eic, adc0, adc1)) + for cell in row[4:]: + if cell: + table_file.write( + ", 0x%s" % cell if len(cell) == 2 else ", 0x0%s" % cell + ) + else: + table_file.write(", 0xff") + table_file.write("},\n") + table_file.write(" #endif\n") + table_file.write("};\n") + + +def main(): + parser = argparse.ArgumentParser( + prog="make-pin-cap.py", + usage="%(prog)s [options] [command]", + description="Generate MCU-specific pin cap table file", + ) + parser.add_argument( + "-c", + "--csv", + dest="csv_filename", + help="Specifies the pin-mux-xxxx.csv filename", + ) + parser.add_argument( + "-t", + "--table", + dest="table_filename", + help="Specifies the name of the generated pin cap table file", + ) + parser.add_argument( + "-m", + "--mcu", + dest="mcu_name", + help="Specifies type of the MCU (SAMD21 or SAMD51)", + ) + args = parser.parse_args(sys.argv[1:]) + + pins = Pins() + + if args.csv_filename: + pins.parse_csv_file(args.csv_filename) + + if args.table_filename: + pins.print_table(args.table_filename, args.mcu_name) + + +if __name__ == "__main__": + main() diff --git a/ports/samd/boards/pin-af-table-SAMD21.csv b/ports/samd/boards/pin-af-table-SAMD21.csv new file mode 100644 index 0000000000..d8ab903c9e --- /dev/null +++ b/ports/samd/boards/pin-af-table-SAMD21.csv @@ -0,0 +1,65 @@ +# The pin_cap_tables contain the information anbout pin mux set and pad +# for some of the peripheral devices with many possible assignments. +# The pin_cap_table is a subset from table 7-1 of the data sheet. +# It contain the information about pin mux set and pad +# The eic and adc columns contain the decimal numer for the respecitive +# quantity, the columns for sercom, tc and tcc have in each cell +# the device number in the upper nibble, and the pad number in the lower +# nibble. If a signal is not available, the cell in the csv table is left empty. +# The first column is the pin id, not the number of the board pin. +# Rows not starting with pa, pb, pc or pd are ignored. +# When editing the table with a spread sheet, take care to import the data as text. +# +# Pin,EIC,ADC,SERCOM1,SERCOM2,TC,TCC +pa00,0,,,10,20, +pa01,1,,,11,21, +pa02,2,0,,,, +pa03,3,1,,,, +pb04,4,12,,,, +pb05,5,13,,,, +pb06,6,14,,,, +pb07,7,15,,,, +pb08,8,2,,40,40, +pb09,9,3,,41,41, +pa04,4,4,,00,00, +pa05,5,5,,01,01, +pa06,6,6,,02,10, +pa07,7,7,,03,11, +pa08,,16,00,20,00,12 +pa09,9,17,01,21,01,13 +pa10,10,18,02,22,10,02 +pa11,11,19,03,23,11,03 +pb10,10,,,42,50,04 +pb11,11,,,43,51,05 +pb12,12,,40,,40,06 +pb13,13,,41,,41,07 +pb14,14,,42,,50, +pb15,15,,43,,51, +pa12,12,,20,40,20,06 +pa13,13,,21,41,20,07 +pa14,14,,22,42,30,04 +pa15,15,,23,43,31,05 +pa16,0,,10,30,20,06 +pa17,1,,11,31,21,07 +pa18,2,,12,32,30,02 +pa19,3,,13,33,31,03 +pb16,9,,50,,60,04 +pb17,1,,51,,61,05 +pa20,4,,52,32,70,04 +pa21,5,,53,33,71,07 +pa22,6,,30,50,40,04 +pa23,7,,31,51,41,05 +pa24,12,,32,52,50,12 +pa25,13,,33,53,51,13 +pb22,6,,,52,70, +pb23,7,,,53,71, +pa27,15,,,,, +pa28,8,,,,, +pa30,10,,,12,10, +pa31,11,,,13,11, +pb30,14,,,50,00,12 +pb31,15,,,51,01,13 +pb00,0,,,52,70, +pb01,1,,,53,71, +pb02,2,,,50,60, +pb03,3,,,51,61, diff --git a/ports/samd/boards/pin-af-table-SAMD51.csv b/ports/samd/boards/pin-af-table-SAMD51.csv new file mode 100644 index 0000000000..70a009ba52 --- /dev/null +++ b/ports/samd/boards/pin-af-table-SAMD51.csv @@ -0,0 +1,113 @@ +# The pin_cap_table is a subset from table 6-1 of the data sheet. +# It contain the information about pin mux set and pad +# for some of the peripheral devices with many possible assignments. +# The colums represent the peripheral class, as defined in pin_cap_t. The +# column number is equivalent to the mux class. +# The eic and adc columns contain the decimal numer for the respecitive +# quantity, the columns for sercom, tc and tcc have in each cell +# the device number in the first, and the pad number in the second +# digit. If a signal is not available, the cell in the csv table is left empty. +# The first column is the pin id, not the number of the board pin. +# Rows not starting with pa, pb, pc or pd are ignored. +# When editing the table with a spread sheet, take care to import the data as text. +# +# Pin,EIC,ADC0,ADC1,SERCOM1,SERCOM2,TC,TCC1,TCC2 +pb03,9,15,,,51,61,, +pa00,0,,,,10,20,, +pa01,1,,,,11,21,, +pc00,0,,10,,,,, +pc01,1,,11,,,,, +pc02,2,,4,,,,, +pc03,3,,5,,,,, +pa02,2,0,,,,,, +pa03,3,10,,,,,, +pb04,4,,6,,,,, +pb05,5,,7,,,,, +pd00,0,,14,,,,, +pd01,1,,15,,,,, +pb06,6,,8,,,,, +pb07,7,,9,,,,, +pb08,8,2,0,,40,40,, +pb09,9,3,1,,41,41,, +pa04,4,4,,,00,00,, +pa05,5,5,,,01,01,, +pa06,6,6,,,02,10,, +pa07,7,7,,,03,11,, +pc04,4,,,60,,,00, +pc05,5,,,61,,,, +pc06,6,,,62,,,, +pc07,9,,,63,,,, +pa08,,8,2,00,21,00,00,14 +pa09,9,9,3,01,20,01,01,15 +pa10,10,10,,02,22,10,02,16 +pa11,11,11,,03,23,11,03,17 +pb10,10,,,,42,50,04,10 +pb11,12,,,,43,51,05,11 +pb12,12,,,40,,40,30,00 +pb13,13,,,41,,41,31,01 +pb14,14,,,42,,50,40,02 +pb15,15,,,43,,51,41,03 +pd08,3,,,70,61,,01, +pd09,4,,,71,60,,02, +pd10,5,,,72,62,,03, +pd11,6,,,73,63,,04, +pd12,7,,,,,,05, +pc10,10,,,62,72,,00,14 +pc11,11,,,63,73,,01,15 +pc12,12,,,70,61,,02,16 +pc13,13,,,71,60,,03,17 +pc14,14,,,72,62,,04,10 +pc15,15,,,73,63,,05,11 +pa12,12,,,20,41,20,06,12 +pa13,13,,,21,40,21,07,13 +pa14,14,,,22,42,30,20,12 +pa15,15,,,23,43,31,21,13 +pa16,0,,,10,31,20,10,04 +pa17,1,,,11,30,21,11,05 +pa18,2,,,12,32,30,12,06 +pa19,3,,,13,33,31,13,07 +pc16,0,,,60,01,,00, +pc17,1,,,61,00,,01, +pc18,2,,,62,02,,02, +pc19,3,,,63,03,,03, +pc20,4,,,,,,04, +pc21,5,,,,,,05, +pc22,6,,,10,31,,05, +pc23,7,,,11,30,,07, +pd20,10,,,12,32,,10, +pd21,11,,,13,33,,11, +pb16,0,,,50,,60,30,04 +pb17,1,,,51,,61,31,05 +pb18,2,,,52,72,,10, +pb19,3,,,53,73,,11, +pb20,4,,,30,71,,12, +pb21,5,,,31,70,,13, +pa20,4,,,52,32,70,14,00 +pa21,5,,,53,33,71,15,01 +pa22,6,,,30,51,40,16,02 +pa23,7,,,31,50,41,17,03 +pa24,8,,,32,52,50,22, +pa25,9,,,33,53,51,, +pb22,22,,,12,52,70,, +pb23,7,,,13,53,71,, +pb24,8,,,00,21,,, +pb25,9,,,01,20,,, +pb26,12,,,20,41,,12, +pb27,13,,,21,40,,13, +pb28,14,,,22,42,,14, +pb29,15,,,23,43,,15, +pc24,8,,,02,22,,, +pc25,9,,,03,23,,, +pc26,10,,,,,,, +pc27,11,,,10,,,, +pc28,12,,,11,,,, +pa27,11,,,,,,, +pa30,14,,,72,12,60,20, +pa31,15,,,73,13,61,21, +pb30,14,,,70,51,00,40,06 +pb31,15,,,71,50,01,41,07 +pc30,14,,12,,,,, +pc31,15,,13,,,,, +pb00,9,12,,,52,70,, +pb01,1,13,,,53,71,, +pb02,2,14,,,50,60,22, From 6765d4bbd66c19898158504ed8102ebd8de4c645 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 5 Jun 2022 09:26:49 +0200 Subject: [PATCH 0485/1041] samd/pin_af: Add the pin af table and its helper functions. The pin af table is a representation of the MUX table from the data sheet. It provides information for each pin about the supported device functions. That information is needed by pin.irq, machine.ADC, machine.PWM, machine.UART, machine.SPI and machine.I2C. For each of these, the table tells for each pin, which device number, af number and pad number is assigned. Using the table gives a straight, uniform access to the information, where the benefit outweights the size of the table, which is not that large. The tables are MCU-specific. It is not required to tell for each board, which and where each of the above devices is available. That makes addding boards easy. Note: The information for DAC and I2S was not included, since it affects only a few pins. --- ports/samd/pin_af.c | 125 ++++++++++++++++++++++++++++++++++++++++++++ ports/samd/pin_af.h | 90 +++++++++++++++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 ports/samd/pin_af.c create mode 100644 ports/samd/pin_af.h diff --git a/ports/samd/pin_af.c b/ports/samd/pin_af.c new file mode 100644 index 0000000000..8c152e0d8b --- /dev/null +++ b/ports/samd/pin_af.c @@ -0,0 +1,125 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Robert Hammelrath + * + * 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. + * + * This file provides and checks pin capabilities as required + * for USART, I2C, SPI, PWM, ADC + * + */ + +#include + +#include "py/runtime.h" +#include "py/misc.h" +#include "pin_af.h" +#include "sam.h" + + +extern const uint8_t tcc_channel_count[]; + +#include PIN_AF_TABLE_C + +// Just look for an table entry for a given pin and raise an error +// in case of no match (which should not happen). + +const pin_af_t *get_pin_af_info(int pin_id) { + for (int i = 0; i < MP_ARRAY_SIZE(pin_af_table); i++) { + if (pin_af_table[i].pin_id == pin_id) { // Pin match + return &pin_af_table[i]; + } + } + mp_raise_ValueError(MP_ERROR_TEXT("wrong pin")); +} + +// Test, wether the given pin is defined and has signals for sercom. +// If that applies return the alt_fct and pad_nr. +// If not, an error will be raised. + +sercom_pad_config_t get_sercom_config(int pin_id, uint8_t sercom_nr) { + const pin_af_t *pct_ptr = get_pin_af_info(pin_id); + if ((pct_ptr->sercom1 >> 4) == sercom_nr) { + return (sercom_pad_config_t) {ALT_FCT_SERCOM1, pct_ptr->sercom1 & 0x0f}; + } else if ((pct_ptr->sercom2 >> 4) == sercom_nr) { + return (sercom_pad_config_t) {ALT_FCT_SERCOM2, pct_ptr->sercom2 & 0x0f}; + } else { + mp_raise_ValueError(MP_ERROR_TEXT("wrong serial device")); + } +} + +// Test, wether the given pin is defined as ADC. +// If that applies return the adc instance and channel. +// If not, an error will be raised. + +adc_config_t get_adc_config(int pin_id, int32_t flag) { + const pin_af_t *pct_ptr = get_pin_af_info(pin_id); + if (pct_ptr->adc0 != 0xff && (flag & (1 << pct_ptr->adc0)) == 0) { + return (adc_config_t) {0, pct_ptr->adc0}; + #if defined(MUC_SAMD51) + } else if (pct_ptr->adc1 != 0xff && (flag & (1 << (pct_ptr->adc1 + 16))) == 0) { + return (adc_config_t) {1, pct_ptr->adc1}; + #endif + } else { + mp_raise_ValueError(MP_ERROR_TEXT("ADC pin used")); + } +} + +// Test, wether the given pin is defined and has signals for pwm. +// If that applies return the alt_fct, tcc number and channel number. +// If not, an error will be raised. +// The function either supplies a channel from a wanted device, or +// tries to provide an unused device, if available. + +pwm_config_t get_pwm_config(int pin_id, int wanted_dev, uint8_t device_status[]) { + const pin_af_t *pct_ptr = get_pin_af_info(pin_id); + uint8_t tcc1 = pct_ptr->tcc1; + uint8_t tcc2 = pct_ptr->tcc2; + + if (wanted_dev != -1) { + if ((tcc1 >> 4) == wanted_dev) { + return (pwm_config_t) {ALT_FCT_TCC1, tcc1}; + } else if ((tcc2 >> 4) == wanted_dev) { + return (pwm_config_t) {ALT_FCT_TCC2, tcc2}; + } else { + mp_raise_ValueError(MP_ERROR_TEXT("wrong device or channel")); + } + } else { + pwm_config_t ret = {}; + if ((tcc1 >> 4) < TCC_INST_NUM) { + ret = (pwm_config_t) {ALT_FCT_TCC1, tcc1}; + if (tcc2 == 0xff) { + return ret; + } + } + if ((tcc2 >> 4) < TCC_INST_NUM) { + // if a device in slot 1 is not available or already in use, use the one in slot 2 + if (tcc1 == 0xff || device_status[(ret.device_channel >> 4)] != 0) { + return (pwm_config_t) {ALT_FCT_TCC2, tcc2}; + } else { + return ret; + } + } else { + mp_raise_ValueError(MP_ERROR_TEXT("not a PWM pin")); + } + } +} diff --git a/ports/samd/pin_af.h b/ports/samd/pin_af.h new file mode 100644 index 0000000000..f9dec6b7da --- /dev/null +++ b/ports/samd/pin_af.h @@ -0,0 +1,90 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Robert Hammelrath + * + * 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. + * + * This file initialises provides and checks pin capabilities as required + * for USART, I2C, SPI, PWM, ADC + * + */ + +#if defined(MCU_SAMD21) + +typedef struct { + uint8_t pin_id; + uint8_t eic; + uint8_t adc0; + uint8_t sercom1; + uint8_t sercom2; + uint8_t tcc1; + uint8_t tcc2; +} pin_af_t; + +#define ALT_FCT_TC 4 +#define ALT_FCT_TCC1 4 +#define ALT_FCT_TCC2 5 + +#elif defined(MCU_SAMD51) + +typedef struct { + uint8_t pin_id; + uint8_t eic; + uint8_t adc0; + uint8_t adc1; + uint8_t sercom1; + uint8_t sercom2; + uint8_t tc; + uint8_t tcc1; + uint8_t tcc2; +} pin_af_t; + +#define ALT_FCT_TC 4 +#define ALT_FCT_TCC1 5 +#define ALT_FCT_TCC2 6 + +#endif + +typedef struct _sercom_pad_config_t { + uint8_t alt_fct; + uint8_t pad_nr; +} sercom_pad_config_t; + +typedef struct _adc_config_t { + uint8_t device; + uint8_t channel; +} adc_config_t; + +typedef struct _pwm_config_t { + uint8_t alt_fct; + uint8_t device_channel; +} pwm_config_t; + +#define ALT_FCT_EIC 0 +#define ALT_FCT_ADC 1 +#define ALT_FCT_SERCOM1 2 +#define ALT_FCT_SERCOM2 3 + +sercom_pad_config_t get_sercom_config(int pin_id, uint8_t sercom); +adc_config_t get_adc_config(int pin_id, int32_t flag); +pwm_config_t get_pwm_config(int pin_id, int wanted_dev, uint8_t used_dev[]); +const pin_af_t *get_pin_af_info(int pin_id); From 5c7e93ec48b04a6a049cc7f2ec90230cd64ecba2 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 5 Jun 2022 10:34:23 +0200 Subject: [PATCH 0486/1041] samd/machine_adc: Add the machine.ADC class. With the method read_u16(). Keyword arguments of the constructor are: - bits=n The resolution; default is 12. - average=n The average of samples, which are taken and cumulated. The default value is 16. Averaging by hw is faster than averaging in code. The ADC runs at a clock freq 1.5 MHz. A single 12 bit conversion takes 8 microseconds. --- ports/samd/Makefile | 2 + ports/samd/machine_adc.c | 238 +++++++++++++++++++++++++++++++++++++++ ports/samd/main.c | 2 + ports/samd/modmachine.c | 4 +- ports/samd/modmachine.h | 3 +- 5 files changed, 247 insertions(+), 2 deletions(-) create mode 100644 ports/samd/machine_adc.c diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 1556d81617..910ecdac31 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -90,6 +90,7 @@ endif SRC_C = \ clock_config.c \ help.c \ + machine_adc.c \ machine_led.c \ machine_pin.c \ main.c \ @@ -138,6 +139,7 @@ endif # List of sources for qstr extraction SRC_QSTR += \ + machine_adc.c \ machine_led.c \ machine_pin.c \ modutime.c \ diff --git a/ports/samd/machine_adc.c b/ports/samd/machine_adc.c new file mode 100644 index 0000000000..97b6a14f17 --- /dev/null +++ b/ports/samd/machine_adc.c @@ -0,0 +1,238 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Philipp Ebensberger + * Copyright (c) 2022 Robert Hammelrath + * + * 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 +#include "py/obj.h" +#include "py/runtime.h" +#include "py/mphal.h" + +#include "sam.h" +#include "pin_af.h" +#include "modmachine.h" + +typedef struct _machine_adc_obj_t { + mp_obj_base_t base; + adc_config_t adc_config; + uint8_t id; + uint8_t avg; + uint8_t bits; +} machine_adc_obj_t; + +#define DEFAULT_ADC_BITS 12 +#define DEFAULT_ADC_AVG 16 + +Adc *const adc_bases[] = ADC_INSTS; +uint32_t busy_flags = 0; +bool init_flags[2] = {false, false}; +static void adc_init(machine_adc_obj_t *self); +static uint8_t resolution[] = { + ADC_CTRLB_RESSEL_8BIT_Val, ADC_CTRLB_RESSEL_10BIT_Val, ADC_CTRLB_RESSEL_12BIT_Val +}; + +// Calculate the floor value of log2(n) +mp_int_t log2i(mp_int_t num) { + mp_int_t res = 0; + for (; num > 1; num >>= 1) { + res += 1; + } + return res; +} + +STATIC void adc_obj_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { + (void)kind; + machine_adc_obj_t *self = MP_OBJ_TO_PTR(o); + + mp_printf(print, "ADC(P%c%02u, ADC%u, channel=%u, bits=%u, average=%u)", + "ABCD"[self->id / 32], self->id % 32, self->adc_config.device, + self->adc_config.channel, self->bits, 1 << self->avg); +} + +STATIC mp_obj_t adc_obj_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_bits, ARG_average }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_bits, MP_ARG_INT, {.u_int = DEFAULT_ADC_BITS} }, + { MP_QSTR_average, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_ADC_AVG} }, + }; + + // Parse the arguments. + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // Unpack and check, whther the pin has ADC capability + int id = mp_hal_get_pin_obj(args[ARG_id].u_obj); + adc_config_t adc_config = get_adc_config(id, busy_flags); + + // Now that we have a valid device and channel, create and populate the ADC instance + machine_adc_obj_t *self = mp_obj_malloc(machine_adc_obj_t, &machine_adc_type); + self->id = id; + self->adc_config = adc_config; + self->bits = DEFAULT_ADC_BITS; + uint16_t bits = args[ARG_bits].u_int; + if (bits >= 8 && bits <= 12) { + self->bits = bits; + } + uint32_t avg = log2i(args[ARG_average].u_int); + self->avg = (avg <= 10 ? avg : 10); + + // flag the device/channel as being in use. + busy_flags |= (1 << (self->adc_config.device * 16 + self->adc_config.channel)); + + adc_init(self); + + return MP_OBJ_FROM_PTR(self); +} + +// read_u16() +STATIC mp_obj_t machine_adc_read_u16(mp_obj_t self_in) { + machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in); + Adc *adc = adc_bases[self->adc_config.device]; + // Set Input channel and resolution + // Select the pin as positive input and gnd as negative input reference, non-diff mode by default + adc->INPUTCTRL.reg = ADC_INPUTCTRL_MUXNEG_GND | self->adc_config.channel; + // set resolution. Scale 8-16 to 0 - 4 for table access. + adc->CTRLB.bit.RESSEL = resolution[(self->bits - 8) / 2]; + // Measure input voltage + adc->SWTRIG.bit.START = 1; + while (adc->INTFLAG.bit.RESRDY == 0) { + } + // Get and return the result + return MP_OBJ_NEW_SMALL_INT(adc->RESULT.reg * (65536 / (1 << self->bits))); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_u16_obj, machine_adc_read_u16); + +// deinit() : release the ADC channel +STATIC mp_obj_t machine_adc_deinit(mp_obj_t self_in) { + machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in); + + busy_flags &= ~((1 << (self->adc_config.device * 16 + self->adc_config.channel))); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_deinit_obj, machine_adc_deinit); + +void adc_deinit_all(void) { + busy_flags = 0; + init_flags[0] = 0; + init_flags[1] = 0; +} + +STATIC const mp_rom_map_elem_t adc_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read_u16), MP_ROM_PTR(&machine_adc_read_u16_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_adc_deinit_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + machine_adc_type, + MP_QSTR_ADC, + MP_TYPE_FLAG_NONE, + make_new, adc_obj_make_new, + print, adc_obj_print, + locals_dict, &adc_locals_dict + ); + +static void adc_init(machine_adc_obj_t *self) { + // ADC & clock init is done only once per ADC + if (init_flags[self->adc_config.device] == false) { + Adc *adc = adc_bases[self->adc_config.device]; + + init_flags[self->adc_config.device] = true; + + #if defined(MCU_SAMD21) + // Configuration SAMD21 + // Enable APBD clocks and PCHCTRL clocks; GCLK2 at 48 MHz + PM->APBCMASK.reg |= PM_APBCMASK_ADC; + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | GCLK_CLKCTRL_ID_ADC; + while (GCLK->STATUS.bit.SYNCBUSY) { + } + // Reset ADC registers + adc->CTRLA.bit.SWRST = 1; + while (adc->CTRLA.bit.SWRST) { + } + // Get the calibration data + uint32_t bias = (*((uint32_t *)ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos; + uint32_t linearity = (*((uint32_t *)ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos; + linearity |= ((*((uint32_t *)ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5; + /* Write the calibration data. */ + ADC->CALIB.reg = ADC_CALIB_BIAS_CAL(bias) | ADC_CALIB_LINEARITY_CAL(linearity); + // Divide 48MHz clock by 32 to obtain 1.5 MHz clock to adc + adc->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV32; + // Select external AREFA as reference voltage. + adc->REFCTRL.reg = ADC_REFCTRL_REFSEL_AREFA; + // Average: Accumulate samples and scale them down accordingly + adc->AVGCTRL.reg = self->avg | ADC_AVGCTRL_ADJRES(self->avg); + // Enable ADC and wait to be ready + adc->CTRLA.bit.ENABLE = 1; + while (adc->STATUS.bit.SYNCBUSY) { + } + + #elif defined(MCU_SAMD51) + // Configuration SAMD51 + // Enable APBD clocks and PCHCTRL clocks; GCLK2 at 48 MHz + if (self->adc_config.device == 0) { + GCLK->PCHCTRL[ADC0_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK2 | GCLK_PCHCTRL_CHEN; + MCLK->APBDMASK.bit.ADC0_ = 1; + } else { + GCLK->PCHCTRL[ADC1_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK2 | GCLK_PCHCTRL_CHEN; + MCLK->APBDMASK.bit.ADC1_ = 1; + } + // Reset ADC registers + adc->CTRLA.bit.SWRST = 1; + while (adc->CTRLA.bit.SWRST) { + } + // Get the calibration data + uint32_t biascomp; + uint32_t biasr2r; + uint32_t biasrefbuf; + if (self->adc_config.device == 0) { + biascomp = (*((uint32_t *)ADC0_FUSES_BIASCOMP_ADDR) & ADC0_FUSES_BIASCOMP_Msk) >> ADC0_FUSES_BIASCOMP_Pos; + biasr2r = (*((uint32_t *)ADC0_FUSES_BIASR2R_ADDR) & ADC0_FUSES_BIASR2R_Msk) >> ADC0_FUSES_BIASR2R_Pos; + biasrefbuf = (*((uint32_t *)ADC0_FUSES_BIASREFBUF_ADDR) & ADC0_FUSES_BIASREFBUF_Msk) >> ADC0_FUSES_BIASREFBUF_Pos; + } else { + biascomp = (*((uint32_t *)ADC1_FUSES_BIASCOMP_ADDR) & ADC1_FUSES_BIASCOMP_Msk) >> ADC1_FUSES_BIASCOMP_Pos; + biasr2r = (*((uint32_t *)ADC1_FUSES_BIASR2R_ADDR) & ADC1_FUSES_BIASR2R_Msk) >> ADC1_FUSES_BIASR2R_Pos; + biasrefbuf = (*((uint32_t *)ADC1_FUSES_BIASREFBUF_ADDR) & ADC1_FUSES_BIASREFBUF_Msk) >> ADC1_FUSES_BIASREFBUF_Pos; + } + /* Write the calibration data. */ + adc->CALIB.reg = ADC_CALIB_BIASCOMP(biascomp) | ADC_CALIB_BIASR2R(biasr2r) | ADC_CALIB_BIASREFBUF(biasrefbuf); + // Divide 48MHz clock by 32 to obtain 1.5 MHz clock to adc + adc->CTRLA.reg = ADC_CTRLA_PRESCALER_DIV32; + // Select external AREFA as reference voltage. + adc->REFCTRL.reg = ADC_REFCTRL_REFSEL_AREFA; + // Average: Accumulate samples and scale them down accordingly + adc->AVGCTRL.reg = self->avg | ADC_AVGCTRL_ADJRES(self->avg); + // Enable ADC and wait to be ready + adc->CTRLA.bit.ENABLE = 1; + while (adc->SYNCBUSY.bit.ENABLE) { + } + + #endif + } + // Set the port as given in self->id as ADC + mp_hal_set_pin_mux(self->id, ALT_FCT_ADC); +} diff --git a/ports/samd/main.c b/ports/samd/main.c index d8c1c596c5..ece86f5889 100644 --- a/ports/samd/main.c +++ b/ports/samd/main.c @@ -33,6 +33,7 @@ #include "shared/runtime/pyexec.h" extern uint8_t _sstack, _estack, _sheap, _eheap; +extern void adc_deinit_all(void); void samd_main(void) { mp_stack_set_top(&_estack); @@ -62,6 +63,7 @@ void samd_main(void) { } mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n"); + adc_deinit_all(); gc_sweep_all(); mp_deinit(); } diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index b095a6b39d..287641cc33 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -129,8 +129,10 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, - { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, + + { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&machine_led_type) }, + { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, }; diff --git a/ports/samd/modmachine.h b/ports/samd/modmachine.h index f7ad2b5e5c..53914a10c7 100644 --- a/ports/samd/modmachine.h +++ b/ports/samd/modmachine.h @@ -28,7 +28,8 @@ #include "py/obj.h" -extern const mp_obj_type_t machine_pin_type; +extern const mp_obj_type_t machine_adc_type; extern const mp_obj_type_t machine_led_type; +extern const mp_obj_type_t machine_pin_type; #endif // MICROPY_INCLUDED_SAMD_MODMACHINE_H From d693758ab28a6b25601f019db78c7f9bc213be38 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 5 Jun 2022 11:03:59 +0200 Subject: [PATCH 0487/1041] samd/machine_pwm: Add the machine.PWM class. Features are: - 3 to 5 different frequency groups. - Freq range of 1Hz - 24 MHz. - Duty rate stays stable on freq change. Keyword options to the PWM constructor: - device=n Select a specific PWM device. If no device is specified, a free device is chosen, if available at that pin. - freq=nnnn - duty_u16=nnnn - duty_ns=nnnn - invert=True/False Allowing two outputs on the same device/channel to have complementary signals. If both freq and duty are provided, PWM output will start immediately. Pins at the same device have the same frequency. If the PWM output number exceeds the number of channels at the PWM device, the effctive channel_no is output_no % channel_count. So with a channel count of 4, output 7 is assigned to channel 3. Pins at a certain channel have the same frequency and duty rate, but may be seperately inverted. --- ports/samd/Makefile | 1 + ports/samd/machine_pwm.c | 362 ++++++++++++++++++++++++++++++++++++++ ports/samd/main.c | 2 + ports/samd/modmachine.c | 1 + ports/samd/modmachine.h | 1 + ports/samd/mpconfigport.h | 4 + ports/samd/mphalport.c | 4 + ports/samd/mphalport.h | 1 + 8 files changed, 376 insertions(+) create mode 100644 ports/samd/machine_pwm.c diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 910ecdac31..514c92ba1b 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -142,6 +142,7 @@ SRC_QSTR += \ machine_adc.c \ machine_led.c \ machine_pin.c \ + machine_pwm.c \ modutime.c \ modmachine.c \ modsamd.c \ diff --git a/ports/samd/machine_pwm.c b/ports/samd/machine_pwm.c new file mode 100644 index 0000000000..6f9ca42b1b --- /dev/null +++ b/ports/samd/machine_pwm.c @@ -0,0 +1,362 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 Damien P. George + * Copyright (c) 2022 Robert Hammelrath + * + * 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/mphal.h" +#include "modmachine.h" + +#include "sam.h" +#include "pin_af.h" + +/******************************************************************************/ +// MicroPython bindings for machine.PWM + +typedef struct _machine_pwm_obj_t { + mp_obj_base_t base; + Tcc *instance; + uint8_t pin_id; + uint8_t alt_fct; + uint8_t device; + uint8_t channel; + uint8_t output; + uint16_t prescaler; + uint32_t period; // full period count ticks +} machine_pwm_obj_t; + +#define PWM_NOT_INIT (0) +#define PWM_CLK_READY (1) +#define PWM_TCC_ENABLED (2) +#define PWM_MASTER_CLK (48000000) +#define PWM_FULL_SCALE (65536) + +static Tcc *tcc_instance[] = TCC_INSTS; + +#if defined(MCU_SAMD21) + +static const int tcc_gclk_id[] = { + GCLK_CLKCTRL_ID_TCC0_TCC1, GCLK_CLKCTRL_ID_TCC0_TCC1, GCLK_CLKCTRL_ID_TCC2_TC3 +}; +const uint8_t tcc_channel_count[] = {4, 2, 2}; +const static uint8_t tcc_channel_offset[] = {0, 4, 6}; +static uint32_t pwm_duty_values[8]; + +#define PERBUF PERB +#define CCBUF CCB + +#elif defined(MCU_SAMD51) + +static const int tcc_gclk_id[] = { + TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, + #if TCC_INST_NUM > 3 + TCC3_GCLK_ID, TCC4_GCLK_ID + #endif +}; + +#if TCC_INST_NUM > 3 +const uint8_t tcc_channel_count[] = {6, 4, 3, 2, 2}; +const static uint8_t tcc_channel_offset[] = {0, 6, 10, 13, 15}; +static uint32_t pwm_duty_values[17]; +#else +const uint8_t tcc_channel_count[] = {6, 4, 3}; +const static uint8_t tcc_channel_offset[] = {0, 6, 10}; +static uint32_t pwm_duty_values[13]; +#endif // TCC_INST_NUM > 3 + +#endif // defined(MCU_SAMD51) + +#define put_duty_value(device, channel, duty) \ + pwm_duty_values[tcc_channel_offset[device] + channel] = duty; + +#define get_duty_value(device, channel) \ + pwm_duty_values[tcc_channel_offset[device] + channel] + +static uint8_t duty_type_flags[TCC_INST_NUM]; +static uint8_t device_status[TCC_INST_NUM]; +static uint8_t output_active[TCC_INST_NUM]; +const uint16_t prescaler_table[] = {1, 2, 4, 8, 16, 64, 256, 1024}; + +STATIC void pwm_stop_device(int device); +STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq); +STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16); +STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns); + +STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "PWM P%c%02u device=%u channel=%u output=%u", + "ABCD"[self->pin_id / 32], self->pin_id % 32, self->device, self->channel, self->output); +} + +// PWM(pin) +STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_pin, ARG_freq, ARG_duty_u16, ARG_duty_ns, ARG_invert, ARG_device }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_freq, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_duty_u16, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_duty_ns, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_device, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + }; + + // Parse the arguments. + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // Get GPIO and optional device to connect to PWM. + uint32_t pin_id = mp_hal_get_pin_obj(args[ARG_pin].u_obj); + int32_t wanted_dev = args[ARG_device].u_int; // -1 = any + + // Get the peripheral object and populate it + + pwm_config_t config = get_pwm_config(pin_id, wanted_dev, device_status); + uint8_t device = config.device_channel >> 4; + if (device >= TCC_INST_NUM) { + mp_raise_ValueError(MP_ERROR_TEXT("wrong device")); + } + + machine_pwm_obj_t *self = mp_obj_malloc(machine_pwm_obj_t, &machine_pwm_type); + self->instance = tcc_instance[device]; + self->device = device; + self->pin_id = pin_id; + self->alt_fct = config.alt_fct; + self->channel = (config.device_channel & 0x0f) % tcc_channel_count[device]; + self->output = config.device_channel & 0x0f; + self->prescaler = 1; + self->period = 1; // Use an invalid but safe value + put_duty_value(self->device, self->channel, 0); + + Tcc *tcc = self->instance; + + if (device_status[device] == PWM_NOT_INIT) { + // Enable the device clock at first use. + #if defined(MCU_SAMD21) + // Enable synchronous clock. The bits are nicely arranged + PM->APBCMASK.reg |= PM_APBCMASK_TCC0 << device; + // Select multiplexer generic clock source and enable. + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | tcc_gclk_id[device]; + // Wait while it updates synchronously. + while (GCLK->STATUS.bit.SYNCBUSY) { + } + #elif defined(MCU_SAMD51) + // GenClk2 to the tcc + GCLK->PCHCTRL[tcc_gclk_id[device]].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(2); + while (GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL_GCLK2) { + } + // Enable MCLK + switch (device) { + case 0: + MCLK->APBBMASK.reg |= MCLK_APBBMASK_TCC0; + break; + case 1: + MCLK->APBBMASK.reg |= MCLK_APBBMASK_TCC1; + break; + case 2: + MCLK->APBCMASK.reg |= MCLK_APBCMASK_TCC2; + break; + #if TCC_INST_NUM > 3 + case 3: + MCLK->APBCMASK.reg |= MCLK_APBCMASK_TCC3; + break; + case 4: + MCLK->APBDMASK.reg |= MCLK_APBDMASK_TCC4; + break; + #endif + } + #endif + // Reset the device + tcc->CTRLA.reg = TCC_CTRLA_SWRST; + while (tcc->SYNCBUSY.reg & TCC_SYNCBUSY_SWRST) { + } + tcc->CTRLA.reg = TCC_CTRLA_PRESCALER_DIV1; + tcc->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; + // Flag the clock as initialized, but not the device as enabled. + device_status[device] = PWM_CLK_READY; + } + + if (args[ARG_invert].u_int != -1) { + bool invert = !!args[ARG_invert].u_int; + if (device_status[device] != PWM_CLK_READY) { + pwm_stop_device(device); + } + uint32_t mask = 1 << (self->output + TCC_DRVCTRL_INVEN0_Pos); + if (invert) { + tcc->DRVCTRL.reg |= mask; + } else { + tcc->DRVCTRL.reg &= ~(mask); + } + } + if (args[ARG_duty_u16].u_int != -1) { + mp_machine_pwm_duty_set_u16(self, args[ARG_duty_u16].u_int); + } + if (args[ARG_duty_ns].u_int != -1) { + mp_machine_pwm_duty_set_ns(self, args[ARG_duty_ns].u_int); + } + if (args[ARG_freq].u_int != -1) { + mp_machine_pwm_freq_set(self, args[ARG_freq].u_int); + } + return MP_OBJ_FROM_PTR(self); +} + +STATIC void pwm_stop_device(int device) { + Tcc *tcc = tcc_instance[device]; + tcc->CTRLA.bit.ENABLE = 0; + while (tcc->SYNCBUSY.reg & TCC_SYNCBUSY_ENABLE) { + } + device_status[device] = PWM_CLK_READY; +} + +// Stop all TTC devices +void pwm_deinit_all(void) { + for (int i = 0; i < TCC_INST_NUM; i++) { + Tcc *tcc = tcc_instance[i]; + tcc->CTRLA.reg = TCC_CTRLA_SWRST; + while (tcc->SYNCBUSY.reg & TCC_SYNCBUSY_SWRST) { + } + device_status[i] = PWM_NOT_INIT; + duty_type_flags[i] = 0; + output_active[i] = 0; + } +} + +// Switch off an output. If all outputs of a device are off, +// switch off that device. +// This stops all channels, but keeps the configuration +// Calling pwm.freq(n) will start an instance again. +STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self) { + mp_hal_clr_pin_mux(self->pin_id); // Switch the output off + output_active[self->device] &= ~(1 << self->output); // clear output flasg + // Stop the device, if no output is active. + if (output_active[self->device] == 0) { + pwm_stop_device(self->device); + } +} + +STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) { + return MP_OBJ_NEW_SMALL_INT(PWM_MASTER_CLK / self->prescaler / self->period); +} + +STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) { + // Set the frequency. The period counter is 24 bit or 16 bit with a pre-scaling + // of up to 1024, allowing a range from 24 MHz down to 1 Hz. + static const uint32_t max_period[5] = {1 << 24, 1 << 24, 1 << 16, 1 << 16, 1 << 16}; + + Tcc *tcc = self->instance; + if (freq < 1) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid freq")); + } + + // Get the actual settings of prescaler & period from the unit + // To be able for cope for changes. + uint32_t prev_period = tcc->PER.reg + 1; + + // Check for the right prescaler + uint8_t index; + for (index = 0; index < 8; index++) { + uint32_t temp = PWM_MASTER_CLK / prescaler_table[index] / freq; + if (temp < max_period[self->device]) { + break; + } + } + self->prescaler = prescaler_table[index]; + + uint32_t period = PWM_MASTER_CLK / self->prescaler / freq; + if (period < 2) { + mp_raise_ValueError(MP_ERROR_TEXT("freq too large")); + } + // Check, if the prescaler has to be changed and stop the device if so. + if (index != tcc->CTRLA.bit.PRESCALER) { + // stop the device + pwm_stop_device(self->device); + // update the prescaler + tcc->CTRLA.bit.PRESCALER = index; + } + // Lock the update to get a glitch-free change of period and duty cycle + tcc->CTRLBSET.reg = TCC_CTRLBSET_LUPD; + tcc->PERBUF.reg = period - 1; + self->period = period; + + // Check if the Duty rate has to be aligned again when freq or prescaler were changed. + // This condition is as well true on first call after instantiation. So (re-)configure + // all channels with a duty_u16 setting. + if (period != prev_period) { + for (uint16_t ch = 0; ch < tcc_channel_count[self->device]; ch++) { + if ((duty_type_flags[self->device] & (1 << ch)) != 0) { // duty_u16 type? + tcc->CCBUF[ch].reg = (uint64_t)get_duty_value(self->device, ch) * period / + PWM_FULL_SCALE; + } + } + } + // If the prescaler was changed, the device is disabled. So this condition is true + // after the instantiation and after a prescaler change. + // (re-)configure all channels with a duty_ns setting. + if (!(tcc->CTRLA.reg & TCC_CTRLA_ENABLE)) { + for (uint16_t ch = 0; ch < tcc_channel_count[self->device]; ch++) { + if ((duty_type_flags[self->device] & (1 << ch)) == 0) { // duty_ns type? + tcc->CCBUF[ch].reg = (uint64_t)get_duty_value(self->device, ch) * PWM_MASTER_CLK / + self->prescaler / 1000000000ULL; + } + } + } + // Remember the output as active. + output_active[self->device] |= 1 << self->output; // set output flag + // (Re-)Select PWM function for given GPIO. + mp_hal_set_pin_mux(self->pin_id, self->alt_fct); + // Enable the device, if required. + if ((device_status[self->device] & PWM_TCC_ENABLED) == 0) { + tcc->CTRLBSET.reg = TCC_CTRLBSET_CMD_UPDATE; + tcc->CTRLA.reg |= TCC_CTRLA_ENABLE; + while (tcc->SYNCBUSY.reg & TCC_SYNCBUSY_ENABLE) { + } + device_status[self->device] |= PWM_TCC_ENABLED; + } + // Unlock the register update, now that the settings are complete + tcc->CTRLBCLR.reg = TCC_CTRLBCLR_LUPD; +} + +STATIC mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self) { + return MP_OBJ_NEW_SMALL_INT(self->instance->CC[self->channel].reg * PWM_FULL_SCALE / (self->instance->PER.reg + 1)); +} + +STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16) { + put_duty_value(self->device, self->channel, duty_u16); + // If the device is enabled, than the period is set and we get a reasonable value for + // the duty cycle, set to the CCBUF register. Otherwise, PWM does not start. + if (self->instance->CTRLA.reg & TCC_CTRLA_ENABLE) { + self->instance->CCBUF[self->channel].reg = (uint64_t)duty_u16 * (self->instance->PER.reg + 1) / PWM_FULL_SCALE; + } + duty_type_flags[self->device] |= 1 << self->channel; +} + +STATIC mp_obj_t mp_machine_pwm_duty_get_ns(machine_pwm_obj_t *self) { + return MP_OBJ_NEW_SMALL_INT(1000000000ULL * self->instance->CC[self->channel].reg * self->prescaler / PWM_MASTER_CLK); +} + +STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns) { + put_duty_value(self->device, self->channel, duty_ns); + self->instance->CCBUF[self->channel].reg = (uint64_t)duty_ns * PWM_MASTER_CLK / self->prescaler / 1000000000ULL; + duty_type_flags[self->device] &= ~(1 << self->channel); +} diff --git a/ports/samd/main.c b/ports/samd/main.c index ece86f5889..4af4b2b4f8 100644 --- a/ports/samd/main.c +++ b/ports/samd/main.c @@ -34,6 +34,7 @@ extern uint8_t _sstack, _estack, _sheap, _eheap; extern void adc_deinit_all(void); +extern void pwm_deinit_all(void); void samd_main(void) { mp_stack_set_top(&_estack); @@ -64,6 +65,7 @@ void samd_main(void) { mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n"); adc_deinit_all(); + pwm_deinit_all(); gc_sweep_all(); mp_deinit(); } diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index 287641cc33..e0a0378461 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -133,6 +133,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&machine_led_type) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, + { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, }; diff --git a/ports/samd/modmachine.h b/ports/samd/modmachine.h index 53914a10c7..00e72ede1a 100644 --- a/ports/samd/modmachine.h +++ b/ports/samd/modmachine.h @@ -31,5 +31,6 @@ extern const mp_obj_type_t machine_adc_type; extern const mp_obj_type_t machine_led_type; extern const mp_obj_type_t machine_pin_type; +extern const mp_obj_type_t machine_pwm_type; #endif // MICROPY_INCLUDED_SAMD_MODMACHINE_H diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 6441818ba2..70bd202a31 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -99,6 +99,10 @@ #define MICROPY_PY_UASYNCIO (1) #define MICROPY_PY_MACHINE_SOFTI2C (1) #define MICROPY_PY_MACHINE_SOFTSPI (1) +#define MICROPY_PY_MACHINE_PWM (1) +#define MICROPY_PY_MACHINE_PWM_INIT (0) +#define MICROPY_PY_MACHINE_PWM_DUTY_U16_NS (1) +#define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/samd/machine_pwm.c" #define MP_STATE_PORT MP_STATE_VM diff --git a/ports/samd/mphalport.c b/ports/samd/mphalport.c index e51f13ab7e..7a3786be8c 100644 --- a/ports/samd/mphalport.c +++ b/ports/samd/mphalport.c @@ -61,6 +61,10 @@ void mp_hal_set_pin_mux(mp_hal_pin_obj_t pin, uint8_t mux) { } } +void mp_hal_clr_pin_mux(mp_hal_pin_obj_t pin) { + int pin_grp = pin / 32; + PORT->Group[pin_grp].PINCFG[pin % 32].bit.PMUXEN = 0; // Disable Mux +} void mp_hal_delay_ms(mp_uint_t ms) { if (ms > 10) { diff --git a/ports/samd/mphalport.h b/ports/samd/mphalport.h index 0a1db7df0c..6161d9821f 100644 --- a/ports/samd/mphalport.h +++ b/ports/samd/mphalport.h @@ -84,6 +84,7 @@ extern uint32_t machine_pin_open_drain_mask[]; mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t pin_in); void mp_hal_set_pin_mux(mp_hal_pin_obj_t pin, uint8_t mux); +void mp_hal_clr_pin_mux(mp_hal_pin_obj_t pin); static inline unsigned int mp_hal_pin_name(mp_hal_pin_obj_t pin) { return pin; From a9eef1b27653b1604d945f95c7ca6d1ce875b9de Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 5 Jun 2022 11:52:33 +0200 Subject: [PATCH 0488/1041] samd/samd_isr: Rework the interrupt tables. Changes are: - Have two separate tables for SAM21 and SAMD51. - Use a short table for SAMD21. - Add a comment to each line telling what it's for, making further use easier. - Add preliminary handlers/entries for PendSV, EIC and Sercom. These will be replaced later when the respecitve modules are added. --- ports/samd/samd_isr.c | 406 ++++++++++++++++++++++++++---------------- 1 file changed, 256 insertions(+), 150 deletions(-) diff --git a/ports/samd/samd_isr.c b/ports/samd/samd_isr.c index a7956c4930..e16018c534 100644 --- a/ports/samd/samd_isr.c +++ b/ports/samd/samd_isr.c @@ -24,14 +24,23 @@ * THE SOFTWARE. */ +#include "py/runtime.h" +#include "py/mphal.h" #include "samd_soc.h" +// includes for Softtimer +// #include "pendsv.h" +// #include "softtimer.h" typedef void (*ISR)(void); extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss; +extern void Default_Handler(void); +extern void SysTick_Handler(void); +extern void PendSV_Handler(void); +extern void EIC_Handler(void); const ISR isr_vector[]; -uint32_t systick_ms; +volatile uint32_t systick_ms; volatile uint32_t systick_ms_upper; void Reset_Handler(void) __attribute__((naked)); @@ -87,8 +96,115 @@ void SysTick_Handler(void) { if (systick_ms == 0) { systick_ms_upper += 1; } + + // if (soft_timer_next == next_tick) { + // pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler); + // } } +// Temporary Handlers to allow builds. +// Will be removed when the respecitve module is added. +void EIC_Handler(void) { +} + +void PendSV_Handler(void) { +} + + +static uint8_t sercom_irq_type[SERCOM_INST_NUM] = {}; +void (*sercom_irq_handler_table[])(int num) = { + // Temporarily commented until the module is added + NULL, // common_uart_irq_handler, + NULL, // common_spi_irq_handler, + NULL // common_i2c_irq_handler +}; + +void sercom_register_irq(int sercom_id, int mode) { + sercom_irq_type[sercom_id] = mode; +} + +static inline void common_sercom_irq_handler(int sercom_id) { + if (sercom_irq_handler_table[sercom_irq_type[sercom_id]]) { + sercom_irq_handler_table[sercom_irq_type[sercom_id]](sercom_id); + } +} + +void Sercom0_Handler(void) { + common_sercom_irq_handler(0); +} +void Sercom1_Handler(void) { + common_sercom_irq_handler(1); +} +void Sercom2_Handler(void) { + common_sercom_irq_handler(2); +} +void Sercom3_Handler(void) { + common_sercom_irq_handler(3); +} +void Sercom4_Handler(void) { + common_sercom_irq_handler(4); +} +void Sercom5_Handler(void) { + common_sercom_irq_handler(5); +} +#if defined(MCU_SAMD51) +void Sercom6_Handler(void) { + common_sercom_irq_handler(6); +} +void Sercom7_Handler(void) { + common_sercom_irq_handler(7); +} +#endif + +#if defined(MCU_SAMD21) +const ISR isr_vector[] __attribute__((section(".isr_vector"))) = { + (ISR)&_estack, + &Reset_Handler, + &Default_Handler, // NMI_Handler + &Default_Handler, // HardFault_Handler + &Default_Handler, // MemManage_Handler + &Default_Handler, // BusFault_Handler + &Default_Handler, // UsageFault_Handler + 0, + 0, + 0, + 0, + &Default_Handler, // SVC_Handler + &Default_Handler, // DebugMon_Handler + 0, + &PendSV_Handler, // PendSV_Handler + &SysTick_Handler, // SysTick_Handler + 0, // 0 Power Manager (PM) + 0, // 1 System Control (SYSCTRL) + 0, // 2 Watchdog Timer (WDT) + 0, // 3 Real-Time Counter (RTC) + &EIC_Handler, // 4 External Interrupt Controller (EIC) + 0, // 5 Non-Volatile Memory Controller (NVMCTRL) + 0, // 6 Direct Memory Access Controller (DMAC) + USB_Handler_wrapper,// 7 Universal Serial Bus (USB) + 0, // 8 Event System Interface (EVSYS) + &Sercom0_Handler, // 9 Serial Communication Interface 0 (SERCOM0) + &Sercom1_Handler, // 10 SAMD21G18A Serial Communication Interface 1 (SERCOM1) + &Sercom2_Handler, // 11 SAMD21G18A Serial Communication Interface 2 (SERCOM2) + &Sercom3_Handler, // 12 SAMD21G18A Serial Communication Interface 3 (SERCOM3) + &Sercom4_Handler, // 13 SAMD21G18A Serial Communication Interface 4 (SERCOM4) + &Sercom5_Handler, // 14 SAMD21G18A Serial Communication Interface 5 (SERCOM5) + 0, // 15 Timer Counter Control 0 (TCC0) + 0, // 16 Timer Counter Control 1 (TCC1) + 0, // 17 Timer Counter Control 2 (TCC2) + 0, // 18 Basic Timer Counter 3 (TC3) + 0, // 19 Basic Timer Counter 4 (TC4) + 0, // 20 Basic Timer Counter 5 (TC5) + 0, // 21 Basic Timer Counter 6 (TC6) + 0, // 22 Basic Timer Counter 7 (TC7) + 0, // 23 Analog Digital Converter (ADC) + 0, // 24 Analog Comparators (AC) + 0, // 25 Digital Analog Converter (DAC) + 0, // 26 Peripheral Touch Controller (PTC) + 0, // 27 Inter-IC Sound Interface (I2S) + +}; +#else const ISR isr_vector[] __attribute__((section(".isr_vector"))) = { (ISR)&_estack, &Reset_Handler, @@ -104,154 +220,144 @@ const ISR isr_vector[] __attribute__((section(".isr_vector"))) = { &Default_Handler, // SVC_Handler &Default_Handler, // DebugMon_Handler 0, - &Default_Handler, // PendSV_Handler + &PendSV_Handler, // PendSV_Handler &SysTick_Handler, // SysTick_Handler - 0, // line 0 - 0, - 0, - 0, - 0, - 0, - 0, - #if defined(MCU_SAMD21) - USB_Handler_wrapper, // line 7 - #else - 0, - #endif - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - #if defined(MCU_SAMD51) - &USB_0_Handler_wrapper, // line 80 - &USB_1_Handler_wrapper, - &USB_2_Handler_wrapper, - &USB_3_Handler_wrapper, - #else - 0, - 0, - 0, - 0, - #endif - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, + 0, // 0 Power Manager (PM) + 0, // 1 Main Clock (MCLK) + 0, // 2 Oscillators Control (OSCCTRL): OSCCTRL_XOSCFAIL_0, OSCCTRL_XOSCRDY_0 + 0, // 3 Oscillators Control (OSCCTRL): OSCCTRL_XOSCFAIL_1, OSCCTRL_XOSCRDY_1 + 0, // 4 Oscillators Control (OSCCTRL): OSCCTRL_DFLLLOCKC, OSCCTRL_DFLLLOCKF, OSCCTRL_DFLLOOB, OSCCTRL_DFLLRCS, OSCCTRL_DFLLRDY + 0, // 5 Oscillators Control (OSCCTRL): OSCCTRL_DPLLLCKF_0, OSCCTRL_DPLLLCKR_0, OSCCTRL_DPLLLDRTO_0, OSCCTRL_DPLLLTO_0 + 0, // 6 Oscillators Control (OSCCTRL): OSCCTRL_DPLLLCKF_1, OSCCTRL_DPLLLCKR_1, OSCCTRL_DPLLLDRTO_1, OSCCTRL_DPLLLTO_1 + 0, // 7 32kHz Oscillators Control (OSC32KCTRL) + 0, // 8 Supply Controller (SUPC): SUPC_B12SRDY, SUPC_B33SRDY, SUP + 0, // 9 Supply Controller (SUPC): SUPC_BOD12DET, SUPC_BOD33DET + 0, // 10 Watchdog Timer (WDT) + 0, // 11 Real-Time Counter (RTC) + &EIC_Handler, // 12 External Interrupt Controller (EIC): EIC_EXTINT_0 + &EIC_Handler, // 13 External Interrupt Controller (EIC): EIC_EXTINT_1 + &EIC_Handler, // 14 External Interrupt Controller (EIC): EIC_EXTINT_2 + &EIC_Handler, // 15 External Interrupt Controller (EIC): EIC_EXTINT_3 + &EIC_Handler, // 16 External Interrupt Controller (EIC): EIC_EXTINT_4 + &EIC_Handler, // 17 External Interrupt Controller (EIC): EIC_EXTINT_5 + &EIC_Handler, // 18 External Interrupt Controller (EIC): EIC_EXTINT_6 + &EIC_Handler, // 19 External Interrupt Controller (EIC): EIC_EXTINT_7 + &EIC_Handler, // 20 External Interrupt Controller (EIC): EIC_EXTINT_8 + &EIC_Handler, // 21 External Interrupt Controller (EIC): EIC_EXTINT_9 + &EIC_Handler, // 22 External Interrupt Controller (EIC): EIC_EXTINT_10 + &EIC_Handler, // 23 External Interrupt Controller (EIC): EIC_EXTINT_11 + &EIC_Handler, // 24 External Interrupt Controller (EIC): EIC_EXTINT_12 + &EIC_Handler, // 25 External Interrupt Controller (EIC): EIC_EXTINT_13 + &EIC_Handler, // 26 External Interrupt Controller (EIC): EIC_EXTINT_14 + &EIC_Handler, // 27 External Interrupt Controller (EIC): EIC_EXTINT_15 + 0, // 28 Frequency Meter (FREQM) + 0, // 29 Non-Volatile Memory Controller (NVMCTRL): NVMCTRL_0 - _7 + 0, // 30 Non-Volatile Memory Controller (NVMCTRL): NVMCTRL_8 - _10 + 0, // 31 Direct Memory Access Controller (DMAC): DMAC_SUSP_0, DMAC_TCMPL_0, DMAC_TERR_0 + 0, // 32 Direct Memory Access Controller (DMAC): DMAC_SUSP_1, DMAC_TCMPL_1, DMAC_TERR_1 + 0, // 33 Direct Memory Access Controller (DMAC): DMAC_SUSP_2, DMAC_TCMPL_2, DMAC_TERR_2 + 0, // 34 Direct Memory Access Controller (DMAC): DMAC_SUSP_3, DMAC_TCMPL_3, DMAC_TERR_3 + 0, // 35 Direct Memory Access Controller (DMAC): DMAC_SUSP_4 - _31, DMAC_TCMPL_4 _31, DMAC_TERR_4- _31 + 0, // 36 Event System Interface (EVSYS): EVSYS_EVD_0, EVSYS_OVR_0 + 0, // 37 Event System Interface (EVSYS): EVSYS_EVD_1, EVSYS_OVR_1 + 0, // 38 Event System Interface (EVSYS): EVSYS_EVD_2, EVSYS_OVR_2 + 0, // 39 Event System Interface (EVSYS): EVSYS_EVD_3, EVSYS_OVR_3 + 0, // 40 Event System Interface (EVSYS): EVSYS_EVD_10, EVSYS_EVD_11 + 0, // 41 Peripheral Access Controller (PAC) + 0, // 42 Trigger Allocator (TAL): TAL_BRK + 0, // 43 Trigger Allocator (TAL): TAL_IPS_x + 0, + 0, // 45 RAM ECC (RAMECC) + &Sercom0_Handler, // 46 Serial Communication Interface 0 (SERCOM0): SERCOM0_0 + &Sercom0_Handler, // 47 Serial Communication Interface 0 (SERCOM0): SERCOM0_1 + &Sercom0_Handler, // 48 Serial Communication Interface 0 (SERCOM0): SERCOM0_2 + &Sercom0_Handler, // 49 Serial Communication Interface 0 (SERCOM0): SERCOM0_3 - 6 + &Sercom1_Handler, // 50 Serial Communication Interface 1 (SERCOM1): SERCOM1_0 + &Sercom1_Handler, // 51 Serial Communication Interface 1 (SERCOM1): SERCOM1_1 + &Sercom1_Handler, // 52 Serial Communication Interface 1 (SERCOM1): SERCOM1_2 + &Sercom1_Handler, // 53 Serial Communication Interface 1 (SERCOM1): SERCOM1_3 - 6 + &Sercom2_Handler, // 54 Serial Communication Interface 2 (SERCOM2): SERCOM2_0 + &Sercom2_Handler, // 55 Serial Communication Interface 2 (SERCOM2): SERCOM2_1 + &Sercom2_Handler, // 56 Serial Communication Interface 2 (SERCOM2): SERCOM2_2 + &Sercom2_Handler, // 57 Serial Communication Interface 2 (SERCOM2): SERCOM2_3 - 6 + &Sercom3_Handler, // 58 Serial Communication Interface 3 (SERCOM3): SERCOM3_0 + &Sercom3_Handler, // 59 Serial Communication Interface 3 (SERCOM3): SERCOM3_1 + &Sercom3_Handler, // 60 Serial Communication Interface 3 (SERCOM3): SERCOM3_2 + &Sercom3_Handler, // 61 Serial Communication Interface 3 (SERCOM3): SERCOM3_3 - 6 + &Sercom4_Handler, // 62 Serial Communication Interface 4 (SERCOM4): SERCOM4_0 + &Sercom4_Handler, // 63 Serial Communication Interface 4 (SERCOM4): SERCOM4_1 + &Sercom4_Handler, // 64 Serial Communication Interface 4 (SERCOM4): SERCOM4_2 + &Sercom4_Handler, // 65 Serial Communication Interface 4 (SERCOM4): SERCOM4_3 - 6 + &Sercom5_Handler, // 66 Serial Communication Interface 5 (SERCOM5): SERCOM5_0 + &Sercom5_Handler, // 67 Serial Communication Interface 5 (SERCOM5): SERCOM5_1 + &Sercom5_Handler, // 68 Serial Communication Interface 5 (SERCOM5): SERCOM5_2 + &Sercom5_Handler, // 69 Serial Communication Interface 5 (SERCOM5): SERCOM5_3 - 6 + &Sercom6_Handler, // 70 Serial Communication Interface 6 (SERCOM6): SERCOM6_0 + &Sercom6_Handler, // 71 Serial Communication Interface 6 (SERCOM6): SERCOM6_1 + &Sercom6_Handler, // 72 Serial Communication Interface 6 (SERCOM6): SERCOM6_2 + &Sercom6_Handler, // 73 Serial Communication Interface 6 (SERCOM6): SERCOM6_3 - 6 + &Sercom7_Handler, // 74 Serial Communication Interface 7 (SERCOM7): SERCOM7_0 + &Sercom7_Handler, // 75 Serial Communication Interface 7 (SERCOM7): SERCOM7_1 + &Sercom7_Handler, // 76 Serial Communication Interface 7 (SERCOM7): SERCOM7_2 + &Sercom7_Handler, // 77 Serial Communication Interface 7 (SERCOM7): SERCOM7_3 - 6 + 0, // 78 Control Area Network 0 (CAN0) + 0, // 79 Control Area Network 1 (CAN1) + &USB_0_Handler_wrapper, // 80 Universal Serial Bus (USB): USB_EORSM_DNRS, ... + &USB_1_Handler_wrapper, // 81 Universal Serial Bus (USB): USB_SOF_HSOF + &USB_2_Handler_wrapper, // 82 Universal Serial Bus (USB): USB_TRCPT0_0 - _7 + &USB_3_Handler_wrapper, // 83 Universal Serial Bus (USB): USB_TRCPT1_0 - _7 + 0, // 84 Ethernet MAC (GMAC) + 0, // 85 Timer Counter Control 0 (TCC0): TCC0_CNT_A ... + 0, // 86 Timer Counter Control 0 (TCC0): TCC0_MC_0 + 0, // 87 Timer Counter Control 0 (TCC0): TCC0_MC_1 + 0, // 88 Timer Counter Control 0 (TCC0): TCC0_MC_2 + 0, // 89 Timer Counter Control 0 (TCC0): TCC0_MC_3 + 0, // 90 Timer Counter Control 0 (TCC0): TCC0_MC_4 + 0, // 91 Timer Counter Control 0 (TCC0): TCC0_MC_5 + 0, // 92 Timer Counter Control 1 (TCC1): TCC1_CNT_A ... + 0, // 93 Timer Counter Control 1 (TCC1): TCC1_MC_0 + 0, // 94 Timer Counter Control 1 (TCC1): TCC1_MC_1 + 0, // 95 Timer Counter Control 1 (TCC1): TCC1_MC_2 + 0, // 96 Timer Counter Control 1 (TCC1): TCC1_MC_3 + 0, // 97 Timer Counter Control 2 (TCC2): TCC2_CNT_A ... + 0, // 98 Timer Counter Control 2 (TCC2): TCC2_MC_0 + 0, // 99 Timer Counter Control 2 (TCC2): TCC2_MC_1 + 0, // 100 Timer Counter Control 2 (TCC2): TCC2_MC_2 + 0, // 101 Timer Counter Control 3 (TCC3): TCC3_CNT_A ... + 0, // 102 Timer Counter Control 3 (TCC3): TCC3_MC_0 + 0, // 103 Timer Counter Control 3 (TCC3): TCC3_MC_1 + 0, // 104 Timer Counter Control 4 (TCC4): TCC4_CNT_A ... + 0, // 105 Timer Counter Control 4 (TCC4): TCC4_MC_0 + 0, // 106 Timer Counter Control 4 (TCC4): TCC4_MC_1 + 0, // 107 Basic Timer Counter 0 (TC0) + 0, // 108 Basic Timer Counter 1 (TC1) + 0, // 109 Basic Timer Counter 2 (TC2) + 0, // 110 Basic Timer Counter 3 (TC3) + 0, // 111 Basic Timer Counter 4 (TC4) + 0, // 112 Basic Timer Counter 5 (TC5) + 0, // 113 Basic Timer Counter 6 (TC6) + 0, // 114 Basic Timer Counter 7 (TC7) + 0, // 115 Quadrature Decoder (PDEC): PDEC_DIR_A, PDEC_ERR_A, PDEC_OVF, PDEC_VLC_A + 0, // 116 Quadrature Decoder (PDEC): PDEC_MC_0 + 0, // 117 Quadrature Decoder (PDEC): PDEC_MC_1 + 0, // 118 Analog Digital Converter 0 (ADC0): ADC0_OVERRUN, ADC0_WINMON + 0, // 119 Analog Digital Converter 0 (ADC0): ADC0_RESRDY + 0, // 120 Analog Digital Converter 1 (ADC1): ADC1_OVERRUN, ADC1_WINMON + 0, // 121 Analog Digital Converter 1 (ADC1): ADC1_RESRDY + 0, // 122 Analog Comparators (AC) + 0, // 123 Digital-to-Analog Converter (DAC): DAC_OVERRUN_A_x, DAC_UNDERRUN_A_x + 0, // 124 Digital-to-Analog Converter (DAC): DAC_EMPTY_0 + 0, // 125 Digital-to-Analog Converter (DAC): DAC_EMPTY_1 + 0, // 126 Digital-to-Analog Converter (DAC): DAC_RESRDY_0 + 0, // 127 Digital-to-Analog Converter (DAC): DAC_RESRDY_1 + 0, // 128 Inter-IC Sound Interface (I2S) + 0, // 129 Parallel Capture Controller (PCC) + 0, // 130 Advanced Encryption Standard (AES) + 0, // 131 True Random Generator (TRNG) + 0, // 132 Integrity Check Monitor (ICM) + 0, // 133 PUblic-Key Cryptography Controller (PUKCC) + 0, // 134 Quad SPI interface (QSPI) + 0, // 135 SD/MMC Host Controller 0 (SDHC0) + 0, // 136 SD/MMC Host Controller 1 (SDHC1) }; +#endif From 4b6f6ccf88c652401e39e621b515d06140d35225 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 5 Jun 2022 14:08:44 +0200 Subject: [PATCH 0489/1041] samd/machine_pin: Add pin.irq() to the machine.Pin class. Its API conforms to the docs. There are 16 IRQ channels available, which will be used as assignable to the GPIO numbers. In most cases, the irq channel is GPIO_no % 16. --- ports/samd/Makefile | 2 + ports/samd/machine_pin.c | 200 +++++++++++++++++++++++++++++++++++++- ports/samd/main.c | 2 + ports/samd/mpconfigport.h | 6 +- ports/samd/samd_isr.c | 3 - 5 files changed, 207 insertions(+), 6 deletions(-) diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 514c92ba1b..163971cde7 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -118,6 +118,7 @@ SRC_C = \ lib/tinyusb/src/portable/microchip/samd/dcd_samd.c \ lib/tinyusb/src/tusb.c \ drivers/bus/softspi.c \ + shared/runtime/mpirq.c \ shared/libc/printf.c \ shared/libc/string0.c \ shared/readline/readline.c \ @@ -148,6 +149,7 @@ SRC_QSTR += \ modsamd.c \ samd_flash.c \ shared/readline/readline.c \ + shared/runtime/mpirq.c \ SRC_QSTR += $(SRC_MOD) $(SRC_CXX) diff --git a/ports/samd/machine_pin.c b/ports/samd/machine_pin.c index 98317abbf2..a70e9ad011 100644 --- a/ports/samd/machine_pin.c +++ b/ports/samd/machine_pin.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2016-2021 Damien P. George + * Copyright (c) 2022 Robert Hammelrath (pin.irq) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,10 +30,12 @@ #include "string.h" #include "py/runtime.h" #include "py/mphal.h" +#include "shared/runtime/mpirq.h" #include "extmod/virtpin.h" #include "modmachine.h" #include "samd_soc.h" #include "pins.h" +#include "pin_af.h" #include "hal_gpio.h" @@ -42,6 +45,17 @@ #define GPIO_STRENGTH_2MA (0) #define GPIO_STRENGTH_8MA (1) +#define GPIO_IRQ_EDGE_RISE (1) +#define GPIO_IRQ_EDGE_FALL (2) + +typedef struct _machine_pin_irq_obj_t { + mp_irq_obj_t base; + uint32_t flags; + uint32_t trigger; + uint8_t pin_id; +} machine_pin_irq_obj_t; + +STATIC const mp_irq_methods_t machine_pin_irq_methods; uint32_t machine_pin_open_drain_mask[4]; @@ -262,6 +276,141 @@ STATIC mp_obj_t machine_pin_drive(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_drive_obj, 1, 2, machine_pin_drive); +// pin.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING, hard=False) +STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_handler, ARG_trigger, ARG_hard }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_trigger, MP_ARG_INT, {.u_int = 3} }, + { MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} }, + }; + machine_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // Get the IRQ object. + uint8_t eic_id = get_pin_af_info(self->id)->eic; + machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]); + if (irq != NULL && irq->pin_id != self->id) { + mp_raise_ValueError(MP_ERROR_TEXT("IRQ already used")); + } + + // Allocate the IRQ object if it doesn't already exist. + if (irq == NULL) { + irq = m_new_obj(machine_pin_irq_obj_t); + irq->base.base.type = &mp_irq_type; + irq->base.methods = (mp_irq_methods_t *)&machine_pin_irq_methods; + irq->base.parent = MP_OBJ_FROM_PTR(self); + irq->base.handler = mp_const_none; + irq->base.ishard = false; + irq->pin_id = 0xff; + MP_STATE_PORT(machine_pin_irq_objects[eic_id]) = irq; + } + // (Re-)configure the irq. + if (n_args > 1 || kw_args->used != 0) { + + // set the mux config of the pin. + mp_hal_set_pin_mux(self->id, ALT_FCT_EIC); + + // Configure IRQ. + #if defined(MCU_SAMD21) + + uint32_t irq_num = 4; + // Disable all IRQs from the affected source while data is updated. + NVIC_DisableIRQ(irq_num); + // Disable EIC + EIC->CTRL.bit.ENABLE = 0; + while (EIC->STATUS.bit.SYNCBUSY != 0) { + } + EIC->INTENCLR.reg = (1 << eic_id); + // Enable the clocks + PM->APBAMASK.bit.EIC_ |= 1; + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | EIC_GCLK_ID; + + #elif defined(MCU_SAMD51) + + uint32_t irq_num = eic_id + 12; + // Disable all IRQs from the affected source while data is updated. + NVIC_DisableIRQ(irq_num); + // Disable EIC + EIC->CTRLA.bit.ENABLE = 0; + while (EIC->SYNCBUSY.bit.ENABLE != 0) { + } + EIC->INTENCLR.reg = (1 << eic_id); + // Enable the clocks + MCLK->APBAMASK.bit.EIC_ |= 1; + GCLK->PCHCTRL[EIC_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK2; + + #endif + // Clear the pending interrupts flag + EIC->INTENCLR.reg = (1 << eic_id); + + // Update IRQ data. + irq->base.handler = args[ARG_handler].u_obj; + irq->base.ishard = args[ARG_hard].u_bool; + irq->flags = 0; + irq->trigger = args[ARG_trigger].u_int; + irq->pin_id = self->id; + + // Enable IRQ if a handler is given. + if (args[ARG_handler].u_obj != mp_const_none) { + // Set EIC channel mode + EIC->CONFIG[eic_id / 8].reg |= irq->trigger << ((eic_id % 8) * 4); + EIC->INTENSET.reg = (1 << eic_id); + EIC->INTFLAG.reg |= (1 << eic_id); + } + + // Enable EIC (again) + #if defined(MCU_SAMD21) + EIC->CTRL.bit.ENABLE = 1; + while (EIC->STATUS.bit.SYNCBUSY != 0) { + } + #elif defined(MCU_SAMD51) + EIC->CTRLA.bit.ENABLE = 1; + while (EIC->SYNCBUSY.bit.ENABLE != 0) { + } + #endif + // Enable interrupt again + NVIC_EnableIRQ(irq_num); + } + return MP_OBJ_FROM_PTR(irq); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_irq_obj, 1, machine_pin_irq); + +void pin_irq_deinit_all(void) { + + EIC->INTENCLR.reg = 0xffff; // Disable all interrupts from the EIC. + for (int i = 0; i < 16; i++) { // Clear all irq object pointers + MP_STATE_PORT(machine_pin_irq_objects[i]) = NULL; + } + // Disable all irq's at the NVIC controller + #if defined(MCU_SAMD21) + NVIC_DisableIRQ(4); + #elif defined(MCU_SAMD51) + for (int i = 12; i < 20; i++) { + NVIC_DisableIRQ(i); + } + #endif +} + +// Common EIC handler for all events. +void EIC_Handler() { + uint32_t mask = 1; + uint32_t isr = EIC->INTFLAG.reg; + for (int eic_id = 0; eic_id < 16; eic_id++, mask <<= 1) { + // Did the ISR fire? + if (isr & mask) { + EIC->INTFLAG.reg |= mask; // clear the ISR flag + machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]); + if (irq != NULL) { + irq->flags = irq->trigger; + mp_irq_handler(&irq->base); + break; + } + } + } +} + STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) }, @@ -273,6 +422,7 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&machine_pin_toggle_obj) }, { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&machine_pin_disable_obj) }, { MP_ROM_QSTR(MP_QSTR_drive), MP_ROM_PTR(&machine_pin_drive_obj) }, + { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_pin_irq_obj) }, // class constants { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_IN) }, @@ -283,6 +433,8 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULL_DOWN) }, { MP_ROM_QSTR(MP_QSTR_LOW_POWER), MP_ROM_INT(GPIO_STRENGTH_2MA) }, { MP_ROM_QSTR(MP_QSTR_HIGH_POWER), MP_ROM_INT(GPIO_STRENGTH_8MA) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_IRQ_EDGE_RISE) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_IRQ_EDGE_FALL) }, }; STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table); @@ -292,10 +444,10 @@ STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, i switch (request) { case MP_PIN_READ: { - return gpio_get_pin_level(self->id); + return mp_hal_pin_read(self->id); } case MP_PIN_WRITE: { - gpio_set_pin_level(self->id, arg); + mp_hal_pin_write(self->id, arg); return 0; } } @@ -317,6 +469,48 @@ MP_DEFINE_CONST_OBJ_TYPE( locals_dict, &machine_pin_locals_dict ); +static uint8_t find_eic_id(int pin) { + for (int eic_id = 0; eic_id < 16; eic_id++) { + machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]); + if (irq != NULL && irq->pin_id == pin) { + return eic_id; + } + } + return 0xff; +} + +STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { + machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); + uint8_t eic_id = find_eic_id(self->id); + if (eic_id != 0xff) { + machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]); + EIC->INTENCLR.reg |= (1 << eic_id); + irq->flags = 0; + irq->trigger = new_trigger; + EIC->INTENSET.reg |= (1 << eic_id); + } + return 0; +} + +STATIC mp_uint_t machine_pin_irq_info(mp_obj_t self_in, mp_uint_t info_type) { + machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); + uint8_t eic_id = find_eic_id(self->id); + if (eic_id != 0xff) { + machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]); + if (info_type == MP_IRQ_INFO_FLAGS) { + return irq->flags; + } else if (info_type == MP_IRQ_INFO_TRIGGERS) { + return irq->trigger; + } + } + return 0; +} + +STATIC const mp_irq_methods_t machine_pin_irq_methods = { + .trigger = machine_pin_irq_trigger, + .info = machine_pin_irq_info, +}; + mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t obj) { if (!mp_obj_is_type(obj, &machine_pin_type)) { mp_raise_ValueError(MP_ERROR_TEXT("expecting a Pin")); @@ -324,3 +518,5 @@ mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t obj) { machine_pin_obj_t *pin = MP_OBJ_TO_PTR(obj); return pin->id; } + +MP_REGISTER_ROOT_POINTER(void *machine_pin_irq_objects[16]); diff --git a/ports/samd/main.c b/ports/samd/main.c index 4af4b2b4f8..520763b5aa 100644 --- a/ports/samd/main.c +++ b/ports/samd/main.c @@ -34,6 +34,7 @@ extern uint8_t _sstack, _estack, _sheap, _eheap; extern void adc_deinit_all(void); +extern void pin_irq_deinit_all(void); extern void pwm_deinit_all(void); void samd_main(void) { @@ -65,6 +66,7 @@ void samd_main(void) { mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n"); adc_deinit_all(); + pin_irq_deinit_all(); pwm_deinit_all(); gc_sweep_all(); mp_deinit(); diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 70bd202a31..574d47b035 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -54,7 +54,7 @@ #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_TEXT samd_help_text #define MICROPY_PY_BUILTINS_HELP_MODULES (1) - +#define MICROPY_ENABLE_SCHEDULER (1) // fixes sys/usys import issue #define MICROPY_MODULE_WEAK_LINKS (1) // Control over Python builtins @@ -104,6 +104,10 @@ #define MICROPY_PY_MACHINE_PWM_DUTY_U16_NS (1) #define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/samd/machine_pwm.c" +// Use VfsLfs's types for fileio/textio +#define mp_type_fileio mp_type_vfs_lfs1_fileio +#define mp_type_textio mp_type_vfs_lfs1_textio + #define MP_STATE_PORT MP_STATE_VM // Miscellaneous settings diff --git a/ports/samd/samd_isr.c b/ports/samd/samd_isr.c index e16018c534..a4e1dd708c 100644 --- a/ports/samd/samd_isr.c +++ b/ports/samd/samd_isr.c @@ -104,9 +104,6 @@ void SysTick_Handler(void) { // Temporary Handlers to allow builds. // Will be removed when the respecitve module is added. -void EIC_Handler(void) { -} - void PendSV_Handler(void) { } From 7d281f6165d50a75ba21eda4d8d253a8982f3543 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 5 Jun 2022 14:28:08 +0200 Subject: [PATCH 0490/1041] samd/modmachine: Add disable_irq(), enable_irq() and idle() to machine. No specific features. --- ports/samd/modmachine.c | 23 +++++++++++++++++++++++ ports/samd/mpconfigport.h | 12 ++++++++++++ 2 files changed, 35 insertions(+) diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index e0a0378461..eafe9972d0 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -120,6 +120,25 @@ STATIC mp_obj_t machine_unique_id(void) { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id); +STATIC mp_obj_t machine_idle(void) { + MICROPY_EVENT_POLL_HOOK; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle); + +STATIC mp_obj_t machine_disable_irq(void) { + uint32_t state = MICROPY_BEGIN_ATOMIC_SECTION(); + return mp_obj_new_int(state); +} +MP_DEFINE_CONST_FUN_OBJ_0(machine_disable_irq_obj, machine_disable_irq); + +STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) { + uint32_t state = mp_obj_get_int(state_in); + MICROPY_END_ATOMIC_SECTION(state); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq); + STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, @@ -136,6 +155,10 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, + + { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) }, + { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, + { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) }, }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 574d47b035..fba4ee13d2 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -111,6 +111,18 @@ #define MP_STATE_PORT MP_STATE_VM // Miscellaneous settings +__attribute__((always_inline)) static inline void enable_irq(uint32_t state) { + __set_PRIMASK(state); +} + +__attribute__((always_inline)) static inline uint32_t disable_irq(void) { + uint32_t state = __get_PRIMASK(); + __disable_irq(); + return state; +} + +#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() +#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state) #define MICROPY_EVENT_POLL_HOOK \ do { \ From b33f2045290a379d2cefc1798780aa46f56e29a1 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 5 Jun 2022 15:03:52 +0200 Subject: [PATCH 0491/1041] samd/machine_uart: Add the machine.UART class. All board pins that have UART's assigned can be used. Baud rate range is 75 Baud to ~2 MBaud. No flow control yet, and only RX is buffered. TX buffer and flow control may be added later for SAMD51 with its larger RAM and Flash. --- ports/samd/Makefile | 2 + ports/samd/machine_uart.c | 475 ++++++++++++++++++++++++++++++++++++++ ports/samd/main.c | 2 + ports/samd/modmachine.c | 1 + ports/samd/modmachine.h | 1 + ports/samd/mpconfigport.h | 1 + ports/samd/samd_isr.c | 4 +- 7 files changed, 484 insertions(+), 2 deletions(-) create mode 100644 ports/samd/machine_uart.c diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 163971cde7..196b7acf11 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -93,6 +93,7 @@ SRC_C = \ machine_adc.c \ machine_led.c \ machine_pin.c \ + machine_uart.c \ main.c \ modutime.c \ modmachine.c \ @@ -144,6 +145,7 @@ SRC_QSTR += \ machine_led.c \ machine_pin.c \ machine_pwm.c \ + machine_uart.c \ modutime.c \ modmachine.c \ modsamd.c \ diff --git a/ports/samd/machine_uart.c b/ports/samd/machine_uart.c new file mode 100644 index 0000000000..9c5cfce839 --- /dev/null +++ b/ports/samd/machine_uart.c @@ -0,0 +1,475 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 Damien P. George + * Copyright (c) 2022 Robert Hammelrath + * + * 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/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) +#define MIN_BUFFER_SIZE (32) +#define MAX_BUFFER_SIZE (32766) +#define USART_BUFFER_TX (0) + +typedef struct _machine_uart_obj_t { + mp_obj_base_t base; + uint8_t id; + uint32_t baudrate; + uint8_t bits; + uint8_t parity; + uint8_t stop; + uint8_t tx; + sercom_pad_config_t tx_pad_config; + uint8_t rx; + sercom_pad_config_t rx_pad_config; + uint16_t timeout; // timeout waiting for first char (in ms) + uint16_t timeout_char; // timeout waiting between chars (in ms) + bool new; + ringbuf_t read_buffer; + #if USART_BUFFER_TX + ringbuf_t write_buffer; + #endif +} machine_uart_obj_t; + +Sercom *sercom_instance[] = SERCOM_INSTS; +machine_uart_obj_t *uart_table[SERCOM_INST_NUM] = {}; + +STATIC const char *_parity_name[] = {"None", "", "0", "1"}; // Is defined as 0, 2, 3 + +// Irq handler + +// take all bytes from the fifo and store them in the buffer +STATIC void uart_drain_rx_fifo(machine_uart_obj_t *self, Sercom *uart) { + while (uart->USART.INTFLAG.bit.RXC != 0) { + if (ringbuf_free(&self->read_buffer) > 0) { + // get a byte from uart and put into the buffer + ringbuf_put(&(self->read_buffer), uart->USART.DATA.bit.DATA); + } else { + // if the buffer is full, discard the data for now + // t.b.d.: flow control + uint32_t temp; + (void)temp; + temp = uart->USART.DATA.bit.DATA; + } + } +} + +void common_uart_irq_handler(int uart_id) { + machine_uart_obj_t *self = uart_table[uart_id]; + // Handle IRQ + if (self != NULL) { + Sercom *uart = sercom_instance[self->id]; + if (uart->USART.INTFLAG.bit.RXC != 0) { + // Now handler the incoming data + uart_drain_rx_fifo(self, uart); + } else if (uart->USART.INTFLAG.bit.DRE != 0) { + // handle the outgoing data + } else { + // Disable the other interrupts, if set by error + uart->USART.INTENCLR.reg = (uint8_t) ~(SERCOM_USART_INTENCLR_DRE | SERCOM_USART_INTENCLR_RXC); + } + } +} + +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) { + } +} + +STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, " + "timeout=%u, timeout_char=%u, rxbuf=%d)", + self->id, self->baudrate, self->bits, _parity_name[self->parity], + self->stop + 1, self->timeout, self->timeout_char, self->read_buffer.size - 1); +} + +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) { + enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx, + ARG_timeout, ARG_timeout_char, ARG_rxbuf, ARG_txbuf}; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_bits, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_parity, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_INT(-1)} }, + { MP_QSTR_stop, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + #if USART_BUFFER_TX + { MP_QSTR_txbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + #endif + }; + + // Parse args + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // Set baudrate if configured. + if (args[ARG_baudrate].u_int > 0) { + self->baudrate = args[ARG_baudrate].u_int; + } + + // Set bits if configured. + if (args[ARG_bits].u_int > 0) { + self->bits = args[ARG_bits].u_int; + } + + // Set parity if configured. + if (args[ARG_parity].u_obj != MP_OBJ_NEW_SMALL_INT(-1)) { + if (args[ARG_parity].u_obj == mp_const_none) { + self->parity = 0; + } else if (mp_obj_get_int(args[ARG_parity].u_obj) & 1) { + self->parity = 1; // odd + } else { + self->parity = 2; // even + } + } + + // Set stop bits if configured. + if (args[ARG_stop].u_int > 0) { + self->stop = (args[ARG_stop].u_int - 1) & 1; + } + + // Set TX/RX pins if configured. + if (args[ARG_tx].u_obj != mp_const_none) { + self->tx = mp_hal_get_pin_obj(args[ARG_tx].u_obj); + } + if (args[ARG_rx].u_obj != mp_const_none) { + self->rx = mp_hal_get_pin_obj(args[ARG_rx].u_obj); + } + + // Set timeout if configured. + if (args[ARG_timeout].u_int >= 0) { + self->timeout = args[ARG_timeout].u_int; + } + + // Set timeout_char if configured. + if (args[ARG_timeout_char].u_int >= 0) { + self->timeout_char = args[ARG_timeout_char].u_int; + } + + // Set the RX buffer size if configured. + size_t rxbuf_len = DEFAULT_BUFFER_SIZE; + if (args[ARG_rxbuf].u_int > 0) { + rxbuf_len = args[ARG_rxbuf].u_int; + if (rxbuf_len < MIN_BUFFER_SIZE) { + rxbuf_len = MIN_BUFFER_SIZE; + } else if (rxbuf_len > MAX_BUFFER_SIZE) { + mp_raise_ValueError(MP_ERROR_TEXT("rxbuf too large")); + } + } + + #if USART_BUFFER_TX + // Set the TX buffer size if configured. + size_t txbuf_len = DEFAULT_BUFFER_SIZE; + if (args[ARG_txbuf].u_int > 0) { + txbuf_len = args[ARG_txbuf].u_int; + if (txbuf_len < MIN_BUFFER_SIZE) { + txbuf_len = MIN_BUFFER_SIZE; + } else if (txbuf_len > MAX_BUFFER_SIZE) { + mp_raise_ValueError(MP_ERROR_TEXT("txbuf too large")); + } + } + #endif + // Initialise the UART peripheral if any arguments given, or it was not initialised previously. + if (n_args > 0 || kw_args->used > 0 || self->new) { + self->new = false; + + // Check the rx/tx pin assignments + if (self->tx == 0xff || self->rx == 0xff || (self->tx / 4) != (self->rx / 4)) { + mp_raise_ValueError(MP_ERROR_TEXT("Non-matching or missing rx/tx")); + } + self->rx_pad_config = get_sercom_config(self->rx, self->id); + self->tx_pad_config = get_sercom_config(self->tx, self->id); + + // Make sure timeout_char is at least as long as a whole character (13 bits to be safe). + uint32_t min_timeout_char = 13000 / self->baudrate + 1; + if (self->timeout_char < min_timeout_char) { + self->timeout_char = min_timeout_char; + } + + // Allocate the RX/TX buffers. + ringbuf_alloc(&(self->read_buffer), rxbuf_len + 1); + MP_STATE_PORT(samd_uart_rx_buffer[self->id]) = self->read_buffer.buf; + + #if USART_BUFFER_TX + ringbuf_alloc(&(self->write_buffer), txbuf_len + 1); + MP_STATE_PORT(samd_uart_tx_buffer[self->id]) = self->write_buffer.buf; + #endif + + // Step 1: Configure the Pin mux. + mp_hal_set_pin_mux(self->rx, self->rx_pad_config.alt_fct); + mp_hal_set_pin_mux(self->tx, self->tx_pad_config.alt_fct); + + // Next: Set up the clocks + enable_sercom_clock(self->id); + + // Next: Configure the USART + Sercom *uart = sercom_instance[self->id]; + // Reset (clear) the peripheral registers. + while (uart->USART.SYNCBUSY.bit.SWRST) { + } + uart->USART.CTRLA.bit.SWRST = 1; // Reset all Registers, disable peripheral + while (uart->USART.SYNCBUSY.bit.SWRST) { + } + + uint8_t txpo = self->tx_pad_config.pad_nr; + #if defined(MCU_SAMD21) + if (self->tx_pad_config.pad_nr == 2) { // Map pad 2 to TXPO = 1 + txpo = 1; + } + #endif + + uart->USART.CTRLA.reg = + SERCOM_USART_CTRLA_DORD // Data order + | SERCOM_USART_CTRLA_FORM(self->parity != 0 ? 1 : 0) // Enable parity or not + | SERCOM_USART_CTRLA_RXPO(self->rx_pad_config.pad_nr) // Set Pad# + | SERCOM_USART_CTRLA_TXPO(txpo) // Set Pad# + | SERCOM_USART_CTRLA_MODE(1) // USART with internal clock + ; + uart->USART.CTRLB.reg = + SERCOM_USART_CTRLB_RXEN // Enable Rx & Tx + | SERCOM_USART_CTRLB_TXEN + | ((self->parity & 1) << SERCOM_USART_CTRLB_PMODE_Pos) + | (self->stop << SERCOM_USART_CTRLB_SBMODE_Pos) + | SERCOM_USART_CTRLB_CHSIZE((self->bits & 7) | (self->bits & 1)) + ; + while (uart->USART.SYNCBUSY.bit.CTRLB) { + } + + // USART is driven by the clock of GCLK Generator 2, freq by get_apb_freq() + // baud rate; 65536 * (1 - 16 * 115200/bus_freq) + uint32_t baud = 65536 - ((uint64_t)(65536 * 16) * self->baudrate + get_apb_freq() / 2) / get_apb_freq(); + uart->USART.BAUD.bit.BAUD = baud; // Set Baud + + // Enable RXC interrupt + uart->USART.INTENSET.bit.RXC = 1; + #if defined(MCU_SAMD21) + NVIC_EnableIRQ(SERCOM0_IRQn + self->id); + #elif defined(MCU_SAMD51) + NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 2); + #endif + sercom_register_irq(self->id, SERCOM_IRQ_TYPE_UART); + + 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) { + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + + // Get UART bus. + int uart_id = mp_obj_get_int(args[0]); + if (uart_id < 0 || uart_id > SERCOM_INST_NUM) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("UART(%d) doesn't exist"), uart_id); + } + + // Create the UART object and fill it with defaults. + machine_uart_obj_t *self = mp_obj_malloc(machine_uart_obj_t, &machine_uart_type); + self->id = uart_id; + self->baudrate = DEFAULT_UART_BAUDRATE; + self->bits = 8; + self->stop = 0; + self->timeout = 1; + self->timeout_char = 1; + self->tx = 0xff; + self->rx = 0xff; + self->new = true; + uart_table[uart_id] = self; + + 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); +} + +// 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); + Sercom *uart = sercom_instance[self->id]; + // clear table entry of uart + uart_table[self->id] = NULL; + // Disable interrupts + uart->USART.INTENCLR.reg = 0xff; + MP_STATE_PORT(samd_uart_rx_buffer[self->id]) = NULL; + #if USART_BUFFER_TX + MP_STATE_PORT(samd_uart_tx_buffer[self->id]) = NULL; + #endif + 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); + // get all bytes from the fifo first + uart_drain_rx_fifo(self, sercom_instance[self->id]); + return MP_OBJ_NEW_SMALL_INT(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); + uint32_t break_time_us = 13 * 1000000 / self->baudrate; + + // Wait for the TX queue & register to clear + // Since the flags are not safe, just wait sufficiently long. + // Once tx buffering is implemented, wait as well for the buffer to clear. + mp_hal_delay_us(2 * break_time_us); + // Disable MUX + PORT->Group[self->tx / 32].PINCFG[self->tx % 32].bit.PMUXEN = 0; + // Set TX pin to low for break time + mp_hal_pin_low(self->tx); + mp_hal_delay_us(break_time_us); + 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); + +void uart_deinit_all(void) { + for (int i = 0; i < SERCOM_INST_NUM; i++) { + if (uart_table[i] != NULL) { + machine_uart_deinit((mp_obj_t)uart_table[i]); + } + } +} + +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_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) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + uint64_t t = mp_hal_ticks_ms() + self->timeout; + uint64_t timeout_char = self->timeout_char; + uint8_t *dest = buf_in; + Sercom *uart = sercom_instance[self->id]; + + // t.b.d. Cater timeout for timer wrap after 50 days. + for (size_t i = 0; i < size; i++) { + // Wait for the first/next character + while (ringbuf_avail(&self->read_buffer) == 0) { + if (uart->USART.INTFLAG.bit.RXC != 0) { + // Force a few incoming bytes to the buffer + uart_drain_rx_fifo(self, uart); + break; + } + if (mp_hal_ticks_ms() > t) { // timed out + if (i <= 0) { + *errcode = MP_EAGAIN; + return MP_STREAM_ERROR; + } else { + return i; + } + } + MICROPY_EVENT_POLL_HOOK + } + *dest++ = ringbuf_get(&(self->read_buffer)); + t = mp_hal_ticks_ms() + timeout_char; + } + return size; +} + +STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + size_t remaining = size; + const uint8_t *src = buf_in; + Sercom *uart = sercom_instance[self->id]; + + while (remaining--) { + while (!(uart->USART.INTFLAG.bit.DRE)) { + } + uart->USART.DATA.bit.DATA = *src; + src += 1; + } + + return size; +} + +STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { + machine_uart_obj_t *self = self_in; + mp_uint_t ret; + Sercom *uart = sercom_instance[self->id]; + if (request == MP_STREAM_POLL) { + uintptr_t flags = arg; + ret = 0; + if ((flags & MP_STREAM_POLL_RD) && (uart->USART.INTFLAG.bit.RXC != 0 || ringbuf_avail(&self->read_buffer) > 0)) { + ret |= MP_STREAM_POLL_RD; + } + if ((flags & MP_STREAM_POLL_WR) && (uart->USART.INTFLAG.bit.DRE != 0)) { + ret |= MP_STREAM_POLL_WR; + } + } else { + *errcode = MP_EINVAL; + ret = MP_STREAM_ERROR; + } + 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 *samd_uart_rx_buffer[SERCOM_INST_NUM]); diff --git a/ports/samd/main.c b/ports/samd/main.c index 520763b5aa..60b8e57faa 100644 --- a/ports/samd/main.c +++ b/ports/samd/main.c @@ -36,6 +36,7 @@ extern uint8_t _sstack, _estack, _sheap, _eheap; extern void adc_deinit_all(void); extern void pin_irq_deinit_all(void); extern void pwm_deinit_all(void); +extern void uart_deinit_all(void); void samd_main(void) { mp_stack_set_top(&_estack); @@ -68,6 +69,7 @@ void samd_main(void) { adc_deinit_all(); pin_irq_deinit_all(); pwm_deinit_all(); + uart_deinit_all(); gc_sweep_all(); mp_deinit(); } diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index eafe9972d0..8c3033f891 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -155,6 +155,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, diff --git a/ports/samd/modmachine.h b/ports/samd/modmachine.h index 00e72ede1a..30de339b4a 100644 --- a/ports/samd/modmachine.h +++ b/ports/samd/modmachine.h @@ -32,5 +32,6 @@ extern const mp_obj_type_t machine_adc_type; extern const mp_obj_type_t machine_led_type; extern const mp_obj_type_t machine_pin_type; extern const mp_obj_type_t machine_pwm_type; +extern const mp_obj_type_t machine_uart_type; #endif // MICROPY_INCLUDED_SAMD_MODMACHINE_H diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index fba4ee13d2..b8cb0f3eb7 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -48,6 +48,7 @@ #define MICROPY_HELPER_REPL (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_ENABLE_SOURCE_LINE (1) +#define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) diff --git a/ports/samd/samd_isr.c b/ports/samd/samd_isr.c index a4e1dd708c..0e0d84db69 100644 --- a/ports/samd/samd_isr.c +++ b/ports/samd/samd_isr.c @@ -109,9 +109,9 @@ void PendSV_Handler(void) { static uint8_t sercom_irq_type[SERCOM_INST_NUM] = {}; +// Temporarily commented until the module is added void (*sercom_irq_handler_table[])(int num) = { - // Temporarily commented until the module is added - NULL, // common_uart_irq_handler, + common_uart_irq_handler, NULL, // common_spi_irq_handler, NULL // common_i2c_irq_handler }; From aa870708ac262824ab5829e0f163f8f1e1332ada Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 5 Jun 2022 17:02:46 +0200 Subject: [PATCH 0492/1041] samd/machine_spi: Add the machine.SPI class. Suported by both SAMD21 and SAMD51. It follows the generic API, except for the bits=nn option, which is not implemented (yet). --- ports/samd/Makefile | 2 + ports/samd/machine_spi.c | 330 ++++++++++++++++++++++++++++++++++++++ ports/samd/main.c | 2 + ports/samd/modmachine.c | 1 + ports/samd/modmachine.h | 1 + ports/samd/mpconfigport.h | 1 + ports/samd/samd_isr.c | 2 +- 7 files changed, 338 insertions(+), 1 deletion(-) create mode 100644 ports/samd/machine_spi.c diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 196b7acf11..ca0309fa69 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -93,6 +93,7 @@ SRC_C = \ machine_adc.c \ machine_led.c \ machine_pin.c \ + machine_spi.c \ machine_uart.c \ main.c \ modutime.c \ @@ -145,6 +146,7 @@ SRC_QSTR += \ machine_led.c \ machine_pin.c \ machine_pwm.c \ + machine_spi.c \ machine_uart.c \ modutime.c \ modmachine.c \ diff --git a/ports/samd/machine_spi.c b/ports/samd/machine_spi.c new file mode 100644 index 0000000000..b3504aeba3 --- /dev/null +++ b/ports/samd/machine_spi.c @@ -0,0 +1,330 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 Damien P. George + * Copyright (c) 2022 Robert Hammelrath + * + * 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/mphal.h" +#include "extmod/machine_spi.h" +#include "modmachine.h" +#include "samd_soc.h" +#include "pin_af.h" +#include "clock_config.h" + +#define DEFAULT_SPI_BAUDRATE (1000000) +#define DEFAULT_SPI_POLARITY (0) +#define DEFAULT_SPI_PHASE (0) +#define DEFAULT_SPI_BITS (8) +#define DEFAULT_SPI_FIRSTBIT (0) + +typedef struct _machine_spi_obj_t { + mp_obj_base_t base; + uint8_t id; + uint8_t polarity; + uint8_t phase; + uint8_t firstbit; + uint8_t sck; + uint8_t mosi; + uint8_t miso; + uint8_t new; + uint32_t baudrate; + sercom_pad_config_t sck_pad_config; + sercom_pad_config_t mosi_pad_config; + sercom_pad_config_t miso_pad_config; + uint8_t *dest; + size_t rxlen; +} machine_spi_obj_t; + +extern Sercom *sercom_instance[]; +void *sercom_table[SERCOM_INST_NUM] = {}; + +void common_spi_irq_handler(int spi_id) { + // handle Sercom IRQ RXC + machine_spi_obj_t *self = sercom_table[spi_id]; + // Handle IRQ + if (self != NULL) { + Sercom *spi = sercom_instance[self->id]; + if (spi->SPI.INTFLAG.bit.RXC != 0) { + if (self->rxlen > 0) { + *(self->dest)++ = spi->SPI.DATA.bit.DATA; + self->rxlen--; + } else { + // Just in the unlikely case there is data but no space in the buffer + // discard the data and clear the intflag + uint32_t temp; + (void)temp; + temp = spi->SPI.DATA.bit.DATA; + } + } + } +} + +STATIC void machine_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "SPI(%u), baudrate=%u, firstbit=%u, polarity=%u, phase=%u, bits=8", + self->id, self->baudrate, self->firstbit, self->polarity, self->phase); +} + +STATIC void machine_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_firstbit, + ARG_sck, ARG_mosi, ARG_miso}; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_firstbit, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + }; + + machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); + + // Parse args + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // Set baudrate if configured. + if (args[ARG_baudrate].u_int >= 0) { + self->baudrate = args[ARG_baudrate].u_int; + } + + // Set polarity if configured. + if (args[ARG_polarity].u_int >= 0) { + self->polarity = args[ARG_polarity].u_int; + } + + // Set phase if configured. + if (args[ARG_phase].u_int >= 0) { + self->phase = args[ARG_phase].u_int; + } + + // Set firstbit if configured. + if (args[ARG_firstbit].u_int >= 0) { + self->firstbit = args[ARG_firstbit].u_int; + } + + // Set SCK/MOSI/MISO pins if configured. + if (args[ARG_sck].u_obj != mp_const_none) { + self->sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj); + } + if (args[ARG_mosi].u_obj != mp_const_none) { + self->mosi = mp_hal_get_pin_obj(args[ARG_mosi].u_obj); + } + if (args[ARG_miso].u_obj != mp_const_none) { + self->miso = mp_hal_get_pin_obj(args[ARG_miso].u_obj); + } + + // Initialise the SPI peripheral if any arguments given, or it was not initialised previously. + if (n_args > 0 || kw_args->used > 0 || self->new) { + self->new = false; + + // Get the pad and alt-fct numbers. + self->sck_pad_config = get_sercom_config(self->sck, self->id); + self->mosi_pad_config = get_sercom_config(self->mosi, self->id); + + uint8_t dopo = 0; + #if defined(MCU_SAMD21) + if (self->mosi_pad_config.pad_nr == 0 && self->sck_pad_config.pad_nr == 1) { + dopo = 0; + } else if (self->mosi_pad_config.pad_nr == 2 && self->sck_pad_config.pad_nr == 3) { + dopo = 1; + } else if (self->mosi_pad_config.pad_nr == 3 && self->sck_pad_config.pad_nr == 1) { + dopo = 2; + } else if (self->mosi_pad_config.pad_nr == 0 && self->sck_pad_config.pad_nr == 3) { + dopo = 3; + } else { + mp_raise_ValueError(MP_ERROR_TEXT("invalid pin for sck or mosi")); + } + #elif defined(MCU_SAMD51) + if (self->mosi_pad_config.pad_nr == 0 && self->sck_pad_config.pad_nr == 1) { + dopo = 0; + } else if (self->mosi_pad_config.pad_nr == 3 && self->sck_pad_config.pad_nr == 1) { + dopo = 2; + } else { + mp_raise_ValueError(MP_ERROR_TEXT("invalid pin for sck or mosi")); + } + #endif + + if (self->miso != 0xff) { // Miso may be undefined + self->miso_pad_config = get_sercom_config(self->miso, self->id); + mp_hal_set_pin_mux(self->miso, self->miso_pad_config.alt_fct); + } + // Configure the Pin mux. + mp_hal_set_pin_mux(self->sck, self->sck_pad_config.alt_fct); + mp_hal_set_pin_mux(self->mosi, self->mosi_pad_config.alt_fct); + + // Set up the clocks + enable_sercom_clock(self->id); + + // Configure the SPI + Sercom *spi = sercom_instance[self->id]; + // Reset (clear) the peripheral registers. + while (spi->SPI.SYNCBUSY.bit.SWRST) { + } + spi->SPI.CTRLA.bit.SWRST = 1; + while (spi->SPI.SYNCBUSY.bit.SWRST) { + } + + // Set the registers + spi->SPI.CTRLA.bit.MODE = 0x03; // SPI master mode + spi->SPI.CTRLA.bit.CPOL = self->polarity; + spi->SPI.CTRLA.bit.CPHA = self->phase; + spi->SPI.CTRLA.bit.DIPO = self->miso_pad_config.pad_nr; + spi->SPI.CTRLA.bit.DOPO = dopo; + spi->SPI.CTRLA.bit.DORD = self->firstbit; + + // Enable receive only if miso is defined + if (self->miso != 0xff) { + spi->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_RXEN; + while (spi->SPI.SYNCBUSY.bit.CTRLB) { + } + } + + #if defined(MCU_SAMD51) + spi->SPI.CTRLC.reg = 1; // 1 clock cycle character spacing + #endif + + // SPI is driven by the clock of GCLK Generator 2, freq in bus_freq + // baud = bus_freq / (2 * baudrate) - 1 + uint32_t baud = get_apb_freq() / (2 * self->baudrate) - 1; + spi->SPI.BAUD.reg = baud; // Set Baud + + // Enable RXC interrupt only if miso is defined + if (self->miso != 0xff) { + #if defined(MCU_SAMD21) + NVIC_EnableIRQ(SERCOM0_IRQn + self->id); + #elif defined(MCU_SAMD51) + NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 2); + #endif + sercom_register_irq(self->id, SERCOM_IRQ_TYPE_SPI); + } + + sercom_enable(spi, 1); + } +} + +STATIC mp_obj_t machine_spi_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 SPI bus. + int spi_id = mp_obj_get_int(args[0]); + if (spi_id < 0 || spi_id > SERCOM_INST_NUM) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SPI(%d) doesn't exist"), spi_id); + } + + // Create the SPI object and fill it with defaults. + machine_spi_obj_t *self = mp_obj_malloc(machine_spi_obj_t, &machine_spi_type); + self->id = spi_id; + self->baudrate = DEFAULT_SPI_BAUDRATE; + self->polarity = DEFAULT_SPI_POLARITY; + self->phase = DEFAULT_SPI_PHASE; + self->firstbit = DEFAULT_SPI_FIRSTBIT; + self->mosi = 0xff; // 0xff: pin not defined (yet) + self->miso = 0xff; + self->sck = 0xff; + + self->new = true; + sercom_table[spi_id] = self; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + machine_spi_init((mp_obj_base_t *)self, n_args - 1, args + 1, &kw_args); + return self; +} + +void sercom_deinit_all(void) { + for (int i = 0; i < SERCOM_INST_NUM; i++) { + if (sercom_table[i] != NULL) { + machine_spi_obj_t *self = sercom_table[i]; + Sercom *spi = sercom_instance[self->id]; + // Disable interrupts (if any) + spi->SPI.INTENCLR.reg = 0xff; + // clear table entry of spi + sercom_table[i] = NULL; + sercom_enable(spi, 0); + } + } +} + +STATIC void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) { + machine_spi_obj_t *self = (machine_spi_obj_t *)self_in; + + Sercom *spi = sercom_instance[self->id]; + size_t txlen = len; + // Clear the input queue, if needed + while (dest && spi->SPI.INTFLAG.bit.RXC) { + uint32_t temp; + (void)temp; + temp = spi->SPI.DATA.bit.DATA; + } + // Set up the irq data pointers and enable IRQ + if (dest) { + if (self->miso == 0xff) { + mp_raise_ValueError(MP_ERROR_TEXT("read is not enabled")); + } + spi->SPI.INTENSET.bit.RXC = 1; + self->dest = dest; + self->rxlen = len; + } + + // Send by polling & receive by IRQ + while (txlen) { + if (spi->SPI.INTFLAG.bit.DRE) { + spi->SPI.DATA.bit.DATA = *src; + src += 1; + txlen--; + } + } + // Receive the remaining data, if any and clear IRQ + // Do no wait forever. + if (dest) { + int32_t timeout = 1000; + while (self->rxlen > 0 && timeout) { + timeout--; + MICROPY_EVENT_POLL_HOOK + } + spi->SPI.INTENCLR.bit.RXC = 1; + } else { + // Wait for the data being shifted out. + while (!spi->SPI.INTFLAG.bit.TXC) { + } + } +} + + +STATIC const mp_machine_spi_p_t machine_spi_p = { + .init = machine_spi_init, + .transfer = machine_spi_transfer, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + machine_spi_type, + MP_QSTR_SPI, + MP_TYPE_FLAG_NONE, + make_new, machine_spi_make_new, + print, machine_spi_print, + protocol, &machine_spi_p, + locals_dict, &mp_machine_spi_locals_dict + ); diff --git a/ports/samd/main.c b/ports/samd/main.c index 60b8e57faa..1f056083a1 100644 --- a/ports/samd/main.c +++ b/ports/samd/main.c @@ -36,6 +36,7 @@ extern uint8_t _sstack, _estack, _sheap, _eheap; extern void adc_deinit_all(void); extern void pin_irq_deinit_all(void); extern void pwm_deinit_all(void); +extern void sercom_deinit_all(void); extern void uart_deinit_all(void); void samd_main(void) { @@ -69,6 +70,7 @@ void samd_main(void) { adc_deinit_all(); pin_irq_deinit_all(); pwm_deinit_all(); + sercom_deinit_all(); uart_deinit_all(); gc_sweep_all(); mp_deinit(); diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index 8c3033f891..712b520f54 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -155,6 +155,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) }, diff --git a/ports/samd/modmachine.h b/ports/samd/modmachine.h index 30de339b4a..143e3488f0 100644 --- a/ports/samd/modmachine.h +++ b/ports/samd/modmachine.h @@ -32,6 +32,7 @@ extern const mp_obj_type_t machine_adc_type; extern const mp_obj_type_t machine_led_type; extern const mp_obj_type_t machine_pin_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_uart_type; #endif // MICROPY_INCLUDED_SAMD_MODMACHINE_H diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index b8cb0f3eb7..22fed00b24 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -99,6 +99,7 @@ #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_UASYNCIO (1) #define MICROPY_PY_MACHINE_SOFTI2C (1) +#define MICROPY_PY_MACHINE_SPI (1) #define MICROPY_PY_MACHINE_SOFTSPI (1) #define MICROPY_PY_MACHINE_PWM (1) #define MICROPY_PY_MACHINE_PWM_INIT (0) diff --git a/ports/samd/samd_isr.c b/ports/samd/samd_isr.c index 0e0d84db69..2a5a3e042c 100644 --- a/ports/samd/samd_isr.c +++ b/ports/samd/samd_isr.c @@ -112,7 +112,7 @@ static uint8_t sercom_irq_type[SERCOM_INST_NUM] = {}; // Temporarily commented until the module is added void (*sercom_irq_handler_table[])(int num) = { common_uart_irq_handler, - NULL, // common_spi_irq_handler, + common_spi_irq_handler, NULL // common_i2c_irq_handler }; From 94d27ae28fd4b815b3ace7dd91643aa0d1b620cd Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 5 Jun 2022 18:11:06 +0200 Subject: [PATCH 0493/1041] samd/machine_i2c: Add the machine.I2C class. Using the common API. Tested with SAMD21 and SAMD51 boards. --- ports/samd/Makefile | 2 + ports/samd/machine_i2c.c | 270 ++++++++++++++++++++++++++++++++++++++ ports/samd/modmachine.c | 1 + ports/samd/modmachine.h | 1 + ports/samd/mpconfigport.h | 1 + ports/samd/samd_isr.c | 4 +- 6 files changed, 277 insertions(+), 2 deletions(-) create mode 100644 ports/samd/machine_i2c.c diff --git a/ports/samd/Makefile b/ports/samd/Makefile index ca0309fa69..c5d36adda4 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -91,6 +91,7 @@ SRC_C = \ clock_config.c \ help.c \ machine_adc.c \ + machine_i2c.c \ machine_led.c \ machine_pin.c \ machine_spi.c \ @@ -143,6 +144,7 @@ endif # List of sources for qstr extraction SRC_QSTR += \ machine_adc.c \ + machine_i2c.c \ machine_led.c \ machine_pin.c \ machine_pwm.c \ diff --git a/ports/samd/machine_i2c.c b/ports/samd/machine_i2c.c new file mode 100644 index 0000000000..4d1b03f7d5 --- /dev/null +++ b/ports/samd/machine_i2c.c @@ -0,0 +1,270 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 Damien P. George + * Copyright (c) 2022 Robert Hammelrath + * + * 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/mphal.h" +#include "py/mperrno.h" +#include "extmod/machine_i2c.h" +#include "modmachine.h" +#include "samd_soc.h" +#include "pin_af.h" +#include "clock_config.h" + +#define DEFAULT_I2C_FREQ (400000) +#define RISETIME_NS (300) +#define I2C_TIMEOUT (100) + +#define IS_BUS_BUSY (i2c->I2CM.STATUS.bit.BUSSTATE == 3) +#define NACK_RECVD (i2c->I2CM.STATUS.bit.RXNACK == 1) +#define IRQ_DATA_SENT (i2c->I2CM.INTFLAG.bit.MB == 1) +#define IRQ_DATA_RECVD (i2c->I2CM.INTFLAG.bit.SB == 1) +#define READ_MODE ((flags & MP_MACHINE_I2C_FLAG_READ) != 0) + +#define PREPARE_ACK i2c->I2CM.CTRLB.bit.ACKACT = 0 +#define PREPARE_NACK i2c->I2CM.CTRLB.bit.ACKACT = 1 +#define SET_STOP_STATE i2c_send_command(i2c, 0x03) + +enum state_t { + state_done = 0, + state_busy, + state_buserr, + state_nack +}; + +typedef struct _machine_i2c_obj_t { + mp_obj_base_t base; + Sercom *instance; + uint8_t id; + uint8_t scl; + uint8_t sda; + uint8_t state; + uint32_t freq; + uint32_t timeout; + size_t len; + uint8_t *buf; +} machine_i2c_obj_t; + +extern Sercom *sercom_instance[]; +extern void *sercom_table[SERCOM_INST_NUM]; + +STATIC void i2c_send_command(Sercom *i2c, uint8_t command) { + i2c->I2CM.CTRLB.bit.CMD = command; + while (i2c->I2CM.SYNCBUSY.bit.SYSOP) { + } +} + +void common_i2c_irq_handler(int i2c_id) { + // handle Sercom I2C IRQ + machine_i2c_obj_t *self = sercom_table[i2c_id]; + // Handle IRQ + if (self != NULL) { + Sercom *i2c = self->instance; + // For now, clear all interrupts + if (IRQ_DATA_RECVD) { + if (self->len > 0) { + *(self->buf)++ = i2c->I2CM.DATA.reg; + self->len--; + self->timeout = I2C_TIMEOUT; + } + if (self->len > 0) { // no ACK at the last byte + PREPARE_ACK; // Send ACK + i2c_send_command(i2c, 0x02); + } else { + PREPARE_NACK; // Send NACK after the last byte + self->state = state_done; + i2c->I2CM.INTFLAG.reg |= SERCOM_I2CM_INTFLAG_SB; + } + } else if (IRQ_DATA_SENT) { + if (NACK_RECVD) { // e.g. NACK after adress for both read and write. + self->state = state_nack; // force stop of transmission + i2c->I2CM.INTFLAG.reg |= SERCOM_I2CM_INTFLAG_MB; + } else if (self->len > 0) { // data to be sent + i2c->I2CM.DATA.bit.DATA = *(self->buf)++; + self->len--; + self->timeout = I2C_TIMEOUT; + } else { // No data left, if there was any. + self->state = state_done; + i2c->I2CM.INTFLAG.reg |= SERCOM_I2CM_INTFLAG_MB; + } + } else { // On any error, e.g. ARBLOST or BUSERROR, stop the transmission + self->len = 0; + self->state = state_buserr; + i2c->I2CM.INTFLAG.reg |= SERCOM_I2CM_INTFLAG_ERROR; + } + } +} + +STATIC void machine_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "I2C(%u, freq=%u, scl=%u, sda=%u)", + self->id, self->freq, self->scl, self->sda); +} + +mp_obj_t machine_i2c_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_freq, ARG_scl, ARG_sda }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_freq, MP_ARG_INT, {.u_int = DEFAULT_I2C_FREQ} }, + { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + }; + + // Parse args. + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // Get I2C bus. + int id = mp_obj_get_int(args[ARG_id].u_obj); + if (id < 0 || id >= SERCOM_INST_NUM) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("I2C(%d) doesn't exist"), id); + } + + // Get the peripheral object. + machine_i2c_obj_t *self = mp_obj_malloc(machine_i2c_obj_t, &machine_hw_i2c_type); + self->id = id; + self->instance = sercom_instance[self->id]; + + // Set SCL/SDA pins. + sercom_pad_config_t scl_pad_config; + self->scl = mp_hal_get_pin_obj(args[ARG_scl].u_obj); + scl_pad_config = get_sercom_config(self->scl, self->id); + + sercom_pad_config_t sda_pad_config; + self->sda = mp_hal_get_pin_obj(args[ARG_sda].u_obj); + sda_pad_config = get_sercom_config(self->sda, self->id); + if (sda_pad_config.pad_nr != 0 || scl_pad_config.pad_nr != 1) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid pin for sda or scl")); + } + sercom_table[self->id] = self; + self->freq = args[ARG_freq].u_int; + + // Configure the Pin mux. + mp_hal_set_pin_mux(self->scl, scl_pad_config.alt_fct); + mp_hal_set_pin_mux(self->sda, sda_pad_config.alt_fct); + + // Set up the clocks + enable_sercom_clock(self->id); + + // Initialise the I2C peripheral + Sercom *i2c = self->instance; + + // Reset the device + i2c->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_SWRST; + while (i2c->I2CM.SYNCBUSY.bit.SWRST == 1) { + } + // Set to master mode, inactivity timeout of 20 SCL cycles and speed. + i2c->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_MODE(0x05) + | SERCOM_I2CM_CTRLA_INACTOUT(3) + | SERCOM_I2CM_CTRLA_SPEED(self->freq > 400000 ? 1 : 0); + + // I2C is driven by the clock of GCLK Generator 2, with it's freq in variable bus_freq + // baud = peripheral_freq / (2 * baudrate) - 5 - (rise_time * peripheral_freq) / 2 + // Just set the minimal configuration for standard and fast mode. + // Set Baud. Assume ~300ns rise time. Maybe set later by a keyword argument. + i2c->I2CM.BAUD.reg = get_apb_freq() / (2 * self->freq) - 5 - (get_apb_freq() / 1000000) * RISETIME_NS / 2000; + + // Enable interrupts + sercom_register_irq(self->id, SERCOM_IRQ_TYPE_SPI); + #if defined(MCU_SAMD21) + NVIC_EnableIRQ(SERCOM0_IRQn + self->id); + #elif defined(MCU_SAMD51) + NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id); // MB interrupt + NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 1); // SB interrupt + NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 3); // ERRROR interrupt + #endif + + // Now enable I2C. + sercom_enable(i2c, 1); + + // Force the bus state to idle + i2c->I2CM.STATUS.bit.BUSSTATE = 1; + + return MP_OBJ_FROM_PTR(self); +} + +STATIC int machine_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags) { + machine_i2c_obj_t *self = (machine_i2c_obj_t *)self_in; + Sercom *i2c = self->instance; + + self->timeout = I2C_TIMEOUT; + self->len = len; + self->buf = buf; + // Wait a while if the bus is busy + while (IS_BUS_BUSY && self->timeout) { + MICROPY_EVENT_POLL_HOOK + if (--self->timeout == 0) { + return -MP_ETIMEDOUT; + } + } + // Enable interrupts and set the state + i2c->I2CM.INTENSET.reg = SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB | SERCOM_I2CM_INTENSET_ERROR; + self->state = state_busy; + + // Send the adress, which kicks off the transfer + i2c->I2CM.ADDR.bit.ADDR = (addr << 1) | READ_MODE; + + // Transfer the data + self->timeout = I2C_TIMEOUT; + while (self->state == state_busy && self->timeout) { + self->timeout--; + MICROPY_EVENT_POLL_HOOK + } + i2c->I2CM.INTENCLR.reg = SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB | SERCOM_I2CM_INTENSET_ERROR; + + // Check the error states after the transfer is stopped + if (self->state == state_nack) { + SET_STOP_STATE; + return self->len == len ? -MP_ENODEV : -MP_EIO; + } else if (self->state == state_buserr) { + SET_STOP_STATE; + return -MP_EIO; + } else if (self->timeout == 0) { + SET_STOP_STATE; + return -MP_ETIMEDOUT; + } + + if (flags & MP_MACHINE_I2C_FLAG_STOP) { + SET_STOP_STATE; + } + + return len; +} + +STATIC const mp_machine_i2c_p_t machine_i2c_p = { + .transfer = mp_machine_i2c_transfer_adaptor, + .transfer_single = machine_i2c_transfer_single, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + machine_hw_i2c_type, + MP_QSTR_I2C, + MP_TYPE_FLAG_NONE, + make_new, machine_i2c_make_new, + print, machine_i2c_print, + protocol, &machine_i2c_p, + locals_dict, &mp_machine_i2c_locals_dict + ); diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index 712b520f54..acd672fafe 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -154,6 +154,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hw_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, diff --git a/ports/samd/modmachine.h b/ports/samd/modmachine.h index 143e3488f0..4319867190 100644 --- a/ports/samd/modmachine.h +++ b/ports/samd/modmachine.h @@ -29,6 +29,7 @@ #include "py/obj.h" extern const mp_obj_type_t machine_adc_type; +extern const mp_obj_type_t machine_hw_i2c_type; extern const mp_obj_type_t machine_led_type; extern const mp_obj_type_t machine_pin_type; extern const mp_obj_type_t machine_pwm_type; diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 22fed00b24..425ecc5977 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -98,6 +98,7 @@ #define MICROPY_PY_URANDOM (1) #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_UASYNCIO (1) +#define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_SOFTI2C (1) #define MICROPY_PY_MACHINE_SPI (1) #define MICROPY_PY_MACHINE_SOFTSPI (1) diff --git a/ports/samd/samd_isr.c b/ports/samd/samd_isr.c index 2a5a3e042c..5cb0668c25 100644 --- a/ports/samd/samd_isr.c +++ b/ports/samd/samd_isr.c @@ -109,11 +109,11 @@ void PendSV_Handler(void) { static uint8_t sercom_irq_type[SERCOM_INST_NUM] = {}; -// Temporarily commented until the module is added + void (*sercom_irq_handler_table[])(int num) = { common_uart_irq_handler, common_spi_irq_handler, - NULL // common_i2c_irq_handler + common_i2c_irq_handler }; void sercom_register_irq(int sercom_id, int mode) { From 15212ae8d423dced7698219def0f2d13287a64b8 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 5 Jun 2022 20:34:37 +0200 Subject: [PATCH 0494/1041] samd/moduos: Add uos.dupterm(). --- ports/samd/Makefile | 2 ++ ports/samd/moduos.c | 57 +++++++++++++++++++++++++++++++++++++++ ports/samd/mpconfigport.h | 2 ++ ports/samd/mphalport.c | 12 +++++++++ 4 files changed, 73 insertions(+) create mode 100644 ports/samd/moduos.c diff --git a/ports/samd/Makefile b/ports/samd/Makefile index c5d36adda4..f31e5ba6ec 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -121,6 +121,7 @@ SRC_C = \ lib/tinyusb/src/portable/microchip/samd/dcd_samd.c \ lib/tinyusb/src/tusb.c \ drivers/bus/softspi.c \ + extmod/uos_dupterm.c \ shared/runtime/mpirq.c \ shared/libc/printf.c \ shared/libc/string0.c \ @@ -155,6 +156,7 @@ SRC_QSTR += \ modsamd.c \ samd_flash.c \ shared/readline/readline.c \ + extmod/uos_dupterm.c \ shared/runtime/mpirq.c \ SRC_QSTR += $(SRC_MOD) $(SRC_CXX) diff --git a/ports/samd/moduos.c b/ports/samd/moduos.c new file mode 100644 index 0000000000..b1118f0195 --- /dev/null +++ b/ports/samd/moduos.c @@ -0,0 +1,57 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Damien P. George + * + * use of the TRNG by + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2019 Artur Pacholec + * Copyright (c) 2022 Robert Hammelrath + * + * 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/mphal.h" +#include "modmachine.h" +#include "sam.h" + +#if MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM +bool mp_uos_dupterm_is_builtin_stream(mp_const_obj_t stream) { + const mp_obj_type_t *type = mp_obj_get_type(stream); + return type == &machine_uart_type; +} +#endif + +#if MICROPY_PY_UOS_DUPTERM_NOTIFY +STATIC mp_obj_t mp_uos_dupterm_notify(mp_obj_t obj_in) { + (void)obj_in; + for (;;) { + int c = mp_uos_dupterm_rx_chr(); + if (c < 0) { + break; + } + ringbuf_put(&stdin_ringbuf, c); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_dupterm_notify_obj, mp_uos_dupterm_notify); +#endif diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 425ecc5977..8238c3d2b5 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -88,6 +88,7 @@ #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_MACHINE (1) #define MICROPY_PY_UOS (1) +#define MICROPY_PY_UOS_INCLUDEFILE "ports/samd/moduos.c" #define MICROPY_READER_VFS (1) #define MICROPY_VFS (1) #define MICROPY_PY_UJSON (1) @@ -102,6 +103,7 @@ #define MICROPY_PY_MACHINE_SOFTI2C (1) #define MICROPY_PY_MACHINE_SPI (1) #define MICROPY_PY_MACHINE_SOFTSPI (1) +#define MICROPY_PY_OS_DUPTERM (3) #define MICROPY_PY_MACHINE_PWM (1) #define MICROPY_PY_MACHINE_PWM_INIT (0) #define MICROPY_PY_MACHINE_PWM_DUTY_U16_NS (1) diff --git a/ports/samd/mphalport.c b/ports/samd/mphalport.c index 7a3786be8c..fc45102390 100644 --- a/ports/samd/mphalport.c +++ b/ports/samd/mphalport.c @@ -97,6 +97,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { if (tud_cdc_connected() && tud_cdc_available()) { ret |= MP_STREAM_POLL_RD; } + #if MICROPY_PY_OS_DUPTERM + ret |= mp_uos_dupterm_poll(poll_flags); + #endif return ret; } @@ -109,6 +112,12 @@ int mp_hal_stdin_rx_chr(void) { return buf[0]; } } + #if MICROPY_PY_OS_DUPTERM + int dupterm_c = mp_uos_dupterm_rx_chr(); + if (dupterm_c >= 0) { + return dupterm_c; + } + #endif MICROPY_EVENT_POLL_HOOK } } @@ -128,4 +137,7 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { i += n2; } } + #if MICROPY_PY_OS_DUPTERM + mp_uos_dupterm_tx_strn(str, len); + #endif } From 45bf25a0022033474b9fe699267297f882ca9772 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 5 Jun 2022 21:08:37 +0200 Subject: [PATCH 0495/1041] samd/moduos: Add uos.urandom() for SAMD51. Based on the hardware RNG. --- ports/samd/boards/mpconfig_samd51.h | 3 +++ ports/samd/moduos.c | 40 +++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/ports/samd/boards/mpconfig_samd51.h b/ports/samd/boards/mpconfig_samd51.h index 1b67b1d02d..d963fe1dd2 100644 --- a/ports/samd/boards/mpconfig_samd51.h +++ b/ports/samd/boards/mpconfig_samd51.h @@ -5,6 +5,9 @@ #define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) +#define MICROPY_PY_UOS_URANDOM (1) +#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (trng_random_u32()) +unsigned long trng_random_u32(void); // Due to a limitation in the TC counter for us, the ticks period is 2**29 #define MICROPY_PY_UTIME_TICKS_PERIOD (0x20000000) diff --git a/ports/samd/moduos.c b/ports/samd/moduos.c index b1118f0195..e0237fd88f 100644 --- a/ports/samd/moduos.c +++ b/ports/samd/moduos.c @@ -34,6 +34,46 @@ #include "modmachine.h" #include "sam.h" +#if defined(MCU_SAMD51) +static bool initialized = false; + +STATIC void trng_start(void) { + if (!initialized) { + MCLK->APBCMASK.bit.TRNG_ = 1; + REG_TRNG_CTRLA = TRNG_CTRLA_ENABLE; + initialized = true; + } +} + +uint32_t trng_random_u32(void) { + trng_start(); + while ((REG_TRNG_INTFLAG & TRNG_INTFLAG_DATARDY) == 0) { + } + return REG_TRNG_DATA; +} + +#if MICROPY_PY_UOS_URANDOM +STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) { + mp_int_t n = mp_obj_get_int(num); + vstr_t vstr; + vstr_init_len(&vstr, n); + uint32_t rngval = 0; + + trng_start(); + for (int i = 0; i < n; i++) { + if ((i % 4) == 0) { + rngval = trng_random_u32(); + } + vstr.buf[i] = rngval & 0xff; + rngval >>= 8; + } + return mp_obj_new_bytes_from_vstr(&vstr); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom); + +#endif // MICROPY_PY_UOS_URANDOM +#endif // defined(MCU_SAMD51) + #if MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM bool mp_uos_dupterm_is_builtin_stream(mp_const_obj_t stream) { const mp_obj_type_t *type = mp_obj_get_type(stream); From 4ef2da176f2ca1e7f3cb02488aba61a018033575 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 5 Jun 2022 21:55:30 +0200 Subject: [PATCH 0496/1041] samd/main: Use the common execution mode of boot.py and main.py. Behaviour is: - Do not execute main.py if boot.py failed. - On a forced exit, do a soft reset. --- ports/samd/main.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/ports/samd/main.c b/ports/samd/main.c index 1f056083a1..5aab39e509 100644 --- a/ports/samd/main.c +++ b/ports/samd/main.c @@ -51,8 +51,17 @@ void samd_main(void) { pyexec_frozen_module("_boot.py"); // Execute user scripts. - pyexec_file_if_exists("boot.py"); - pyexec_file_if_exists("main.py"); + int ret = pyexec_file_if_exists("boot.py"); + if (ret & PYEXEC_FORCED_EXIT) { + goto soft_reset_exit; + } + // Do not execute main.py if boot.py failed + if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL && ret != 0) { + ret = pyexec_file_if_exists("main.py"); + if (ret & PYEXEC_FORCED_EXIT) { + goto soft_reset_exit; + } + } for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { @@ -66,6 +75,7 @@ void samd_main(void) { } } + soft_reset_exit: mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n"); adc_deinit_all(); pin_irq_deinit_all(); From 009c51c13fc13233a28386d5e78ac79cd773cc79 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 5 Jun 2022 22:03:16 +0200 Subject: [PATCH 0497/1041] samd/mpconfigport: Enable a few more MicroPython features. Additional features are: - Support executing .mpy files. - Allow const(). - Enable auto-indent in REPL. - Enable enumerate, min/max, attrtuple, input. --- ports/samd/mpconfigport.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 8238c3d2b5..c2c614e10b 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -38,14 +38,20 @@ #define MICROPY_ALLOC_PATH_MAX (256) #define MICROPY_QSTR_BYTES_IN_HASH (1) +// MicroPython emitters +#define MICROPY_PERSISTENT_CODE_LOAD (1) +#define MICROPY_EMIT_THUMB (0) +#define MICROPY_EMIT_INLINE_THUMB (0) + // Compiler configuration -#define MICROPY_COMP_CONST (0) +#define MICROPY_COMP_CONST (1) // Python internal features #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_HELPER_REPL (1) +#define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_STREAMS_NON_BLOCK (1) @@ -66,15 +72,16 @@ #define MICROPY_PY_BUILTINS_SET (0) #define MICROPY_PY_BUILTINS_FROZENSET (0) #define MICROPY_PY_BUILTINS_PROPERTY (0) -#define MICROPY_PY_BUILTINS_ENUMERATE (0) +#define MICROPY_PY_BUILTINS_ENUMERATE (1) #define MICROPY_PY_BUILTINS_FILTER (0) #define MICROPY_PY_BUILTINS_REVERSED (0) #define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) -#define MICROPY_PY_BUILTINS_MIN_MAX (0) +#define MICROPY_PY_BUILTINS_MIN_MAX (1) +#define MICROPY_PY_BUILTINS_INPUT (1) #define MICROPY_PY___FILE__ (0) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) -#define MICROPY_PY_ATTRTUPLE (0) +#define MICROPY_PY_ATTRTUPLE (1) #define MICROPY_PY_COLLECTIONS (0) #define MICROPY_PY_SYS (1) #define MICROPY_PY_SYS_PLATFORM "samd" From 3625388d8ce028df4bb23077e1a569c987fa91fb Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 6 Jun 2022 10:20:44 +0200 Subject: [PATCH 0498/1041] samd/samd_isr: Change the way a Sercom ISR is registered and called. Code size diff: +12 Bytes BSS diff: -12 Bytes RAM usage: +16 Bytes Speed increase: a few clock cycles per call Style improvement: ++ --- ports/samd/machine_i2c.c | 2 +- ports/samd/machine_spi.c | 2 +- ports/samd/machine_uart.c | 2 +- ports/samd/samd_isr.c | 18 +++++++----------- ports/samd/samd_soc.h | 5 +---- 5 files changed, 11 insertions(+), 18 deletions(-) diff --git a/ports/samd/machine_i2c.c b/ports/samd/machine_i2c.c index 4d1b03f7d5..90ea5e10ca 100644 --- a/ports/samd/machine_i2c.c +++ b/ports/samd/machine_i2c.c @@ -188,7 +188,7 @@ mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n i2c->I2CM.BAUD.reg = get_apb_freq() / (2 * self->freq) - 5 - (get_apb_freq() / 1000000) * RISETIME_NS / 2000; // Enable interrupts - sercom_register_irq(self->id, SERCOM_IRQ_TYPE_SPI); + sercom_register_irq(self->id, &common_i2c_irq_handler); #if defined(MCU_SAMD21) NVIC_EnableIRQ(SERCOM0_IRQn + self->id); #elif defined(MCU_SAMD51) diff --git a/ports/samd/machine_spi.c b/ports/samd/machine_spi.c index b3504aeba3..ddb8756e9a 100644 --- a/ports/samd/machine_spi.c +++ b/ports/samd/machine_spi.c @@ -218,7 +218,7 @@ STATIC void machine_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj #elif defined(MCU_SAMD51) NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 2); #endif - sercom_register_irq(self->id, SERCOM_IRQ_TYPE_SPI); + sercom_register_irq(self->id, &common_spi_irq_handler); } sercom_enable(spi, 1); diff --git a/ports/samd/machine_uart.c b/ports/samd/machine_uart.c index 9c5cfce839..0ed7fb95d0 100644 --- a/ports/samd/machine_uart.c +++ b/ports/samd/machine_uart.c @@ -281,7 +281,7 @@ STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args #elif defined(MCU_SAMD51) NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 2); #endif - sercom_register_irq(self->id, SERCOM_IRQ_TYPE_UART); + sercom_register_irq(self->id, &common_uart_irq_handler); sercom_enable(uart, 1); } diff --git a/ports/samd/samd_isr.c b/ports/samd/samd_isr.c index 5cb0668c25..ed88ca229d 100644 --- a/ports/samd/samd_isr.c +++ b/ports/samd/samd_isr.c @@ -108,21 +108,17 @@ void PendSV_Handler(void) { } -static uint8_t sercom_irq_type[SERCOM_INST_NUM] = {}; +void (*sercom_irq_handler_table[SERCOM_INST_NUM])(int num) = {}; -void (*sercom_irq_handler_table[])(int num) = { - common_uart_irq_handler, - common_spi_irq_handler, - common_i2c_irq_handler -}; - -void sercom_register_irq(int sercom_id, int mode) { - sercom_irq_type[sercom_id] = mode; +void sercom_register_irq(int sercom_id, void (*sercom_irq_handler)) { + if (sercom_id < SERCOM_INST_NUM) { + sercom_irq_handler_table[sercom_id] = sercom_irq_handler; + } } static inline void common_sercom_irq_handler(int sercom_id) { - if (sercom_irq_handler_table[sercom_irq_type[sercom_id]]) { - sercom_irq_handler_table[sercom_irq_type[sercom_id]](sercom_id); + if (sercom_irq_handler_table[sercom_id]) { + sercom_irq_handler_table[sercom_id](sercom_id); } } diff --git a/ports/samd/samd_soc.h b/ports/samd/samd_soc.h index b97159dc7f..e8560b50e8 100644 --- a/ports/samd/samd_soc.h +++ b/ports/samd/samd_soc.h @@ -39,11 +39,8 @@ void USB_1_Handler_wrapper(void); void USB_2_Handler_wrapper(void); void USB_3_Handler_wrapper(void); -void common_uart_irq_handler(int uart_nr); -void common_spi_irq_handler(int spi_nr); -void common_i2c_irq_handler(int i2c_nr); void sercom_enable(Sercom *spi, int state); -void sercom_register_irq(int sercom_id, int mode); +void sercom_register_irq(int sercom_id, void (*sercom_irq_handler)); #define SERCOM_IRQ_TYPE_UART (0) #define SERCOM_IRQ_TYPE_SPI (1) From 32c973d554a31d919ca582d77f4d524760093d4d Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 6 Jun 2022 11:13:25 +0200 Subject: [PATCH 0499/1041] samd/machine_timer: Add machine.Timer based on the shared soft-timer. --- ports/samd/Makefile | 4 + ports/samd/boards/mpconfig_samd21.h | 11 +++ ports/samd/boards/mpconfig_samd51.h | 20 ++++ ports/samd/machine_timer.c | 146 ++++++++++++++++++++++++++++ ports/samd/main.c | 2 + ports/samd/modmachine.c | 1 + ports/samd/modmachine.h | 1 + ports/samd/mphalport.h | 4 + ports/samd/pendsv.c | 71 ++++++++++++++ ports/samd/pendsv.h | 41 ++++++++ ports/samd/samd_isr.c | 18 ++-- 11 files changed, 307 insertions(+), 12 deletions(-) create mode 100644 ports/samd/machine_timer.c create mode 100644 ports/samd/pendsv.c create mode 100644 ports/samd/pendsv.h diff --git a/ports/samd/Makefile b/ports/samd/Makefile index f31e5ba6ec..e3d0d28f8f 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -95,12 +95,14 @@ SRC_C = \ machine_led.c \ machine_pin.c \ machine_spi.c \ + machine_timer.c \ machine_uart.c \ main.c \ modutime.c \ modmachine.c \ modsamd.c \ mphalport.c \ + pendsv.c \ pin_af.c \ $(BUILD)/pins.c \ samd_flash.c \ @@ -128,6 +130,7 @@ SRC_C = \ shared/readline/readline.c \ shared/runtime/gchelper_native.c \ shared/runtime/pyexec.c \ + shared/runtime/softtimer.c \ shared/runtime/stdout_helpers.c \ shared/runtime/sys_stdio_mphal.c \ shared/timeutils/timeutils.c \ @@ -150,6 +153,7 @@ SRC_QSTR += \ machine_pin.c \ machine_pwm.c \ machine_spi.c \ + machine_timer.c \ machine_uart.c \ modutime.c \ modmachine.c \ diff --git a/ports/samd/boards/mpconfig_samd21.h b/ports/samd/boards/mpconfig_samd21.h index 1924f66f06..587f3f4b3a 100644 --- a/ports/samd/boards/mpconfig_samd21.h +++ b/ports/samd/boards/mpconfig_samd21.h @@ -7,3 +7,14 @@ #define CPU_FREQ (48000000) #define APB_FREQ (48000000) + +#define IRQ_PRI_PENDSV ((1 << __NVIC_PRIO_BITS) - 1) + +static inline uint32_t raise_irq_pri(uint32_t pri) { + (void)pri; + return 0; +} + +static inline void restore_irq_pri(uint32_t basepri) { + (void)basepri; +} diff --git a/ports/samd/boards/mpconfig_samd51.h b/ports/samd/boards/mpconfig_samd51.h index d963fe1dd2..95fc635e5e 100644 --- a/ports/samd/boards/mpconfig_samd51.h +++ b/ports/samd/boards/mpconfig_samd51.h @@ -22,3 +22,23 @@ unsigned long trng_random_u32(void); #define CPU_FREQ (120000000) #define APB_FREQ (48000000) #define DPLLx_REF_FREQ (32768) + +#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003) +#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 7, 0) + +static inline uint32_t raise_irq_pri(uint32_t pri) { + uint32_t basepri = __get_BASEPRI(); + // If non-zero, the processor does not process any exception with a + // priority value greater than or equal to BASEPRI. + // When writing to BASEPRI_MAX the write goes to BASEPRI only if either: + // - Rn is non-zero and the current BASEPRI value is 0 + // - Rn is non-zero and less than the current BASEPRI value + pri <<= (8 - __NVIC_PRIO_BITS); + __ASM volatile ("msr basepri_max, %0" : : "r" (pri) : "memory"); + return basepri; +} + +// "basepri" should be the value returned from raise_irq_pri +static inline void restore_irq_pri(uint32_t basepri) { + __set_BASEPRI(basepri); +} diff --git a/ports/samd/machine_timer.c b/ports/samd/machine_timer.c new file mode 100644 index 0000000000..640d1d200f --- /dev/null +++ b/ports/samd/machine_timer.c @@ -0,0 +1,146 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 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/mphal.h" +#include "shared/runtime/softtimer.h" + +typedef soft_timer_entry_t machine_timer_obj_t; + +const mp_obj_type_t machine_timer_type; + +STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); + qstr mode = self->mode == SOFT_TIMER_MODE_ONE_SHOT ? MP_QSTR_ONE_SHOT : MP_QSTR_PERIODIC; + mp_printf(print, "Timer(mode=%q, period=%u)", mode, self->delta_ms); +} + +STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_mode, ARG_callback, ARG_period, ARG_tick_hz, ARG_freq, }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SOFT_TIMER_MODE_PERIODIC} }, + { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, + { MP_QSTR_tick_hz, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} }, + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + }; + + // Parse args + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + self->mode = args[ARG_mode].u_int; + + uint64_t delta_ms = self->delta_ms; + if (args[ARG_freq].u_obj != mp_const_none) { + // Frequency specified in Hz + #if MICROPY_PY_BUILTINS_FLOAT + delta_ms = (uint32_t)(MICROPY_FLOAT_CONST(1000.0) / mp_obj_get_float(args[ARG_freq].u_obj)); + #else + delta_ms = 1000 / mp_obj_get_int(args[ARG_freq].u_obj); + #endif + } else if (args[ARG_period].u_int != 0xffffffff) { + // Period specified + delta_ms = (uint64_t)args[ARG_period].u_int * 1000 / args[ARG_tick_hz].u_int; + } + + if (delta_ms < 1) { + delta_ms = 1; + } else if (delta_ms >= 0x40000000) { + mp_raise_ValueError(MP_ERROR_TEXT("period too large")); + } + self->delta_ms = (uint32_t)delta_ms; + + if (args[ARG_callback].u_obj != MP_OBJ_NULL) { + self->py_callback = args[ARG_callback].u_obj; + } + + if (self->py_callback != mp_const_none) { + soft_timer_insert(self, self->delta_ms); + } + + return mp_const_none; +} + +STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t); + self->pairheap.base.type = &machine_timer_type; + self->flags = SOFT_TIMER_FLAG_PY_CALLBACK | SOFT_TIMER_FLAG_GC_ALLOCATED; + self->delta_ms = 1000; + self->py_callback = mp_const_none; + + // Get timer id (only soft timer (-1) supported at the moment) + mp_int_t id = -1; + if (n_args > 0) { + id = mp_obj_get_int(args[0]); + --n_args; + ++args; + } + if (id != -1) { + mp_raise_ValueError(MP_ERROR_TEXT("Timer doesn't exist")); + } + + if (n_args > 0 || n_kw > 0) { + // Start the timer + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + machine_timer_init_helper(self, n_args, args, &kw_args); + } + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t machine_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + machine_timer_obj_t *self = MP_OBJ_TO_PTR(args[0]); + soft_timer_remove(self); + return machine_timer_init_helper(self, n_args - 1, args + 1, kw_args); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init); + +STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) { + machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); + soft_timer_remove(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit); + +STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_timer_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj) }, + + { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(SOFT_TIMER_MODE_ONE_SHOT) }, + { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(SOFT_TIMER_MODE_PERIODIC) }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + machine_timer_type, + MP_QSTR_Timer, + MP_TYPE_FLAG_NONE, + make_new, machine_timer_make_new, + print, machine_timer_print, + locals_dict, &machine_timer_locals_dict + ); diff --git a/ports/samd/main.c b/ports/samd/main.c index 5aab39e509..889af4a1e4 100644 --- a/ports/samd/main.c +++ b/ports/samd/main.c @@ -31,6 +31,7 @@ #include "py/stackctrl.h" #include "shared/runtime/gchelper.h" #include "shared/runtime/pyexec.h" +#include "shared/runtime/softtimer.h" extern uint8_t _sstack, _estack, _sheap, _eheap; extern void adc_deinit_all(void); @@ -82,6 +83,7 @@ void samd_main(void) { pwm_deinit_all(); sercom_deinit_all(); uart_deinit_all(); + soft_timer_deinit(); gc_sweep_all(); mp_deinit(); } diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index acd672fafe..852d10912d 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -157,6 +157,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hw_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, + { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) }, diff --git a/ports/samd/modmachine.h b/ports/samd/modmachine.h index 4319867190..b6da5e46f5 100644 --- a/ports/samd/modmachine.h +++ b/ports/samd/modmachine.h @@ -34,6 +34,7 @@ extern const mp_obj_type_t machine_led_type; extern const mp_obj_type_t machine_pin_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; #endif // MICROPY_INCLUDED_SAMD_MODMACHINE_H diff --git a/ports/samd/mphalport.h b/ports/samd/mphalport.h index 6161d9821f..2eb4ce7ca6 100644 --- a/ports/samd/mphalport.h +++ b/ports/samd/mphalport.h @@ -40,6 +40,10 @@ extern volatile uint32_t systick_ms_upper; void mp_hal_set_interrupt_char(int c); +// Define an alias fo systick_ms, because the shared softtimer.c uses +// the symbol uwTick for the systick ms counter. +#define uwTick systick_ms + #define mp_hal_delay_us_fast mp_hal_delay_us static inline mp_uint_t mp_hal_ticks_ms(void) { diff --git a/ports/samd/pendsv.c b/ports/samd/pendsv.c new file mode 100644 index 0000000000..00dd6068d1 --- /dev/null +++ b/ports/samd/pendsv.c @@ -0,0 +1,71 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 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 + +#include "py/runtime.h" +#include "shared/runtime/interrupt_char.h" +#include "sam.h" +#include "pendsv.h" + + +#if defined(PENDSV_DISPATCH_NUM_SLOTS) +uint32_t pendsv_dispatch_active; +pendsv_dispatch_t pendsv_dispatch_table[PENDSV_DISPATCH_NUM_SLOTS]; +#endif + +void pendsv_init(void) { + #if defined(PENDSV_DISPATCH_NUM_SLOTS) + pendsv_dispatch_active = false; + #endif + + // set PendSV interrupt at lowest priority + NVIC_SetPriority(PendSV_IRQn, IRQ_PRI_PENDSV); +} + +#if defined(PENDSV_DISPATCH_NUM_SLOTS) +void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f) { + pendsv_dispatch_table[slot] = f; + pendsv_dispatch_active = true; + SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; +} + +void pendsv_dispatch_handler(void) { + for (size_t i = 0; i < PENDSV_DISPATCH_NUM_SLOTS; ++i) { + if (pendsv_dispatch_table[i] != NULL) { + pendsv_dispatch_t f = pendsv_dispatch_table[i]; + pendsv_dispatch_table[i] = NULL; + f(); + } + } +} + +void PendSV_Handler(void) { + if (pendsv_dispatch_active) { + pendsv_dispatch_handler(); + } +} +#endif diff --git a/ports/samd/pendsv.h b/ports/samd/pendsv.h new file mode 100644 index 0000000000..c21af906b4 --- /dev/null +++ b/ports/samd/pendsv.h @@ -0,0 +1,41 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 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. + */ +#ifndef MICROPY_INCLUDED_SAMD_PENDSV_H +#define MICROPY_INCLUDED_SAMD_PENDSV_H + +enum { + PENDSV_DISPATCH_SOFT_TIMER, // For later & for having at least one entry + PENDSV_DISPATCH_MAX +}; + +#define PENDSV_DISPATCH_NUM_SLOTS PENDSV_DISPATCH_MAX + +typedef void (*pendsv_dispatch_t)(void); + +void pendsv_init(void); +void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f); + +#endif // MICROPY_INCLUDED_SAMD_PENDSV_H diff --git a/ports/samd/samd_isr.c b/ports/samd/samd_isr.c index ed88ca229d..b507d5d1aa 100644 --- a/ports/samd/samd_isr.c +++ b/ports/samd/samd_isr.c @@ -27,9 +27,9 @@ #include "py/runtime.h" #include "py/mphal.h" #include "samd_soc.h" -// includes for Softtimer -// #include "pendsv.h" -// #include "softtimer.h" + +#include "pendsv.h" +#include "shared/runtime/softtimer.h" typedef void (*ISR)(void); @@ -97,17 +97,11 @@ void SysTick_Handler(void) { systick_ms_upper += 1; } - // if (soft_timer_next == next_tick) { - // pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler); - // } + if (soft_timer_next == next_tick) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler); + } } -// Temporary Handlers to allow builds. -// Will be removed when the respecitve module is added. -void PendSV_Handler(void) { -} - - void (*sercom_irq_handler_table[SERCOM_INST_NUM])(int num) = {}; void sercom_register_irq(int sercom_id, void (*sercom_irq_handler)) { From 7a2f2d88f74dcad73acd1f4f7721a3575f68ffc2 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 6 Jun 2022 11:23:09 +0200 Subject: [PATCH 0500/1041] samd/machine_wdt: Add the machine.WDT class. --- ports/samd/Makefile | 2 + ports/samd/machine_wdt.c | 141 +++++++++++++++++++++++++++++++++++++++ ports/samd/modmachine.c | 1 + ports/samd/modmachine.h | 1 + 4 files changed, 145 insertions(+) create mode 100644 ports/samd/machine_wdt.c diff --git a/ports/samd/Makefile b/ports/samd/Makefile index e3d0d28f8f..71a902a0a5 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -97,6 +97,7 @@ SRC_C = \ machine_spi.c \ machine_timer.c \ machine_uart.c \ + machine_wdt.c \ main.c \ modutime.c \ modmachine.c \ @@ -155,6 +156,7 @@ SRC_QSTR += \ machine_spi.c \ machine_timer.c \ machine_uart.c \ + machine_wdt.c \ modutime.c \ modmachine.c \ modsamd.c \ diff --git a/ports/samd/machine_wdt.c b/ports/samd/machine_wdt.c new file mode 100644 index 0000000000..c0fbfdbfbc --- /dev/null +++ b/ports/samd/machine_wdt.c @@ -0,0 +1,141 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "modmachine.h" + +#include "sam.h" + +#define MIN_TIMEOUT 512 +#define MAX_TIMEOUT 16384 + +typedef struct _machine_wdt_obj_t { + mp_obj_base_t base; +} machine_wdt_obj_t; + +extern mp_int_t log2i(mp_int_t num); + +STATIC const machine_wdt_obj_t machine_wdt = {{&machine_wdt_type}}; + +STATIC void set_timeout(uint32_t timeout) { + // Set new timeout. Have to disable WDT first. + + // Confine to the valid range + if (timeout < MIN_TIMEOUT) { + timeout = MIN_TIMEOUT; + } else if (timeout > MAX_TIMEOUT) { + timeout = MAX_TIMEOUT; + } + + #if defined(MCU_SAMD21) + WDT->CTRL.reg = 0; + while (WDT->STATUS.reg & WDT_STATUS_SYNCBUSY) { + } + WDT->CONFIG.reg = log2i(timeout) - 3; + WDT->CTRL.reg = WDT_CTRL_ENABLE; + while (WDT->STATUS.reg & WDT_STATUS_SYNCBUSY) { + } + #elif defined(MCU_SAMD51) + WDT->CTRLA.reg = 0; + while (WDT->SYNCBUSY.reg & WDT_SYNCBUSY_ENABLE) { + } + WDT->CONFIG.reg = log2i(timeout) - 3; + WDT->CTRLA.reg = WDT_CTRLA_ENABLE; + while (WDT->SYNCBUSY.reg & WDT_SYNCBUSY_ENABLE) { + } + #endif +} + +STATIC mp_obj_t machine_wdt_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_timeout, ARG_lock }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_timeout, MP_ARG_INT, {.u_int = 5000} }, + }; + + // Parse the arguments. + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + #if defined(MCU_SAMD51) + // Verify the WDT id. SAMD51 only, saving a few bytes for SAMD21 + mp_int_t id = args[ARG_id].u_int; + if (id != 0) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("WDT(%d) doesn't exist"), id); + } + #endif + + // Start the watchdog (timeout is in milliseconds). + uint32_t timeout = args[ARG_timeout].u_int; + // Configure the WDT + #if defined(MCU_SAMD21) + + // Enable APBx clocks and GCLK clock + PM->APBAMASK.reg |= PM_APBAMASK_WDT; + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK8 | GCLK_CLKCTRL_ID_WDT; + + #elif defined(MCU_SAMD51) + + // Enable APBx clocks and 1kHz clock + MCLK->APBAMASK.reg |= MCLK_APBAMASK_WDT; + OSC32KCTRL->OSCULP32K.bit.EN1K = 1; + + #endif + + set_timeout(timeout); + + return MP_OBJ_FROM_PTR(&machine_wdt); +} + +STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) { + (void)self_in; + WDT->CLEAR.reg = 0xa5; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed); + +STATIC mp_obj_t machine_wdt_timeout_ms(mp_obj_t self_in, mp_obj_t timout_in) { + uint32_t timeout = mp_obj_get_int(timout_in); + + set_timeout(timeout); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_wdt_timeout_ms_obj, machine_wdt_timeout_ms); + +STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&machine_wdt_feed_obj) }, + { MP_ROM_QSTR(MP_QSTR_timeout_ms), MP_ROM_PTR(&machine_wdt_timeout_ms_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + machine_wdt_type, + MP_QSTR_WDT, + MP_TYPE_FLAG_NONE, + make_new, machine_wdt_make_new, + locals_dict, &machine_wdt_locals_dict + ); diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index 852d10912d..cabd6b9c57 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -159,6 +159,7 @@ 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_Timer), MP_ROM_PTR(&machine_timer_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, + { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) }, { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, diff --git a/ports/samd/modmachine.h b/ports/samd/modmachine.h index b6da5e46f5..61b26a1fa3 100644 --- a/ports/samd/modmachine.h +++ b/ports/samd/modmachine.h @@ -36,5 +36,6 @@ 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_SAMD_MODMACHINE_H From 6e2dff6baea2a6109fa030a97d2ffdcafd6c3681 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 6 Jun 2022 12:26:13 +0200 Subject: [PATCH 0501/1041] samd/modsamd: Add pininfo() function to the samd module. samd.pininfo() returns the data stored in the pin af table for a pin. Using a small script, a nice representation of the table can be created. --- ports/samd/machine_pin.c | 2 -- ports/samd/modsamd.c | 44 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/ports/samd/machine_pin.c b/ports/samd/machine_pin.c index a70e9ad011..bef19d177d 100644 --- a/ports/samd/machine_pin.c +++ b/ports/samd/machine_pin.c @@ -92,7 +92,6 @@ int pin_find(mp_obj_t pin, const machine_pin_obj_t machine_pin_obj[], int table_ return wanted_pin; } - // Pin.init(mode, pull=None, *, value=None, drive=0). No 'alt' yet. STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_pull, ARG_value, ARG_drive, ARG_alt }; @@ -157,7 +156,6 @@ mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, if (self == NULL || self->base.type == NULL) { mp_raise_ValueError(MP_ERROR_TEXT("invalid pin")); } - self = (machine_pin_obj_t *)&machine_pin_obj[wanted_pin]; if (n_args > 1 || n_kw > 0) { // pin mode given, so configure this GPIO diff --git a/ports/samd/modsamd.c b/ports/samd/modsamd.c index 68fd6b53e5..05ed69bad0 100644 --- a/ports/samd/modsamd.c +++ b/ports/samd/modsamd.c @@ -24,14 +24,56 @@ * THE SOFTWARE. */ +#include "string.h" #include "py/runtime.h" +#include "py/mphal.h" + +#include "sam.h" +#include "pin_af.h" +#include "pins.h" #include "samd_soc.h" extern const mp_obj_type_t samd_flash_type; +STATIC mp_obj_t samd_pininfo(mp_obj_t pin_obj) { + mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_obj); + const pin_af_t *pin_af = get_pin_af_info(pin); + const char *name = ((machine_pin_obj_t *)MP_OBJ_TO_PTR(pin_obj))->name; + if (pin_af) { + #if defined(MCU_SAMD21) + mp_obj_t tuple[7] = { + tuple[0] = mp_obj_new_str(name, strlen(name)), + tuple[1] = mp_obj_new_int(pin_af->eic), + tuple[2] = mp_obj_new_int(pin_af->adc0), + tuple[3] = mp_obj_new_int(pin_af->sercom1), + tuple[4] = mp_obj_new_int(pin_af->sercom2), + tuple[5] = mp_obj_new_int(pin_af->tcc1), + tuple[6] = mp_obj_new_int(pin_af->tcc2), + }; + return mp_obj_new_tuple(7, tuple); + #elif defined(MCU_SAMD51) + mp_obj_t tuple[9] = { + tuple[0] = mp_obj_new_str(name, strlen(name)), + tuple[1] = mp_obj_new_int(pin_af->eic), + tuple[2] = mp_obj_new_int(pin_af->adc0), + tuple[3] = mp_obj_new_int(pin_af->adc1), + tuple[4] = mp_obj_new_int(pin_af->sercom1), + tuple[5] = mp_obj_new_int(pin_af->sercom2), + tuple[6] = mp_obj_new_int(pin_af->tc), + tuple[7] = mp_obj_new_int(pin_af->tcc1), + tuple[8] = mp_obj_new_int(pin_af->tcc2), + }; + return mp_obj_new_tuple(9, tuple); + #endif + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(samd_pininfo_obj, samd_pininfo); + STATIC const mp_rom_map_elem_t samd_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_samd) }, - { MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&samd_flash_type) }, + { MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&samd_flash_type) }, + { MP_ROM_QSTR(MP_QSTR_pininfo), MP_ROM_PTR(&samd_pininfo_obj) }, }; STATIC MP_DEFINE_CONST_DICT(samd_module_globals, samd_module_globals_table); From aa2d746ef4ef64cbf8093b22facabca2c495be1f Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 6 Jun 2022 13:35:16 +0200 Subject: [PATCH 0502/1041] samd/machine_led: Optimise size of the machine.LED class. By reducing the methods to on(), off(), toggle() and call, and using the method implementation of the machine.Pin class. The code size reduction is 756 byte. --- ports/samd/machine_led.c | 108 ++++----------------------------------- ports/samd/machine_pin.c | 6 +-- 2 files changed, 13 insertions(+), 101 deletions(-) diff --git a/ports/samd/machine_led.c b/ports/samd/machine_led.c index 9c15769581..48ab869199 100644 --- a/ports/samd/machine_led.c +++ b/ports/samd/machine_led.c @@ -32,37 +32,16 @@ #include "modmachine.h" #include "pins.h" -// ASF4 (MCU package specific pin defs in 'boards') -#include "hal_gpio.h" +extern mp_obj_t machine_pin_low_obj; +extern mp_obj_t machine_pin_high_obj; +extern mp_obj_t machine_pin_toggle_obj; +extern mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); STATIC void machine_led_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_led_obj_t *self = self_in; mp_printf(print, "LED(%u)", self->id); } -// LED.init(mode, *, value=None) -STATIC mp_obj_t machine_led_obj_init_helper(const machine_led_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_mode, ARG_value }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, - { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, - }; - - // parse args - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - // set initial value (do this before configuring mode/pull) - if (args[ARG_value].u_obj != mp_const_none) { - gpio_set_pin_level(self->id, mp_obj_is_true(args[ARG_value].u_obj)); - } - - // configure mode - gpio_set_pin_direction(self->id, GPIO_DIRECTION_OUT); - - return mp_const_none; -} - // constructor(id, ...) mp_obj_t mp_led_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); @@ -73,90 +52,23 @@ mp_obj_t mp_led_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, if (0 <= wanted_led && wanted_led < MP_ARRAY_SIZE(machine_led_obj)) { self = (machine_led_obj_t *)&machine_led_obj[wanted_led]; } - // the array could be padded with 'nulls' (see other Ports). // Will also error if the asked for LED (index) is greater than the array row size. if (self == NULL || self->base.type == NULL) { mp_raise_ValueError(MP_ERROR_TEXT("invalid LED")); } - - if (n_args > 1 || n_kw > 0) { - // mode given, so configure this GPIO - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - machine_led_obj_init_helper(self, n_args - 1, args + 1, &kw_args); - } + mp_hal_pin_output(self->id); + mp_hal_pin_low(self->id); return MP_OBJ_FROM_PTR(self); } -// fast method for getting/setting pin value -STATIC mp_obj_t machine_led_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, false); - machine_led_obj_t *self = self_in; - if (n_args == 0) { - // get pin - return MP_OBJ_NEW_SMALL_INT(gpio_get_pin_level(self->id)); - } else { - // set pin - bool value = mp_obj_is_true(args[0]); - gpio_set_pin_level(self->id, value); - - return mp_const_none; - } -} - -// pin.init(mode) -STATIC mp_obj_t machine_led_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - return machine_led_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); -} -MP_DEFINE_CONST_FUN_OBJ_KW(machine_led_init_obj, 1, machine_led_obj_init); - -// pin.value([value]) -STATIC mp_obj_t machine_led_value(size_t n_args, const mp_obj_t *args) { - return machine_led_call(args[0], n_args - 1, 0, args + 1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_led_value_obj, 1, 2, machine_led_value); - -// pin.low() -STATIC mp_obj_t machine_led_low(mp_obj_t self_in) { - machine_led_obj_t *self = MP_OBJ_TO_PTR(self_in); - gpio_set_pin_direction(self->id, GPIO_DIRECTION_OUT); - gpio_set_pin_level(self->id, false); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_led_low_obj, machine_led_low); - -// pin.high() -STATIC mp_obj_t machine_led_high(mp_obj_t self_in) { - machine_led_obj_t *self = MP_OBJ_TO_PTR(self_in); - gpio_set_pin_direction(self->id, GPIO_DIRECTION_OUT); - gpio_set_pin_level(self->id, true); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_led_high_obj, machine_led_high); - -// pin.toggle() -STATIC mp_obj_t machine_led_toggle(mp_obj_t self_in) { - machine_led_obj_t *self = MP_OBJ_TO_PTR(self_in); - gpio_set_pin_direction(self->id, GPIO_DIRECTION_OUT); - gpio_toggle_pin_level(self->id); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_led_toggle_obj, machine_led_toggle); STATIC const mp_rom_map_elem_t machine_led_locals_dict_table[] = { // instance methods - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_led_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_led_value_obj) }, - { MP_ROM_QSTR(MP_QSTR_low), MP_ROM_PTR(&machine_led_low_obj) }, - { MP_ROM_QSTR(MP_QSTR_high), MP_ROM_PTR(&machine_led_high_obj) }, - { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&machine_led_low_obj) }, - { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_led_high_obj) }, - { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&machine_led_toggle_obj) }, + { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&machine_pin_low_obj) }, + { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_pin_high_obj) }, + { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&machine_pin_toggle_obj) }, }; STATIC MP_DEFINE_CONST_DICT(machine_led_locals_dict, machine_led_locals_dict_table); @@ -166,6 +78,6 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, make_new, mp_led_make_new, print, machine_led_print, - call, machine_led_call, + call, machine_pin_call, locals_dict, &machine_led_locals_dict ); diff --git a/ports/samd/machine_pin.c b/ports/samd/machine_pin.c index bef19d177d..e900174a91 100644 --- a/ports/samd/machine_pin.c +++ b/ports/samd/machine_pin.c @@ -220,7 +220,7 @@ STATIC mp_obj_t machine_pin_low(mp_obj_t self_in) { } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_low_obj, machine_pin_low); +MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_low_obj, machine_pin_low); // Pin.high() Totem-pole (push-pull) STATIC mp_obj_t machine_pin_high(mp_obj_t self_in) { @@ -232,7 +232,7 @@ STATIC mp_obj_t machine_pin_high(mp_obj_t self_in) { } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_high_obj, machine_pin_high); +MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_high_obj, machine_pin_high); // Pin.toggle(). Only TOGGLE pins set as OUTPUT. STATIC mp_obj_t machine_pin_toggle(mp_obj_t self_in) { @@ -254,7 +254,7 @@ STATIC mp_obj_t machine_pin_toggle(mp_obj_t self_in) { } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_toggle_obj, machine_pin_toggle); +MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_toggle_obj, machine_pin_toggle); // Pin.drive(). Normal (0) is 2mA, High (1) allows 8mA. STATIC mp_obj_t machine_pin_drive(size_t n_args, const mp_obj_t *args) { From f5da77b5ce66a393984fe8f71627f93e95c39edc Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 7 Jun 2022 20:37:44 +0200 Subject: [PATCH 0503/1041] samd/machine_dac: Add the machine.DAC class. It suuports 1 channel @ 10 bit for SAMD21, 2 channels @ 12 bit for SAMD51. Instantiation by: dac = machine.DAC(ch) # 0 or 1 Method write: dac.write(value) The output voltage range is 0..Vdd. --- ports/samd/Makefile | 2 + ports/samd/machine_dac.c | 162 +++++++++++++++++++++++++++++++++++++++ ports/samd/modmachine.c | 1 + ports/samd/modmachine.h | 1 + ports/samd/pin_af.h | 1 + 5 files changed, 167 insertions(+) create mode 100644 ports/samd/machine_dac.c diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 71a902a0a5..43b6a1adc3 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -91,6 +91,7 @@ SRC_C = \ clock_config.c \ help.c \ machine_adc.c \ + machine_dac.c \ machine_i2c.c \ machine_led.c \ machine_pin.c \ @@ -149,6 +150,7 @@ endif # List of sources for qstr extraction SRC_QSTR += \ machine_adc.c \ + machine_dac.c \ machine_i2c.c \ machine_led.c \ machine_pin.c \ diff --git a/ports/samd/machine_dac.c b/ports/samd/machine_dac.c new file mode 100644 index 0000000000..41c6784cce --- /dev/null +++ b/ports/samd/machine_dac.c @@ -0,0 +1,162 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Nick Moore + * Copyright (c) 2022 Robert Hammelrath + * + * 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 +#include "py/obj.h" +#include "py/runtime.h" +#include "py/mphal.h" + +#include "sam.h" +#include "pin_af.h" +#include "modmachine.h" + +typedef struct _dac_obj_t { + mp_obj_base_t base; + uint8_t id; + mp_hal_pin_obj_t gpio_id; +} dac_obj_t; + +STATIC const dac_obj_t dac_obj[] = { + #if defined(MCU_SAMD21) + {{&machine_dac_type}, 0, PIN_PA02}, + #elif defined(MCU_SAMD51) + {{&machine_dac_type}, 0, PIN_PA02}, + {{&machine_dac_type}, 1, PIN_PA05}, + #endif +}; +Dac *const dac_bases[] = DAC_INSTS; + +#if defined(MCU_SAMD21) +#define MAX_DAC_VALUE (1023) +#elif defined(MCU_SAMD51) +#define MAX_DAC_VALUE (4095) +static bool dac_init = false; +#endif + + +STATIC mp_obj_t dac_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, 1, true); + uint8_t id = mp_obj_get_int(args[0]); + const dac_obj_t *self = NULL; + if (0 <= id && id <= MP_ARRAY_SIZE(dac_obj)) { + self = &dac_obj[id]; + } else { + mp_raise_ValueError(MP_ERROR_TEXT("invalid Pin for DAC")); + } + + Dac *dac = dac_bases[0]; // Just one DAC + + // Init DAC + #if defined(MCU_SAMD21) + + // Configuration SAMD21 + // Enable APBC clocks and PCHCTRL clocks; GCLK3 at 1 MHz + PM->APBCMASK.reg |= PM_APBCMASK_DAC; + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK3 | GCLK_CLKCTRL_ID_DAC; + while (GCLK->STATUS.bit.SYNCBUSY) { + } + // Reset DAC registers + dac->CTRLA.bit.SWRST = 1; + while (dac->CTRLA.bit.SWRST) { + } + dac->CTRLB.reg = DAC_CTRLB_EOEN | DAC_CTRLB_REFSEL(DAC_CTRLB_REFSEL_AVCC_Val); + // Enable DAC and wait to be ready + dac->CTRLA.bit.ENABLE = 1; + while (dac->STATUS.bit.SYNCBUSY) { + } + + #elif defined(MCU_SAMD51) + + // Configuration SAMD51 + // Enable APBD clocks and PCHCTRL clocks; GCLK3 at 8 MHz + if (!dac_init) { + dac_init = true; + MCLK->APBDMASK.reg |= MCLK_APBDMASK_DAC; + GCLK->PCHCTRL[DAC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK3 | GCLK_PCHCTRL_CHEN; + + // Reset DAC registers + dac->CTRLA.bit.SWRST = 1; + while (dac->CTRLA.bit.SWRST) { + } + dac->CTRLB.reg = DAC_CTRLB_REFSEL(DAC_CTRLB_REFSEL_VDDANA_Val); + } else { + dac->CTRLA.bit.ENABLE = 0; + while (dac->SYNCBUSY.bit.ENABLE) { + } + } + dac->DACCTRL[self->id].reg = DAC_DACCTRL_ENABLE | DAC_DACCTRL_REFRESH(2) | DAC_DACCTRL_CCTRL_CC12M; + + // Enable DAC and wait to be ready + dac->CTRLA.bit.ENABLE = 1; + while (dac->SYNCBUSY.bit.ENABLE) { + } + #endif + + // Set the port as given in self->gpio_id as DAC + mp_hal_set_pin_mux(self->gpio_id, ALT_FCT_DAC); + + return MP_OBJ_FROM_PTR(self); +} + +STATIC void dac_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + dac_obj_t *self = self_in; + mp_printf(print, "DAC(%u) PIN_PA%02u", self->id, self->gpio_id); +} + +STATIC mp_obj_t dac_write(mp_obj_t self_in, mp_obj_t value_in) { + Dac *dac = dac_bases[0]; // Just one DAC + int value = mp_obj_get_int(value_in); + if (value < 0 || value > MAX_DAC_VALUE) { + mp_raise_ValueError(MP_ERROR_TEXT("value out of range")); + } + #if defined(MCU_SAMD21) + dac->DATA.reg = value; + #elif defined(MCU_SAMD51) + dac_obj_t *self = self_in; + dac->DATA[self->id].reg = value; + #endif + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(dac_write_obj, dac_write); + +STATIC const mp_rom_map_elem_t dac_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&dac_write_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(dac_locals_dict, dac_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + machine_dac_type, + MP_QSTR_DAC, + MP_TYPE_FLAG_NONE, + make_new, dac_make_new, + print, dac_print, + locals_dict, &dac_locals_dict + ); diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index cabd6b9c57..f7ad47b3c5 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -150,6 +150,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, + { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) }, { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&machine_led_type) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, diff --git a/ports/samd/modmachine.h b/ports/samd/modmachine.h index 61b26a1fa3..6a745da067 100644 --- a/ports/samd/modmachine.h +++ b/ports/samd/modmachine.h @@ -29,6 +29,7 @@ #include "py/obj.h" extern const mp_obj_type_t machine_adc_type; +extern const mp_obj_type_t machine_dac_type; extern const mp_obj_type_t machine_hw_i2c_type; extern const mp_obj_type_t machine_led_type; extern const mp_obj_type_t machine_pin_type; diff --git a/ports/samd/pin_af.h b/ports/samd/pin_af.h index f9dec6b7da..b75f4ddd02 100644 --- a/ports/samd/pin_af.h +++ b/ports/samd/pin_af.h @@ -81,6 +81,7 @@ typedef struct _pwm_config_t { #define ALT_FCT_EIC 0 #define ALT_FCT_ADC 1 +#define ALT_FCT_DAC 1 #define ALT_FCT_SERCOM1 2 #define ALT_FCT_SERCOM2 3 From 029e9af4576f3000aabf5e6eac589f6bb644af92 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 7 Jun 2022 21:52:03 +0200 Subject: [PATCH 0504/1041] samd/modmachine: Add machine.time_pulse_us. Software based. Resolution: - +/-2 microseconds on SAMD51. - +/-4 microseconds on SAMD21. --- ports/samd/modmachine.c | 6 ++++-- ports/samd/mpconfigport.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index f7ad47b3c5..c191afda79 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -26,10 +26,11 @@ #include "py/runtime.h" #include "extmod/machine_mem.h" -#include "samd_soc.h" -#include "modmachine.h" +#include "extmod/machine_pulse.h" #include "extmod/machine_i2c.h" #include "extmod/machine_spi.h" +#include "modmachine.h" +#include "samd_soc.h" // ASF 4 #include "hal_flash.h" @@ -165,6 +166,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) }, + { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index c2c614e10b..48631080d2 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -111,6 +111,7 @@ #define MICROPY_PY_MACHINE_SPI (1) #define MICROPY_PY_MACHINE_SOFTSPI (1) #define MICROPY_PY_OS_DUPTERM (3) +#define MICROPY_PY_MACHINE_PULSE (1) #define MICROPY_PY_MACHINE_PWM (1) #define MICROPY_PY_MACHINE_PWM_INIT (0) #define MICROPY_PY_MACHINE_PWM_DUTY_U16_NS (1) From aa6dbbcffd4f0a5c7572b8aa1ef256794838f969 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 8 Jun 2022 10:54:02 +0200 Subject: [PATCH 0505/1041] samd/mcu: Factor out MCU policy for SAMD21 and SAMD51. Which contains a mpconfigmcu.h, mpconfigmcu.mk and manifest.py file for each MCU group. That looks better than the previous choice. --- ports/samd/Makefile | 16 +++++----------- .../samd21/mpconfigmcu.h} | 0 ports/samd/mcu/samd21/mpconfigmcu.mk | 1 + .../samd51/mpconfigmcu.h} | 0 ports/samd/mcu/samd51/mpconfigmcu.mk | 1 + ports/samd/mpconfigport.h | 2 +- 6 files changed, 8 insertions(+), 12 deletions(-) rename ports/samd/{boards/mpconfig_samd21.h => mcu/samd21/mpconfigmcu.h} (100%) create mode 100644 ports/samd/mcu/samd21/mpconfigmcu.mk rename ports/samd/{boards/mpconfig_samd51.h => mcu/samd51/mpconfigmcu.h} (100%) create mode 100644 ports/samd/mcu/samd51/mpconfigmcu.mk diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 43b6a1adc3..1455e748cc 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -9,14 +9,15 @@ ifeq ($(wildcard $(BOARD_DIR)/.),) $(error Invalid BOARD specified: $(BOARD_DIR)) endif +MCU_SERIES_LOWER = $(shell echo $(MCU_SERIES) | tr '[:upper:]' '[:lower:]') + include ../../py/mkenv.mk include $(BOARD_DIR)/mpconfigboard.mk +include mcu/$(MCU_SERIES_LOWER)/mpconfigmcu.mk # Qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h -QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h - -MCU_SERIES_LOWER = $(shell echo $(MCU_SERIES) | tr '[:upper:]' '[:lower:]') +QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h mcu/$(MCU_SERIES_LOWER)/mpconfigmcu.h FROZEN_MANIFEST ?= boards/manifest.py @@ -30,6 +31,7 @@ INC += -I. INC += -I$(TOP) INC += -I$(BUILD) INC += -I$(BOARD_DIR) +INC += -Imcu/$(MCU_SERIES_LOWER) INC += -I$(TOP)/lib/cmsis/inc INC += -I$(TOP)/lib/asf4/$(MCU_SERIES_LOWER)/hal/include INC += -I$(TOP)/lib/asf4/$(MCU_SERIES_LOWER)/hal/utils/include @@ -62,8 +64,6 @@ CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) CFLAGS += -DMPCONFIG_MCU_H='' CFLAGS += -DPIN_AF_TABLE_C='<$(BUILD)/$(GEN_PIN_AF)>' -QSTR_GLOBAL_DEPENDENCIES += boards/mpconfig_$(MCU_SERIES_LOWER).h - LDFLAGS = -nostdlib $(addprefix -T,$(LD_FILES)) -Map=$@.map --cref LDFLAGS += $(LDFLAGS_MOD) @@ -141,12 +141,6 @@ SRC_C += $(SRC_MOD) SRC_CXX += $(SRC_MOD_CXX) -ifeq ($(MCU_SERIES),SAMD21) -SRC_S = shared/runtime/gchelper_m0.s -else -SRC_S = shared/runtime/gchelper_m3.s -endif - # List of sources for qstr extraction SRC_QSTR += \ machine_adc.c \ diff --git a/ports/samd/boards/mpconfig_samd21.h b/ports/samd/mcu/samd21/mpconfigmcu.h similarity index 100% rename from ports/samd/boards/mpconfig_samd21.h rename to ports/samd/mcu/samd21/mpconfigmcu.h diff --git a/ports/samd/mcu/samd21/mpconfigmcu.mk b/ports/samd/mcu/samd21/mpconfigmcu.mk new file mode 100644 index 0000000000..cc435da8cc --- /dev/null +++ b/ports/samd/mcu/samd21/mpconfigmcu.mk @@ -0,0 +1 @@ +SRC_S += shared/runtime/gchelper_m0.s diff --git a/ports/samd/boards/mpconfig_samd51.h b/ports/samd/mcu/samd51/mpconfigmcu.h similarity index 100% rename from ports/samd/boards/mpconfig_samd51.h rename to ports/samd/mcu/samd51/mpconfigmcu.h diff --git a/ports/samd/mcu/samd51/mpconfigmcu.mk b/ports/samd/mcu/samd51/mpconfigmcu.mk new file mode 100644 index 0000000000..461a0182ef --- /dev/null +++ b/ports/samd/mcu/samd51/mpconfigmcu.mk @@ -0,0 +1 @@ +SRC_S += shared/runtime/gchelper_m3.s diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 48631080d2..8a067d3482 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -29,7 +29,7 @@ // Board specific definitions #include "mpconfigboard.h" // MCU-Specific definitions -#include MPCONFIG_MCU_H +#include "mpconfigmcu.h" // Memory allocation policies #define MICROPY_GC_STACK_ENTRY_TYPE uint16_t From 7da76639027057245cfee043733193b3265e7a54 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 9 Jun 2022 13:44:22 +0200 Subject: [PATCH 0506/1041] samd/mphalport: Add a mp_hal_ticks_ms_64() function. Returning a 64 bit number. This will be used by the utime module and the machine.UART module for timeout avoiding overflow. --- ports/samd/mphalport.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ports/samd/mphalport.h b/ports/samd/mphalport.h index 2eb4ce7ca6..c2aca8b0e2 100644 --- a/ports/samd/mphalport.h +++ b/ports/samd/mphalport.h @@ -50,6 +50,10 @@ static inline mp_uint_t mp_hal_ticks_ms(void) { return systick_ms; } +static inline uint64_t mp_hal_ticks_ms_64(void) { + return ((uint64_t)systick_ms_upper << 32) + systick_ms; +} + static inline mp_uint_t mp_hal_ticks_us(void) { #if defined(MCU_SAMD21) @@ -74,7 +78,7 @@ static inline mp_uint_t mp_hal_ticks_cpu(void) { } static inline uint64_t mp_hal_time_ns(void) { - return ((uint64_t)systick_ms + (uint64_t)systick_ms_upper * 0x100000000) * 1000000; + return mp_hal_ticks_ms_64() * 1000000; } // C-level pin HAL From 37449df821a47698779b48e6c101b084cfbdb6c7 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 9 Jun 2022 14:33:31 +0200 Subject: [PATCH 0507/1041] samd/modutime: Enable time.time() based on systick_ms(). Allowing to set a time and retrieve the time. It is based on systick_ms() with the precision of the MCU clock. Unless that is based on a crystal, the error seen was about 0.5% at room temperature. --- ports/samd/modutime.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ports/samd/modutime.c b/ports/samd/modutime.c index bbeedcfda0..a54544e62c 100644 --- a/ports/samd/modutime.c +++ b/ports/samd/modutime.c @@ -27,6 +27,9 @@ #include "py/runtime.h" #include "extmod/utime_mphal.h" #include "shared/timeutils/timeutils.h" +#include "mphalport.h" + +static uint32_t time_offset = 0; // localtime([secs]) STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { @@ -34,9 +37,10 @@ STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { mp_int_t seconds; if (n_args == 0 || args[0] == mp_const_none) { // seconds = pyb_rtc_get_us_since_epoch() / 1000 / 1000; - seconds = mp_obj_get_int(args[0]); + seconds = mp_hal_ticks_ms_64() / 1000 + time_offset; } else { seconds = mp_obj_get_int(args[0]); + time_offset = seconds - mp_hal_ticks_ms_64() / 1000; } timeutils_seconds_since_epoch_to_struct_time(seconds, &tm); mp_obj_t tuple[8] = { @@ -72,7 +76,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime); // time() STATIC mp_obj_t time_time(void) { - mp_raise_NotImplementedError("time"); + return mp_obj_new_int_from_uint(mp_hal_ticks_ms_64() / 1000 + time_offset); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time); From 9a567b04e7c43024a2a4dce2618b24f822dfe5bc Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 9 Jun 2022 13:46:54 +0200 Subject: [PATCH 0508/1041] samd/machine_uart: Support buffered TX for UART. It can be enabled/disabled by a configuration switch. The code size increase is 308 bytes, but it requires RAM space for buffers, the larger UART object and root pointers. --- ports/samd/machine_uart.c | 78 +++++++++++++++++++++++------ ports/samd/mcu/samd21/mpconfigmcu.h | 2 + ports/samd/mcu/samd51/mpconfigmcu.h | 2 + 3 files changed, 66 insertions(+), 16 deletions(-) diff --git a/ports/samd/machine_uart.c b/ports/samd/machine_uart.c index 0ed7fb95d0..92e63ee51e 100644 --- a/ports/samd/machine_uart.c +++ b/ports/samd/machine_uart.c @@ -37,7 +37,6 @@ #define DEFAULT_BUFFER_SIZE (256) #define MIN_BUFFER_SIZE (32) #define MAX_BUFFER_SIZE (32766) -#define USART_BUFFER_TX (0) typedef struct _machine_uart_obj_t { mp_obj_base_t base; @@ -54,7 +53,7 @@ typedef struct _machine_uart_obj_t { uint16_t timeout_char; // timeout waiting between chars (in ms) bool new; ringbuf_t read_buffer; - #if USART_BUFFER_TX + #if MICROPY_HW_UART_TXBUF ringbuf_t write_buffer; #endif } machine_uart_obj_t; @@ -91,7 +90,15 @@ void common_uart_irq_handler(int uart_id) { // Now handler the incoming data uart_drain_rx_fifo(self, uart); } else if (uart->USART.INTFLAG.bit.DRE != 0) { + #if MICROPY_HW_UART_TXBUF // handle the outgoing data + if (ringbuf_avail(&self->write_buffer) > 0) { + uart->USART.DATA.bit.DATA = ringbuf_get(&self->write_buffer); + } else { + // Stop the interrupt if there is no more data + uart->USART.INTENCLR.bit.DRE = 1; + } + #endif } else { // Disable the other interrupts, if set by error uart->USART.INTENCLR.reg = (uint8_t) ~(SERCOM_USART_INTENCLR_DRE | SERCOM_USART_INTENCLR_RXC); @@ -127,7 +134,7 @@ STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - #if USART_BUFFER_TX + #if MICROPY_HW_UART_TXBUF { MP_QSTR_txbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, #endif }; @@ -191,7 +198,7 @@ STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args } } - #if USART_BUFFER_TX + #if MICROPY_HW_UART_TXBUF // Set the TX buffer size if configured. size_t txbuf_len = DEFAULT_BUFFER_SIZE; if (args[ARG_txbuf].u_int > 0) { @@ -224,7 +231,7 @@ STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args ringbuf_alloc(&(self->read_buffer), rxbuf_len + 1); MP_STATE_PORT(samd_uart_rx_buffer[self->id]) = self->read_buffer.buf; - #if USART_BUFFER_TX + #if MICROPY_HW_UART_TXBUF ringbuf_alloc(&(self->write_buffer), txbuf_len + 1); MP_STATE_PORT(samd_uart_tx_buffer[self->id]) = self->write_buffer.buf; #endif @@ -274,6 +281,8 @@ STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args uint32_t baud = 65536 - ((uint64_t)(65536 * 16) * self->baudrate + get_apb_freq() / 2) / get_apb_freq(); uart->USART.BAUD.bit.BAUD = baud; // Set Baud + sercom_register_irq(self->id, &common_uart_irq_handler); + // Enable RXC interrupt uart->USART.INTENSET.bit.RXC = 1; #if defined(MCU_SAMD21) @@ -281,7 +290,13 @@ STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args #elif defined(MCU_SAMD51) NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 2); #endif - sercom_register_irq(self->id, &common_uart_irq_handler); + #if MICROPY_HW_UART_TXBUF + // Enable DRE interrupt + // SAMD21 has just 1 IRQ for all USART events, so no need for an additional NVIC enable + #if defined(MCU_SAMD51) + NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 0); + #endif + #endif sercom_enable(uart, 1); } @@ -330,7 +345,7 @@ STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) { // Disable interrupts uart->USART.INTENCLR.reg = 0xff; MP_STATE_PORT(samd_uart_rx_buffer[self->id]) = NULL; - #if USART_BUFFER_TX + #if MICROPY_HW_UART_TXBUF MP_STATE_PORT(samd_uart_tx_buffer[self->id]) = NULL; #endif return mp_const_none; @@ -339,7 +354,7 @@ 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); - // get all bytes from the fifo first + // get all bytes from the fifo first. May be obsolete. uart_drain_rx_fifo(self, sercom_instance[self->id]); return MP_OBJ_NEW_SMALL_INT(ringbuf_avail(&self->read_buffer)); } @@ -349,9 +364,14 @@ STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); uint32_t break_time_us = 13 * 1000000 / self->baudrate; + // Wait for the tx buffer to drain. + #if MICROPY_HW_UART_TXBUF + while (ringbuf_avail(&self->write_buffer) > 0) { + MICROPY_EVENT_POLL_HOOK + } + #endif // Wait for the TX queue & register to clear // Since the flags are not safe, just wait sufficiently long. - // Once tx buffering is implemented, wait as well for the buffer to clear. mp_hal_delay_us(2 * break_time_us); // Disable MUX PORT->Group[self->tx / 32].PINCFG[self->tx % 32].bit.PMUXEN = 0; @@ -389,7 +409,7 @@ STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_t STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - uint64_t t = mp_hal_ticks_ms() + self->timeout; + uint64_t t = mp_hal_ticks_ms_64() + self->timeout; uint64_t timeout_char = self->timeout_char; uint8_t *dest = buf_in; Sercom *uart = sercom_instance[self->id]; @@ -403,7 +423,7 @@ STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t siz uart_drain_rx_fifo(self, uart); break; } - if (mp_hal_ticks_ms() > t) { // timed out + if (mp_hal_ticks_ms_64() > t) { // timed out if (i <= 0) { *errcode = MP_EAGAIN; return MP_STREAM_ERROR; @@ -421,17 +441,40 @@ 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) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - size_t remaining = size; + size_t i = 0; const uint8_t *src = buf_in; Sercom *uart = sercom_instance[self->id]; - while (remaining--) { - while (!(uart->USART.INTFLAG.bit.DRE)) { + #if MICROPY_HW_UART_TXBUF + uint64_t t = mp_hal_ticks_ms_64() + self->timeout; + + while (i < size) { + // Wait for the first/next character to be sent. + while (ringbuf_free(&(self->write_buffer)) == 0) { + if (mp_hal_ticks_ms_64() > t) { // timed out + if (i <= 0) { + *errcode = MP_EAGAIN; + return MP_STREAM_ERROR; + } else { + return i; + } + } + MICROPY_EVENT_POLL_HOOK } - uart->USART.DATA.bit.DATA = *src; - src += 1; + ringbuf_put(&(self->write_buffer), *src++); + i++; + uart->USART.INTENSET.bit.DRE = 1; // kick off the IRQ } + #else + + while (i < size) { + while (!(uart->USART.INTFLAG.bit.DRE)) { + } + uart->USART.DATA.bit.DATA = *src++; + i++; + } + #endif return size; } @@ -473,3 +516,6 @@ MP_DEFINE_CONST_OBJ_TYPE( ); MP_REGISTER_ROOT_POINTER(void *samd_uart_rx_buffer[SERCOM_INST_NUM]); +#if MICROPY_HW_UART_TXBUF +MP_REGISTER_ROOT_POINTER(void *samd_uart_tx_buffer[SERCOM_INST_NUM]); +#endif diff --git a/ports/samd/mcu/samd21/mpconfigmcu.h b/ports/samd/mcu/samd21/mpconfigmcu.h index 587f3f4b3a..7b91be1430 100644 --- a/ports/samd/mcu/samd21/mpconfigmcu.h +++ b/ports/samd/mcu/samd21/mpconfigmcu.h @@ -5,6 +5,8 @@ #define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF) #define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; +#define MICROPY_HW_UART_TXBUF (1) + #define CPU_FREQ (48000000) #define APB_FREQ (48000000) diff --git a/ports/samd/mcu/samd51/mpconfigmcu.h b/ports/samd/mcu/samd51/mpconfigmcu.h index 95fc635e5e..089ca48de8 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.h +++ b/ports/samd/mcu/samd51/mpconfigmcu.h @@ -19,6 +19,8 @@ unsigned long trng_random_u32(void); #define MICROPY_HW_FLASH_STORAGE_BYTES (0x1FFFF) #define VFS_BLOCK_SIZE_BYTES (1536) // +#define MICROPY_HW_UART_TXBUF (1) + #define CPU_FREQ (120000000) #define APB_FREQ (48000000) #define DPLLx_REF_FREQ (32768) From a9304af8fa7165c41be1cad3d55042a5cc14d13c Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 6 Jun 2022 21:06:09 +0200 Subject: [PATCH 0509/1041] samd/boards: Add missing/lost board config and pin definitions. Fixes are: - Pin definitions for ADAFRUIT_FEATHER_Mx_EXPRESS and ADAFRUIT_ITSYBITSY_M4_EXPRESS. - For ADAFRUIT_ITSYBITSY_M0_EXPRESS, change the MISO/MOSI name. - For MINISAM_M4, add the default SPI pins. - For boards with 32k crystal, add the XOSC32K setting. --- .../boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h | 2 ++ ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv | 3 +++ .../boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h | 2 ++ ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv | 9 +++++++++ .../samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv | 6 +++--- .../samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv | 10 ++++++++-- ports/samd/boards/MINISAM_M4/pins.csv | 3 +++ ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h | 2 ++ ports/samd/boards/SEEED_XIAO/mpconfigboard.h | 2 ++ 9 files changed, 34 insertions(+), 5 deletions(-) diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h index cec9e9ccdd..815597899c 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h @@ -1,2 +1,4 @@ #define MICROPY_HW_BOARD_NAME "Feather M0 Express" #define MICROPY_HW_MCU_NAME "SAMD21G18A" + +#define MICROPY_HW_XOSC32K (1) diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv index 84e68157ac..0985ee1646 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv @@ -29,6 +29,9 @@ PIN_PB22,TX PIN_PB23,RX PIN_PA23,SCL PIN_PA22,SDA +PIN_PB10,MOSI +PIN_PA12,MISO +PIN_PB11,SCK PIN_PA06,NEOPIXEL PIN_PA13,FLASH_CS diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h index 48599eec47..35945395fc 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h @@ -1,2 +1,4 @@ #define MICROPY_HW_BOARD_NAME "Feather M4 Express" #define MICROPY_HW_MCU_NAME "SAMD51J19A" + +#define MICROPY_HW_XOSC32K (1) diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv index 5b999c39e0..32daac3d0f 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv @@ -7,6 +7,8 @@ PIN_PB17,D0 PIN_PB16,D1 +- +- PIN_PA14,D4 PIN_PA16,D5 PIN_PA18,D6 @@ -30,5 +32,12 @@ PIN_PB22,MISO PIN_PA17,SCK PIN_PB01,VDIV PIN_PA03,AREF +PIN_PB03,NEOPIXEL +PIN_PB11,FLASH_CS +PIN_PB10,FLASH_SCK +PIN_PA08,FLASH_MOSI +PIN_PA09,FLASH_MISO +PIN_PA10,FLASH_WP +PIN_PA11,FLASH_HOLD LED_PA17,LED diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv index 50c3c1cf68..d7d59c2357 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv @@ -8,7 +8,7 @@ PIN_PA11,D0 PIN_PA10,D1 PIN_PA14,D2 -PIN_PB09,D3 +PIN_PA09,D3 PIN_PA08,D4 PIN_PA15,D5 - @@ -27,8 +27,8 @@ PIN_PA05,A4 PIN_PB02,A5 PIN_PA22,SDA PIN_PA23,SCL -PIN_PB10,MO -PIN_PA12,MI +PIN_PB10,MOSI +PIN_PA12,MISO PIN_PB11,SCK PIN_PA00,DOTSTAR_CLK PIN_PA01,DOTSTAR_DATA diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv index 90e38761a1..ce760a269c 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv @@ -27,10 +27,16 @@ PIN_PA04,A4 PIN_PA06,A5 PIN_PA12,SDA PIN_PA13,SCL -PIN_PA00,MO -PIN_PB23,MI +PIN_PA00,MOSI +PIN_PB23,MISO PIN_PA01,SCK PIN_PB02,DOTSTAR_CLK PIN_PB03,DOTSTAR_DATA +PIN_PB11,FLASH_CS +PIN_PB10,FLASH_SCK +PIN_PA08,FLASH_MOSI +PIN_PA09,FLASH_MISO +PIN_PA10,FLASH_WP +PIN_PA11,FLASH_HOLD LED_PA22,LED diff --git a/ports/samd/boards/MINISAM_M4/pins.csv b/ports/samd/boards/MINISAM_M4/pins.csv index 7442a028d1..cf9a3bd19b 100644 --- a/ports/samd/boards/MINISAM_M4/pins.csv +++ b/ports/samd/boards/MINISAM_M4/pins.csv @@ -21,6 +21,9 @@ PIN_PA00,BUTTON PIN_PA03,AREF PIN_PA12,SDA PIN_PA13,SCL +PIN_PB22,MOSI +PIN_PB23,MISO +PIN_PA01,SCK PIN_PB03,DOTSTAR_DATA PIN_PB02,DOTSTAR_CLK diff --git a/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h b/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h index c69b5b4c14..064d1ecc0d 100644 --- a/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h +++ b/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h @@ -1,2 +1,4 @@ #define MICROPY_HW_BOARD_NAME "SAMD21-XPLAINED-PRO" #define MICROPY_HW_MCU_NAME "SAMD21J18A" + +#define MICROPY_HW_XOSC32K (1) diff --git a/ports/samd/boards/SEEED_XIAO/mpconfigboard.h b/ports/samd/boards/SEEED_XIAO/mpconfigboard.h index 2026efc6b1..98994a5bc0 100644 --- a/ports/samd/boards/SEEED_XIAO/mpconfigboard.h +++ b/ports/samd/boards/SEEED_XIAO/mpconfigboard.h @@ -1,2 +1,4 @@ #define MICROPY_HW_BOARD_NAME "Seeed Xiao" #define MICROPY_HW_MCU_NAME "SAMD21G18A" + +#define MICROPY_HW_XOSC32K (1) From fd7b57dd22ce0105e04c5f9b2d12ca3a3075ca0a Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 10 Jun 2022 08:23:09 +0200 Subject: [PATCH 0510/1041] samd/mphalport: Use CYCCNT for SAMD51's mp_hal_ticks_cpu(). And use mp_hal_ticks_us() for SAM21's mp_hal_ticks_cpu(). The SAMD21 has no CYCCNT register, and the SysTick register has only a 1 ms span (== 48000 count range). --- ports/samd/mphalport.h | 18 ++++++++++++++---- ports/samd/samd_soc.c | 4 ++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/ports/samd/mphalport.h b/ports/samd/mphalport.h index c2aca8b0e2..b7e65da35d 100644 --- a/ports/samd/mphalport.h +++ b/ports/samd/mphalport.h @@ -71,12 +71,22 @@ static inline mp_uint_t mp_hal_ticks_us(void) { #endif } -// ticks_cpu is limited to a 1 ms period, since the CPU SysTick counter -// is used for the 1 ms SysTick_Handler interrupt. -static inline mp_uint_t mp_hal_ticks_cpu(void) { - return (system_time_t)SysTick->VAL; +#if defined (MCU_SAMD21) + +#define mp_hal_ticks_cpu mp_hal_ticks_us + +#elif defined (MCU_SAMD51) +static inline void mp_hal_ticks_cpu_enable(void) { + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + DWT->CYCCNT = 0; + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; } +static inline mp_uint_t mp_hal_ticks_cpu(void) { + return (system_time_t)DWT->CYCCNT; +} +#endif + static inline uint64_t mp_hal_time_ns(void) { return mp_hal_ticks_ms_64() * 1000000; } diff --git a/ports/samd/samd_soc.c b/ports/samd/samd_soc.c index 8d6e808f63..aca6df0dd8 100644 --- a/ports/samd/samd_soc.c +++ b/ports/samd/samd_soc.c @@ -36,6 +36,7 @@ #include "samd_soc.h" #include "sam.h" #include "tusb.h" +#include "mphalport.h" static void usb_init(void) { // Init USB clock @@ -110,4 +111,7 @@ void samd_init(void) { SysTick_Config(get_cpu_freq() / 1000); init_us_counter(); usb_init(); + #if defined (MCU_SAMD51) + mp_hal_ticks_cpu_enable(); + #endif } From a4157521731878c7363ff59f15d68eb68b486cb5 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 10 Jun 2022 16:40:50 +0200 Subject: [PATCH 0511/1041] samd/machine_bitstream: Add the machine.bitstream() function. The SAMD21 implementation is an adaption of @jimmo's code for STM32Lxx. The only changes are the addresses and names of the port registers and the timing parameters. SAMD21: The precision is about +/-25ns at 48MHz clock frequency. The first two cycles are about 40-60 ns longer than set. But still good enough to drive a neopixel device. SAMD51: The precision is about +/-30ns at 120MHz clock frequency. Good enough to drive a neopixel device. --- ports/samd/Makefile | 3 +- ports/samd/machine_bitstream.c | 206 +++++++++++++++++++++++++++++++++ ports/samd/modmachine.c | 2 + ports/samd/mpconfigport.h | 1 + ports/samd/mphalport.h | 4 +- ports/samd/samd_soc.c | 2 +- 6 files changed, 214 insertions(+), 4 deletions(-) create mode 100644 ports/samd/machine_bitstream.c diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 1455e748cc..f1bc67e6ee 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -87,10 +87,11 @@ LIBSTDCPP_FILE_NAME = "$(shell $(CXX) $(CXXFLAGS) -print-file-name=libstdc++.a)" LDFLAGS += -L"$(shell dirname $(LIBSTDCPP_FILE_NAME))" endif -SRC_C = \ +SRC_C += \ clock_config.c \ help.c \ machine_adc.c \ + machine_bitstream.c \ machine_dac.c \ machine_i2c.c \ machine_led.c \ diff --git a/ports/samd/machine_bitstream.c b/ports/samd/machine_bitstream.c new file mode 100644 index 0000000000..9959d947cb --- /dev/null +++ b/ports/samd/machine_bitstream.c @@ -0,0 +1,206 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Jim Mussared + * + * 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. + */ + +// This is a translation of the cycle counter implementation in ports/stm32/machine_bitstream.c. + +#include "py/mpconfig.h" +#include "py/mphal.h" +#include "clock_config.h" + +#if MICROPY_PY_MACHINE_BITSTREAM + +#if __CORTEX_M == 0 + +// No cycle counter on M0, do manual cycle counting instead. + +// STM32F091 @ 48MHz +#define NS_CYCLES_PER_ITER_HIGH (3) +#define NS_CYCLES_PER_ITER_LOW (3) +#define NS_OVERHEAD_CYCLES_HIGH (12) +#define NS_OVERHEAD_CYCLES_LOW (15) + +uint32_t mp_hal_delay_ns_calc(uint32_t ns, bool high) { + uint32_t ncycles = (get_cpu_freq() / 1000000 * ns + 500) / 1000; // + 500 for proper rounding + uint32_t overhead = MIN(ncycles, high ? NS_OVERHEAD_CYCLES_HIGH : NS_OVERHEAD_CYCLES_LOW); + return MAX(1, MP_ROUND_DIVIDE(ncycles - overhead, high ? NS_CYCLES_PER_ITER_HIGH : NS_CYCLES_PER_ITER_LOW)); +} + +void machine_bitstream_high_low(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const uint8_t *buf, size_t len) { + volatile const uint32_t mask = 1 << (pin % 32); + volatile uint32_t *outclr = &PORT->Group[pin / 32].OUTCLR.reg; + volatile uint32_t *outset = &PORT->Group[pin / 32].OUTSET.reg; + + // Convert ns to loop iterations [high_time_0, low_time_0, high_time_1, low_time_1]. + for (size_t i = 0; i < 4; ++i) { + timing_ns[i] = mp_hal_delay_ns_calc(timing_ns[i], i % 2 == 0); + } + + mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); + + // Measured timing for SAMD21 at 48MHz (cycle=20.83ns) + // timing_ns = (1,1,1,1) + // high: 310 + // low: 375 + // high0: 375 + // low0: 400 + // timing_ns = (500, 500, 500, 500) + // high: 500 + // low: 500 + // high0: 565 + // low0: 540 + // timing_ns = (1000, 1000, 1000, 1000) + // high: 1000 + // low: 1000 + // high0: 1065 + // low0: 1040 + + // --> high is 12 + n*3 cycles + // low is 15 + n*3 cycles + + // NeoPixel timing (400, 850, 800, 450) (+/-150ns) gives timing_ns=(2, 9, 8, 3) which in cycles is + // (12 + 6, 15 + 27, 15 + 24, 12 + 9) = (18, 42, 39, 21) + // --> (375, 875, 812, 437) nanoseconds. + // Measured output on logic analyser is (375, 875, 815, 435) (+/-5ns at 200MHz) + + // Note: the first high/low cycle is longer by 2-3 cycles (40-60ns). + // This is slightly outside spec, but doesn't seem to cause a problem. + + __asm volatile ( + // Force consistent register assignment. + // r6 = len + "ldr r6, %0\n" + // r4 = buf + "ldr r4, %1\n" + // r5 = timing_ms + "ldr r5, %2\n" + + // Must align for consistent timing. + ".align 4\n" + + // Don't increment/decrement before first iteration. + "b .outer2\n" + ".outer:\n" + // ++buf, --len + " add r4, #1\n" + " sub r6, #1\n" + + // len iterations + ".outer2:\n" + " cmp r6, #0\n" + " beq .done\n" + + // r0 = *buf + " ldrb r0, [r4, #0]\n" + + // 8 bits in byte + " mov r7, #8\n" + " .inner:\n" + // *outset = mask + " ldr r2, %3\n" + " ldr r1, %5\n" + " str r1, [r2, #0]\n" + + // r3 = (r0 >> 4) & 8 (r0 is 8 if high bit is 1 else 0) + " mov r8, r6\n" + " lsr r3, r0, #4\n" + " mov r6, #8\n" + " and r3, r6\n" + " mov r6, r8\n" + + // r2 = timing_ns[r2] + " ldr r2, [r5, r3]\n" + " .loop1:\n sub r2, #1\n bne .loop1\n" + + // *outclr = mask + " ldr r2, %4\n" + " str r1, [r2, #0]\n" + + // r2 = timing_ns[r3 + 4] + " add r3, #4\n" + " ldr r2, [r5, r3]\n" + " .loop2:\n sub r2, #1\n bne .loop2\n" + + // b >>= 1 + " lsl r0, r0, #1\n" + + " sub r7, #1\n" + // end of inner loop + " beq .outer\n" + // continue inner loop + " b .inner\n" + + ".done:\n" + : + : "m" (len), "m" (buf), "m" (timing_ns), "m" (outset), "m" (outclr), "m" (mask) + : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8" + ); + + MICROPY_END_ATOMIC_SECTION(atomic_state); +} + +#else // > CORTEX_M0 + +#define NS_TICKS_OVERHEAD (70) + +void machine_bitstream_high_low(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const uint8_t *buf, size_t len) { + uint32_t fcpu_mhz = get_cpu_freq() / 1000000; + uint32_t ticks_overhead = fcpu_mhz * NS_TICKS_OVERHEAD / 1000; + // Convert ns to us ticks [high_time_0, period_0, high_time_1, period_1]. + for (size_t i = 0; i < 4; ++i) { + timing_ns[i] = fcpu_mhz * timing_ns[i] / 1000; + if (timing_ns[i] > ticks_overhead) { + timing_ns[i] -= ticks_overhead; + } + if (i % 2 == 1) { + // Convert low_time to period (i.e. add high_time). + timing_ns[i] += timing_ns[i - 1] - ticks_overhead; + } + } + + mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); + DWT->CYCCNT = 0; + + for (size_t i = 0; i < len; ++i) { + uint8_t b = buf[i]; + for (size_t j = 0; j < 8; ++j) { + uint32_t start_ticks = mp_hal_ticks_cpu(); + uint32_t *t = &timing_ns[b >> 6 & 2]; + mp_hal_pin_high(pin); + while ((mp_hal_ticks_cpu() - start_ticks) < t[0]) { + } + b <<= 1; + mp_hal_pin_low(pin); + while ((mp_hal_ticks_cpu() - start_ticks) < t[1]) { + } + } + } + MICROPY_END_ATOMIC_SECTION(atomic_state); + +} + +#endif // > CORTEX_M0 + +#endif // MICROPY_PY_MACHINE_BITSTREAM diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index c191afda79..f6cf7f8155 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -25,6 +25,7 @@ */ #include "py/runtime.h" +#include "extmod/machine_bitstream.h" #include "extmod/machine_mem.h" #include "extmod/machine_pulse.h" #include "extmod/machine_i2c.h" @@ -167,6 +168,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, + { MP_ROM_QSTR(MP_QSTR_bitstream), MP_ROM_PTR(&machine_bitstream_obj) }, }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 8a067d3482..986c42fc7f 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -111,6 +111,7 @@ #define MICROPY_PY_MACHINE_SPI (1) #define MICROPY_PY_MACHINE_SOFTSPI (1) #define MICROPY_PY_OS_DUPTERM (3) +#define MICROPY_PY_MACHINE_BITSTREAM (1) #define MICROPY_PY_MACHINE_PULSE (1) #define MICROPY_PY_MACHINE_PWM (1) #define MICROPY_PY_MACHINE_PWM_INIT (0) diff --git a/ports/samd/mphalport.h b/ports/samd/mphalport.h index b7e65da35d..f1efd55003 100644 --- a/ports/samd/mphalport.h +++ b/ports/samd/mphalport.h @@ -71,11 +71,11 @@ static inline mp_uint_t mp_hal_ticks_us(void) { #endif } -#if defined (MCU_SAMD21) +#if defined(MCU_SAMD21) #define mp_hal_ticks_cpu mp_hal_ticks_us -#elif defined (MCU_SAMD51) +#elif defined(MCU_SAMD51) static inline void mp_hal_ticks_cpu_enable(void) { CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT = 0; diff --git a/ports/samd/samd_soc.c b/ports/samd/samd_soc.c index aca6df0dd8..d0df4a7e28 100644 --- a/ports/samd/samd_soc.c +++ b/ports/samd/samd_soc.c @@ -111,7 +111,7 @@ void samd_init(void) { SysTick_Config(get_cpu_freq() / 1000); init_us_counter(); usb_init(); - #if defined (MCU_SAMD51) + #if defined(MCU_SAMD51) mp_hal_ticks_cpu_enable(); #endif } From 929dfc66a30c361d2a0bd5b64dec021a49c7b471 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 15 Jun 2022 15:16:07 +0200 Subject: [PATCH 0512/1041] samd/mpconfigport: Restructure to use ROM feature levels. Changes are: - Set the feature level for each MCU: CORE features for SAMD21, and EXTRA features for SAMD51. - Remove all definitions that are included in the core feature level. - Keep the default settings for feature level and float, to make the choice obvious. --- ports/samd/Makefile | 1 + ports/samd/mcu/samd21/mpconfigmcu.h | 22 +++++++++++++++------- ports/samd/mcu/samd51/mpconfigmcu.h | 25 ++++++++++++++++--------- ports/samd/mpconfigport.h | 23 +---------------------- 4 files changed, 33 insertions(+), 38 deletions(-) diff --git a/ports/samd/Makefile b/ports/samd/Makefile index f1bc67e6ee..5b268286c3 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -161,6 +161,7 @@ SRC_QSTR += \ shared/readline/readline.c \ extmod/uos_dupterm.c \ shared/runtime/mpirq.c \ + shared/runtime/sys_stdio_mphal.c \ SRC_QSTR += $(SRC_MOD) $(SRC_CXX) diff --git a/ports/samd/mcu/samd21/mpconfigmcu.h b/ports/samd/mcu/samd21/mpconfigmcu.h index 7b91be1430..dd16a6c8af 100644 --- a/ports/samd/mcu/samd21/mpconfigmcu.h +++ b/ports/samd/mcu/samd21/mpconfigmcu.h @@ -1,16 +1,24 @@ // Deinitions common to all SAMD21 boards #include "samd21.h" -#define MICROPY_HW_FLASH_STORAGE_BASE (0x30000) -#define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF) -#define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES) -#define MICROPY_HW_UART_TXBUF (1) +// MicroPython emitters +#define MICROPY_EMIT_THUMB (0) +#define MICROPY_EMIT_INLINE_THUMB (0) -#define CPU_FREQ (48000000) -#define APB_FREQ (48000000) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) -#define IRQ_PRI_PENDSV ((1 << __NVIC_PRIO_BITS) - 1) +#define MICROPY_HW_FLASH_STORAGE_BASE (0x30000) +#define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF) +#define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; + +#define MICROPY_HW_UART_TXBUF (1) + +#define CPU_FREQ (48000000) +#define APB_FREQ (48000000) + +#define IRQ_PRI_PENDSV ((1 << __NVIC_PRIO_BITS) - 1) static inline uint32_t raise_irq_pri(uint32_t pri) { (void)pri; diff --git a/ports/samd/mcu/samd51/mpconfigmcu.h b/ports/samd/mcu/samd51/mpconfigmcu.h index 089ca48de8..c3253fcbec 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.h +++ b/ports/samd/mcu/samd51/mpconfigmcu.h @@ -1,10 +1,17 @@ // Deinitions common to all SAMD51 boards #include "samd51.h" +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_FULL_FEATURES) + +// MicroPython emitters +#define MICROPY_EMIT_THUMB (1) +#define MICROPY_EMIT_INLINE_THUMB (1) + #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) + #define MICROPY_PY_UOS_URANDOM (1) #define MICROPY_PY_URANDOM_SEED_INIT_FUNC (trng_random_u32()) unsigned long trng_random_u32(void); @@ -15,18 +22,18 @@ unsigned long trng_random_u32(void); // samd_flash.c flash parameters // Build a 128k Flash storage at top. 512k-128k=384k=0x60000 // 512*1024= 0x80000 minus 128*1024= 0x20000 = 0x60000 -#define MICROPY_HW_FLASH_STORAGE_BASE (0x60000) -#define MICROPY_HW_FLASH_STORAGE_BYTES (0x1FFFF) -#define VFS_BLOCK_SIZE_BYTES (1536) // +#define MICROPY_HW_FLASH_STORAGE_BASE (0x60000) +#define MICROPY_HW_FLASH_STORAGE_BYTES (0x1FFFF) +#define VFS_BLOCK_SIZE_BYTES (1536) // -#define MICROPY_HW_UART_TXBUF (1) +#define MICROPY_HW_UART_TXBUF (1) -#define CPU_FREQ (120000000) -#define APB_FREQ (48000000) -#define DPLLx_REF_FREQ (32768) +#define CPU_FREQ (120000000) +#define APB_FREQ (48000000) +#define DPLLx_REF_FREQ (32768) -#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003) -#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 7, 0) +#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003) +#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 7, 0) static inline uint32_t raise_irq_pri(uint32_t pri) { uint32_t basepri = __get_BASEPRI(); diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 986c42fc7f..8b8305f0b4 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -40,8 +40,6 @@ // MicroPython emitters #define MICROPY_PERSISTENT_CODE_LOAD (1) -#define MICROPY_EMIT_THUMB (0) -#define MICROPY_EMIT_INLINE_THUMB (0) // Compiler configuration #define MICROPY_COMP_CONST (1) @@ -56,33 +54,18 @@ #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) -#define MICROPY_CPYTHON_COMPAT (0) -#define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_TEXT samd_help_text #define MICROPY_PY_BUILTINS_HELP_MODULES (1) #define MICROPY_ENABLE_SCHEDULER (1) -// fixes sys/usys import issue #define MICROPY_MODULE_WEAK_LINKS (1) + // Control over Python builtins -#define MICROPY_PY_ASYNC_AWAIT (0) #define MICROPY_PY_BUILTINS_BYTES_HEX (1) -#define MICROPY_PY_BUILTINS_STR_COUNT (0) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) -#define MICROPY_PY_BUILTINS_SET (0) -#define MICROPY_PY_BUILTINS_FROZENSET (0) -#define MICROPY_PY_BUILTINS_PROPERTY (0) -#define MICROPY_PY_BUILTINS_ENUMERATE (1) -#define MICROPY_PY_BUILTINS_FILTER (0) -#define MICROPY_PY_BUILTINS_REVERSED (0) -#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) -#define MICROPY_PY_BUILTINS_MIN_MAX (1) #define MICROPY_PY_BUILTINS_INPUT (1) -#define MICROPY_PY___FILE__ (0) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) -#define MICROPY_PY_ATTRTUPLE (1) -#define MICROPY_PY_COLLECTIONS (0) #define MICROPY_PY_SYS (1) #define MICROPY_PY_SYS_PLATFORM "samd" #define MICROPY_PY_SYS_EXIT (1) @@ -118,10 +101,6 @@ #define MICROPY_PY_MACHINE_PWM_DUTY_U16_NS (1) #define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/samd/machine_pwm.c" -// Use VfsLfs's types for fileio/textio -#define mp_type_fileio mp_type_vfs_lfs1_fileio -#define mp_type_textio mp_type_vfs_lfs1_textio - #define MP_STATE_PORT MP_STATE_VM // Miscellaneous settings From f00356a486ed7ea9650f59f1259b2732d9a1bb21 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 15 Jun 2022 18:49:24 +0200 Subject: [PATCH 0513/1041] samd/clock_config: Split clock_config.c to separate SAMD21/SAMD51 files. And put the file into the mcu directory. The file got a little bit long and hard to read. --- ports/samd/Makefile | 2 +- ports/samd/mcu/samd21/clock_config.c | 168 +++++++++++++++++++++ ports/samd/{ => mcu/samd51}/clock_config.c | 131 ---------------- 3 files changed, 169 insertions(+), 132 deletions(-) create mode 100644 ports/samd/mcu/samd21/clock_config.c rename ports/samd/{ => mcu/samd51}/clock_config.c (59%) diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 5b268286c3..8d49778b3b 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -88,7 +88,7 @@ LDFLAGS += -L"$(shell dirname $(LIBSTDCPP_FILE_NAME))" endif SRC_C += \ - clock_config.c \ + mcu/$(MCU_SERIES_LOWER)/clock_config.c \ help.c \ machine_adc.c \ machine_bitstream.c \ diff --git a/ports/samd/mcu/samd21/clock_config.c b/ports/samd/mcu/samd21/clock_config.c new file mode 100644 index 0000000000..3d189d67e1 --- /dev/null +++ b/ports/samd/mcu/samd21/clock_config.c @@ -0,0 +1,168 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * This file provides functions for configuring the clocks. + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Robert Hammelrath + * + * 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 + +#include "py/runtime.h" +#include "samd_soc.h" + +static uint32_t cpu_freq = CPU_FREQ; +static uint32_t apb_freq = APB_FREQ; + +int sercom_gclk_id[] = { + GCLK_CLKCTRL_ID_SERCOM0_CORE, GCLK_CLKCTRL_ID_SERCOM1_CORE, + GCLK_CLKCTRL_ID_SERCOM2_CORE, GCLK_CLKCTRL_ID_SERCOM3_CORE, + GCLK_CLKCTRL_ID_SERCOM4_CORE, GCLK_CLKCTRL_ID_SERCOM5_CORE +}; + +uint32_t get_cpu_freq(void) { + return cpu_freq; +} + +uint32_t get_apb_freq(void) { + return apb_freq; +} + +void set_cpu_freq(uint32_t cpu_freq_arg) { + cpu_freq = cpu_freq_arg; +} + + +void init_clocks(uint32_t cpu_freq) { + + // SAMD21 Clock settings + // GCLK0: 48MHz from DFLL open loop mode or closed loop mode from 32k Crystal + // GCLK1: 32768 Hz from 32K ULP or 32k Crystal + // GCLK2: 48MHz from DFLL for Peripherals + // GCLK3: 1Mhz for the us-counter (TC4/TC5) + // GCLK8: 1kHz clock for WDT + + NVMCTRL->CTRLB.bit.MANW = 1; // errata "Spurious Writes" + NVMCTRL->CTRLB.bit.RWS = 1; // 1 read wait state for 48MHz + + #if MICROPY_HW_XOSC32K + // Set up OSC32K according datasheet 17.6.3 + SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP(0x3) | SYSCTRL_XOSC32K_EN32K | + SYSCTRL_XOSC32K_XTALEN; + SYSCTRL->XOSC32K.bit.ENABLE = 1; + while (SYSCTRL->PCLKSR.bit.XOSC32KRDY == 0) { + } + // Set up the DFLL48 according to the data sheet 17.6.7.1.2 + // Step 1: Set up the reference clock + // Connect the OSC32K via GCLK1 to the DFLL input and for further use. + GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) | GCLK_GENDIV_DIV(1); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_ID(1); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_DFLL48 | GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_CLKEN; + // Enable access to the DFLLCTRL reg acc. to Errata 1.2.1 + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE; + while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { + } + // Step 2: Set the coarse and fine values. + // The coarse setting will be taken from the calibration data. So the value used here + // does not matter. Get the coarse value from the calib data. In case it is not set, + // set a midrange value. + uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) + >> FUSES_DFLL48M_COARSE_CAL_Pos; + if (coarse == 0x3f) { + coarse = 0x1f; + } + SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(512); + while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { + } + // Step 3: Set the multiplication values. The offset of 16384 to the freq is for rounding. + SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_MUL((CPU_FREQ + 16384) / 32768) | + SYSCTRL_DFLLMUL_FSTEP(1) | SYSCTRL_DFLLMUL_CSTEP(1); + while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { + } + // Step 4: Start the DFLL and wait for the PLL lock. We just wait for the fine lock, since + // coarse adjusting is bypassed. + SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_WAITLOCK | + SYSCTRL_DFLLCTRL_BPLCKC | SYSCTRL_DFLLCTRL_ENABLE; + while (SYSCTRL->PCLKSR.bit.DFLLLCKF == 0) { + } + + #else // MICROPY_HW_XOSC32K + + // Enable DFLL48M + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE; + while (!SYSCTRL->PCLKSR.bit.DFLLRDY) { + } + SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(1) | SYSCTRL_DFLLMUL_FSTEP(1) + | SYSCTRL_DFLLMUL_MUL(48000); + uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) + >> FUSES_DFLL48M_COARSE_CAL_Pos; + if (coarse == 0x3f) { + coarse = 0x1f; + } + SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(512); + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_USBCRM + | SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_ENABLE; + while (!SYSCTRL->PCLKSR.bit.DFLLRDY) { + } + // Enable 32768 Hz on GCLK1 for consistency + GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) | GCLK_GENDIV_DIV(48016384 / 32768); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(1); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + + #endif // MICROPY_HW_XOSC32K + + // Enable GCLK output: 48M on both CCLK0 and GCLK2 + GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) | GCLK_GENDIV_DIV(1); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(0); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + GCLK->GENDIV.reg = GCLK_GENDIV_ID(2) | GCLK_GENDIV_DIV(1); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(2); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + + // Enable GCLK output: 1MHz on GCLK3 for TC4 + GCLK->GENDIV.reg = GCLK_GENDIV_ID(3) | GCLK_GENDIV_DIV(48); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(3); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + // Set GCLK8 to 1 kHz. + GCLK->GENDIV.reg = GCLK_GENDIV_ID(8) | GCLK_GENDIV_DIV(32); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(8); + while (GCLK->STATUS.bit.SYNCBUSY) { + } +} + +void enable_sercom_clock(int id) { + // Next: Set up the clocks + // Enable synchronous clock. The bits are nicely arranged + PM->APBCMASK.reg |= 0x04 << id; + // Select multiplexer generic clock source and enable. + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | sercom_gclk_id[id]; + // Wait while it updates synchronously. + while (GCLK->STATUS.bit.SYNCBUSY) { + } +} diff --git a/ports/samd/clock_config.c b/ports/samd/mcu/samd51/clock_config.c similarity index 59% rename from ports/samd/clock_config.c rename to ports/samd/mcu/samd51/clock_config.c index 0f5634fdb7..3a3f40385f 100644 --- a/ports/samd/clock_config.c +++ b/ports/samd/mcu/samd51/clock_config.c @@ -34,13 +34,6 @@ static uint32_t cpu_freq = CPU_FREQ; static uint32_t apb_freq = APB_FREQ; -#if defined(MCU_SAMD21) -int sercom_gclk_id[] = { - GCLK_CLKCTRL_ID_SERCOM0_CORE, GCLK_CLKCTRL_ID_SERCOM1_CORE, - GCLK_CLKCTRL_ID_SERCOM2_CORE, GCLK_CLKCTRL_ID_SERCOM3_CORE, - GCLK_CLKCTRL_ID_SERCOM4_CORE, GCLK_CLKCTRL_ID_SERCOM5_CORE -}; -#elif defined(MCU_SAMD51) int sercom_gclk_id[] = { SERCOM0_GCLK_ID_CORE, SERCOM1_GCLK_ID_CORE, SERCOM2_GCLK_ID_CORE, SERCOM3_GCLK_ID_CORE, @@ -49,7 +42,6 @@ int sercom_gclk_id[] = { SERCOM6_GCLK_ID_CORE, SERCOM7_GCLK_ID_CORE, #endif }; -#endif uint32_t get_cpu_freq(void) { return cpu_freq; @@ -59,12 +51,6 @@ uint32_t get_apb_freq(void) { return apb_freq; } -#if defined(MCU_SAMD21) -void set_cpu_freq(uint32_t cpu_freq_arg) { - cpu_freq = cpu_freq_arg; -} - -#elif defined(MCU_SAMD51) void set_cpu_freq(uint32_t cpu_freq_arg) { cpu_freq = cpu_freq_arg; @@ -97,113 +83,8 @@ void set_cpu_freq(uint32_t cpu_freq_arg) { while (GCLK->SYNCBUSY.bit.GENCTRL0) { } } -#endif void init_clocks(uint32_t cpu_freq) { - #if defined(MCU_SAMD21) - - // SAMD21 Clock settings - // GCLK0: 48MHz from DFLL open loop mode or closed loop mode from 32k Crystal - // GCLK1: 32768 Hz from 32K ULP or 32k Crystal - // GCLK2: 48MHz from DFLL for Peripherals - // GCLK3: 1Mhz for the us-counter (TC3/TC4) - // GCLK8: 1kHz clock for WDT - - NVMCTRL->CTRLB.bit.MANW = 1; // errata "Spurious Writes" - NVMCTRL->CTRLB.bit.RWS = 1; // 1 read wait state for 48MHz - - #if MICROPY_HW_XOSC32K - // Set up OSC32K according datasheet 17.6.3 - SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP(0x3) | SYSCTRL_XOSC32K_EN32K | - SYSCTRL_XOSC32K_XTALEN; - SYSCTRL->XOSC32K.bit.ENABLE = 1; - while (SYSCTRL->PCLKSR.bit.XOSC32KRDY == 0) { - } - // Set up the DFLL48 according to the data sheet 17.6.7.1.2 - // Step 1: Set up the reference clock - // Connect the OSC32K via GCLK1 to the DFLL input and for further use. - GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) | GCLK_GENDIV_DIV(1); - GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_ID(1); - while (GCLK->STATUS.bit.SYNCBUSY) { - } - GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_DFLL48 | GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_CLKEN; - // Enable access to the DFLLCTRL reg acc. to Errata 1.2.1 - SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE; - while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { - } - // Step 2: Set the coarse and fine values. - // The coarse setting will be taken from the calibration data. So the value used here - // does not matter. Get the coarse value from the calib data. In case it is not set, - // set a midrange value. - uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) - >> FUSES_DFLL48M_COARSE_CAL_Pos; - if (coarse == 0x3f) { - coarse = 0x1f; - } - SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(512); - while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { - } - // Step 3: Set the multiplication values. The offset of 16384 to the freq is for rounding. - SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_MUL((CPU_FREQ + 16384) / 32768) | - SYSCTRL_DFLLMUL_FSTEP(1) | SYSCTRL_DFLLMUL_CSTEP(1); - while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { - } - // Step 4: Start the DFLL and wait for the PLL lock. We just wait for the fine lock, since - // coarse adjusting is bypassed. - SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_WAITLOCK | - SYSCTRL_DFLLCTRL_BPLCKC | SYSCTRL_DFLLCTRL_ENABLE; - while (SYSCTRL->PCLKSR.bit.DFLLLCKF == 0) { - } - - #else // MICROPY_HW_XOSC32K - - // Enable DFLL48M - SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE; - while (!SYSCTRL->PCLKSR.bit.DFLLRDY) { - } - SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(1) | SYSCTRL_DFLLMUL_FSTEP(1) - | SYSCTRL_DFLLMUL_MUL(48000); - uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) - >> FUSES_DFLL48M_COARSE_CAL_Pos; - if (coarse == 0x3f) { - coarse = 0x1f; - } - SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(512); - SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_USBCRM - | SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_ENABLE; - while (!SYSCTRL->PCLKSR.bit.DFLLRDY) { - } - // Enable 32768 Hz on GCLK1 for consistency - GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) | GCLK_GENDIV_DIV(48016384 / 32768); - GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(1); - while (GCLK->STATUS.bit.SYNCBUSY) { - } - - #endif // MICROPY_HW_XOSC32K - - // Enable GCLK output: 48M on both CCLK0 and GCLK2 - GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) | GCLK_GENDIV_DIV(1); - GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(0); - while (GCLK->STATUS.bit.SYNCBUSY) { - } - GCLK->GENDIV.reg = GCLK_GENDIV_ID(2) | GCLK_GENDIV_DIV(1); - GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(2); - while (GCLK->STATUS.bit.SYNCBUSY) { - } - - // Enable GCLK output: 1MHz on GCLK3 for TC3 - GCLK->GENDIV.reg = GCLK_GENDIV_ID(3) | GCLK_GENDIV_DIV(48); - GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(3); - while (GCLK->STATUS.bit.SYNCBUSY) { - } - // Set GCLK8 to 1 kHz. - GCLK->GENDIV.reg = GCLK_GENDIV_ID(8) | GCLK_GENDIV_DIV(32); - GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(8); - while (GCLK->STATUS.bit.SYNCBUSY) { - } - - #elif defined(MCU_SAMD51) - // SAMD51 clock settings // GCLK0: 48MHz from DFLL48M or 48 - 200 MHz from DPLL0 (SAMD51) // GCLK1: DPLLx_REF_FREQ 32768 Hz from 32KULP or 32k Crystal @@ -299,21 +180,10 @@ void init_clocks(uint32_t cpu_freq) { GCLK->GENCTRL[3].reg = GCLK_GENCTRL_DIV(6) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; while (GCLK->SYNCBUSY.bit.GENCTRL3) { } - - #endif // defined(MCU_SAMD51) } void enable_sercom_clock(int id) { // Next: Set up the clocks - #if defined(MCU_SAMD21) - // Enable synchronous clock. The bits are nicely arranged - PM->APBCMASK.reg |= 0x04 << id; - // Select multiplexer generic clock source and enable. - GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | sercom_gclk_id[id]; - // Wait while it updates synchronously. - while (GCLK->STATUS.bit.SYNCBUSY) { - } - #elif defined(MCU_SAMD51) GCLK->PCHCTRL[sercom_gclk_id[id]].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK2; // no easy way to set the clocks, except enabling all of them switch (id) { @@ -344,5 +214,4 @@ void enable_sercom_clock(int id) { break; #endif } - #endif } From 20e7313453b34778df7cddbe3bc6bd72d3b737d7 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 15 Jun 2022 18:58:02 +0200 Subject: [PATCH 0514/1041] samd/clock_config: Add HW_DFLL_USB_SYNC and HW_MCU_OSC32KULP extensions. Two new compile flags are: MICROPY_HW_DFLL_USB_SYNC: Effective only if DFLL48 does not run from the crystal. It will synchronize the DFLL48M clock with the USB's SOF pulse. If no USB is connected, it will fall back to open loop mode. The DFLL48M clock is then pretty precise, but with a higher clock jitter at SAMD51 devices. MICROPY_HW_MCU_OSC32KULP: Effective only if the devics uses a crystal as clock source. Run the MCU clock from the ULP 32kHz oszillator instead of the crystal. This flag was added to cater for a interference problem of the crystal and Neopixel/Debug pins at Adafruit FEATHER Mx boards, which causes the board to crash. Drawback: ticks_ms() and time.time() vs. than ticks_us() and the peripherals like PWM run at not synchronous clocks. --- .../mpconfigboard.h | 3 +- .../mpconfigboard.h | 2 + .../mpconfigboard.h | 2 + ports/samd/clock_config.h | 1 + ports/samd/mcu/samd21/clock_config.c | 68 +++++++++++++--- ports/samd/mcu/samd51/clock_config.c | 78 +++++++++++++++++-- ports/samd/samd_soc.c | 1 + 7 files changed, 137 insertions(+), 18 deletions(-) diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h index 35945395fc..b78c003b19 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h @@ -1,4 +1,5 @@ #define MICROPY_HW_BOARD_NAME "Feather M4 Express" #define MICROPY_HW_MCU_NAME "SAMD51J19A" -#define MICROPY_HW_XOSC32K (1) +#define MICROPY_HW_XOSC32K (1) +#define MICROPY_HW_MCU_OSC32KULP (1) diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h index d647af9312..160c61ea2a 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h @@ -1,2 +1,4 @@ #define MICROPY_HW_BOARD_NAME "ItsyBitsy M0 Express" #define MICROPY_HW_MCU_NAME "SAMD21G18A" + +#define MICROPY_HW_DFLL_USB_SYNC (1) diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h index 2fffc9c7de..f53481d631 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h @@ -1,2 +1,4 @@ #define MICROPY_HW_BOARD_NAME "ItsyBitsy M4 Express" #define MICROPY_HW_MCU_NAME "SAMD51G19A" + +#define MICROPY_HW_DFLL_USB_SYNC (1) diff --git a/ports/samd/clock_config.h b/ports/samd/clock_config.h index 0e7a9e3280..6e48b286f4 100644 --- a/ports/samd/clock_config.h +++ b/ports/samd/clock_config.h @@ -30,4 +30,5 @@ void init_clocks(uint32_t cpu_freq); void set_cpu_freq(uint32_t cpu_freq); uint32_t get_cpu_freq(void); uint32_t get_apb_freq(void); +void check_usb_recovery_mode(void); void enable_sercom_clock(int id); diff --git a/ports/samd/mcu/samd21/clock_config.c b/ports/samd/mcu/samd21/clock_config.c index 3d189d67e1..e330d7ba6a 100644 --- a/ports/samd/mcu/samd21/clock_config.c +++ b/ports/samd/mcu/samd21/clock_config.c @@ -29,10 +29,12 @@ #include #include "py/runtime.h" +#include "py/mphal.h" #include "samd_soc.h" static uint32_t cpu_freq = CPU_FREQ; static uint32_t apb_freq = APB_FREQ; +static uint32_t dfll48m_calibration; int sercom_gclk_id[] = { GCLK_CLKCTRL_ID_SERCOM0_CORE, GCLK_CLKCTRL_ID_SERCOM1_CORE, @@ -52,14 +54,28 @@ void set_cpu_freq(uint32_t cpu_freq_arg) { cpu_freq = cpu_freq_arg; } +void check_usb_recovery_mode(void) { + #if !MICROPY_HW_XOSC32K + mp_hal_delay_ms(500); + // Check USB status. If not connected, switch DFLL48M back to open loop + if (USB->DEVICE.DeviceEndpoint[0].EPCFG.reg == 0) { + // Set/keep the open loop mode of the device. + SYSCTRL->DFLLVAL.reg = dfll48m_calibration; + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_ENABLE; + } + #endif // MICROPY_HW_XOSC32K +} void init_clocks(uint32_t cpu_freq) { + dfll48m_calibration = 0; // please the compiler + // SAMD21 Clock settings // GCLK0: 48MHz from DFLL open loop mode or closed loop mode from 32k Crystal - // GCLK1: 32768 Hz from 32K ULP or 32k Crystal + // GCLK1: 32768 Hz from 32K ULP or DFLL48M // GCLK2: 48MHz from DFLL for Peripherals // GCLK3: 1Mhz for the us-counter (TC4/TC5) + // GCLK4: 32kHz from crystal, if present // GCLK8: 1kHz clock for WDT NVMCTRL->CTRLB.bit.MANW = 1; // errata "Spurious Writes" @@ -74,19 +90,34 @@ void init_clocks(uint32_t cpu_freq) { } // Set up the DFLL48 according to the data sheet 17.6.7.1.2 // Step 1: Set up the reference clock - // Connect the OSC32K via GCLK1 to the DFLL input and for further use. + + #if MICROPY_HW_MCU_OSC32KULP + // Connect the GCLK1 to the XOSC32KULP + GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) | GCLK_GENDIV_DIV(1); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(1); + #else + // Connect the GCLK1 to OSC32K via GCLK1 to the DFLL input and for further use. GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) | GCLK_GENDIV_DIV(1); GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_ID(1); + #endif + while (GCLK->STATUS.bit.SYNCBUSY) { } - GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_DFLL48 | GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_CLKEN; + + // Connect the GCLK4 to OSC32K via GCLK1 to the DFLL input and for further use. + GCLK->GENDIV.reg = GCLK_GENDIV_ID(4) | GCLK_GENDIV_DIV(1); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_ID(4); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + + // Connect GCLK4 to the DFLL input and for further use. + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_DFLL48 | GCLK_CLKCTRL_GEN_GCLK4 | GCLK_CLKCTRL_CLKEN; // Enable access to the DFLLCTRL reg acc. to Errata 1.2.1 SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE; while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { } // Step 2: Set the coarse and fine values. - // The coarse setting will be taken from the calibration data. So the value used here - // does not matter. Get the coarse value from the calib data. In case it is not set, + // Get the coarse value from the calib data. In case it is not set, // set a midrange value. uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) >> FUSES_DFLL48M_COARSE_CAL_Pos; @@ -103,7 +134,7 @@ void init_clocks(uint32_t cpu_freq) { } // Step 4: Start the DFLL and wait for the PLL lock. We just wait for the fine lock, since // coarse adjusting is bypassed. - SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_WAITLOCK | + SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_WAITLOCK | SYSCTRL_DFLLCTRL_STABLE | SYSCTRL_DFLLCTRL_BPLCKC | SYSCTRL_DFLLCTRL_ENABLE; while (SYSCTRL->PCLKSR.bit.DFLLLCKF == 0) { } @@ -114,18 +145,33 @@ void init_clocks(uint32_t cpu_freq) { SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE; while (!SYSCTRL->PCLKSR.bit.DFLLRDY) { } - SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(1) | SYSCTRL_DFLLMUL_FSTEP(1) - | SYSCTRL_DFLLMUL_MUL(48000); + uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) >> FUSES_DFLL48M_COARSE_CAL_Pos; if (coarse == 0x3f) { coarse = 0x1f; } - SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(512); - SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_USBCRM + SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(511); + + #if MICROPY_HW_DFLL_USB_SYNC + // Configure the DFLL48M for USB clock recovery. + // Will have to switch back if no USB + SYSCTRL->DFLLSYNC.bit.READREQ = 1; + dfll48m_calibration = SYSCTRL->DFLLVAL.reg; + // Set the Multiplication factor. + SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(1) | SYSCTRL_DFLLMUL_FSTEP(1) + | SYSCTRL_DFLLMUL_MUL(48000); + // Set the mode to closed loop USB Recovery mode + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_USBCRM | SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_ENABLE; + #else + // Set/keep the open loop mode of the device. + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_ENABLE; + #endif + while (!SYSCTRL->PCLKSR.bit.DFLLRDY) { } + // Enable 32768 Hz on GCLK1 for consistency GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) | GCLK_GENDIV_DIV(48016384 / 32768); GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(1); @@ -154,10 +200,10 @@ void init_clocks(uint32_t cpu_freq) { GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(8); while (GCLK->STATUS.bit.SYNCBUSY) { } + } void enable_sercom_clock(int id) { - // Next: Set up the clocks // Enable synchronous clock. The bits are nicely arranged PM->APBCMASK.reg |= 0x04 << id; // Select multiplexer generic clock source and enable. diff --git a/ports/samd/mcu/samd51/clock_config.c b/ports/samd/mcu/samd51/clock_config.c index 3a3f40385f..62c05193dd 100644 --- a/ports/samd/mcu/samd51/clock_config.c +++ b/ports/samd/mcu/samd51/clock_config.c @@ -29,10 +29,12 @@ #include #include "py/runtime.h" +#include "py/mphal.h" #include "samd_soc.h" static uint32_t cpu_freq = CPU_FREQ; static uint32_t apb_freq = APB_FREQ; +static uint32_t dfll48m_calibration; int sercom_gclk_id[] = { SERCOM0_GCLK_ID_CORE, SERCOM1_GCLK_ID_CORE, @@ -84,12 +86,43 @@ void set_cpu_freq(uint32_t cpu_freq_arg) { } } +void check_usb_recovery_mode(void) { + #if !MICROPY_HW_XOSC32K + mp_hal_delay_ms(500); + // Check USB status. If not connected, switch DFLL48M back to open loop + if (USB->DEVICE.DeviceEndpoint[0].EPCFG.reg == 0) { + // as per Errata 2.8.3 + OSCCTRL->DFLLMUL.reg = 0; + while (OSCCTRL->DFLLSYNC.bit.DFLLMUL == 1) { + } + // Set the mode to open loop mode + OSCCTRL->DFLLCTRLB.reg = 0; + while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) { + } + OSCCTRL->DFLLCTRLA.reg = OSCCTRL_DFLLCTRLA_RUNSTDBY | OSCCTRL_DFLLCTRLA_ENABLE; + while (OSCCTRL->DFLLSYNC.bit.ENABLE == 1) { + } + OSCCTRL->DFLLVAL.reg = dfll48m_calibration; // Reload DFLLVAL register + while (OSCCTRL->DFLLSYNC.bit.DFLLVAL == 1) { + } + // Set the mode to open loop mode + OSCCTRL->DFLLCTRLB.reg = 0; + while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) { + } + } + #endif // MICROPY_HW_XOSC32K +} + void init_clocks(uint32_t cpu_freq) { + + dfll48m_calibration = 0; // please the compiler + // SAMD51 clock settings // GCLK0: 48MHz from DFLL48M or 48 - 200 MHz from DPLL0 (SAMD51) - // GCLK1: DPLLx_REF_FREQ 32768 Hz from 32KULP or 32k Crystal + // GCLK1: 32768 Hz from 32KULP or DFLL48M // GCLK2: 48MHz from DFLL48M for Peripheral devices // GCLK3: 16Mhz for the us-counter (TC0/TC1) + // GCLK4: 32kHz from crystal, if present // DPLL0: 48 - 200 MHz // Steps to set up clocks: @@ -102,6 +135,7 @@ void init_clocks(uint32_t cpu_freq) { // Setup GCLK0 to 120MHz // Setup GCLK2 to 48MHz for Peripherals // Setup GCLK3 to 8MHz for TC0/TC1 + // Setup GCLK4 to 32kHz crystal, if present // Setup GCLK0 for 48MHz as default state to keep the MCU running during config change. GCLK->GENCTRL[0].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; @@ -124,15 +158,26 @@ void init_clocks(uint32_t cpu_freq) { while (OSC32KCTRL->STATUS.bit.XOSC32KRDY == 0) { } + #if MICROPY_HW_MCU_OSC32KULP + // Setup GCLK1 for 32kHz ULP + GCLK->GENCTRL[1].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K; + #else // Setup GCLK1 for 32kHz crystal GCLK->GENCTRL[1].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K; + #endif + while (GCLK->SYNCBUSY.bit.GENCTRL1) { } + // Setup GCLK4 for 32kHz crystal + GCLK->GENCTRL[4].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K; + while (GCLK->SYNCBUSY.bit.GENCTRL4) { + } + // Set-up the DFLL48M in closed loop mode with input from the 32kHz crystal - // Step 1: Peripheral channel 0 is driven by GCLK1 and it feeds DFLL48M - GCLK->PCHCTRL[0].reg = GCLK_PCHCTRL_GEN_GCLK1 | GCLK_PCHCTRL_CHEN; + // Step 1: Peripheral channel 0 is driven by GCLK4 and it feeds DFLL48M + GCLK->PCHCTRL[0].reg = GCLK_PCHCTRL_GEN_GCLK4 | GCLK_PCHCTRL_CHEN; while (GCLK->PCHCTRL[0].bit.CHEN == 0) { } // Step 2: Set the multiplication values. The offset of 16384 to the freq is for rounding. @@ -141,7 +186,7 @@ void init_clocks(uint32_t cpu_freq) { while (OSCCTRL->DFLLSYNC.bit.DFLLMUL == 1) { } // Step 3: Set the mode to closed loop - OSCCTRL->DFLLCTRLB.reg = OSCCTRL_DFLLCTRLB_BPLCKC | OSCCTRL_DFLLCTRLB_MODE; + OSCCTRL->DFLLCTRLB.reg = OSCCTRL_DFLLCTRLB_BPLCKC | OSCCTRL_DFLLCTRLB_STABLE | OSCCTRL_DFLLCTRLB_MODE; while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) { } // Wait for lock fine @@ -154,12 +199,34 @@ void init_clocks(uint32_t cpu_freq) { #else // MICROPY_HW_XOSC32K - // Set GCLK1 to DPLL0_REF_FREQ as defined in mpconfigboard.h (e.g. 32768 Hz) + // Derive GCLK1 from DFLL48M at DPLL0_REF_FREQ as defined in mpconfigboard.h (e.g. 32768 Hz) GCLK->GENCTRL[1].reg = ((APB_FREQ + DPLLx_REF_FREQ / 2) / DPLLx_REF_FREQ) << GCLK_GENCTRL_DIV_Pos | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; while (GCLK->SYNCBUSY.bit.GENCTRL1) { } + OSCCTRL->DFLLCTRLA.bit.RUNSTDBY = 1; + OSCCTRL->DFLLCTRLA.bit.ONDEMAND = 0; + + OSCCTRL->DFLLCTRLA.bit.ENABLE = 1; + while (OSCCTRL->DFLLSYNC.bit.ENABLE == 1) { + } + + #if MICROPY_HW_DFLL_USB_SYNC + // Configure the DFLL48M for USB clock recovery. + // Will have to switch back if no USB + dfll48m_calibration = OSCCTRL->DFLLVAL.reg; + // Set the Multiplication factor. + OSCCTRL->DFLLMUL.reg = OSCCTRL_DFLLMUL_MUL(48000) | + OSCCTRL_DFLLMUL_FSTEP(1) | OSCCTRL_DFLLMUL_CSTEP(1); + while (OSCCTRL->DFLLSYNC.bit.DFLLMUL == 1) { + } + // Set the mode to closed loop USB Recovery + OSCCTRL->DFLLCTRLB.reg = OSCCTRL_DFLLCTRLB_USBCRM | OSCCTRL_DFLLCTRLB_CCDIS | OSCCTRL_DFLLCTRLB_MODE; + while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) { + } + #endif + #endif // MICROPY_HW_XOSC32K // Peripheral channel 1 is driven by GCLK1 and it feeds DPLL0 @@ -183,7 +250,6 @@ void init_clocks(uint32_t cpu_freq) { } void enable_sercom_clock(int id) { - // Next: Set up the clocks GCLK->PCHCTRL[sercom_gclk_id[id]].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK2; // no easy way to set the clocks, except enabling all of them switch (id) { diff --git a/ports/samd/samd_soc.c b/ports/samd/samd_soc.c index d0df4a7e28..f4a27f3df7 100644 --- a/ports/samd/samd_soc.c +++ b/ports/samd/samd_soc.c @@ -111,6 +111,7 @@ void samd_init(void) { SysTick_Config(get_cpu_freq() / 1000); init_us_counter(); usb_init(); + check_usb_recovery_mode(); #if defined(MCU_SAMD51) mp_hal_ticks_cpu_enable(); #endif From 85fb8b8b027d0af560a2b74e5bd4a0554600f6bd Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 16 Jun 2022 11:32:21 +0200 Subject: [PATCH 0515/1041] samd/pin_af: Simplify the pin-af-table handling. Changes are: - The pin-af-table-SAMDxx.csv file are moved to the mcu directories with the name as pin-af-table.csv. - The handling in Makefile and pin_af.c is simplified. --- ports/samd/Makefile | 3 +-- .../samd21/pin-af-table.csv} | 8 ++++---- .../samd51/pin-af-table.csv} | 0 ports/samd/pin_af.c | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) rename ports/samd/{boards/pin-af-table-SAMD21.csv => mcu/samd21/pin-af-table.csv} (95%) rename ports/samd/{boards/pin-af-table-SAMD51.csv => mcu/samd51/pin-af-table.csv} (100%) diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 8d49778b3b..9a03502abc 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -48,7 +48,7 @@ INC += -I$(TOP)/lib/asf4/$(MCU_SERIES_LOWER)/include/pio INC += -I$(TOP)/lib/tinyusb/src MAKE_PIN_AF = boards/make-pin-af.py -PIN_AF_TABLE_CSV = boards/pin-af-table-$(MCU_SERIES).csv +PIN_AF_TABLE_CSV = mcu/$(MCU_SERIES_LOWER)/pin-af-table.csv GEN_PIN_AF = pin_af_table.c MAKE_PINS = boards/make-pins.py @@ -62,7 +62,6 @@ CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib -mthumb $(CFLAGS_MCU_$(MCU_SERI CFLAGS += -DMCU_$(MCU_SERIES) -D__$(CMSIS_MCU)__ CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) CFLAGS += -DMPCONFIG_MCU_H='' -CFLAGS += -DPIN_AF_TABLE_C='<$(BUILD)/$(GEN_PIN_AF)>' LDFLAGS = -nostdlib $(addprefix -T,$(LD_FILES)) -Map=$@.map --cref LDFLAGS += $(LDFLAGS_MOD) diff --git a/ports/samd/boards/pin-af-table-SAMD21.csv b/ports/samd/mcu/samd21/pin-af-table.csv similarity index 95% rename from ports/samd/boards/pin-af-table-SAMD21.csv rename to ports/samd/mcu/samd21/pin-af-table.csv index d8ab903c9e..6445d148b8 100644 --- a/ports/samd/boards/pin-af-table-SAMD21.csv +++ b/ports/samd/mcu/samd21/pin-af-table.csv @@ -59,7 +59,7 @@ pa30,10,,,12,10, pa31,11,,,13,11, pb30,14,,,50,00,12 pb31,15,,,51,01,13 -pb00,0,,,52,70, -pb01,1,,,53,71, -pb02,2,,,50,60, -pb03,3,,,51,61, +pb00,0,8,,52,70, +pb01,1,9,,53,71, +pb02,2,10,,50,60, +pb03,3,11,,51,61, diff --git a/ports/samd/boards/pin-af-table-SAMD51.csv b/ports/samd/mcu/samd51/pin-af-table.csv similarity index 100% rename from ports/samd/boards/pin-af-table-SAMD51.csv rename to ports/samd/mcu/samd51/pin-af-table.csv diff --git a/ports/samd/pin_af.c b/ports/samd/pin_af.c index 8c152e0d8b..926c4ae0c2 100644 --- a/ports/samd/pin_af.c +++ b/ports/samd/pin_af.c @@ -38,7 +38,7 @@ extern const uint8_t tcc_channel_count[]; -#include PIN_AF_TABLE_C +#include "pin_af_table.c" // Just look for an table entry for a given pin and raise an error // in case of no match (which should not happen). From 560170de024353354b4bcd1682392f2bb282c12d Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 21 Jun 2022 18:00:51 +0200 Subject: [PATCH 0516/1041] samd/samd_flash: Remove obsolete printf's and return values instead. Returning values is much more useful. --- ports/samd/samd_flash.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/ports/samd/samd_flash.c b/ports/samd/samd_flash.c index 522522ef84..2fffd614f9 100644 --- a/ports/samd/samd_flash.c +++ b/ports/samd/samd_flash.c @@ -96,21 +96,17 @@ STATIC mp_obj_t eraseblock(uint32_t sector_in) { } STATIC mp_obj_t samd_flash_version(void) { - printf("Flash Driver Version: %lu\n", flash_get_version()); - return mp_const_none; + return MP_OBJ_NEW_SMALL_INT(flash_get_version()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(samd_flash_version_obj, samd_flash_version); -STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(samd_flash_version_static_obj, MP_ROM_PTR(&samd_flash_version_obj)); STATIC mp_obj_t samd_flash_size(void) { // ASF4 API calls mp_int_t PAGES = flash_get_total_pages(&flash_desc); mp_int_t PAGE_SIZE = flash_get_page_size(&flash_desc); - printf("Flash Size: %u Bytes\n", PAGES * PAGE_SIZE); - return mp_const_none; + return MP_OBJ_NEW_SMALL_INT(PAGES * PAGE_SIZE); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(samd_flash_size_obj, samd_flash_size); -STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(samd_flash_size_static_obj, MP_ROM_PTR(&samd_flash_size_obj)); STATIC mp_obj_t samd_flash_readblocks(size_t n_args, const mp_obj_t *args) { uint32_t offset = (mp_obj_get_int(args[1]) * BLOCK_SIZE) + samd_flash_obj.flash_base; @@ -172,8 +168,8 @@ STATIC mp_obj_t samd_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg STATIC MP_DEFINE_CONST_FUN_OBJ_3(samd_flash_ioctl_obj, samd_flash_ioctl); STATIC const mp_rom_map_elem_t samd_flash_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_flash_version), MP_ROM_PTR(&samd_flash_version_static_obj) }, - { MP_ROM_QSTR(MP_QSTR_flash_size), MP_ROM_PTR(&samd_flash_size_static_obj) }, + { MP_ROM_QSTR(MP_QSTR_flash_version), MP_ROM_PTR(&samd_flash_version_obj) }, + { MP_ROM_QSTR(MP_QSTR_flash_size), MP_ROM_PTR(&samd_flash_size_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_init), MP_ROM_PTR(&samd_flash_init_obj) }, { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&samd_flash_readblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&samd_flash_writeblocks_obj) }, From b0017304625b5d33bea548166b010bd2c3bf465d Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 24 Jun 2022 08:27:23 +0200 Subject: [PATCH 0517/1041] samd/Makefile: Fix a dependency problem with "make -j". The build directory was not created before attempting to create the generated files in it. --- ports/samd/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 9a03502abc..d8ca0f8ba6 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -194,12 +194,13 @@ $(BUILD)/firmware.uf2: $(BUILD)/firmware.bin pin_af.c: $(BUILD)/$(GEN_PIN_AF) -$(BUILD)/$(GEN_PIN_AF): $(PIN_AF_TABLE_CSV) +$(BUILD)/$(GEN_PIN_AF): $(PIN_AF_TABLE_CSV) | $(HEADER_BUILD) $(ECHO) "Create $@" $(Q)$(PYTHON) $(MAKE_PIN_AF) --csv $(PIN_AF_TABLE_CSV) --table $(BUILD)/$(GEN_PIN_AF) --mcu $(MCU_SERIES) +machine_led.c machine_pin.c modsamd.c: $(GEN_PINS_HDR) -$(GEN_PINS_SRC): $(BOARD_PINS) +$(GEN_PINS_SRC) $(GEN_PINS_HDR): $(BOARD_PINS) | $(HEADER_BUILD) $(ECHO) "Create $@" $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --pins $(GEN_PINS_SRC) --inc $(GEN_PINS_HDR) From e9a76310ec567dd94712a92876ca150bac43f103 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 28 Jun 2022 16:59:01 +0200 Subject: [PATCH 0518/1041] samd/mphalport: Fix USB endpoint handling ignoring Ctrl-C. Porting PR #8040 by @hoihu to SAMD, following the commit 587339022689187a1acbccc1d0e2425a67385ff7. One small addition: before executing keyboard interrupt, the input buffer is cleared. --- ports/samd/Makefile | 1 + ports/samd/mphalport.c | 79 ++++++++++++++++++++++++++++++------------ ports/samd/mphalport.h | 1 + 3 files changed, 59 insertions(+), 22 deletions(-) diff --git a/ports/samd/Makefile b/ports/samd/Makefile index d8ca0f8ba6..5ff00f21f9 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -131,6 +131,7 @@ SRC_C += \ shared/libc/string0.c \ shared/readline/readline.c \ shared/runtime/gchelper_native.c \ + shared/runtime/interrupt_char.c \ shared/runtime/pyexec.c \ shared/runtime/softtimer.c \ shared/runtime/stdout_helpers.c \ diff --git a/ports/samd/mphalport.c b/ports/samd/mphalport.c index fc45102390..ad3817768f 100644 --- a/ports/samd/mphalport.c +++ b/ports/samd/mphalport.c @@ -33,23 +33,55 @@ #include "samd_soc.h" #include "tusb.h" -#if MICROPY_KBD_EXCEPTION -int mp_interrupt_char = -1; - -void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { - (void)itf; - (void)wanted_char; - tud_cdc_read_char(); // discard interrupt char - mp_sched_keyboard_interrupt(); -} - -void mp_hal_set_interrupt_char(int c) { - mp_interrupt_char = c; - tud_cdc_set_wanted_char(c); -} - +#ifndef MICROPY_HW_STDIN_BUFFER_LEN +#define MICROPY_HW_STDIN_BUFFER_LEN 128 #endif +STATIC uint8_t stdin_ringbuf_array[MICROPY_HW_STDIN_BUFFER_LEN]; +ringbuf_t stdin_ringbuf = { stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0 }; + +uint8_t cdc_itf_pending; // keep track of cdc interfaces which need attention to poll + +void poll_cdc_interfaces(void) { + // any CDC interfaces left to poll? + if (cdc_itf_pending && ringbuf_free(&stdin_ringbuf)) { + for (uint8_t itf = 0; itf < 8; ++itf) { + if (cdc_itf_pending & (1 << itf)) { + tud_cdc_rx_cb(itf); + if (!cdc_itf_pending) { + break; + } + } + } + } +} + +void tud_cdc_rx_cb(uint8_t itf) { + // consume pending USB data immediately to free usb buffer and keep the endpoint from stalling. + // in case the ringbuffer is full, mark the CDC interface that need attention later on for polling + cdc_itf_pending &= ~(1 << itf); + for (uint32_t bytes_avail = tud_cdc_n_available(itf); bytes_avail > 0; --bytes_avail) { + if (ringbuf_free(&stdin_ringbuf)) { + int data_char = tud_cdc_read_char(); + #if MICROPY_KBD_EXCEPTION + if (data_char == mp_interrupt_char) { + // Clear the ring buffer + stdin_ringbuf.iget = stdin_ringbuf.iput = 0; + // and stop + mp_sched_keyboard_interrupt(); + } else { + ringbuf_put(&stdin_ringbuf, data_char); + } + #else + ringbuf_put(&stdin_ringbuf, data_char); + #endif + } else { + cdc_itf_pending |= (1 << itf); + return; + } + } +} + void mp_hal_set_pin_mux(mp_hal_pin_obj_t pin, uint8_t mux) { int pin_grp = pin / 32; int port_grp = (pin % 32) / 2; @@ -94,9 +126,12 @@ void mp_hal_delay_us(mp_uint_t us) { uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { uintptr_t ret = 0; - if (tud_cdc_connected() && tud_cdc_available()) { + + poll_cdc_interfaces(); + if ((poll_flags & MP_STREAM_POLL_RD) && ringbuf_peek(&stdin_ringbuf) != -1) { ret |= MP_STREAM_POLL_RD; } + #if MICROPY_PY_OS_DUPTERM ret |= mp_uos_dupterm_poll(poll_flags); #endif @@ -105,13 +140,13 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { int mp_hal_stdin_rx_chr(void) { for (;;) { - if (tud_cdc_connected() && tud_cdc_available()) { - uint8_t buf[1]; - uint32_t count = tud_cdc_read(buf, sizeof(buf)); - if (count) { - return buf[0]; - } + + poll_cdc_interfaces(); + int c = ringbuf_get(&stdin_ringbuf); + if (c != -1) { + return c; } + #if MICROPY_PY_OS_DUPTERM int dupterm_c = mp_uos_dupterm_rx_chr(); if (dupterm_c >= 0) { diff --git a/ports/samd/mphalport.h b/ports/samd/mphalport.h index f1efd55003..ced0d642b4 100644 --- a/ports/samd/mphalport.h +++ b/ports/samd/mphalport.h @@ -27,6 +27,7 @@ #ifndef MICROPY_INCLUDED_SAMD_MPHALPORT_H #define MICROPY_INCLUDED_SAMD_MPHALPORT_H +#include "py/ringbuf.h" #include "py/mpconfig.h" // ASF4 From d9338aabc5647979f4a0ec3cb0a7e987a2a2249f Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 30 Jun 2022 16:50:15 +0200 Subject: [PATCH 0519/1041] samd: Change the symbol names for the peripheral clocks. From APB_FREQ to DFLL48M_FREQ, and from apb_freq to peripheral_freq. --- ports/samd/clock_config.h | 2 +- ports/samd/machine_i2c.c | 2 +- ports/samd/machine_pwm.c | 3 ++- ports/samd/machine_spi.c | 4 ++-- ports/samd/machine_uart.c | 4 ++-- ports/samd/mcu/samd21/clock_config.c | 6 +++--- ports/samd/mcu/samd21/mpconfigmcu.h | 2 +- ports/samd/mcu/samd51/clock_config.c | 12 ++++++------ ports/samd/mcu/samd51/mpconfigmcu.h | 2 +- 9 files changed, 19 insertions(+), 18 deletions(-) diff --git a/ports/samd/clock_config.h b/ports/samd/clock_config.h index 6e48b286f4..35b7e53281 100644 --- a/ports/samd/clock_config.h +++ b/ports/samd/clock_config.h @@ -29,6 +29,6 @@ void init_clocks(uint32_t cpu_freq); void set_cpu_freq(uint32_t cpu_freq); uint32_t get_cpu_freq(void); -uint32_t get_apb_freq(void); +uint32_t get_peripheral_freq(void); void check_usb_recovery_mode(void); void enable_sercom_clock(int id); diff --git a/ports/samd/machine_i2c.c b/ports/samd/machine_i2c.c index 90ea5e10ca..25dfa99340 100644 --- a/ports/samd/machine_i2c.c +++ b/ports/samd/machine_i2c.c @@ -185,7 +185,7 @@ mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n // baud = peripheral_freq / (2 * baudrate) - 5 - (rise_time * peripheral_freq) / 2 // Just set the minimal configuration for standard and fast mode. // Set Baud. Assume ~300ns rise time. Maybe set later by a keyword argument. - i2c->I2CM.BAUD.reg = get_apb_freq() / (2 * self->freq) - 5 - (get_apb_freq() / 1000000) * RISETIME_NS / 2000; + i2c->I2CM.BAUD.reg = get_peripheral_freq() / (2 * self->freq) - 5 - (get_peripheral_freq() / 1000000) * RISETIME_NS / 2000; // Enable interrupts sercom_register_irq(self->id, &common_i2c_irq_handler); diff --git a/ports/samd/machine_pwm.c b/ports/samd/machine_pwm.c index 6f9ca42b1b..d987927d31 100644 --- a/ports/samd/machine_pwm.c +++ b/ports/samd/machine_pwm.c @@ -28,6 +28,7 @@ #include "py/runtime.h" #include "py/mphal.h" #include "modmachine.h" +#include "clock_config.h" #include "sam.h" #include "pin_af.h" @@ -50,7 +51,7 @@ typedef struct _machine_pwm_obj_t { #define PWM_NOT_INIT (0) #define PWM_CLK_READY (1) #define PWM_TCC_ENABLED (2) -#define PWM_MASTER_CLK (48000000) +#define PWM_MASTER_CLK (get_peripheral_freq()) #define PWM_FULL_SCALE (65536) static Tcc *tcc_instance[] = TCC_INSTS; diff --git a/ports/samd/machine_spi.c b/ports/samd/machine_spi.c index ddb8756e9a..8321f19cf0 100644 --- a/ports/samd/machine_spi.c +++ b/ports/samd/machine_spi.c @@ -206,9 +206,9 @@ STATIC void machine_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj spi->SPI.CTRLC.reg = 1; // 1 clock cycle character spacing #endif - // SPI is driven by the clock of GCLK Generator 2, freq in bus_freq + // SPI is driven by the clock of GCLK Generator 2, freq by get_peripheral_freq() // baud = bus_freq / (2 * baudrate) - 1 - uint32_t baud = get_apb_freq() / (2 * self->baudrate) - 1; + uint32_t baud = get_peripheral_freq() / (2 * self->baudrate) - 1; spi->SPI.BAUD.reg = baud; // Set Baud // Enable RXC interrupt only if miso is defined diff --git a/ports/samd/machine_uart.c b/ports/samd/machine_uart.c index 92e63ee51e..1031f26c26 100644 --- a/ports/samd/machine_uart.c +++ b/ports/samd/machine_uart.c @@ -276,9 +276,9 @@ STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args while (uart->USART.SYNCBUSY.bit.CTRLB) { } - // USART is driven by the clock of GCLK Generator 2, freq by get_apb_freq() + // USART is driven by the clock of GCLK Generator 2, freq by get_peripheral_freq() // baud rate; 65536 * (1 - 16 * 115200/bus_freq) - uint32_t baud = 65536 - ((uint64_t)(65536 * 16) * self->baudrate + get_apb_freq() / 2) / get_apb_freq(); + uint32_t baud = 65536 - ((uint64_t)(65536 * 16) * self->baudrate + get_peripheral_freq() / 2) / get_peripheral_freq(); uart->USART.BAUD.bit.BAUD = baud; // Set Baud sercom_register_irq(self->id, &common_uart_irq_handler); diff --git a/ports/samd/mcu/samd21/clock_config.c b/ports/samd/mcu/samd21/clock_config.c index e330d7ba6a..2402ed2e31 100644 --- a/ports/samd/mcu/samd21/clock_config.c +++ b/ports/samd/mcu/samd21/clock_config.c @@ -33,7 +33,7 @@ #include "samd_soc.h" static uint32_t cpu_freq = CPU_FREQ; -static uint32_t apb_freq = APB_FREQ; +static uint32_t peripheral_freq = DFLL48M_FREQ; static uint32_t dfll48m_calibration; int sercom_gclk_id[] = { @@ -46,8 +46,8 @@ uint32_t get_cpu_freq(void) { return cpu_freq; } -uint32_t get_apb_freq(void) { - return apb_freq; +uint32_t get_peripheral_freq(void) { + return peripheral_freq; } void set_cpu_freq(uint32_t cpu_freq_arg) { diff --git a/ports/samd/mcu/samd21/mpconfigmcu.h b/ports/samd/mcu/samd21/mpconfigmcu.h index dd16a6c8af..ecb125bbdb 100644 --- a/ports/samd/mcu/samd21/mpconfigmcu.h +++ b/ports/samd/mcu/samd21/mpconfigmcu.h @@ -16,7 +16,7 @@ #define MICROPY_HW_UART_TXBUF (1) #define CPU_FREQ (48000000) -#define APB_FREQ (48000000) +#define DFLL48M_FREQ (48000000) #define IRQ_PRI_PENDSV ((1 << __NVIC_PRIO_BITS) - 1) diff --git a/ports/samd/mcu/samd51/clock_config.c b/ports/samd/mcu/samd51/clock_config.c index 62c05193dd..31c8f5a865 100644 --- a/ports/samd/mcu/samd51/clock_config.c +++ b/ports/samd/mcu/samd51/clock_config.c @@ -33,7 +33,7 @@ #include "samd_soc.h" static uint32_t cpu_freq = CPU_FREQ; -static uint32_t apb_freq = APB_FREQ; +static uint32_t peripheral_freq = DFLL48M_FREQ; static uint32_t dfll48m_calibration; int sercom_gclk_id[] = { @@ -49,8 +49,8 @@ uint32_t get_cpu_freq(void) { return cpu_freq; } -uint32_t get_apb_freq(void) { - return apb_freq; +uint32_t get_peripheral_freq(void) { + return peripheral_freq; } void set_cpu_freq(uint32_t cpu_freq_arg) { @@ -181,7 +181,7 @@ void init_clocks(uint32_t cpu_freq) { while (GCLK->PCHCTRL[0].bit.CHEN == 0) { } // Step 2: Set the multiplication values. The offset of 16384 to the freq is for rounding. - OSCCTRL->DFLLMUL.reg = OSCCTRL_DFLLMUL_MUL((APB_FREQ + DPLLx_REF_FREQ / 2) / DPLLx_REF_FREQ) | + OSCCTRL->DFLLMUL.reg = OSCCTRL_DFLLMUL_MUL((DFLL48M_FREQ + DPLLx_REF_FREQ / 2) / DPLLx_REF_FREQ) | OSCCTRL_DFLLMUL_FSTEP(1) | OSCCTRL_DFLLMUL_CSTEP(1); while (OSCCTRL->DFLLSYNC.bit.DFLLMUL == 1) { } @@ -200,7 +200,7 @@ void init_clocks(uint32_t cpu_freq) { #else // MICROPY_HW_XOSC32K // Derive GCLK1 from DFLL48M at DPLL0_REF_FREQ as defined in mpconfigboard.h (e.g. 32768 Hz) - GCLK->GENCTRL[1].reg = ((APB_FREQ + DPLLx_REF_FREQ / 2) / DPLLx_REF_FREQ) << GCLK_GENCTRL_DIV_Pos + GCLK->GENCTRL[1].reg = ((DFLL48M_FREQ + DPLLx_REF_FREQ / 2) / DPLLx_REF_FREQ) << GCLK_GENCTRL_DIV_Pos | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; while (GCLK->SYNCBUSY.bit.GENCTRL1) { } @@ -236,7 +236,7 @@ void init_clocks(uint32_t cpu_freq) { set_cpu_freq(cpu_freq); - apb_freq = APB_FREQ; // To be changed if CPU_FREQ < 48M + peripheral_freq = DFLL48M_FREQ; // To be changed if CPU_FREQ < 48M // Setup GCLK2 for DPLL1 output (48 MHz) GCLK->GENCTRL[2].reg = GCLK_GENCTRL_DIV(1) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; diff --git a/ports/samd/mcu/samd51/mpconfigmcu.h b/ports/samd/mcu/samd51/mpconfigmcu.h index c3253fcbec..2c1ea7fee2 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.h +++ b/ports/samd/mcu/samd51/mpconfigmcu.h @@ -29,7 +29,7 @@ unsigned long trng_random_u32(void); #define MICROPY_HW_UART_TXBUF (1) #define CPU_FREQ (120000000) -#define APB_FREQ (48000000) +#define DFLL48M_FREQ (48000000) #define DPLLx_REF_FREQ (32768) #define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003) From 00dcf0464318764066f81f90992d5bfc40acebf1 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 21 Jun 2022 17:32:48 +0200 Subject: [PATCH 0520/1041] samd/mcu: Add floating point suport for SAMD21 devices. For consistency it should be there. --- ports/samd/mcu/samd21/mpconfigmcu.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ports/samd/mcu/samd21/mpconfigmcu.h b/ports/samd/mcu/samd21/mpconfigmcu.h index ecb125bbdb..9329a6eb89 100644 --- a/ports/samd/mcu/samd21/mpconfigmcu.h +++ b/ports/samd/mcu/samd21/mpconfigmcu.h @@ -7,7 +7,10 @@ #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) +#define MICROPY_PY_BUILTINS_COMPLEX (0) +#define MICROPY_PY_MATH (0) +#define MICROPY_PY_CMATH (0) #define MICROPY_HW_FLASH_STORAGE_BASE (0x30000) #define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF) From 387025f5d12ec6313b396e63e770dd9f22f9daeb Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 21 Jun 2022 20:31:20 +0200 Subject: [PATCH 0521/1041] samd/mcu: Enable the math module on SAMD51. --- ports/samd/mcu/samd51/mpconfigmcu.h | 3 ++- ports/samd/mcu/samd51/mpconfigmcu.mk | 29 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/ports/samd/mcu/samd51/mpconfigmcu.h b/ports/samd/mcu/samd51/mpconfigmcu.h index 2c1ea7fee2..0e5a885655 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.h +++ b/ports/samd/mcu/samd51/mpconfigmcu.h @@ -9,7 +9,8 @@ #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #define MICROPY_PY_BUILTINS_COMPLEX (0) -#define MICROPY_PY_MATH (0) +#define MICROPY_PY_MATH (1) +#define MP_NEED_LOG2 (1) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_UOS_URANDOM (1) diff --git a/ports/samd/mcu/samd51/mpconfigmcu.mk b/ports/samd/mcu/samd51/mpconfigmcu.mk index 461a0182ef..0aedbbe28a 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.mk +++ b/ports/samd/mcu/samd51/mpconfigmcu.mk @@ -1 +1,30 @@ SRC_S += shared/runtime/gchelper_m3.s + +SRC_MOD += $(addprefix lib/libm/,\ + acoshf.c \ + asinfacosf.c \ + asinhf.c \ + atan2f.c \ + atanf.c \ + atanhf.c \ + ef_rem_pio2.c \ + erf_lgamma.c \ + fmodf.c \ + kf_cos.c \ + kf_rem_pio2.c \ + kf_sin.c \ + kf_tan.c \ + log1pf.c \ + math.c \ + nearbyintf.c \ + roundf.c \ + sf_cos.c \ + sf_erf.c \ + sf_frexp.c \ + sf_ldexp.c \ + sf_modf.c \ + sf_sin.c \ + sf_tan.c \ + wf_lgamma.c \ + wf_tgamma.c \ + ) From 9f4df86016d8181dc06683d528dbd85473a1dbb9 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 2 Jul 2022 16:26:17 +0200 Subject: [PATCH 0522/1041] samd/boards: Move the flash filesystem definitions to the linker files. They used to be in mpconfigmcu.h, but have to be different for different chip variants, like the SAMD51x20. --- ports/samd/boards/samd21x18a.ld | 3 +++ ports/samd/boards/samd51g19a.ld | 3 +++ ports/samd/boards/samd51j19a.ld | 3 +++ ports/samd/boards/samd51p19a.ld | 3 +++ ports/samd/mcu/samd21/mpconfigmcu.h | 2 -- ports/samd/mcu/samd51/mpconfigmcu.h | 7 +------ ports/samd/samd_flash.c | 6 ++++-- 7 files changed, 17 insertions(+), 10 deletions(-) diff --git a/ports/samd/boards/samd21x18a.ld b/ports/samd/boards/samd21x18a.ld index b7d59c315b..81a84a15d7 100644 --- a/ports/samd/boards/samd21x18a.ld +++ b/ports/samd/boards/samd21x18a.ld @@ -13,5 +13,8 @@ MEMORY _estack = ORIGIN(RAM) + LENGTH(RAM) - 8; _sstack = _estack - 8K; +_oflash_fs = ORIGIN(FLASH) + 192K - 8K; +_sflash_fs = LENGTH(FLASH) - 192K + 8K - 1; + _sheap = _ebss; _eheap = _sstack; diff --git a/ports/samd/boards/samd51g19a.ld b/ports/samd/boards/samd51g19a.ld index e0baa9bba0..cd03320ba4 100644 --- a/ports/samd/boards/samd51g19a.ld +++ b/ports/samd/boards/samd51g19a.ld @@ -13,5 +13,8 @@ MEMORY _estack = ORIGIN(RAM) + LENGTH(RAM) - 8; _sstack = _estack - 16K; +_oflash_fs = ORIGIN(FLASH) + 384K - 16K; +_sflash_fs = LENGTH(FLASH) - 384K + 16K - 1; + _sheap = _ebss; _eheap = _sstack; diff --git a/ports/samd/boards/samd51j19a.ld b/ports/samd/boards/samd51j19a.ld index e0baa9bba0..cd03320ba4 100644 --- a/ports/samd/boards/samd51j19a.ld +++ b/ports/samd/boards/samd51j19a.ld @@ -13,5 +13,8 @@ MEMORY _estack = ORIGIN(RAM) + LENGTH(RAM) - 8; _sstack = _estack - 16K; +_oflash_fs = ORIGIN(FLASH) + 384K - 16K; +_sflash_fs = LENGTH(FLASH) - 384K + 16K - 1; + _sheap = _ebss; _eheap = _sstack; diff --git a/ports/samd/boards/samd51p19a.ld b/ports/samd/boards/samd51p19a.ld index e0baa9bba0..cd03320ba4 100644 --- a/ports/samd/boards/samd51p19a.ld +++ b/ports/samd/boards/samd51p19a.ld @@ -13,5 +13,8 @@ MEMORY _estack = ORIGIN(RAM) + LENGTH(RAM) - 8; _sstack = _estack - 16K; +_oflash_fs = ORIGIN(FLASH) + 384K - 16K; +_sflash_fs = LENGTH(FLASH) - 384K + 16K - 1; + _sheap = _ebss; _eheap = _sstack; diff --git a/ports/samd/mcu/samd21/mpconfigmcu.h b/ports/samd/mcu/samd21/mpconfigmcu.h index 9329a6eb89..7ee23b59b1 100644 --- a/ports/samd/mcu/samd21/mpconfigmcu.h +++ b/ports/samd/mcu/samd21/mpconfigmcu.h @@ -12,8 +12,6 @@ #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) -#define MICROPY_HW_FLASH_STORAGE_BASE (0x30000) -#define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF) #define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; #define MICROPY_HW_UART_TXBUF (1) diff --git a/ports/samd/mcu/samd51/mpconfigmcu.h b/ports/samd/mcu/samd51/mpconfigmcu.h index 0e5a885655..19193992f0 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.h +++ b/ports/samd/mcu/samd51/mpconfigmcu.h @@ -19,12 +19,7 @@ unsigned long trng_random_u32(void); // Due to a limitation in the TC counter for us, the ticks period is 2**29 #define MICROPY_PY_UTIME_TICKS_PERIOD (0x20000000) -// MicroPython configs -// samd_flash.c flash parameters -// Build a 128k Flash storage at top. 512k-128k=384k=0x60000 -// 512*1024= 0x80000 minus 128*1024= 0x20000 = 0x60000 -#define MICROPY_HW_FLASH_STORAGE_BASE (0x60000) -#define MICROPY_HW_FLASH_STORAGE_BYTES (0x1FFFF) + #define VFS_BLOCK_SIZE_BYTES (1536) // #define MICROPY_HW_UART_TXBUF (1) diff --git a/ports/samd/samd_flash.c b/ports/samd/samd_flash.c index 2fffd614f9..6d9ee96895 100644 --- a/ports/samd/samd_flash.c +++ b/ports/samd/samd_flash.c @@ -53,11 +53,13 @@ typedef struct _samd_flash_obj_t { uint32_t flash_size; } samd_flash_obj_t; +extern uint8_t _oflash_fs, _sflash_fs; + // Build a Flash storage at top. STATIC samd_flash_obj_t samd_flash_obj = { .base = { &samd_flash_type }, - .flash_base = MICROPY_HW_FLASH_STORAGE_BASE, // Board specific: mpconfigboard.h - .flash_size = MICROPY_HW_FLASH_STORAGE_BYTES, // Board specific: mpconfigboard.h + .flash_base = (uint32_t)&_oflash_fs, // Get from MCU-Specific loader script. + .flash_size = (uint32_t)&_sflash_fs, // Get from MCU-Specific loader script. }; // FLASH stuff From 65f99e371d3459cdaca4ae01895e706ff93ab285 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 2 Jul 2022 16:36:11 +0200 Subject: [PATCH 0523/1041] samd/boards: Use the same linker file for all SAMD51x19 variants. --- .../mpconfigboard.mk | 2 +- .../mpconfigboard.mk | 2 +- ports/samd/boards/MINISAM_M4/mpconfigboard.mk | 2 +- .../SEEED_WIO_TERMINAL/mpconfigboard.mk | 2 +- ports/samd/boards/samd51j19a.ld | 20 ------------------- ports/samd/boards/samd51p19a.ld | 20 ------------------- .../boards/{samd51g19a.ld => samd51x19a.ld} | 0 7 files changed, 4 insertions(+), 44 deletions(-) delete mode 100644 ports/samd/boards/samd51j19a.ld delete mode 100644 ports/samd/boards/samd51p19a.ld rename ports/samd/boards/{samd51g19a.ld => samd51x19a.ld} (100%) diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk index d29e2b1097..781faa2410 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk @@ -1,6 +1,6 @@ MCU_SERIES = SAMD51 CMSIS_MCU = SAMD51J19A -LD_FILES = boards/samd51j19a.ld sections.ld +LD_FILES = boards/samd51x19a.ld sections.ld TEXT0 = 0x4000 # The ?='s allow overriding in mpconfigboard.mk. diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk index 6b0192c77b..da3e47589a 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk @@ -1,6 +1,6 @@ MCU_SERIES = SAMD51 CMSIS_MCU = SAMD51G19A -LD_FILES = boards/samd51g19a.ld sections.ld +LD_FILES = boards/samd51x19a.ld sections.ld TEXT0 = 0x4000 # The ?='s allow overriding in mpconfigboard.mk. diff --git a/ports/samd/boards/MINISAM_M4/mpconfigboard.mk b/ports/samd/boards/MINISAM_M4/mpconfigboard.mk index 6ed0ff552b..73afb02104 100644 --- a/ports/samd/boards/MINISAM_M4/mpconfigboard.mk +++ b/ports/samd/boards/MINISAM_M4/mpconfigboard.mk @@ -1,7 +1,7 @@ # https://www.minifigboards.com/mini-sam-m4/mini-sam-m4-hardware/ MCU_SERIES = SAMD51 CMSIS_MCU = SAMD51G19A -LD_FILES = boards/samd51g19a.ld sections.ld +LD_FILES = boards/samd51x19a.ld sections.ld TEXT0 = 0x4000 # The ?='s allow overriding in mpconfigboard.mk. diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.mk b/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.mk index 90fb7f2dd0..c2c4da6152 100644 --- a/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.mk +++ b/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.mk @@ -1,6 +1,6 @@ MCU_SERIES = SAMD51 CMSIS_MCU = SAMD51P19A -LD_FILES = boards/samd51p19a.ld sections.ld +LD_FILES = boards/samd51x19a.ld sections.ld TEXT0 = 0x4000 # The ?='s allow overriding in mpconfigboard.mk. diff --git a/ports/samd/boards/samd51j19a.ld b/ports/samd/boards/samd51j19a.ld deleted file mode 100644 index cd03320ba4..0000000000 --- a/ports/samd/boards/samd51j19a.ld +++ /dev/null @@ -1,20 +0,0 @@ -/* - GNU linker script for SAMD51 -*/ - -/* Specify the memory areas */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x00004000, LENGTH = 512K - 16K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K -} - -/* Top end of the stack, with room for double-tap variable */ -_estack = ORIGIN(RAM) + LENGTH(RAM) - 8; -_sstack = _estack - 16K; - -_oflash_fs = ORIGIN(FLASH) + 384K - 16K; -_sflash_fs = LENGTH(FLASH) - 384K + 16K - 1; - -_sheap = _ebss; -_eheap = _sstack; diff --git a/ports/samd/boards/samd51p19a.ld b/ports/samd/boards/samd51p19a.ld deleted file mode 100644 index cd03320ba4..0000000000 --- a/ports/samd/boards/samd51p19a.ld +++ /dev/null @@ -1,20 +0,0 @@ -/* - GNU linker script for SAMD51 -*/ - -/* Specify the memory areas */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x00004000, LENGTH = 512K - 16K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K -} - -/* Top end of the stack, with room for double-tap variable */ -_estack = ORIGIN(RAM) + LENGTH(RAM) - 8; -_sstack = _estack - 16K; - -_oflash_fs = ORIGIN(FLASH) + 384K - 16K; -_sflash_fs = LENGTH(FLASH) - 384K + 16K - 1; - -_sheap = _ebss; -_eheap = _sstack; diff --git a/ports/samd/boards/samd51g19a.ld b/ports/samd/boards/samd51x19a.ld similarity index 100% rename from ports/samd/boards/samd51g19a.ld rename to ports/samd/boards/samd51x19a.ld From 4cf527eb05d9b9a93a92ec427e719bf81a8de305 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 15 Jul 2022 22:44:23 +0200 Subject: [PATCH 0524/1041] samd/main: Initialize readline on start up. Somehow that was forgotten. --- ports/samd/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/samd/main.c b/ports/samd/main.c index 889af4a1e4..0f24e2382e 100644 --- a/ports/samd/main.c +++ b/ports/samd/main.c @@ -29,6 +29,7 @@ #include "py/gc.h" #include "py/mperrno.h" #include "py/stackctrl.h" +#include "shared/readline/readline.h" #include "shared/runtime/gchelper.h" #include "shared/runtime/pyexec.h" #include "shared/runtime/softtimer.h" @@ -48,6 +49,9 @@ void samd_main(void) { gc_init(&_sheap, &_eheap); mp_init(); + // Initialise sub-systems. + readline_init0(); + // Execute _boot.py to set up the filesystem. pyexec_frozen_module("_boot.py"); From 972212907ddc7f611f41d7e267ceca396f1bb4ba Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 10 Jul 2022 11:55:56 +0200 Subject: [PATCH 0525/1041] samd/mcu: Use lf2s for SAMD51 and lfs1 for SAMD21. Using lfs1 gives a smaller code, but lfs2 has more features. --- ports/samd/mcu/samd21/mpconfigmcu.h | 1 + ports/samd/mcu/samd51/mpconfigmcu.mk | 2 ++ ports/samd/modules/_boot.py | 8 +++++--- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ports/samd/mcu/samd21/mpconfigmcu.h b/ports/samd/mcu/samd21/mpconfigmcu.h index 7ee23b59b1..a84b31276b 100644 --- a/ports/samd/mcu/samd21/mpconfigmcu.h +++ b/ports/samd/mcu/samd21/mpconfigmcu.h @@ -6,6 +6,7 @@ // MicroPython emitters #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) +#define MICROPY_MODULE_BUILTIN_INIT (1) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #define MICROPY_PY_BUILTINS_COMPLEX (0) diff --git a/ports/samd/mcu/samd51/mpconfigmcu.mk b/ports/samd/mcu/samd51/mpconfigmcu.mk index 0aedbbe28a..e83e8911dd 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.mk +++ b/ports/samd/mcu/samd51/mpconfigmcu.mk @@ -1,3 +1,5 @@ +MICROPY_VFS_LFS2 ?= 1 + SRC_S += shared/runtime/gchelper_m3.s SRC_MOD += $(addprefix lib/libm/,\ diff --git a/ports/samd/modules/_boot.py b/ports/samd/modules/_boot.py index 84b02480b7..e183125f2e 100644 --- a/ports/samd/modules/_boot.py +++ b/ports/samd/modules/_boot.py @@ -6,11 +6,13 @@ samd.Flash.flash_init() bdev = samd.Flash() # Try to mount the filesystem, and format the flash if it doesn't exist. +fs_type = uos.VfsLfs2 if hasattr(uos, "VfsLfs2") else uos.VfsLfs1 + try: - vfs = uos.VfsLfs1(bdev) + vfs = fs_type(bdev) except: - uos.VfsLfs1.mkfs(bdev) - vfs = uos.VfsLfs1(bdev) + fs_type.mkfs(bdev) + vfs = fs_type(bdev) uos.mount(vfs, "/") gc.collect() From 366c801b3553191241e329c2f6d7f718f49af105 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 4 Oct 2022 09:17:29 +0200 Subject: [PATCH 0526/1041] samd/machine_pin: Change the printing of Pin and LED objects. It now prints lines like: Pin("D9", mode=IN, pull=PULL_UP, GPIO=PA07) or LED("LED") showing for consistency the names as given in pins.csv. For pins, the GPIO numer is printed as well for a reference. --- ports/samd/boards/make-pins.py | 2 +- ports/samd/machine_led.c | 2 +- ports/samd/machine_pin.c | 14 +++++++++++++- ports/samd/mphalport.h | 12 +++++++++++- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/ports/samd/boards/make-pins.py b/ports/samd/boards/make-pins.py index 2b62ba7c59..679e2c9d19 100644 --- a/ports/samd/boards/make-pins.py +++ b/ports/samd/boards/make-pins.py @@ -68,7 +68,7 @@ class Pins: if self.board_leds: pins_file.write("\nconst machine_led_obj_t machine_led_obj[] = {\n") for pin in self.board_leds: - pins_file.write(" {{&machine_pin_type}, ") + pins_file.write(" {{&machine_led_type}, ") pins_file.write(pin[0] + ', "' + pin[1]) pins_file.write('"},\n') pins_file.write("};\n") diff --git a/ports/samd/machine_led.c b/ports/samd/machine_led.c index 48ab869199..54c2cb18bc 100644 --- a/ports/samd/machine_led.c +++ b/ports/samd/machine_led.c @@ -39,7 +39,7 @@ extern mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c STATIC void machine_led_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_led_obj_t *self = self_in; - mp_printf(print, "LED(%u)", self->id); + mp_printf(print, "LED(\"%s\")", self->name); } // constructor(id, ...) diff --git a/ports/samd/machine_pin.c b/ports/samd/machine_pin.c index e900174a91..fc72c8f756 100644 --- a/ports/samd/machine_pin.c +++ b/ports/samd/machine_pin.c @@ -64,7 +64,19 @@ uint32_t machine_pin_open_drain_mask[4]; STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_pin_obj_t *self = self_in; - mp_printf(print, "GPIO P%c%02u", "ABCD"[self->id / 32], self->id % 32); + char *mode_str; + char *pull_str[] = {"PULL_OFF", "PULL_UP", "PULL_DOWN"}; + if (GPIO_IS_OPEN_DRAIN(self->id)) { + mode_str = "OPEN_DRAIN"; + } else { + mode_str = (mp_hal_get_pin_direction(self->id) == GPIO_DIRECTION_OUT) ? "OUT" : "IN"; + } + + mp_printf(print, "Pin(\"%s\", mode=%s, pull=%s, GPIO=P%c%02u)", + self->name, + mode_str, + pull_str[mp_hal_get_pull_mode(self->id)], + "ABCD"[self->id / 32], self->id % 32); } STATIC void pin_validate_drive(bool strength) { diff --git a/ports/samd/mphalport.h b/ports/samd/mphalport.h index ced0d642b4..6f4f838cfb 100644 --- a/ports/samd/mphalport.h +++ b/ports/samd/mphalport.h @@ -126,7 +126,17 @@ static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) { } static inline unsigned int mp_hal_get_pin_direction(mp_hal_pin_obj_t pin) { - return (PORT->Group[pin / 32].DIR.reg & (1 << (pin % 32))) >> (pin % 32); + return (PORT->Group[pin / 32].DIR.reg & (1 << (pin % 32))) ? + GPIO_DIRECTION_OUT : GPIO_DIRECTION_IN; +} + +static inline unsigned int mp_hal_get_pull_mode(mp_hal_pin_obj_t pin) { + bool pull_en = (PORT->Group[pin / 32].PINCFG[pin % 32].reg & PORT_PINCFG_PULLEN) != 0; + if (pull_en) { + return gpio_get_pin_level(pin) ? GPIO_PULL_UP : GPIO_PULL_DOWN; + } else { + return GPIO_PULL_OFF; + } } static inline int mp_hal_pin_read(mp_hal_pin_obj_t pin) { From f6d06b3ce0f476f9edeaeae855876c83b61d9175 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 6 Oct 2022 10:06:56 +1100 Subject: [PATCH 0527/1041] tools/verifygitlog.py: Ignore comment lines in commit messages. The "signed-off" check assumes that the Signed-off-by: line is the last, but there may me many lines of comments after this. Signed-off-by: Jim Mussared --- tools/verifygitlog.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/verifygitlog.py b/tools/verifygitlog.py index f9d98106d6..5d45e4a4cc 100755 --- a/tools/verifygitlog.py +++ b/tools/verifygitlog.py @@ -102,7 +102,10 @@ def run(args): filename = args[-1] verbose("checking commit message from", filename) with open(args[-1]) as f: - lines = [line.rstrip("\r\n") for line in f] + # Remove comment lines as well as any empty lines at the end. + lines = [line.rstrip("\r\n") for line in f if not line.startswith("#")] + while not lines[-1]: + lines.pop() verify_message_body(lines, err) else: # Normal operation, pass arguments to git log for sha in git_log("%h", *args): From b8982ec5f90a5aa9d802e9d54912dc4e7ba0916a Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 5 Aug 2022 13:55:56 +1000 Subject: [PATCH 0528/1041] tools/verifygitlog.py: Add additional help for subject line issues. This check used to just show the regular expression that failed to match, but the rules are pretty subtle and hard to interpret from the regular expression alone. Add some basic checks for the main things that go wrong: - Missing capitalisation. - Missing full-stop. - Missing path. - Single-word subject. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared --- tools/verifygitlog.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/tools/verifygitlog.py b/tools/verifygitlog.py index 5d45e4a4cc..c237cb46be 100755 --- a/tools/verifygitlog.py +++ b/tools/verifygitlog.py @@ -46,6 +46,23 @@ def git_log(pretty_format, *args): yield line.decode().rstrip("\r\n") +def diagnose_subject_line(subject_line, subject_line_format, err): + err.error("Subject line: " + subject_line) + if not subject_line.endswith("."): + err.error('* should end with "."') + if not re.match(r"^[^!]+: ", subject_line): + err.error('* should start with "path: "') + if re.match(r"^[^!]+: *$", subject_line): + err.error("* should contain a subject after the path.") + m = re.match(r"^[^!]+: ([a-z][^ ]*)", subject_line) + if m: + err.error('* first word of subject ("{}") should be capitalised.'.format(m.group(1))) + if re.match(r"^[^!]+: [^ ]+$", subject_line): + err.error("* subject should contain more than one word.") + err.error("* should match: " + repr(subject_line_format)) + err.error('* Example: "py/runtime: Add support for foo to bar."') + + def verify(sha, err): verbose("verify", sha) err.prefix = "commit " + sha + ": " @@ -75,9 +92,9 @@ def verify_message_body(raw_body, err): very_verbose("subject_line", subject_line) subject_line_format = r"^[^!]+: [A-Z]+.+ .+\.$" if not re.match(subject_line_format, subject_line): - err.error("Subject line should match " + repr(subject_line_format) + ": " + subject_line) + diagnose_subject_line(subject_line, subject_line_format, err) if len(subject_line) >= 73: - err.error("Subject line should be 72 or less characters: " + subject_line) + err.error("Subject line should be 72 or fewer characters: " + subject_line) # Second one divides subject and body. if len(raw_body) > 1 and raw_body[1]: @@ -90,7 +107,7 @@ def verify_message_body(raw_body, err): err.error("Message lines should be 75 or less characters: " + line) if not raw_body[-1].startswith("Signed-off-by: ") or "@" not in raw_body[-1]: - err.warning("Message should be signed-off") + err.warning('Message should be signed-off. Use "git commit -s".') def run(args): From 4fc543c829add6bb13b111b5e12103893bbc0706 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 6 Oct 2022 00:43:28 +1100 Subject: [PATCH 0529/1041] CODECONVENTIONS.md: Update pre-commit instructions. Signed-off-by: Jim Mussared --- CODECONVENTIONS.md | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/CODECONVENTIONS.md b/CODECONVENTIONS.md index 2daea8431f..53b202ea37 100644 --- a/CODECONVENTIONS.md +++ b/CODECONVENTIONS.md @@ -72,16 +72,27 @@ different formatting, and the configuration file formats are often incompatible. Automatic Pre-Commit Hooks ========================== -To have code formatting and commit message conventions automatically checked -using [pre-commit](https://pre-commit.com/), run the following commands in your -local MicroPython directory: +To have code formatting and commit message conventions automatically checked, +a configuration file is provided for the [pre-commit] +(https://pre-commit.com/) tool. + +First install `pre-commit`, either from your system package manager or via +`pip`. When installing `pre-commit` via pip, it is recommended to use a +virtual environment. Other sources, such as Brew are also available, see +[the docs](https://pre-commit.com/index.html#install) for details. ``` -$ pip install pre-commit +$ apt install pre-commit # Ubuntu +$ pacman -Sy python-precommit # Arch Linux +$ brew install pre-commit # Brew +$ pip install pre-commit # PyPI +``` -$ pre-commit install +Then inside the MicroPython repository, register the git hooks for pre-commit +by running: -$ pre-commit install --hook-type commit-msg +``` +$ pre-commit install --hook-type pre-commit --hook-type commit-msg ``` pre-commit will now automatically run during `git commit` for both code and @@ -91,6 +102,12 @@ The same formatting checks will be run by CI for any Pull Request submitted to MicroPython. Pre-commit allows you to see any failure more quickly, and in many cases will automatically correct it in your local working copy. +To unregister `pre-commit` from your MicroPython repository, run: + +``` +$ pre-commit uninstall --hook-type pre-commit --hook-type commit-msg +``` + Tips: * To skip pre-commit checks on a single commit, use `git commit -n` (for @@ -98,8 +115,6 @@ Tips: * To ignore the pre-commit message format check temporarily, start the commit message subject line with "WIP" (for "Work In Progress"). -(It is also possible to install pre-commit using Brew or other sources, see -[the docs](https://pre-commit.com/index.html#install) for details.) Python code conventions ======================= From c44b3927b8f464e1e01c07b2431e7db251e6d8c0 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 7 Oct 2022 11:06:43 +1100 Subject: [PATCH 0530/1041] py/objstr: Add a helper to set mp_obj_str_t data. Signed-off-by: Jim Mussared --- py/objstr.c | 6 ++++++ py/objstr.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/py/objstr.c b/py/objstr.c index 55e737fffc..8c639e7354 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -2045,6 +2045,12 @@ mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_u } } +void mp_obj_str_set_data(mp_obj_str_t *str, const byte *data, size_t len) { + str->data = data; + str->len = len; + str->hash = qstr_compute_hash(data, len); +} + // This locals table is used for the following types: str, bytes, bytearray, array.array. // Each type takes a different section (start to end offset) of this table. STATIC const mp_rom_map_elem_t array_bytearray_str_bytes_locals_table[] = { diff --git a/py/objstr.h b/py/objstr.h index 6c6735bf5e..72fe1cfef0 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -94,6 +94,8 @@ mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte *data, siz mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags); +void mp_obj_str_set_data(mp_obj_str_t *str, const byte *data, size_t len); + const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len, mp_obj_t index, bool is_slice); const byte *find_subbytes(const byte *haystack, size_t hlen, const byte *needle, size_t nlen, int direction); From 0e8dfaf5384c672fc61bc10926688809db2b2ab2 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 7 Oct 2022 02:13:58 +1100 Subject: [PATCH 0531/1041] py/modsys: Add support for sys.executable. Only intended to be used on Unix and other "OS" ports. Matches CPython. This should give the absolute path to the executing binary. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared Signed-off-by: Damien George --- py/modsys.c | 10 ++++++++++ py/mpconfig.h | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/py/modsys.c b/py/modsys.c index 56e83029c4..35af761a08 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -115,6 +115,12 @@ STATIC const mp_rom_obj_tuple_t mp_sys_implementation_obj = { STATIC const MP_DEFINE_STR_OBJ(mp_sys_platform_obj, MICROPY_PY_SYS_PLATFORM); #endif +#ifdef MICROPY_PY_SYS_EXECUTABLE +// executable - the path to the micropython binary +// This object is non-const and is populated at startup in main() +MP_DEFINE_STR_OBJ(mp_sys_executable_obj, ""); +#endif + // exit([retval]): raise SystemExit, with optional argument given to the exception STATIC mp_obj_t mp_sys_exit(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { @@ -262,6 +268,10 @@ STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_getsizeof), MP_ROM_PTR(&mp_sys_getsizeof_obj) }, #endif + #if MICROPY_PY_SYS_EXECUTABLE + { MP_ROM_QSTR(MP_QSTR_executable), MP_ROM_PTR(&mp_sys_executable_obj) }, + #endif + /* * Extensions to CPython */ diff --git a/py/mpconfig.h b/py/mpconfig.h index 698d264d2e..99fa87e5c1 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -1372,6 +1372,13 @@ typedef double mp_float_t; #define MICROPY_PY_SYS_EXC_INFO (0) #endif +// Whether to provide "sys.executable", which is the absolute path to the +// micropython binary +// Intended for use on the "OS" ports (e.g. Unix) +#ifndef MICROPY_PY_SYS_EXECUTABLE +#define MICROPY_PY_SYS_EXECUTABLE (0) +#endif + // Whether to provide "sys.exit" function #ifndef MICROPY_PY_SYS_EXIT #define MICROPY_PY_SYS_EXIT (1) From 8e912a501a926f59f330f8a71c2ac1bd4af88a9e Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 7 Oct 2022 02:13:58 +1100 Subject: [PATCH 0532/1041] unix: Enable sys.executable. Gives the absolute path to the unix micropython binary. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared Signed-off-by: Damien George --- ports/unix/main.c | 16 ++++++++++++++++ ports/unix/mpconfigport.h | 3 +++ tests/unix/extra_coverage.py.exp | 9 +++++---- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/ports/unix/main.c b/ports/unix/main.c index 44823ee174..7920db02f2 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -43,6 +43,7 @@ #include "py/builtin.h" #include "py/repl.h" #include "py/gc.h" +#include "py/objstr.h" #include "py/stackctrl.h" #include "py/mphal.h" #include "py/mpthread.h" @@ -435,6 +436,17 @@ STATIC void set_sys_argv(char *argv[], int argc, int start_arg) { } } +#if MICROPY_PY_SYS_EXECUTABLE +extern mp_obj_str_t mp_sys_executable_obj; +STATIC char executable_path[MICROPY_ALLOC_PATH_MAX]; + +STATIC void sys_set_excecutable(char *argv0) { + if (realpath(argv0, executable_path)) { + mp_obj_str_set_data(&mp_sys_executable_obj, (byte *)executable_path, strlen(executable_path)); + } +} +#endif + #ifdef _WIN32 #define PATHLIST_SEP_CHAR ';' #else @@ -598,6 +610,10 @@ MP_NOINLINE int main_(int argc, char **argv) { printf(" peak %d\n", m_get_peak_bytes_allocated()); */ + #if MICROPY_PY_SYS_EXECUTABLE + sys_set_excecutable(argv[0]); + #endif + const int NOTHING_EXECUTED = -2; int ret = NOTHING_EXECUTED; bool inspect = false; diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 08ddd21f63..a67d11b9e7 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -154,6 +154,9 @@ typedef long mp_off_t; // Don't default sys.argv because we do that in main. #define MICROPY_PY_SYS_PATH_ARGV_DEFAULTS (0) +// Enable sys.executable. +#define MICROPY_PY_SYS_EXECUTABLE (1) + #define MICROPY_PY_USOCKET_LISTEN_BACKLOG_DEFAULT (SOMAXCONN < 128 ? SOMAXCONN : 128) // Bare-metal ports don't have stderr. Printing debug to stderr may give tests diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index 2941154556..2f5409b85b 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -62,10 +62,11 @@ ime utime utimeq argv atexit byteorder exc_info -exit getsizeof implementation maxsize -modules path platform print_exception -ps1 ps2 stderr stdin -stdout tracebacklimit version version_info +executable exit getsizeof implementation +maxsize modules path platform +print_exception ps1 ps2 +stderr stdin stdout tracebacklimit +version version_info ementation # attrtuple (start=1, stop=2, step=3) From 17f2783e4aa4534823e2dc33e77389ad498f2d24 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 8 Oct 2022 23:08:53 +1100 Subject: [PATCH 0533/1041] all: Use += rather than = everywhere for CFLAGS/LDFLAGS/LIBS. This avoids a surprise where an = can cancel out an earlier +=. Signed-off-by: Jim Mussared --- docs/develop/porting.rst | 4 ++-- examples/embedding/Makefile | 4 ++-- examples/embedding/Makefile.upylib | 4 ++-- ports/cc3200/Makefile | 4 ++-- ports/esp8266/Makefile | 6 +++--- ports/mimxrt/Makefile | 2 +- ports/minimal/Makefile | 8 ++++---- ports/nrf/Makefile | 2 +- ports/pic16bit/Makefile | 6 +++--- ports/powerpc/Makefile | 4 ++-- ports/renesas-ra/Makefile | 2 +- ports/samd/Makefile | 6 +++--- ports/stm32/Makefile | 2 +- ports/stm32/mboot/Makefile | 6 +++--- ports/teensy/Makefile | 4 ++-- ports/windows/Makefile | 4 ++-- 16 files changed, 34 insertions(+), 34 deletions(-) diff --git a/docs/develop/porting.rst b/docs/develop/porting.rst index 0511f5d276..74974a39e1 100644 --- a/docs/develop/porting.rst +++ b/docs/develop/porting.rst @@ -98,8 +98,8 @@ We also need a Makefile at this point for the port: include $(TOP)/extmod/extmod.mk # Set CFLAGS and libraries. - CFLAGS = -I. -I$(BUILD) -I$(TOP) - LIBS = -lm + CFLAGS += -I. -I$(BUILD) -I$(TOP) + LIBS += -lm # Define the required source files. SRC_C = \ diff --git a/examples/embedding/Makefile b/examples/embedding/Makefile index 7de1219b26..edaa577f57 100644 --- a/examples/embedding/Makefile +++ b/examples/embedding/Makefile @@ -1,6 +1,6 @@ MPTOP = ../.. -CFLAGS = -std=c99 -I. -I$(MPTOP) -DNO_QSTR -LDFLAGS = -L./build +CFLAGS += -std=c99 -I. -I$(MPTOP) -DNO_QSTR +LDFLAGS += -L./build hello-embed: hello-embed.o -lmicropython diff --git a/examples/embedding/Makefile.upylib b/examples/embedding/Makefile.upylib index a8e2b91d56..99ce94b7ad 100644 --- a/examples/embedding/Makefile.upylib +++ b/examples/embedding/Makefile.upylib @@ -20,7 +20,7 @@ INC += -I$(BUILD) # compiler settings CWARN = -Wall -Werror CWARN += -Wpointer-arith -Wuninitialized -CFLAGS = $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) +CFLAGS += $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) # Some systems (eg MacOS) need -fno-common so that mp_state_ctx is placed in the BSS. CFLAGS += -fno-common @@ -70,7 +70,7 @@ else # Use gcc syntax for map file LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref endif -LDFLAGS = $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA) +LDFLAGS += $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA) ifeq ($(MICROPY_FORCE_32BIT),1) # Note: you may need to install i386 versions of dependency packages, diff --git a/ports/cc3200/Makefile b/ports/cc3200/Makefile index b880ad646b..6c034c5863 100644 --- a/ports/cc3200/Makefile +++ b/ports/cc3200/Makefile @@ -20,7 +20,7 @@ include ../../py/mkenv.mk CROSS_COMPILE ?= arm-none-eabi- CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -march=armv7e-m -mabi=aapcs -mcpu=cortex-m4 -msoft-float -mfloat-abi=soft -fsingle-precision-constant -Wdouble-promotion -CFLAGS = -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) -Os +CFLAGS += -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) -Os CFLAGS += -g -ffunction-sections -fdata-sections -fno-common -fsigned-char -mno-unaligned-access CFLAGS += -Iboards/$(BOARD) CFLAGS += $(CFLAGS_MOD) @@ -28,7 +28,7 @@ CFLAGS += $(CFLAGS_MOD) # Workaround gcc 12.1 bug. CFLAGS += -Wno-array-bounds -LDFLAGS = -Wl,-nostdlib -Wl,--gc-sections -Wl,-Map=$@.map +LDFLAGS += -Wl,-nostdlib -Wl,--gc-sections -Wl,-Map=$@.map FLASH_SIZE_WIPY = 2M FLASH_SIZE_LAUNCHXL = 1M diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index c027f690fb..6002dc5e5a 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -57,12 +57,12 @@ CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \ -Wl,-EL -mlongcalls -mtext-section-literals -mforce-l32 \ -DLWIP_OPEN_SRC -CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \ +CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \ $(CFLAGS_XTENSA) $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) -I$(BOARD_DIR) LD_FILES ?= boards/esp8266_2m.ld -LDFLAGS = -nostdlib -T $(LD_FILES) -Map=$(@:.elf=.map) --cref -LIBS = -L$(ESP_SDK)/lib -lmain -ljson -llwip_open -lpp -lnet80211 -lwpa -lphy -lnet80211 $(LDFLAGS_MOD) +LDFLAGS += -nostdlib -T $(LD_FILES) -Map=$(@:.elf=.map) --cref +LIBS += -L$(ESP_SDK)/lib -lmain -ljson -llwip_open -lpp -lnet80211 -lwpa -lphy -lnet80211 $(LDFLAGS_MOD) LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) LIBS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index 6a18879ac5..8493c47a71 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -393,7 +393,7 @@ CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) # Linker Flags # ============================================================================= -LDFLAGS = \ +LDFLAGS += \ --cref \ --gc-sections \ --print-memory-usage \ diff --git a/ports/minimal/Makefile b/ports/minimal/Makefile index 0e875cc249..2e85bd912e 100644 --- a/ports/minimal/Makefile +++ b/ports/minimal/Makefile @@ -23,12 +23,12 @@ ifeq ($(CROSS), 1) DFU = $(TOP)/tools/dfu.py PYDFU = $(TOP)/tools/pydfu.py CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mcpu=cortex-m4 -msoft-float -fsingle-precision-constant -Wdouble-promotion -Wfloat-conversion -CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT) -LDFLAGS = -nostdlib -T stm32f405.ld -Map=$@.map --cref --gc-sections +CFLAGS += $(INC) -Wall -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT) +LDFLAGS += -nostdlib -T stm32f405.ld -Map=$@.map --cref --gc-sections else LD = gcc -CFLAGS = $(INC) -Wall -Werror -Wdouble-promotion -Wfloat-conversion -std=c99 $(COPT) -LDFLAGS = -Wl,-Map=$@.map,--cref -Wl,--gc-sections +CFLAGS += $(INC) -Wall -Werror -Wdouble-promotion -Wfloat-conversion -std=c99 $(COPT) +LDFLAGS += -Wl,-Map=$@.map,--cref -Wl,--gc-sections endif CSUPEROPT = -Os # save some code space diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index bc295cac80..38d0bd7fce 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -129,7 +129,7 @@ CFLAGS += -fno-strict-aliasing CFLAGS += -Iboards/$(BOARD) CFLAGS += -DNRF5_HAL_H='<$(MCU_VARIANT)_hal.h>' -LDFLAGS = $(CFLAGS) +LDFLAGS += $(CFLAGS) LDFLAGS += -Xlinker -Map=$(@:.elf=.map) LDFLAGS += -mthumb -mabi=aapcs $(addprefix -T,$(LD_FILES)) -L boards/ diff --git a/ports/pic16bit/Makefile b/ports/pic16bit/Makefile index 392196cbc2..d2c8df4707 100644 --- a/ports/pic16bit/Makefile +++ b/ports/pic16bit/Makefile @@ -21,7 +21,7 @@ INC += -I$(XC16)/include INC += -I$(XC16)/support/$(PARTFAMILY)/h CFLAGS_PIC16BIT = -mcpu=$(PART) -mlarge-code -CFLAGS = $(INC) -Wall -Werror -std=gnu99 -nostdlib $(CFLAGS_PIC16BIT) $(COPT) +CFLAGS += $(INC) -Wall -Werror -std=gnu99 -nostdlib $(CFLAGS_PIC16BIT) $(COPT) #Debugging/Optimization ifeq ($(DEBUG), 1) @@ -30,8 +30,8 @@ else CFLAGS += -O1 -DNDEBUG endif -LDFLAGS = --heap=0 -nostdlib -T $(XC16)/support/$(PARTFAMILY)/gld/p$(PART).gld -Map=$@.map --cref -p$(PART) -LIBS = -L$(XC16)/lib -L$(XC16)/lib/$(PARTFAMILY) -lc -lm -lpic30 +LDFLAGS += --heap=0 -nostdlib -T $(XC16)/support/$(PARTFAMILY)/gld/p$(PART).gld -Map=$@.map --cref -p$(PART) +LIBS += -L$(XC16)/lib -L$(XC16)/lib/$(PARTFAMILY) -lc -lm -lpic30 SRC_C = \ main.c \ diff --git a/ports/powerpc/Makefile b/ports/powerpc/Makefile index 0986fd13eb..8fc9b11166 100644 --- a/ports/powerpc/Makefile +++ b/ports/powerpc/Makefile @@ -21,14 +21,14 @@ INC += -I. INC += -I$(TOP) INC += -I$(BUILD) -CFLAGS = $(INC) -g -Wall -Wdouble-promotion -Wfloat-conversion -std=c99 $(COPT) +CFLAGS += $(INC) -g -Wall -Wdouble-promotion -Wfloat-conversion -std=c99 $(COPT) CFLAGS += -mno-string -mno-multiple -mno-vsx -mno-altivec -nostdlib CFLAGS += -mlittle-endian -mstrict-align -msoft-float CFLAGS += -Os CFLAGS += -fdata-sections -ffunction-sections -fno-stack-protector -ffreestanding CFLAGS += -U_FORTIFY_SOURCE -LDFLAGS = -N -T powerpc.lds -nostdlib +LDFLAGS += -N -T powerpc.lds -nostdlib LIBS = diff --git a/ports/renesas-ra/Makefile b/ports/renesas-ra/Makefile index 92d8be0692..6c37aeb1e1 100644 --- a/ports/renesas-ra/Makefile +++ b/ports/renesas-ra/Makefile @@ -139,7 +139,7 @@ CFLAGS += -fsingle-precision-constant endif endif -LDFLAGS = -nostdlib -L $(LD_DIR) $(addprefix -T,$(LD_FILES)) -Map=$(@:.elf=.map) --cref +LDFLAGS += -nostdlib -L $(LD_DIR) $(addprefix -T,$(LD_FILES)) -Map=$(@:.elf=.map) --cref LDFLAGS += --defsym=_estack_reserve=8 LIBS += "$(shell $(CC) $(CFLAGS) -print-libgcc-file-name)" diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 5ff00f21f9..512820088a 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -58,15 +58,15 @@ GEN_PINS_HDR = $(BUILD)/pins.h CFLAGS_MCU_SAMD21 = -mtune=cortex-m0plus -mcpu=cortex-m0plus -msoft-float CFLAGS_MCU_SAMD51 = -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib -mthumb $(CFLAGS_MCU_$(MCU_SERIES)) -fsingle-precision-constant -Wdouble-promotion +CFLAGS += $(INC) -Wall -Werror -std=c99 -nostdlib -mthumb $(CFLAGS_MCU_$(MCU_SERIES)) -fsingle-precision-constant -Wdouble-promotion CFLAGS += -DMCU_$(MCU_SERIES) -D__$(CMSIS_MCU)__ CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) CFLAGS += -DMPCONFIG_MCU_H='' -LDFLAGS = -nostdlib $(addprefix -T,$(LD_FILES)) -Map=$@.map --cref +LDFLAGS += -nostdlib $(addprefix -T,$(LD_FILES)) -Map=$@.map --cref LDFLAGS += $(LDFLAGS_MOD) -LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) +LIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) # Tune for Debugging or Optimization CFLAGS += -g # always include debug info in the ELF diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 4b4a9f0ce3..903730982e 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -99,7 +99,7 @@ CFLAGS += -fsingle-precision-constant endif endif -LDFLAGS = -nostdlib -L $(LD_DIR) $(addprefix -T,$(LD_FILES)) -Wl,-Map=$(@:.elf=.map) -Wl,--cref +LDFLAGS += -nostdlib -L $(LD_DIR) $(addprefix -T,$(LD_FILES)) -Wl,-Map=$(@:.elf=.map) -Wl,--cref LDFLAGS += -Wl,--defsym=_estack_reserve=8 LIBS += "$(shell $(CC) $(CFLAGS) -print-libgcc-file-name)" diff --git a/ports/stm32/mboot/Makefile b/ports/stm32/mboot/Makefile index 4c903b4ff6..176092f8c0 100755 --- a/ports/stm32/mboot/Makefile +++ b/ports/stm32/mboot/Makefile @@ -58,7 +58,7 @@ INC += -I../$(USBDEV_DIR)/core/inc -I../$(USBDEV_DIR)/class/inc # the compiler does not optimise these functions in terms of themselves. CFLAGS_BUILTIN ?= -ffreestanding -fno-builtin -fno-lto -CFLAGS = $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Wfloat-conversion -Werror -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_EXTRA) +CFLAGS += $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Wfloat-conversion -Werror -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_EXTRA) CFLAGS += -D$(CMSIS_MCU) CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES)) CFLAGS += $(COPT) @@ -75,8 +75,8 @@ CFLAGS += -DMICROPY_HW_STM32WB_FLASH_SYNCRONISATION=0 CFLAGS += -DBOOTLOADER_DFU_USB_VID=$(BOOTLOADER_DFU_USB_VID) -DBOOTLOADER_DFU_USB_PID=$(BOOTLOADER_DFU_USB_PID) MBOOT_LD_FILES ?= stm32_memory.ld stm32_sections.ld -LDFLAGS = -nostdlib -L . $(addprefix -T,$(MBOOT_LD_FILES)) -Map=$(@:.elf=.map) --cref -LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) +LDFLAGS += -nostdlib -L . $(addprefix -T,$(MBOOT_LD_FILES)) -Map=$(@:.elf=.map) --cref +LIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) # Remove uncalled code from the final image. CFLAGS += -fdata-sections -ffunction-sections diff --git a/ports/teensy/Makefile b/ports/teensy/Makefile index d7161fcbbc..52fc812ad4 100644 --- a/ports/teensy/Makefile +++ b/ports/teensy/Makefile @@ -75,8 +75,8 @@ INC += -I$(TOP)/ports/stm32 INC += -I$(BUILD) INC += -Icore -CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4) -LDFLAGS = -nostdlib -T mk20dx256.ld -msoft-float -mfloat-abi=soft +CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4) +LDFLAGS += -nostdlib -T mk20dx256.ld -msoft-float -mfloat-abi=soft ifeq ($(USE_ARDUINO_TOOLCHAIN),1) diff --git a/ports/windows/Makefile b/ports/windows/Makefile index 1e793800f8..64334bc18b 100644 --- a/ports/windows/Makefile +++ b/ports/windows/Makefile @@ -32,8 +32,8 @@ INC += -I$(BUILD) INC += -I$(VARIANT_DIR) # compiler settings -CFLAGS = $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Werror -std=gnu99 -DUNIX -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) -LDFLAGS = $(LDFLAGS_MOD) -lm -lbcrypt $(LDFLAGS_EXTRA) +CFLAGS += $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Werror -std=gnu99 -DUNIX -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) +LDFLAGS += -lm -lbcrypt $(LDFLAGS_EXTRA) # Debugging/Optimization ifdef DEBUG From 67d05ed02b26b6ba2dcc638f2deed937a08417d7 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 8 Oct 2022 23:23:52 +1100 Subject: [PATCH 0534/1041] ports: Make generated pin.c handling more consistent across ports. Signed-off-by: Jim Mussared --- ports/mimxrt/Makefile | 7 +++--- ports/nrf/Makefile | 26 ++++++++++---------- ports/samd/Makefile | 5 +++- ports/stm32/Makefile | 57 +++++++++++++++++++++---------------------- ports/teensy/Makefile | 26 ++++++++++---------- 5 files changed, 61 insertions(+), 60 deletions(-) diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index 8493c47a71..6095f5fd23 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -15,7 +15,7 @@ MICROPY_VFS_LFS2 ?= 1 MICROPY_VFS_FAT ?= 1 # qstr definitions (must come before including py.mk) -QSTR_DEFS = qstrdefsport.h +QSTR_DEFS += qstrdefsport.h QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h # Generation scripts @@ -49,7 +49,6 @@ GEN_FLEXRAM_CONFIG_SRC = $(BUILD)/flexram_config.s GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h GEN_PINS_AF_PY = $(BUILD)/pins_af.py GEN_PINS_HDR = $(HEADER_BUILD)/pins.h -GEN_PINS_QSTR = $(BUILD)/pins_qstr.h GEN_PINS_SRC = $(BUILD)/pins_gen.c # ============================================================================= @@ -435,7 +434,7 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_SS:.S=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) -OBJ += $(BUILD)/pins_gen.o +OBJ += $(GEN_PINS_SRC:.c=.o) # Workaround for bug in older gcc, warning on "static usbd_device_t _usbd_dev = { 0 };" $(BUILD)/lib/tinyusb/src/device/usbd.o: CFLAGS += -Wno-missing-braces @@ -486,7 +485,7 @@ $(BUILD)/%_gen.c $(HEADER_BUILD)/%.h: $(BOARD_PINS) $(MAKE_PINS) $(AF_FILE) $(PR --iomux $(abspath $(TOP)/$(MCU_DIR)/drivers/fsl_iomuxc.h) \ --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) > $(GEN_PINS_SRC) -$(BUILD)/pins_gen.o: $(BUILD)/pins_gen.c +$(GEN_PINS_SRC:.c=.o): $(GEN_PINS_SRC) $(call compile_c) include $(TOP)/py/mkrules.mk diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 38d0bd7fce..9e0354194d 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -45,7 +45,7 @@ endif -include boards/$(BOARD)/modules/boardmodules.mk # qstr definitions (must come before including py.mk) -QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h +QSTR_DEFS = qstrdefsport.h $(GEN_PINS_QSTR) # MicroPython feature configurations ifeq ($(DEBUG), 0) @@ -106,6 +106,16 @@ endif NRF_DEFINES += -D$(MCU_SUB_VARIANT_UPPER) NRF_DEFINES += -DCONFIG_GPIO_AS_PINRESET +MAKE_PINS = boards/make-pins.py +BOARD_PINS = boards/$(BOARD)/pins.csv +AF_FILE = $(MCU_VARIANT)_af.csv +PREFIX_FILE = boards/$(MCU_VARIANT)_prefix.c +GEN_PINS_SRC = $(BUILD)/pins_gen.c +GEN_PINS_HDR = $(HEADER_BUILD)/pins.h +GEN_PINS_QSTR = $(BUILD)/pins_qstr.h +GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h +GEN_PINS_AF_PY = $(BUILD)/pins_af.py + CFLAGS_CORTEX_M = -mthumb -mabi=aapcs -fsingle-precision-constant -Wdouble-promotion CFLAGS_MCU_m33 = $(CFLAGS_CORTEX_M) -mcpu=cortex-m33 -march=armv8-m.main+dsp -mcmse -mfpu=fpv5-sp-d16 -mfloat-abi=hard @@ -354,7 +364,7 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_NRFX_HAL:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SYSTEM_C_SRC:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) -OBJ += $(BUILD)/pins_gen.o +OBJ += $(GEN_PINS_SRC:.c=.o) $(BUILD)/$(OOFATFS_DIR)/ff.o: COPT += -Os $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os @@ -528,19 +538,9 @@ $(BUILD)/%_gen.c $(HEADER_BUILD)/%.h $(HEADER_BUILD)/%_af_const.h $(BUILD)/%_qst $(ECHO) "Create $@" $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) --qstr $(GEN_PINS_QSTR) --af-const $(GEN_PINS_AF_CONST) --af-py $(GEN_PINS_AF_PY) > $(GEN_PINS_SRC) -$(BUILD)/pins_gen.o: $(BUILD)/pins_gen.c +$(GEN_PINS_SRC:.c=.o): $(GEN_PINS_SRC) $(call compile_c) -MAKE_PINS = boards/make-pins.py -BOARD_PINS = boards/$(BOARD)/pins.csv -AF_FILE = $(MCU_VARIANT)_af.csv -PREFIX_FILE = boards/$(MCU_VARIANT)_prefix.c -GEN_PINS_SRC = $(BUILD)/pins_gen.c -GEN_PINS_HDR = $(HEADER_BUILD)/pins.h -GEN_PINS_QSTR = $(BUILD)/pins_qstr.h -GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h -GEN_PINS_AF_PY = $(BUILD)/pins_af.py - ifneq ($(FROZEN_MANIFEST),) CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool CFLAGS += -DMICROPY_MODULE_FROZEN_MPY diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 512820088a..735d25bf27 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -106,7 +106,6 @@ SRC_C += \ mphalport.c \ pendsv.c \ pin_af.c \ - $(BUILD)/pins.c \ samd_flash.c \ samd_isr.c \ samd_soc.c \ @@ -170,6 +169,7 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) +OBJ += $(GEN_PINS_SRC:.c=.o) ifneq ($(FROZEN_MANIFEST),) CFLAGS += -DMICROPY_MODULE_FROZEN_MPY @@ -205,4 +205,7 @@ $(GEN_PINS_SRC) $(GEN_PINS_HDR): $(BOARD_PINS) | $(HEADER_BUILD) $(ECHO) "Create $@" $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --pins $(GEN_PINS_SRC) --inc $(GEN_PINS_HDR) +$(GEN_PINS_SRC:.c=.o): $(GEN_PINS_SRC) + $(call compile_c) + include $(TOP)/py/mkrules.mk diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 903730982e..403b68b240 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -15,7 +15,7 @@ include ../../py/mkenv.mk include $(BOARD_DIR)/mpconfigboard.mk # Files that are generated and needed before the QSTR build. -QSTR_GENERATED_HEADERS = $(BUILD)/pins_qstr.h $(BUILD)/modstm_qstr.h +QSTR_GENERATED_HEADERS = $(GEN_PINS_QSTR) $(GEN_STMCONST_QSTR) # qstr definitions (must come before including py.mk) QSTR_DEFS += qstrdefsport.h $(QSTR_GENERATED_HEADERS) @@ -57,6 +57,31 @@ OPENOCD_CONFIG ?= boards/openocd_stm32f4.cfg include stm32.mk +PLLVALUES = boards/pllvalues.py +MAKE_PINS = boards/make-pins.py +BOARD_PINS = $(BOARD_DIR)/pins.csv +PREFIX_FILE = boards/stm32f4xx_prefix.c +GEN_PINS_SRC = $(BUILD)/pins_$(BOARD).c +GEN_PINS_HDR = $(HEADER_BUILD)/pins.h +GEN_PINS_QSTR = $(BUILD)/pins_qstr.h +GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h +GEN_PINS_AF_DEFS = $(HEADER_BUILD)/pins_af_defs.h +GEN_PINS_AF_PY = $(BUILD)/pins_af.py + +INSERT_USB_IDS = $(TOP)/tools/insert-usb-ids.py +FILE2H = $(TOP)/tools/file2h.py + +USB_IDS_FILE = mpconfigboard_common.h +CDCINF_TEMPLATE = pybcdc.inf_template +GEN_CDCINF_FILE = $(HEADER_BUILD)/pybcdc.inf +GEN_CDCINF_HEADER = $(HEADER_BUILD)/pybcdc_inf.h + +GEN_PLLFREQTABLE_HDR = $(HEADER_BUILD)/pllfreqtable.h +GEN_STMCONST_HDR = $(HEADER_BUILD)/modstm_const.h +GEN_STMCONST_QSTR = $(BUILD)/modstm_qstr.h +GEN_STMCONST_MPZ = $(HEADER_BUILD)/modstm_mpz.h +CMSIS_MCU_HDR = $(STM32LIB_CMSIS_ABS)/Include/$(CMSIS_MCU_LOWER).h + # Select the cross compile prefix CROSS_COMPILE ?= arm-none-eabi- @@ -537,8 +562,7 @@ OBJ += $(addprefix $(BUILD)/, $(HAL_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(USBDEV_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) -OBJ += $(BUILD)/pins_$(BOARD).o +OBJ += $(GEN_PINS_SRC:.c=.o) # This file contains performance critical functions so turn up the optimisation # level. It doesn't add much to the code size and improves performance a bit. @@ -689,25 +713,6 @@ $(BUILD)/firmware.hex: $(BUILD)/firmware.elf $(BUILD)/firmware.elf: $(OBJ) $(call GENERATE_ELF,$@,$^) -PLLVALUES = boards/pllvalues.py -MAKE_PINS = boards/make-pins.py -BOARD_PINS = $(BOARD_DIR)/pins.csv -PREFIX_FILE = boards/stm32f4xx_prefix.c -GEN_PINS_SRC = $(BUILD)/pins_$(BOARD).c -GEN_PINS_HDR = $(HEADER_BUILD)/pins.h -GEN_PINS_QSTR = $(BUILD)/pins_qstr.h -GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h -GEN_PINS_AF_DEFS = $(HEADER_BUILD)/pins_af_defs.h -GEN_PINS_AF_PY = $(BUILD)/pins_af.py - -INSERT_USB_IDS = $(TOP)/tools/insert-usb-ids.py -FILE2H = $(TOP)/tools/file2h.py - -USB_IDS_FILE = mpconfigboard_common.h -CDCINF_TEMPLATE = pybcdc.inf_template -GEN_CDCINF_FILE = $(HEADER_BUILD)/pybcdc.inf -GEN_CDCINF_HEADER = $(HEADER_BUILD)/pybcdc_inf.h - # List of sources for qstr extraction SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SRC_MOD) $(SHARED_SRC_C) $(EXTMOD_SRC_C) # Append any auto-generated sources that are needed by sources listed in @@ -738,15 +743,9 @@ $(BUILD)/%_$(BOARD).c $(HEADER_BUILD)/%.h $(HEADER_BUILD)/%_af_const.h $(HEADER_ --af-defs $(GEN_PINS_AF_DEFS) --af-defs-cmp-strings \ --af-py $(GEN_PINS_AF_PY) > $(GEN_PINS_SRC) -$(BUILD)/pins_$(BOARD).o: $(BUILD)/pins_$(BOARD).c +$(GEN_PINS_SRC:.c=.o): $(GEN_PINS_SRC) $(call compile_c) -GEN_PLLFREQTABLE_HDR = $(HEADER_BUILD)/pllfreqtable.h -GEN_STMCONST_HDR = $(HEADER_BUILD)/modstm_const.h -GEN_STMCONST_QSTR = $(BUILD)/modstm_qstr.h -GEN_STMCONST_MPZ = $(HEADER_BUILD)/modstm_mpz.h -CMSIS_MCU_HDR = $(STM32LIB_CMSIS_ABS)/Include/$(CMSIS_MCU_LOWER).h - modmachine.c: $(GEN_PLLFREQTABLE_HDR) $(GEN_PLLFREQTABLE_HDR): $(PLLVALUES) | $(HEADER_BUILD) $(ECHO) "GEN $@" diff --git a/ports/teensy/Makefile b/ports/teensy/Makefile index 52fc812ad4..876ddf1c1d 100644 --- a/ports/teensy/Makefile +++ b/ports/teensy/Makefile @@ -1,7 +1,7 @@ include ../../py/mkenv.mk # qstr definitions (must come before including py.mk) -QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h +QSTR_DEFS = qstrdefsport.h $(GEN_PINS_QSTR) # MicroPython feature configurations MICROPY_ROM_TEXT_COMPRESSION ?= 1 @@ -66,6 +66,16 @@ $(info Using toolchain from PATH) CROSS_COMPILE ?= arm-none-eabi- endif +MAKE_PINS = make-pins.py +BOARD_PINS = teensy_pins.csv +AF_FILE = mk20dx256_af.csv +PREFIX_FILE = mk20dx256_prefix.c +GEN_PINS_SRC = $(BUILD)/pins_gen.c +GEN_PINS_HDR = $(HEADER_BUILD)/pins.h +GEN_PINS_QSTR = $(BUILD)/pins_qstr.h +GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h +GEN_PINS_AF_PY = $(BUILD)/pins_af.py + CFLAGS_TEENSY = -DF_CPU=96000000 -DUSB_SERIAL -D__MK20DX256__ CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mcpu=cortex-m4 -msoft-float -mfloat-abi=soft -fsingle-precision-constant -Wdouble-promotion $(CFLAGS_TEENSY) @@ -157,7 +167,7 @@ SRC_TEENSY = $(addprefix core/,\ OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(STM_SRC_C:.c=.o) $(SRC_TEENSY:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o)) OBJ += $(BUILD)/shared/runtime/gchelper_m3.o -OBJ += $(BUILD)/pins_gen.o +OBJ += $(GEN_PINS_SRC:.c=.o) all: hex hex: $(BUILD)/micropython.hex @@ -195,16 +205,6 @@ $(BUILD)/%.hex: $(BUILD)/%.elf $(ECHO) "HEX $<" $(Q)$(OBJCOPY) -O ihex -R .eeprom "$<" "$@" -MAKE_PINS = make-pins.py -BOARD_PINS = teensy_pins.csv -AF_FILE = mk20dx256_af.csv -PREFIX_FILE = mk20dx256_prefix.c -GEN_PINS_SRC = $(BUILD)/pins_gen.c -GEN_PINS_HDR = $(HEADER_BUILD)/pins.h -GEN_PINS_QSTR = $(BUILD)/pins_qstr.h -GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h -GEN_PINS_AF_PY = $(BUILD)/pins_af.py - # List of sources for qstr extraction SRC_QSTR += $(SRC_C) $(STM_SRC_C) $(SHARED_SRC_C) # Append any auto-generated sources that are needed by sources listed in @@ -224,7 +224,7 @@ $(BUILD)/%_gen.c $(HEADER_BUILD)/%.h $(HEADER_BUILD)/%_af_const.h $(BUILD)/%_qst $(ECHO) "Create $@" $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) --qstr $(GEN_PINS_QSTR) --af-const $(GEN_PINS_AF_CONST) --af-py $(GEN_PINS_AF_PY) > $(GEN_PINS_SRC) -$(BUILD)/pins_gen.o: $(BUILD)/pins_gen.c +$(GEN_PINS_SRC:.c=.o): $(GEN_PINS_SRC) $(call compile_c) $(BUILD)/%.pp: $(BUILD)/%.c From 3cc6decfc4d6b459014940ae01f90d4f1fae0da6 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 8 Oct 2022 23:28:24 +1100 Subject: [PATCH 0535/1041] py/py.mk: Make user-C-module handling self-contained in py.mk. Removes the need for the port to add anything to OBJS or SRC_QSTR. Also makes it possible for user-C-modules to differentiate between code that should be processed for QSTR vs other files (e.g. helpers and libraries). Signed-off-by: Jim Mussared --- docs/develop/cmodules.rst | 14 +++++++++++--- ports/samd/Makefile | 3 ++- ports/stm32/Makefile | 3 ++- py/py.mk | 34 ++++++++++++++++++++++++++++------ 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/docs/develop/cmodules.rst b/docs/develop/cmodules.rst index 143057f7f1..1b3ba04da4 100644 --- a/docs/develop/cmodules.rst +++ b/docs/develop/cmodules.rst @@ -49,9 +49,17 @@ A MicroPython user C module is a directory with the following files: in your ``micropython.mk`` to a local make variable, eg ``EXAMPLE_MOD_DIR := $(USERMOD_DIR)`` - Your ``micropython.mk`` must add your modules source files relative to your - expanded copy of ``$(USERMOD_DIR)`` to ``SRC_USERMOD``, eg - ``SRC_USERMOD += $(EXAMPLE_MOD_DIR)/example.c`` + Your ``micropython.mk`` must add your modules source files to the + ``SRC_USERMOD_C`` or ``SRC_USERMOD_LIB_C`` variables. The former will be + processed for ``MP_QSTR_`` and ``MP_REGISTER_MODULE`` definitions, the latter + will not (e.g. helpers and library code that isn't MicroPython-specific). + These paths should include your expaned copy of ``$(USERMOD_DIR)``, e.g.:: + + SRC_USERMOD_C += $(EXAMPLE_MOD_DIR)/modexample.c + SRC_USERMOD_LIB_C += $(EXAMPLE_MOD_DIR)/utils/algorithm.c + + Similarly, use ``SRC_USERMOD_CXX`` and ``SRC_USERMOD_LIB_CXX`` for C++ + source files. If you have custom compiler options (like ``-I`` to add directories to search for header files), these should be added to ``CFLAGS_USERMOD`` for C code diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 735d25bf27..9386a8dacc 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -81,7 +81,8 @@ endif # Flags for optional C++ source code CXXFLAGS += $(filter-out -std=c99,$(CFLAGS)) CXXFLAGS += $(CXXFLAGS_MOD) -ifneq ($(SRC_CXX)$(SRC_MOD_CXX),) +# TODO make this common -- shouldn't be using these "private" vars from py.mk +ifneq ($(SRC_CXX)$(SRC_USERMOD_CXX)$(SRC_USERMOD_LIB_CXX),) LIBSTDCPP_FILE_NAME = "$(shell $(CXX) $(CXXFLAGS) -print-file-name=libstdc++.a)" LDFLAGS += -L"$(shell dirname $(LIBSTDCPP_FILE_NAME))" endif diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 403b68b240..4e594d19ff 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -157,7 +157,8 @@ endif # Flags for optional C++ source code CXXFLAGS += $(filter-out -Wmissing-prototypes -Wold-style-definition -std=gnu99,$(CFLAGS)) CXXFLAGS += $(CXXFLAGS_MOD) -ifneq ($(SRC_CXX)$(SRC_MOD_CXX),) +# TODO make this common -- shouldn't be using these "private" vars from py.mk +ifneq ($(SRC_CXX)$(SRC_USERMOD_CXX)$(SRC_USERMOD_LIB_CXX),) LIBSTDCPP_FILE_NAME = "$(shell $(CXX) $(CXXFLAGS) -print-file-name=libstdc++.a)" LDFLAGS += -L"$(shell dirname $(LIBSTDCPP_FILE_NAME))" endif diff --git a/py/py.mk b/py/py.mk index 8aac460b47..ec69ca42d9 100644 --- a/py/py.mk +++ b/py/py.mk @@ -32,22 +32,44 @@ endif ifneq ($(USER_C_MODULES),) # pre-define USERMOD variables as expanded so that variables are immediate # expanded as they're added to them -SRC_USERMOD := + +# C/C++ files that are included in the QSTR/module build +SRC_USERMOD_C := SRC_USERMOD_CXX := +# Other C/C++ files (e.g. libraries or helpers) +SRC_USERMOD_LIB_C := +SRC_USERMOD_LIB_CXX := +# Optionally set flags CFLAGS_USERMOD := CXXFLAGS_USERMOD := LDFLAGS_USERMOD := + +# Backwards compatibility with older user c modules that set SRC_USERMOD +# added to SRC_USERMOD_C below +SRC_USERMOD := + $(foreach module, $(wildcard $(USER_C_MODULES)/*/micropython.mk), \ $(eval USERMOD_DIR = $(patsubst %/,%,$(dir $(module))))\ $(info Including User C Module from $(USERMOD_DIR))\ $(eval include $(module))\ ) -SRC_MOD += $(patsubst $(USER_C_MODULES)/%.c,%.c,$(SRC_USERMOD)) -SRC_MOD_CXX += $(patsubst $(USER_C_MODULES)/%.cpp,%.cpp,$(SRC_USERMOD_CXX)) -CFLAGS_MOD += $(CFLAGS_USERMOD) -CXXFLAGS_MOD += $(CXXFLAGS_USERMOD) -LDFLAGS_MOD += $(LDFLAGS_USERMOD) +SRC_USERMOD_C += $(SRC_USERMOD) + +SRC_USERMOD_PATHFIX_C += $(patsubst $(USER_C_MODULES)/%.c,%.c,$(SRC_USERMOD_C)) +SRC_USERMOD_PATHFIX_CXX += $(patsubst $(USER_C_MODULES)/%.cpp,%.cpp,$(SRC_USERMOD_CXX)) +SRC_USERMOD_PATHFIX_LIB_C += $(patsubst $(USER_C_MODULES)/%.c,%.c,$(SRC_USERMOD_LIB_C)) +SRC_USERMOD_PATHFIX_LIB_CXX += $(patsubst $(USER_C_MODULES)/%.cpp,%.cpp,$(SRC_USERMOD_LIB_CXX)) + +CFLAGS += $(CFLAGS_USERMOD) +CXXFLAGS += $(CXXFLAGS_USERMOD) +LDFLAGS += $(LDFLAGS_USERMOD) + +SRC_QSTR += $(SRC_USERMOD_PATHFIX_C) $(SRC_USERMOD_PATHFIX_CXX) +PY_O += $(addprefix $(BUILD)/, $(SRC_USERMOD_PATHFIX_C:.c=.o)) +PY_O += $(addprefix $(BUILD)/, $(SRC_USERMOD_PATHFIX_CXX:.cpp=.o)) +PY_O += $(addprefix $(BUILD)/, $(SRC_USERMOD_PATHFIX_LIB_C:.c=.o)) +PY_O += $(addprefix $(BUILD)/, $(SRC_USERMOD_PATHFIX_LIB_CXX:.cpp=.o)) endif # py object files From 065af04a4e86aa5bdbdedb89140241e5d0030ffb Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 8 Oct 2022 23:38:18 +1100 Subject: [PATCH 0536/1041] unix/Makefile: Don't use _MOD variable names. This conflicts with the triple-usage of these variables for user-C-modules and extmod source. For CFLAGS_MOD, just use CFLAGS directly. For SRC, use SRC_C directly as the relevant files are all guarded by the preprocessor anyway. Signed-off-by: Jim Mussared --- ports/unix/Makefile | 46 ++++++++++++++++++++++----------------------- ports/unix/modjni.c | 10 +++++----- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 709cc79853..e234621346 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -110,27 +110,25 @@ ifeq ($(MICROPY_FORCE_32BIT),1) # starting with linux-libc-dev:i386 ifeq ($(MICROPY_PY_FFI),1) ifeq ($(UNAME_S),Linux) -CFLAGS_MOD += -I/usr/include/i686-linux-gnu +CFLAGS += -I/usr/include/i686-linux-gnu endif endif endif ifeq ($(MICROPY_USE_READLINE),1) INC += -I$(TOP)/shared/readline -CFLAGS_MOD += -DMICROPY_USE_READLINE=1 +CFLAGS += -DMICROPY_USE_READLINE=1 SHARED_SRC_C_EXTRA += readline/readline.c endif ifeq ($(MICROPY_PY_TERMIOS),1) -CFLAGS_MOD += -DMICROPY_PY_TERMIOS=1 -SRC_MOD += modtermios.c +CFLAGS += -DMICROPY_PY_TERMIOS=1 endif ifeq ($(MICROPY_PY_SOCKET),1) -CFLAGS_MOD += -DMICROPY_PY_SOCKET=1 -SRC_MOD += modusocket.c +CFLAGS += -DMICROPY_PY_SOCKET=1 endif ifeq ($(MICROPY_PY_THREAD),1) -CFLAGS_MOD += -DMICROPY_PY_THREAD=1 -DMICROPY_PY_THREAD_GIL=0 -LDFLAGS_MOD += $(LIBPTHREAD) +CFLAGS += -DMICROPY_PY_THREAD=1 -DMICROPY_PY_THREAD_GIL=0 +LDFLAGS += $(LIBPTHREAD) endif ifeq ($(MICROPY_PY_USSL),1) @@ -139,7 +137,7 @@ GIT_SUBMODULES += lib/axtls endif ifeq ($(MICROPY_SSL_MBEDTLS),1) GIT_SUBMODULES += lib/mbedtls -CFLAGS_MOD += -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' +CFLAGS += -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' endif endif @@ -163,8 +161,8 @@ MICROPY_BLUETOOTH_BTSTACK ?= 1 endif endif -CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH=1 -CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1 +CFLAGS += -DMICROPY_PY_BLUETOOTH=1 +CFLAGS += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1 ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) @@ -192,7 +190,7 @@ else # NimBLE is enabled. GIT_SUBMODULES += lib/mynewt-nimble -CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS=1 +CFLAGS += -DMICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS=1 include $(TOP)/extmod/nimble/nimble.mk endif @@ -205,31 +203,29 @@ ifeq ($(MICROPY_STANDALONE),1) # Build libffi from source. GIT_SUBMODULES += lib/libffi DEPLIBS += libffi -LIBFFI_CFLAGS_MOD := -I$(shell ls -1d $(BUILD)/lib/libffi/out/lib/libffi-*/include) +LIBFFI_CFLAGS := -I$(shell ls -1d $(BUILD)/lib/libffi/out/lib/libffi-*/include) ifeq ($(MICROPY_FORCE_32BIT),1) - LIBFFI_LDFLAGS_MOD = $(BUILD)/lib/libffi/out/lib32/libffi.a + LIBFFI_LDFLAGS = $(BUILD)/lib/libffi/out/lib32/libffi.a else - LIBFFI_LDFLAGS_MOD = $(BUILD)/lib/libffi/out/lib/libffi.a + LIBFFI_LDFLAGS = $(BUILD)/lib/libffi/out/lib/libffi.a endif else # Use system version of libffi. -LIBFFI_CFLAGS_MOD := $(shell pkg-config --cflags libffi) -LIBFFI_LDFLAGS_MOD := $(shell pkg-config --libs libffi) +LIBFFI_CFLAGS := $(shell pkg-config --cflags libffi) +LIBFFI_LDFLAGS := $(shell pkg-config --libs libffi) endif ifeq ($(UNAME_S),Linux) -LIBFFI_LDFLAGS_MOD += -ldl +LIBFFI_LDFLAGS += -ldl endif -CFLAGS_MOD += $(LIBFFI_CFLAGS_MOD) -DMICROPY_PY_FFI=1 -LDFLAGS_MOD += $(LIBFFI_LDFLAGS_MOD) -SRC_MOD += modffi.c +CFLAGS += $(LIBFFI_CFLAGS) -DMICROPY_PY_FFI=1 +LDFLAGS += $(LIBFFI_LDFLAGS) endif ifeq ($(MICROPY_PY_JNI),1) # Path for 64-bit OpenJDK, should be adjusted for other JDKs -CFLAGS_MOD += -I/usr/lib/jvm/java-7-openjdk-amd64/include -DMICROPY_PY_JNI=1 -SRC_MOD += modjni.c +CFLAGS += -I/usr/lib/jvm/java-7-openjdk-amd64/include -DMICROPY_PY_JNI=1 endif # source files @@ -250,6 +246,10 @@ SRC_C += \ mpbtstackport_usb.c \ mpnimbleport.c \ $(SRC_MOD) \ + modtermios.c \ + modusocket.c \ + modffi.c \ + modjni.c \ $(wildcard $(VARIANT_DIR)/*.c) SHARED_SRC_C += $(addprefix shared/,\ diff --git a/ports/unix/modjni.c b/ports/unix/modjni.c index 5988876f88..10622f588f 100644 --- a/ports/unix/modjni.c +++ b/ports/unix/modjni.c @@ -24,19 +24,19 @@ * THE SOFTWARE. */ +#include "py/runtime.h" +#include "py/binary.h" + +#if MICROPY_PY_JNI + #include #include #include #include #include -#include "py/runtime.h" -#include "py/binary.h" - #include -#if MICROPY_PY_JNI - #define JJ(call, ...) (*env)->call(env, __VA_ARGS__) #define JJ1(call) (*env)->call(env) #define MATCH(s, static) (!strncmp(s, static, sizeof(static) - 1)) From 87011f63530f55411843622af8b1bc2dbf98a6f7 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 8 Oct 2022 23:47:57 +1100 Subject: [PATCH 0537/1041] extmod/extmod.mk: Make extmod.mk handle GIT_SUBMODULES. This applies to nimble, btstack, axtls, mbedtls, lwip. Rather than having the ports individually manage GIT_SUBMODULES for these components, make extmod.mk append them when the relevant feature is enabled. Signed-off-by: Jim Mussared --- extmod/btstack/btstack.mk | 1 + extmod/extmod.mk | 4 +++- extmod/nimble/nimble.mk | 2 ++ ports/mimxrt/Makefile | 2 +- ports/stm32/Makefile | 4 +--- ports/unix/Makefile | 5 +---- tools/ci.sh | 6 ++++-- 7 files changed, 13 insertions(+), 11 deletions(-) diff --git a/extmod/btstack/btstack.mk b/extmod/btstack/btstack.mk index 7ecc230003..14b8d08bf1 100644 --- a/extmod/btstack/btstack.mk +++ b/extmod/btstack/btstack.mk @@ -2,6 +2,7 @@ ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) +GIT_SUBMODULES += lib/btstack MICROPY_BLUETOOTH_BTSTACK_USB ?= 0 BTSTACK_EXTMOD_DIR = extmod/btstack diff --git a/extmod/extmod.mk b/extmod/extmod.mk index ae3e45bd55..bd89719917 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -100,6 +100,7 @@ CFLAGS_MOD += -DMICROPY_PY_USSL=1 ifeq ($(MICROPY_SSL_AXTLS),1) CFLAGS_MOD += -DMICROPY_SSL_AXTLS=1 -I$(TOP)/lib/axtls/ssl -I$(TOP)/lib/axtls/crypto -I$(TOP)/extmod/axtls-include AXTLS_DIR = lib/axtls +GIT_SUBMODULES += $(AXTLS_DIR) $(BUILD)/$(AXTLS_DIR)/%.o: CFLAGS += -Wno-all -Wno-unused-parameter -Wno-uninitialized -Wno-sign-compare -Wno-old-style-definition -Dmp_stream_errno=errno $(AXTLS_DEFS_EXTRA) SRC_MOD += $(addprefix $(AXTLS_DIR)/,\ ssl/asn1.c \ @@ -118,7 +119,7 @@ SRC_MOD += $(addprefix $(AXTLS_DIR)/,\ ) else ifeq ($(MICROPY_SSL_MBEDTLS),1) MBEDTLS_DIR = lib/mbedtls -CFLAGS_MOD += -DMICROPY_SSL_MBEDTLS=1 -I$(TOP)/$(MBEDTLS_DIR)/include +GIT_SUBMODULES += $(MBEDTLS_DIR) SRC_MOD += lib/mbedtls_errors/mp_mbedtls_errors.c SRC_MOD += $(addprefix $(MBEDTLS_DIR)/library/,\ aes.c \ @@ -199,6 +200,7 @@ endif # lwip ifeq ($(MICROPY_PY_LWIP),1) +GIT_SUBMODULES += lib/lwip # A port should add an include path where lwipopts.h can be found (eg extmod/lwip-include) LWIP_DIR = lib/lwip/src INC += -I$(TOP)/$(LWIP_DIR)/include diff --git a/extmod/nimble/nimble.mk b/extmod/nimble/nimble.mk index 806630074e..e825261eea 100644 --- a/extmod/nimble/nimble.mk +++ b/extmod/nimble/nimble.mk @@ -17,6 +17,8 @@ CFLAGS_MOD += -DMICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY=$(MICROPY_BLUETOOTH_NIMBL ifeq ($(MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY),0) +GIT_SUBMODULES += lib/mynewt-nimble + # On all ports where we provide the full implementation (i.e. not just # bindings like on ESP32), then we don't need to use the ringbuffer. In this # case, all NimBLE events are run by the MicroPython scheduler. On Unix, the diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index 6095f5fd23..b8b08cb011 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -7,7 +7,7 @@ BOARD_DIR ?= boards/$(BOARD) BUILD ?= build-$(BOARD) PORT ?= /dev/ttyACM0 CROSS_COMPILE ?= arm-none-eabi- -GIT_SUBMODULES += lib/tinyusb lib/nxp_driver lib/lwip lib/mbedtls +GIT_SUBMODULES += lib/tinyusb lib/nxp_driver # MicroPython feature configurations FROZEN_MANIFEST ?= boards/manifest.py diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 4e594d19ff..8b503112ae 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -35,7 +35,7 @@ MBOOT_TEXT0_ADDR ?= 0x08000000 include $(TOP)/py/py.mk include $(TOP)/extmod/extmod.mk -GIT_SUBMODULES += lib/libhydrogen lib/lwip lib/mbedtls lib/stm32lib +GIT_SUBMODULES += lib/libhydrogen lib/stm32lib query-variants: $(ECHO) "VARIANTS:" $(BOARD_VARIANTS) @@ -531,14 +531,12 @@ endif endif ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) -GIT_SUBMODULES += lib/mynewt-nimble CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS=1 include $(TOP)/extmod/nimble/nimble.mk SRC_C += mpnimbleport.c endif ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) -GIT_SUBMODULES += lib/btstack MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1 include $(TOP)/extmod/btstack/btstack.mk SRC_C += mpbtstackport.c diff --git a/ports/unix/Makefile b/ports/unix/Makefile index e234621346..facdab2e04 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -133,10 +133,9 @@ endif ifeq ($(MICROPY_PY_USSL),1) ifeq ($(MICROPY_SSL_AXTLS),1) -GIT_SUBMODULES += lib/axtls + endif ifeq ($(MICROPY_SSL_MBEDTLS),1) -GIT_SUBMODULES += lib/mbedtls CFLAGS += -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' endif endif @@ -182,14 +181,12 @@ endif endif # BTstack is enabled. -GIT_SUBMODULES += lib/btstack include $(TOP)/extmod/btstack/btstack.mk SRC_BTSTACK += lib/btstack/platform/embedded/btstack_run_loop_embedded.c else # NimBLE is enabled. -GIT_SUBMODULES += lib/mynewt-nimble CFLAGS += -DMICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS=1 include $(TOP)/extmod/nimble/nimble.mk diff --git a/tools/ci.sh b/tools/ci.sh index 9963f7796c..86fd44fdfb 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -198,8 +198,9 @@ function ci_mimxrt_setup { function ci_mimxrt_build { make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/mimxrt submodules + make ${MAKEOPTS} -C ports/mimxrt BOARD=MIMXRT1020_EVK submodules make ${MAKEOPTS} -C ports/mimxrt BOARD=MIMXRT1020_EVK + make ${MAKEOPTS} -C ports/mimxrt BOARD=TEENSY40 submodules make ${MAKEOPTS} -C ports/mimxrt BOARD=TEENSY40 } @@ -310,6 +311,7 @@ function ci_stm32_setup { function ci_stm32_pyb_build { make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/stm32 MICROPY_PY_NETWORK_WIZNET5K=5200 submodules + make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF2 submodules git submodule update --init lib/btstack git submodule update --init lib/mynewt-nimble make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_NETWORK_WIZNET5K=5200 USER_C_MODULES=../../examples/usercmodule @@ -326,7 +328,7 @@ function ci_stm32_pyb_build { function ci_stm32_nucleo_build { make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/stm32 submodules + make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_H743ZI submodules git submodule update --init lib/mynewt-nimble # Test building various MCU families, some with additional options. From d6d87225585a9494093d791c807bce652e4c82d8 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 8 Oct 2022 23:59:08 +1100 Subject: [PATCH 0538/1041] extmod: Make extmod.mk self-contained. This makes it so that all a port needs to do is set the relevant variables and "include extmod.mk" and doesn't need to worry about adding anything to OBJ, CFLAGS, SRC_QSTR, etc. Make all extmod variables (src, flags, etc) private to extmod.mk. Also move common/shared, extmod-related fragments (e.g. wiznet, cyw43, bluetooth) into extmod.mk. Now that SRC_MOD, CFLAGS_MOD, CXXFLAGS_MOD are unused by both extmod.mk (and user-C-modules in a previous commit), remove all uses of them from port makefiles. Signed-off-by: Jim Mussared --- extmod/btstack/btstack.mk | 38 +++-- extmod/extmod.mk | 208 ++++++++++++++++++--------- extmod/network_wiznet5k.c | 5 +- extmod/nimble/nimble.mk | 14 +- mpy-cross/Makefile | 2 +- ports/cc3200/Makefile | 1 - ports/esp8266/Makefile | 13 +- ports/mimxrt/Makefile | 17 +-- ports/minimal/Makefile | 13 +- ports/nrf/Makefile | 11 +- ports/renesas-ra/Makefile | 18 +-- ports/samd/Makefile | 23 ++- ports/samd/mcu/samd51/mpconfigmcu.mk | 2 +- ports/stm32/Makefile | 67 +-------- ports/stm32/mboot/Makefile | 2 +- ports/stm32/mpconfigport.h | 8 ++ ports/teensy/Makefile | 5 +- ports/unix/Makefile | 50 +------ ports/unix/mpconfigport.h | 8 ++ ports/windows/Makefile | 13 +- py/py.mk | 2 +- 21 files changed, 236 insertions(+), 284 deletions(-) diff --git a/extmod/btstack/btstack.mk b/extmod/btstack/btstack.mk index 14b8d08bf1..ca95931562 100644 --- a/extmod/btstack/btstack.mk +++ b/extmod/btstack/btstack.mk @@ -3,17 +3,19 @@ ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) GIT_SUBMODULES += lib/btstack + MICROPY_BLUETOOTH_BTSTACK_USB ?= 0 +MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1 BTSTACK_EXTMOD_DIR = extmod/btstack -EXTMOD_SRC_C += extmod/btstack/modbluetooth_btstack.c +SRC_EXTMOD_C += $(BTSTACK_EXTMOD_DIR)/modbluetooth_btstack.c INC += -I$(TOP)/$(BTSTACK_EXTMOD_DIR) -CFLAGS_MOD += -DMICROPY_BLUETOOTH_BTSTACK=1 -CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS=1 -CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING=1 +CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_BTSTACK=1 +CFLAGS_EXTMOD += -DMICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS=1 +CFLAGS_EXTMOD += -DMICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING=1 BTSTACK_DIR = $(TOP)/lib/btstack @@ -28,44 +30,50 @@ INC += -I$(BTSTACK_DIR)/3rd-party/bluedroid/encoder/include INC += -I$(BTSTACK_DIR)/3rd-party/md5 INC += -I$(BTSTACK_DIR)/3rd-party/yxml -SRC_BTSTACK = \ +SRC_BTSTACK_C = \ $(addprefix lib/btstack/src/, $(SRC_FILES)) \ $(addprefix lib/btstack/src/ble/, $(filter-out %_tlv.c, $(SRC_BLE_FILES))) \ ifeq ($(MICROPY_BLUETOOTH_BTSTACK_USB),1) ifeq ($(MICROPY_BLUETOOTH_BTSTACK_H4),1) - $(error Cannot specifiy both MICROPY_BLUETOOTH_BTSTACK_USB and MICROPY_BLUETOOTH_BTSTACK_H4) + $(error Cannot enable both MICROPY_BLUETOOTH_BTSTACK_USB and MICROPY_BLUETOOTH_BTSTACK_H4) +endif +endif + +ifneq ($(MICROPY_BLUETOOTH_BTSTACK_USB),1) +ifneq ($(MICROPY_BLUETOOTH_BTSTACK_H4),1) + $(error Must enable one of MICROPY_BLUETOOTH_BTSTACK_USB or MICROPY_BLUETOOTH_BTSTACK_H4) endif endif ifeq ($(MICROPY_BLUETOOTH_BTSTACK_USB),1) -SRC_BTSTACK += \ +SRC_BTSTACK_C += \ lib/btstack/platform/libusb/hci_transport_h2_libusb.c -CFLAGS_MOD += -DMICROPY_BLUETOOTH_BTSTACK_USB=1 +CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_BTSTACK_USB=1 -CFLAGS += $(shell pkg-config libusb-1.0 --cflags) -LDFLAGS += $(shell pkg-config libusb-1.0 --libs) +CFLAGS_THIRDPARTY += $(shell pkg-config libusb-1.0 --cflags) +LDFLAGS_THIRDPARTY += $(shell pkg-config libusb-1.0 --libs) endif ifeq ($(MICROPY_BLUETOOTH_BTSTACK_H4),1) -SRC_BTSTACK += \ +SRC_BTSTACK_C += \ lib/btstack/src/hci_transport_h4.c \ lib/btstack/chipset/zephyr/btstack_chipset_zephyr.c -EXTMOD_SRC_C += \ +SRC_BTSTACK_C += \ extmod/btstack/btstack_hci_uart.c \ -CFLAGS_MOD += -DMICROPY_BLUETOOTH_BTSTACK_H4=1 +CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_BTSTACK_H4=1 endif ifeq ($(MICROPY_BLUETOOTH_BTSTACK_ENABLE_CLASSIC),1) include $(BTSTACK_DIR)/src/classic/Makefile.inc -SRC_BTSTACK += \ +SRC_BTSTACK_C += \ $(addprefix lib/btstack/src/classic/, $(SRC_CLASSIC_FILES)) endif -LIB_SRC_C += $(SRC_BTSTACK) +SRC_THIRDPARTY_C += $(SRC_BTSTACK_C) # Suppress some warnings. BTSTACK_WARNING_CFLAGS = -Wno-old-style-definition -Wno-unused-variable -Wno-unused-parameter -Wno-implicit-fallthrough diff --git a/extmod/extmod.mk b/extmod/extmod.mk index bd89719917..3b10fc857c 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -1,55 +1,66 @@ # This makefile fragment adds the source code files for the core extmod modules # and provides rules to build 3rd-party components for extmod modules. -PY_EXTMOD_O_BASENAME = \ - extmod/moduasyncio.o \ - extmod/moductypes.o \ - extmod/modujson.o \ - extmod/moduos.o \ - extmod/modure.o \ - extmod/moduzlib.o \ - extmod/moduheapq.o \ - extmod/modutimeq.o \ - extmod/moduhashlib.o \ - extmod/moducryptolib.o \ - extmod/modubinascii.o \ - extmod/virtpin.o \ - extmod/machine_bitstream.o \ - extmod/machine_mem.o \ - extmod/machine_pinbase.o \ - extmod/machine_signal.o \ - extmod/machine_pulse.o \ - extmod/machine_pwm.o \ - extmod/machine_i2c.o \ - extmod/machine_spi.o \ - extmod/modbluetooth.o \ - extmod/modlwip.o \ - extmod/modussl_axtls.o \ - extmod/modussl_mbedtls.o \ - extmod/moduplatform.o\ - extmod/modurandom.o \ - extmod/moduselect.o \ - extmod/moduwebsocket.o \ - extmod/modwebrepl.o \ - extmod/modframebuf.o \ - extmod/vfs.o \ - extmod/vfs_blockdev.o \ - extmod/vfs_reader.o \ - extmod/vfs_posix.o \ - extmod/vfs_posix_file.o \ - extmod/vfs_fat.o \ - extmod/vfs_fat_diskio.o \ - extmod/vfs_fat_file.o \ - extmod/vfs_lfs.o \ - extmod/utime_mphal.o \ - extmod/uos_dupterm.o \ - shared/libc/abort_.o \ - shared/libc/printf.o \ +SRC_EXTMOD_C += \ + extmod/machine_bitstream.c \ + extmod/machine_i2c.c \ + extmod/machine_mem.c \ + extmod/machine_pinbase.c \ + extmod/machine_pulse.c \ + extmod/machine_pwm.c \ + extmod/machine_signal.c \ + extmod/machine_spi.c \ + extmod/modbluetooth.c \ + extmod/modbtree.c \ + extmod/modframebuf.c \ + extmod/modlwip.c \ + extmod/modnetwork.c \ + extmod/modonewire.c \ + extmod/moduasyncio.c \ + extmod/modubinascii.c \ + extmod/moducryptolib.c \ + extmod/moductypes.c \ + extmod/moduhashlib.c \ + extmod/moduheapq.c \ + extmod/modujson.c \ + extmod/moduos.c \ + extmod/moduplatform.c\ + extmod/modurandom.c \ + extmod/modure.c \ + extmod/moduselect.c \ + extmod/modusocket.c \ + extmod/modussl_axtls.c \ + extmod/modussl_mbedtls.c \ + extmod/modutimeq.c \ + extmod/moduwebsocket.c \ + extmod/moduzlib.c \ + extmod/modwebrepl.c \ + extmod/network_cyw43.c \ + extmod/network_ninaw10.c \ + extmod/network_wiznet5k.c \ + extmod/uos_dupterm.c \ + extmod/utime_mphal.c \ + extmod/vfs.c \ + extmod/vfs_blockdev.c \ + extmod/vfs_fat.c \ + extmod/vfs_fat_diskio.c \ + extmod/vfs_fat_file.c \ + extmod/vfs_lfs.c \ + extmod/vfs_posix.c \ + extmod/vfs_posix_file.c \ + extmod/vfs_reader.c \ + extmod/virtpin.c \ + shared/libc/abort_.c \ + shared/libc/printf.c \ -PY_EXTMOD_O = $(addprefix $(BUILD)/, $(PY_EXTMOD_O_BASENAME)) +SRC_THIRDPARTY_C += \ -PY_O += $(PY_EXTMOD_O) -SRC_QSTR += $(PY_EXTMOD_O_BASENAME:.o=.c) +PY_O += $(addprefix $(BUILD)/, $(SRC_EXTMOD_C:.c=.o)) +PY_O += $(addprefix $(BUILD)/, $(SRC_THIRDPARTY_C:.c=.o)) +SRC_QSTR += $(SRC_EXTMOD_C) + +CFLAGS += $(CFLAGS_EXTMOD) $(CFLAGS_THIRDPARTY) +LDFLAGS += $(LDFLAGS_EXTMOD) $(LDFLAGS_THIRDPARTY) ################################################################################ # VFS FAT FS @@ -57,11 +68,11 @@ SRC_QSTR += $(PY_EXTMOD_O_BASENAME:.o=.c) OOFATFS_DIR = lib/oofatfs # this sets the config file for FatFs -CFLAGS_MOD += -DFFCONF_H=\"$(OOFATFS_DIR)/ffconf.h\" +CFLAGS_THIRDPARTY += -DFFCONF_H=\"$(OOFATFS_DIR)/ffconf.h\" ifeq ($(MICROPY_VFS_FAT),1) -CFLAGS_MOD += -DMICROPY_VFS_FAT=1 -SRC_MOD += $(addprefix $(OOFATFS_DIR)/,\ +CFLAGS_EXTMOD += -DMICROPY_VFS_FAT=1 +SRC_THIRDPARTY_C += $(addprefix $(OOFATFS_DIR)/,\ ff.c \ ffunicode.c \ ) @@ -73,18 +84,18 @@ endif LITTLEFS_DIR = lib/littlefs ifeq ($(MICROPY_VFS_LFS1),1) -CFLAGS_MOD += -DMICROPY_VFS_LFS1=1 -CFLAGS_MOD += -DLFS1_NO_MALLOC -DLFS1_NO_DEBUG -DLFS1_NO_WARN -DLFS1_NO_ERROR -DLFS1_NO_ASSERT -SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\ +CFLAGS_EXTMOD += -DMICROPY_VFS_LFS1=1 +CFLAGS_THIRDPARTY += -DLFS1_NO_MALLOC -DLFS1_NO_DEBUG -DLFS1_NO_WARN -DLFS1_NO_ERROR -DLFS1_NO_ASSERT +SRC_THIRDPARTY_C += $(addprefix $(LITTLEFS_DIR)/,\ lfs1.c \ lfs1_util.c \ ) endif ifeq ($(MICROPY_VFS_LFS2),1) -CFLAGS_MOD += -DMICROPY_VFS_LFS2=1 -CFLAGS_MOD += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT -SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\ +CFLAGS_EXTMOD += -DMICROPY_VFS_LFS2=1 +CFLAGS_THIRDPARTY += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT +SRC_THIRDPARTY_C += $(addprefix $(LITTLEFS_DIR)/,\ lfs2.c \ lfs2_util.c \ ) @@ -96,13 +107,13 @@ endif # ussl ifeq ($(MICROPY_PY_USSL),1) -CFLAGS_MOD += -DMICROPY_PY_USSL=1 +CFLAGS_EXTMOD += -DMICROPY_PY_USSL=1 ifeq ($(MICROPY_SSL_AXTLS),1) -CFLAGS_MOD += -DMICROPY_SSL_AXTLS=1 -I$(TOP)/lib/axtls/ssl -I$(TOP)/lib/axtls/crypto -I$(TOP)/extmod/axtls-include AXTLS_DIR = lib/axtls GIT_SUBMODULES += $(AXTLS_DIR) +CFLAGS_EXTMOD += -DMICROPY_SSL_AXTLS=1 -I$(TOP)/lib/axtls/ssl -I$(TOP)/lib/axtls/crypto -I$(TOP)/extmod/axtls-include $(BUILD)/$(AXTLS_DIR)/%.o: CFLAGS += -Wno-all -Wno-unused-parameter -Wno-uninitialized -Wno-sign-compare -Wno-old-style-definition -Dmp_stream_errno=errno $(AXTLS_DEFS_EXTRA) -SRC_MOD += $(addprefix $(AXTLS_DIR)/,\ +SRC_THIRDPARTY_C += $(addprefix $(AXTLS_DIR)/,\ ssl/asn1.c \ ssl/loader.c \ ssl/tls1.c \ @@ -120,8 +131,9 @@ SRC_MOD += $(addprefix $(AXTLS_DIR)/,\ else ifeq ($(MICROPY_SSL_MBEDTLS),1) MBEDTLS_DIR = lib/mbedtls GIT_SUBMODULES += $(MBEDTLS_DIR) -SRC_MOD += lib/mbedtls_errors/mp_mbedtls_errors.c -SRC_MOD += $(addprefix $(MBEDTLS_DIR)/library/,\ +CFLAGS_EXTMOD += -DMICROPY_SSL_MBEDTLS=1 -I$(TOP)/$(MBEDTLS_DIR)/include +SRC_THIRDPARTY_C += lib/mbedtls_errors/mp_mbedtls_errors.c +SRC_THIRDPARTY_C += $(addprefix $(MBEDTLS_DIR)/library/,\ aes.c \ aesni.c \ arc4.c \ @@ -204,10 +216,10 @@ GIT_SUBMODULES += lib/lwip # A port should add an include path where lwipopts.h can be found (eg extmod/lwip-include) LWIP_DIR = lib/lwip/src INC += -I$(TOP)/$(LWIP_DIR)/include -CFLAGS_MOD += -DMICROPY_PY_LWIP=1 -$(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS_MOD += -Wno-address -SRC_MOD += shared/netutils/netutils.c -SRC_MOD += $(addprefix $(LWIP_DIR)/,\ +CFLAGS_EXTMOD += -DMICROPY_PY_LWIP=1 +$(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS += -Wno-address +SRC_THIRDPARTY_C += shared/netutils/netutils.c +SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\ apps/mdns/mdns.c \ core/def.c \ core/dns.c \ @@ -246,8 +258,8 @@ SRC_MOD += $(addprefix $(LWIP_DIR)/,\ netif/ethernet.c \ ) ifeq ($(MICROPY_PY_LWIP_SLIP),1) -CFLAGS_MOD += -DMICROPY_PY_LWIP_SLIP=1 -SRC_MOD += $(LWIP_DIR)/netif/slipif.c +CFLAGS_EXTMOD += -DMICROPY_PY_LWIP_SLIP=1 +SRC_THIRDPARTY_C += $(LWIP_DIR)/netif/slipif.c endif endif @@ -258,8 +270,7 @@ ifeq ($(MICROPY_PY_BTREE),1) BTREE_DIR = lib/berkeley-db-1.xx BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error=printf -Dabort=abort_ "-Dvirt_fd_t=void*" $(BTREE_DEFS_EXTRA) INC += -I$(TOP)/$(BTREE_DIR)/PORT/include -SRC_MOD += extmod/modbtree.c -SRC_MOD += $(addprefix $(BTREE_DIR)/,\ +SRC_THIRDPARTY_C += $(addprefix $(BTREE_DIR)/,\ btree/bt_close.c \ btree/bt_conv.c \ btree/bt_debug.c \ @@ -275,10 +286,67 @@ SRC_MOD += $(addprefix $(BTREE_DIR)/,\ btree/bt_utils.c \ mpool/mpool.c \ ) -CFLAGS_MOD += -DMICROPY_PY_BTREE=1 +CFLAGS_EXTMOD += -DMICROPY_PY_BTREE=1 # we need to suppress certain warnings to get berkeley-db to compile cleanly # and we have separate BTREE_DEFS so the definitions don't interfere with other source code $(BUILD)/$(BTREE_DIR)/%.o: CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS) $(BUILD)/extmod/modbtree.o: CFLAGS += $(BTREE_DEFS) endif +################################################################################ +# networking + +ifeq ($(MICROPY_PY_NETWORK_CYW43),1) +CFLAGS_EXTMOD += -DMICROPY_PY_NETWORK_CYW43=1 +DRIVERS_SRC_C += drivers/cyw43/cyw43_ctrl.c drivers/cyw43/cyw43_lwip.c +LIBS += $(TOP)/drivers/cyw43/libcyw43.a +endif + +ifneq ($(MICROPY_PY_NETWORK_WIZNET5K),) +ifneq ($(MICROPY_PY_NETWORK_WIZNET5K),0) +WIZNET5K_DIR=lib/wiznet5k +GIT_SUBMODULES += lib/wiznet5k +INC += -I$(TOP)/$(WIZNET5K_DIR) -I$(TOP)/$(WIZNET5K_DIR)/Ethernet +CFLAGS += -DMICROPY_PY_NETWORK_WIZNET5K=$(MICROPY_PY_NETWORK_WIZNET5K) -D_WIZCHIP_=$(MICROPY_PY_NETWORK_WIZNET5K) +CFLAGS_THIRDPARTY += -DWIZCHIP_PREFIXED_EXPORTS=1 +ifeq ($(MICROPY_PY_LWIP),1) +# When using MACRAW mode (with lwIP), maximum buffer space must be used for the raw socket +CFLAGS_THIRDPARTY += -DWIZCHIP_USE_MAX_BUFFER +endif +SRC_THIRDPARTY_C += $(addprefix $(WIZNET5K_DIR)/,\ + Ethernet/W$(MICROPY_PY_NETWORK_WIZNET5K)/w$(MICROPY_PY_NETWORK_WIZNET5K).c \ + Ethernet/wizchip_conf.c \ + Ethernet/socket.c \ + Internet/DNS/dns.c \ + Internet/DHCP/dhcp.c \ + ) +endif +endif + +################################################################################ +# bluetooth + +ifeq ($(MICROPY_PY_BLUETOOTH),1) +CFLAGS_EXTMOD += -DMICROPY_PY_BLUETOOTH=1 + +ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) +ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) +$(error Cannot enable both NimBLE and BTstack at the same time) +endif +endif + +ifneq ($(MICROPY_BLUETOOTH_NIMBLE),1) +ifneq ($(MICROPY_BLUETOOTH_BTSTACK),1) +$(error Must enable one of MICROPY_BLUETOOTH_NIMBLE or MICROPY_BLUETOOTH_BTSTACK) +endif +endif + +ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) +include $(TOP)/extmod/nimble/nimble.mk +endif + +ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) +include $(TOP)/extmod/btstack/btstack.mk +endif + +endif diff --git a/extmod/network_wiznet5k.c b/extmod/network_wiznet5k.c index af20145081..78cbff4ce2 100644 --- a/extmod/network_wiznet5k.c +++ b/extmod/network_wiznet5k.c @@ -33,6 +33,9 @@ #include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" + +#if MICROPY_PY_NETWORK_WIZNET5K + #include "shared/netutils/netutils.h" #include "extmod/modnetwork.h" #include "extmod/machine_spi.h" @@ -40,8 +43,6 @@ #include "modmachine.h" #include "drivers/bus/spi.h" -#if MICROPY_PY_NETWORK_WIZNET5K - #include "lib/wiznet5k/Ethernet/wizchip_conf.h" // The WIZNET5K module supports two usage modes: diff --git a/extmod/nimble/nimble.mk b/extmod/nimble/nimble.mk index e825261eea..fc1709f0e5 100644 --- a/extmod/nimble/nimble.mk +++ b/extmod/nimble/nimble.mk @@ -5,15 +5,15 @@ ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) EXTMOD_DIR = extmod NIMBLE_EXTMOD_DIR = $(EXTMOD_DIR)/nimble -EXTMOD_SRC_C += $(NIMBLE_EXTMOD_DIR)/modbluetooth_nimble.c +SRC_EXTMOD_C += $(NIMBLE_EXTMOD_DIR)/modbluetooth_nimble.c -CFLAGS_MOD += -DMICROPY_BLUETOOTH_NIMBLE=1 +CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_NIMBLE=1 # Use NimBLE from the submodule in lib/mynewt-nimble by default, # allowing a port to use their own system version (e.g. ESP32). MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY ?= 0 -CFLAGS_MOD += -DMICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY=$(MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY) +CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY=$(MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY) ifeq ($(MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY),0) @@ -24,16 +24,16 @@ GIT_SUBMODULES += lib/mynewt-nimble # case, all NimBLE events are run by the MicroPython scheduler. On Unix, the # scheduler is also responsible for polling the UART, whereas on STM32 the # UART is also polled by the RX IRQ. -CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS=1 +CFLAGS_EXTMOD += -DMICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS=1 # Without the ringbuffer, and with the full implementation, we can also # enable pairing and bonding. This requires both synchronous events and # some customisation of the key store. -CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING=1 +CFLAGS_EXTMOD += -DMICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING=1 NIMBLE_LIB_DIR = lib/mynewt-nimble -LIB_SRC_C += $(addprefix $(NIMBLE_LIB_DIR)/, \ +SRC_THIRDPARTY_C += $(addprefix $(NIMBLE_LIB_DIR)/, \ $(addprefix ext/tinycrypt/src/, \ aes_encrypt.c \ cmac_mode.c \ @@ -98,7 +98,7 @@ LIB_SRC_C += $(addprefix $(NIMBLE_LIB_DIR)/, \ ) # nimble/host/store/ram/src/ble_store_ram.c \ -EXTMOD_SRC_C += $(addprefix $(NIMBLE_EXTMOD_DIR)/, \ +SRC_THIRDPARTY_C += $(addprefix $(NIMBLE_EXTMOD_DIR)/, \ nimble/nimble_npl_os.c \ hal/hal_uart.c \ ) diff --git a/mpy-cross/Makefile b/mpy-cross/Makefile index 4b6e03df8e..7a71577e2b 100644 --- a/mpy-cross/Makefile +++ b/mpy-cross/Makefile @@ -19,7 +19,7 @@ INC += -I$(TOP) # compiler settings CWARN = -Wall -Werror CWARN += -Wextra -Wno-unused-parameter -Wpointer-arith -CFLAGS += $(INC) $(CWARN) -std=gnu99 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) +CFLAGS += $(INC) $(CWARN) -std=gnu99 $(COPT) $(CFLAGS_EXTRA) CFLAGS += -fdata-sections -ffunction-sections -fno-asynchronous-unwind-tables # Debugging/Optimization diff --git a/ports/cc3200/Makefile b/ports/cc3200/Makefile index 6c034c5863..61af0bfd98 100644 --- a/ports/cc3200/Makefile +++ b/ports/cc3200/Makefile @@ -23,7 +23,6 @@ CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -march=armv7e-m -mabi=aapcs -mcpu=co CFLAGS += -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) -Os CFLAGS += -g -ffunction-sections -fdata-sections -fno-common -fsigned-char -mno-unaligned-access CFLAGS += -Iboards/$(BOARD) -CFLAGS += $(CFLAGS_MOD) # Workaround gcc 12.1 bug. CFLAGS += -Wno-array-bounds diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index 6002dc5e5a..168d1d9f6a 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -58,11 +58,11 @@ CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \ -DLWIP_OPEN_SRC CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \ - $(CFLAGS_XTENSA) $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) -I$(BOARD_DIR) + $(CFLAGS_XTENSA) $(COPT) $(CFLAGS_EXTRA) -I$(BOARD_DIR) LD_FILES ?= boards/esp8266_2m.ld LDFLAGS += -nostdlib -T $(LD_FILES) -Map=$(@:.elf=.map) --cref -LIBS += -L$(ESP_SDK)/lib -lmain -ljson -llwip_open -lpp -lnet80211 -lwpa -lphy -lnet80211 $(LDFLAGS_MOD) +LIBS += -L$(ESP_SDK)/lib -lmain -ljson -llwip_open -lpp -lnet80211 -lwpa -lphy -lnet80211 LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) LIBS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc @@ -107,11 +107,6 @@ SRC_C = \ posix_helpers.c \ hspi.c \ $(wildcard $(BOARD_DIR)/*.c) \ - $(SRC_MOD) - -EXTMOD_SRC_C = $(addprefix extmod/,\ - modonewire.c \ - ) LIB_SRC_C = $(addprefix lib/,\ libm/math.c \ @@ -163,17 +158,15 @@ DRIVERS_SRC_C = $(addprefix drivers/,\ SRC_S = \ gchelper.s \ -OBJ = OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) -OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(EXTMOD_SRC_C) $(SHARED_SRC_C) $(DRIVERS_SRC_C) +SRC_QSTR += $(SRC_C) $(SHARED_SRC_C) # Append any auto-generated sources that are needed by sources listed in SRC_QSTR SRC_QSTR_AUTO_DEPS += diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index b8b08cb011..640864e582 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -150,10 +150,6 @@ SRC_C += \ drivers/bus/softspi.c \ drivers/dht/dht.c \ eth.c \ - extmod/modnetwork.c \ - extmod/modonewire.c \ - extmod/modusocket.c \ - extmod/uos_dupterm.c \ fatfs_port.c \ hal/pwm_backport.c \ led.c \ @@ -257,16 +253,6 @@ SRC_S += shared/runtime/gchelper_m3.s \ # QSTR Sources # ============================================================================= -# All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP -ifeq ($(MICROPY_PY_LWIP),1) -SRC_QSTR += \ - extmod/modlwip.c \ - extmod/modnetwork.c \ - extmod/modusocket.c \ - extmod/moduwebsocket.c \ - network_lan.c -endif - # List of sources for qstr extraction SRC_QSTR += \ extmod/modonewire.c \ @@ -386,7 +372,7 @@ CFLAGS += \ -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' endif -CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) +CFLAGS += $(CFLAGS_EXTRA) # ============================================================================= # Linker Flags @@ -433,7 +419,6 @@ OBJ += $(LIBM_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_SS:.S=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) OBJ += $(GEN_PINS_SRC:.c=.o) # Workaround for bug in older gcc, warning on "static usbd_device_t _usbd_dev = { 0 };" diff --git a/ports/minimal/Makefile b/ports/minimal/Makefile index 2e85bd912e..1a20412e0d 100644 --- a/ports/minimal/Makefile +++ b/ports/minimal/Makefile @@ -44,11 +44,6 @@ endif # Flags for optional C++ source code CXXFLAGS += $(filter-out -std=c99,$(CFLAGS)) -CXXFLAGS += $(CXXFLAGS_MOD) - -# Flags for user C modules -CFLAGS += $(CFLAGS_MOD) -LDFLAGS += $(LDFLAGS_MOD) LIBS = @@ -65,14 +60,10 @@ ifeq ($(CROSS), 1) SRC_C += shared/libc/string0.c endif -SRC_C += $(SRC_MOD) - -SRC_CXX += $(SRC_MOD_CXX) - SRC_QSTR += shared/readline/readline.c shared/runtime/pyexec.c -SRC_QSTR += $(SRC_MOD) $(SRC_MOD_CXX) -OBJ += $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) +OBJ += $(PY_CORE_O) +OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o)) ifeq ($(CROSS), 1) diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 9e0354194d..4128404da4 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -132,9 +132,8 @@ CFLAGS += -ffunction-sections -fdata-sections LDFLAGS += -Wl,--gc-sections endif - CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES)) -CFLAGS += $(INC) -Wall -Werror -ansi -std=c11 -nostdlib $(COPT) $(NRF_DEFINES) $(CFLAGS_MOD) $(CFLAGS_EXTRA) +CFLAGS += $(INC) -Wall -Werror -ansi -std=c11 -nostdlib $(COPT) $(NRF_DEFINES) $(CFLAGS_EXTRA) CFLAGS += -fno-strict-aliasing CFLAGS += -Iboards/$(BOARD) CFLAGS += -DNRF5_HAL_H='<$(MCU_VARIANT)_hal.h>' @@ -357,8 +356,8 @@ SRC_C += \ LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) LIBS += -L $(dir $(LIBGCC_FILE_NAME)) -lgcc -OBJ += $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) +OBJ += $(PY_O) +OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_NRFX:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_NRFX_HAL:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) @@ -515,11 +514,11 @@ flash: deploy $(BUILD)/$(OUTPUT_FILENAME).elf: $(OBJ) $(ECHO) "LINK $@" - $(Q)$(CC) $(LDFLAGS) -o $@ $(OBJ) $(LDFLAGS_MOD) $(LIBS) + $(Q)$(CC) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(Q)$(SIZE) $@ # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_LIB) $(DRIVERS_SRC_C) $(SRC_BOARD_MODULES) $(SRC_MOD) +SRC_QSTR += $(SRC_C) $(SRC_LIB) $(DRIVERS_SRC_C) $(SRC_BOARD_MODULES) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR diff --git a/ports/renesas-ra/Makefile b/ports/renesas-ra/Makefile index 6c37aeb1e1..2b0358b270 100644 --- a/ports/renesas-ra/Makefile +++ b/ports/renesas-ra/Makefile @@ -121,7 +121,7 @@ CFLAGS_MCU_RA4W1 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_RA6M1 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_RA6M2 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 -CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -Wdouble-promotion -Wfloat-conversion -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_EXTRA) +CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -Wdouble-promotion -Wfloat-conversion -std=gnu99 -nostdlib $(CFLAGS_EXTRA) #CFLAGS += -D$(CMSIS_MCU) CFLAGS += $(CFLAGS_MCU_$(CMSIS_MCU)) CFLAGS += $(COPT) @@ -161,8 +161,9 @@ endif # Flags for optional C++ source code CXXFLAGS += $(filter-out -Wmissing-prototypes -Wold-style-definition -std=gnu99,$(CFLAGS)) -CXXFLAGS += $(CXXFLAGS_MOD) -ifneq ($(SRC_CXX)$(SRC_MOD_CXX),) + +# TODO make this common -- shouldn't be using these "private" vars from py.mk +ifneq ($(SRC_CXX)$(SRC_USERMOD_CXX)$(SRC_USERMOD_LIB_CXX),) LIBSTDCPP_FILE_NAME = "$(shell $(CXX) $(CXXFLAGS) -print-file-name=libstdc++.a)" LDFLAGS += -L"$(shell dirname $(LIBSTDCPP_FILE_NAME))" endif @@ -279,10 +280,6 @@ ifeq ($(MICROPY_FLOAT_IMPL),double) $(LIBM_O): CFLAGS := $(filter-out -Wdouble-promotion -Wfloat-conversion, $(CFLAGS)) endif -EXTMOD_SRC_C += $(addprefix extmod/,\ - modonewire.c \ - ) - DRIVERS_SRC_C += $(addprefix drivers/,\ bus/softspi.c \ bus/softqspi.c \ @@ -334,9 +331,6 @@ SRC_C += $(addprefix $(BOARD_DIR)/ra_gen/,\ vector_data.c \ ) -SRC_CXX += \ - $(SRC_MOD_CXX) - SRC_O += \ $(STARTUP_FILE) \ $(SYSTEM_FILE) @@ -408,13 +402,11 @@ OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) OBJ += $(LIBM_O) OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(HAL_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_O)) -OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) OBJ += $(BUILD)/pins_$(BOARD).o # This file contains performance critical functions so turn up the optimisation @@ -514,7 +506,7 @@ GEN_PINS_AF_PY = $(BUILD)/pins_af.py FILE2H = $(TOP)/tools/file2h.py # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SRC_MOD) $(SHARED_SRC_C) $(EXTMOD_SRC_C) +SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SHARED_SRC_C) # Making OBJ use an order-only depenedency on the generated pins.h file # has the side effect of making the pins.h file before we actually compile diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 9386a8dacc..2c5f6a1ab2 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -60,11 +60,10 @@ CFLAGS_MCU_SAMD21 = -mtune=cortex-m0plus -mcpu=cortex-m0plus -msoft-float CFLAGS_MCU_SAMD51 = -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard CFLAGS += $(INC) -Wall -Werror -std=c99 -nostdlib -mthumb $(CFLAGS_MCU_$(MCU_SERIES)) -fsingle-precision-constant -Wdouble-promotion CFLAGS += -DMCU_$(MCU_SERIES) -D__$(CMSIS_MCU)__ -CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) +CFLAGS += $(CFLAGS_EXTRA) CFLAGS += -DMPCONFIG_MCU_H='' LDFLAGS += -nostdlib $(addprefix -T,$(LD_FILES)) -Map=$@.map --cref -LDFLAGS += $(LDFLAGS_MOD) LIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) @@ -80,7 +79,7 @@ endif # Flags for optional C++ source code CXXFLAGS += $(filter-out -std=c99,$(CFLAGS)) -CXXFLAGS += $(CXXFLAGS_MOD) + # TODO make this common -- shouldn't be using these "private" vars from py.mk ifneq ($(SRC_CXX)$(SRC_USERMOD_CXX)$(SRC_USERMOD_LIB_CXX),) LIBSTDCPP_FILE_NAME = "$(shell $(CXX) $(CXXFLAGS) -print-file-name=libstdc++.a)" @@ -114,10 +113,6 @@ SRC_C += \ lib/asf4/$(MCU_SERIES_LOWER)/hal/src/hal_atomic.c \ lib/asf4/$(MCU_SERIES_LOWER)/hal/src/hal_flash.c \ lib/asf4/$(MCU_SERIES_LOWER)/hpl/nvmctrl/hpl_nvmctrl.c \ - lib/libm/ef_sqrt.c \ - lib/libm/fmodf.c \ - lib/libm/math.c \ - lib/libm/nearbyintf.c \ lib/tinyusb/src/class/cdc/cdc_device.c \ lib/tinyusb/src/common/tusb_fifo.c \ lib/tinyusb/src/device/usbd.c \ @@ -125,7 +120,6 @@ SRC_C += \ lib/tinyusb/src/portable/microchip/samd/dcd_samd.c \ lib/tinyusb/src/tusb.c \ drivers/bus/softspi.c \ - extmod/uos_dupterm.c \ shared/runtime/mpirq.c \ shared/libc/printf.c \ shared/libc/string0.c \ @@ -138,9 +132,11 @@ SRC_C += \ shared/runtime/sys_stdio_mphal.c \ shared/timeutils/timeutils.c \ -SRC_C += $(SRC_MOD) - -SRC_CXX += $(SRC_MOD_CXX) +LIBM_SRC_C += \ + lib/libm/ef_sqrt.c \ + lib/libm/fmodf.c \ + lib/libm/math.c \ + lib/libm/nearbyintf.c \ # List of sources for qstr extraction SRC_QSTR += \ @@ -159,17 +155,16 @@ SRC_QSTR += \ modsamd.c \ samd_flash.c \ shared/readline/readline.c \ - extmod/uos_dupterm.c \ shared/runtime/mpirq.c \ shared/runtime/sys_stdio_mphal.c \ -SRC_QSTR += $(SRC_MOD) $(SRC_CXX) +SRC_QSTR += $(SRC_CXX) OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(LIBM_SRC_C:.c=.o)) OBJ += $(GEN_PINS_SRC:.c=.o) ifneq ($(FROZEN_MANIFEST),) diff --git a/ports/samd/mcu/samd51/mpconfigmcu.mk b/ports/samd/mcu/samd51/mpconfigmcu.mk index e83e8911dd..f8ed02f841 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.mk +++ b/ports/samd/mcu/samd51/mpconfigmcu.mk @@ -2,7 +2,7 @@ MICROPY_VFS_LFS2 ?= 1 SRC_S += shared/runtime/gchelper_m3.s -SRC_MOD += $(addprefix lib/libm/,\ +LIBM_SRC_C += $(addprefix lib/libm/,\ acoshf.c \ asinfacosf.c \ asinhf.c \ diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 8b503112ae..79bf8b54bf 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -95,7 +95,7 @@ INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/inc #INC += -I$(USBHOST_DIR) INC += -Ilwip_inc -CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -Wdouble-promotion -Wfloat-conversion -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_EXTRA) +CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -Wdouble-promotion -Wfloat-conversion -std=gnu99 -nostdlib $(CFLAGS_EXTRA) CFLAGS += -D$(CMSIS_MCU) -DUSE_FULL_LL_DRIVER CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES)) CFLAGS += $(COPT) @@ -156,7 +156,7 @@ endif # Flags for optional C++ source code CXXFLAGS += $(filter-out -Wmissing-prototypes -Wold-style-definition -std=gnu99,$(CFLAGS)) -CXXFLAGS += $(CXXFLAGS_MOD) + # TODO make this common -- shouldn't be using these "private" vars from py.mk ifneq ($(SRC_CXX)$(SRC_USERMOD_CXX)$(SRC_USERMOD_LIB_CXX),) LIBSTDCPP_FILE_NAME = "$(shell $(CXX) $(CXXFLAGS) -print-file-name=libstdc++.a)" @@ -275,12 +275,6 @@ ifeq ($(MICROPY_FLOAT_IMPL),double) $(LIBM_O): CFLAGS := $(filter-out -Wdouble-promotion -Wfloat-conversion, $(CFLAGS)) endif -EXTMOD_SRC_C += $(addprefix extmod/,\ - modonewire.c \ - modnetwork.c \ - modusocket.c \ - ) - DRIVERS_SRC_C += $(addprefix drivers/,\ bus/softspi.c \ bus/softqspi.c \ @@ -358,11 +352,9 @@ SRC_C += \ servo.c \ dac.c \ adc.c \ + sdio.c \ $(wildcard $(BOARD_DIR)/*.c) -SRC_CXX += \ - $(SRC_MOD_CXX) - SRC_O += \ $(STARTUP_FILE) \ $(SYSTEM_FILE) @@ -482,70 +474,26 @@ USBDEV_SRC_C += $(addprefix $(USBDEV_DIR)/,\ class/src/usbd_msc_scsi.c \ ) -ifeq ($(MICROPY_PY_BLUETOOTH),1) -CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH=1 -CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1 -endif - -ifeq ($(MICROPY_PY_NETWORK_CYW43),1) -CFLAGS_MOD += -DMICROPY_PY_NETWORK_CYW43=1 -SRC_C += sdio.c -EXTMOD_SRC_C += extmod/network_cyw43.c -DRIVERS_SRC_C += drivers/cyw43/cyw43_ctrl.c drivers/cyw43/cyw43_lwip.c -LIBS += $(TOP)/drivers/cyw43/libcyw43.a -endif - -ifneq ($(MICROPY_PY_NETWORK_WIZNET5K),0) -WIZNET5K_DIR=lib/wiznet5k -GIT_SUBMODULES += lib/wiznet5k -INC += -I$(TOP)/$(WIZNET5K_DIR) -I$(TOP)/$(WIZNET5K_DIR)/Ethernet -CFLAGS_MOD += -DMICROPY_PY_NETWORK_WIZNET5K=$(MICROPY_PY_NETWORK_WIZNET5K) -D_WIZCHIP_=$(MICROPY_PY_NETWORK_WIZNET5K) -CFLAGS_MOD += -DWIZCHIP_PREFIXED_EXPORTS=1 -ifeq ($(MICROPY_PY_LWIP),1) -# When using MACRAW mode (with lwIP), maximum buffer space must be used for the raw socket -CFLAGS_MOD += -DWIZCHIP_USE_MAX_BUFFER -endif -SRC_MOD += extmod/network_wiznet5k.c -SRC_MOD += $(addprefix $(WIZNET5K_DIR)/,\ - Ethernet/W$(MICROPY_PY_NETWORK_WIZNET5K)/w$(MICROPY_PY_NETWORK_WIZNET5K).c \ - Ethernet/wizchip_conf.c \ - Ethernet/socket.c \ - Internet/DNS/dns.c \ - Internet/DHCP/dhcp.c \ - ) -endif - ifeq ($(MICROPY_SSL_MBEDTLS),1) -CFLAGS_MOD += -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' -SRC_MOD += mbedtls/mbedtls_port.c +CFLAGS += -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' +LIB_SRC_C += mbedtls/mbedtls_port.c endif ifeq ($(MICROPY_PY_BLUETOOTH),1) - SRC_C += mpbthciport.c ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) -ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) -$(error Cannot enable both NimBLE and BTstack at the same time) -endif -endif - -ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) -CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS=1 -include $(TOP)/extmod/nimble/nimble.mk SRC_C += mpnimbleport.c endif ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) -MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1 -include $(TOP)/extmod/btstack/btstack.mk SRC_C += mpbtstackport.c +MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1 endif ifeq ($(MICROPY_PY_NETWORK_CYW43),1) DRIVERS_SRC_C += drivers/cyw43/cywbt.c endif - endif # SRC_O should be placed first to work around this LTO bug with binutils <2.35: @@ -555,7 +503,6 @@ OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) OBJ += $(LIBM_O) OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(HAL_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(USBDEV_SRC_C:.c=.o)) @@ -713,7 +660,7 @@ $(BUILD)/firmware.elf: $(OBJ) $(call GENERATE_ELF,$@,$^) # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SRC_MOD) $(SHARED_SRC_C) $(EXTMOD_SRC_C) +SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SHARED_SRC_C) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR SRC_QSTR_AUTO_DEPS += $(GEN_CDCINF_HEADER) diff --git a/ports/stm32/mboot/Makefile b/ports/stm32/mboot/Makefile index 176092f8c0..12ffdbc7e4 100755 --- a/ports/stm32/mboot/Makefile +++ b/ports/stm32/mboot/Makefile @@ -58,7 +58,7 @@ INC += -I../$(USBDEV_DIR)/core/inc -I../$(USBDEV_DIR)/class/inc # the compiler does not optimise these functions in terms of themselves. CFLAGS_BUILTIN ?= -ffreestanding -fno-builtin -fno-lto -CFLAGS += $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Wfloat-conversion -Werror -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_EXTRA) +CFLAGS += $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Wfloat-conversion -Werror -std=gnu99 -nostdlib $(CFLAGS_EXTRA) CFLAGS += -D$(CMSIS_MCU) CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES)) CFLAGS += $(COPT) diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 69b29e8ec3..34b3a6abad 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -309,6 +309,14 @@ static inline mp_uint_t disable_irq(void) { #define MICROPY_PY_BLUETOOTH_HCI_READ_MODE MICROPY_PY_BLUETOOTH_HCI_READ_MODE_BYTE #endif +#ifndef MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE +#define MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE (1) +#endif + +#ifndef MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS +#define MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS (MICROPY_BLUETOOTH_NIMBLE) +#endif + // We need an implementation of the log2 function which is not a macro #define MP_NEED_LOG2 (1) diff --git a/ports/teensy/Makefile b/ports/teensy/Makefile index 876ddf1c1d..89e5cbce9d 100644 --- a/ports/teensy/Makefile +++ b/ports/teensy/Makefile @@ -164,7 +164,10 @@ SRC_TEENSY = $(addprefix core/,\ yield.c \ ) -OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(STM_SRC_C:.c=.o) $(SRC_TEENSY:.c=.o)) +OBJ += $(PY_O) +OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_TEENSY:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o)) OBJ += $(BUILD)/shared/runtime/gchelper_m3.o OBJ += $(GEN_PINS_SRC:.c=.o) diff --git a/ports/unix/Makefile b/ports/unix/Makefile index facdab2e04..360cdd6f8c 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -39,7 +39,7 @@ INC += -I$(BUILD) # compiler settings CWARN = -Wall -Werror CWARN += -Wextra -Wno-unused-parameter -Wpointer-arith -Wdouble-promotion -Wfloat-conversion -CFLAGS += $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) -I$(VARIANT_DIR) $(CFLAGS_EXTRA) +CFLAGS += $(INC) $(CWARN) -std=gnu99 -DUNIX $(COPT) -I$(VARIANT_DIR) $(CFLAGS_EXTRA) # Debugging/Optimization ifdef DEBUG @@ -142,35 +142,10 @@ endif # If the variant enables it, enable modbluetooth. ifeq ($(MICROPY_PY_BLUETOOTH),1) - +ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) HAVE_LIBUSB := $(shell (which pkg-config > /dev/null && pkg-config --exists libusb-1.0) 2>/dev/null && echo '1') -# Only one stack can be enabled. -ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) -ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) -$(error Cannot enable both NimBLE and BTstack at the same time) -endif -endif - -# Default to btstack, but a variant (or make command line) can set NimBLE -# explicitly (which is always via H4 UART). -ifneq ($(MICROPY_BLUETOOTH_NIMBLE),1) -ifneq ($(MICROPY_BLUETOOTH_BTSTACK),1) -MICROPY_BLUETOOTH_BTSTACK ?= 1 -endif -endif - -CFLAGS += -DMICROPY_PY_BLUETOOTH=1 -CFLAGS += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1 - -ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) - # Figure out which BTstack transport to use. -ifeq ($(MICROPY_BLUETOOTH_BTSTACK_H4),1) -ifeq ($(MICROPY_BLUETOOTH_BTSTACK_USB),1) -$(error Cannot enable BTstack support for USB and H4 UART at the same time) -endif -else ifeq ($(HAVE_LIBUSB),1) # Default to btstack-over-usb. MICROPY_BLUETOOTH_BTSTACK_USB ?= 1 @@ -178,20 +153,9 @@ else # Fallback to HCI controller via a H4 UART (e.g. Zephyr on nRF) over a /dev/tty serial port. MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1 endif + +SRC_BTSTACK_C += lib/btstack/platform/embedded/btstack_run_loop_embedded.c endif - -# BTstack is enabled. -include $(TOP)/extmod/btstack/btstack.mk -SRC_BTSTACK += lib/btstack/platform/embedded/btstack_run_loop_embedded.c - -else - -# NimBLE is enabled. -CFLAGS += -DMICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS=1 -include $(TOP)/extmod/nimble/nimble.mk - -endif - endif ifeq ($(MICROPY_PY_FFI),1) @@ -242,7 +206,6 @@ SRC_C += \ mpbtstackport_h4.c \ mpbtstackport_usb.c \ mpnimbleport.c \ - $(SRC_MOD) \ modtermios.c \ modusocket.c \ modffi.c \ @@ -256,17 +219,14 @@ SHARED_SRC_C += $(addprefix shared/,\ ) SRC_CXX += \ - $(SRC_MOD_CXX) OBJ = $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o)) OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SHARED_SRC_C) $(EXTMOD_SRC_C) +SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SHARED_SRC_C) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR SRC_QSTR_AUTO_DEPS += diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index a67d11b9e7..a0b9192bfc 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -240,3 +240,11 @@ static inline unsigned long mp_urandom_seed_init(void) { // Configure the implementation of machine.idle(). #include #define MICROPY_UNIX_MACHINE_IDLE sched_yield(); + +#ifndef MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE +#define MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE (1) +#endif + +#ifndef MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS +#define MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS (MICROPY_BLUETOOTH_NIMBLE) +#endif diff --git a/ports/windows/Makefile b/ports/windows/Makefile index 64334bc18b..e7f0f2ff61 100644 --- a/ports/windows/Makefile +++ b/ports/windows/Makefile @@ -32,7 +32,7 @@ INC += -I$(BUILD) INC += -I$(VARIANT_DIR) # compiler settings -CFLAGS += $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Werror -std=gnu99 -DUNIX -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) +CFLAGS += $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Werror -std=gnu99 -DUNIX -D__USE_MINGW_ANSI_STDIO=1 $(COPT) $(CFLAGS_EXTRA) LDFLAGS += -lm -lbcrypt $(LDFLAGS_EXTRA) # Debugging/Optimization @@ -56,31 +56,26 @@ SRC_C = \ realpath.c \ init.c \ fmode.c \ - $(SRC_MOD) \ $(wildcard $(VARIANT_DIR)/*.c) SHARED_SRC_C += $(addprefix shared/,\ $(SHARED_SRC_C_EXTRA) \ ) -SRC_CXX += \ - $(SRC_MOD_CXX) - OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o)) OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) ifeq ($(MICROPY_USE_READLINE),1) -CFLAGS_MOD += -DMICROPY_USE_READLINE=1 +CFLAGS += -DMICROPY_USE_READLINE=1 SRC_C += shared/readline/readline.c endif LIB += -lws2_32 # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SHARED_SRC_C) $(EXTMOD_SRC_C) +SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SHARED_SRC_C) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR SRC_QSTR_AUTO_DEPS += @@ -89,7 +84,7 @@ ifneq ($(FROZEN_MANIFEST),) CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool -DMICROPY_MODULE_FROZEN_MPY=1 -DMPZ_DIG_SIZE=16 endif -CXXFLAGS += $(filter-out -std=gnu99,$(CFLAGS) $(CXXFLAGS_MOD)) +CXXFLAGS += $(filter-out -std=gnu99,$(CFLAGS)) include $(TOP)/py/mkrules.mk diff --git a/py/py.mk b/py/py.mk index ec69ca42d9..fde612d804 100644 --- a/py/py.mk +++ b/py/py.mk @@ -207,7 +207,7 @@ endif # Sources that may contain qstrings SRC_QSTR_IGNORE = py/nlr% -SRC_QSTR += $(SRC_MOD) $(filter-out $(SRC_QSTR_IGNORE),$(PY_CORE_O_BASENAME:.o=.c)) +SRC_QSTR += $(filter-out $(SRC_QSTR_IGNORE),$(PY_CORE_O_BASENAME:.o=.c)) # Anything that depends on FORCE will be considered out-of-date FORCE: From 43bcfb148b21d0f6dfa18d6d565f2c686dec80af Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sun, 9 Oct 2022 00:05:11 +1100 Subject: [PATCH 0539/1041] mimxrt/Makefile: Split up SRC_C variables. This improves clarity a bit, but also ensures that only the required files are added to SRC_QSTR. Signed-off-by: Jim Mussared --- ports/mimxrt/Makefile | 47 +++++++++++++------------------------------ 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index 640864e582..2119e027ef 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -178,6 +178,11 @@ SRC_C += \ pendsv.c \ pin.c \ sdcard.c \ + systick.c \ + ticks.c \ + tusb_port.c \ + +SHARED_SRC_C += \ shared/libc/printf.c \ shared/libc/string0.c \ shared/netutils/dhcpserver.c \ @@ -191,23 +196,17 @@ SRC_C += \ shared/runtime/stdout_helpers.c \ shared/runtime/sys_stdio_mphal.c \ shared/timeutils/timeutils.c \ - systick.c \ - ticks.c \ - tusb_port.c \ - $(SRC_TINYUSB_C) \ - $(SRC_HAL_IMX_C) \ - $(SRC_ETH_C) # Add sources for respective board flash type ifeq ($(MICROPY_HW_FLASH_TYPE),$(filter $(MICROPY_HW_FLASH_TYPE),qspi_nor_flash qspi_hyper_flash)) # Add hal/flexspi_nor_flash.c or hal/flashspi_hyper_flash.c respectively - SRC_C += hal/flexspi_$(subst qspi_,,$(MICROPY_HW_FLASH_TYPE)).c + SRC_HAL_C += hal/flexspi_$(subst qspi_,,$(MICROPY_HW_FLASH_TYPE)).c # # Add custom (board specific) or default configuration ifeq ($(MICROPY_HW_BOARD_FLASH_FILES),1) - SRC_C += $(BOARD_DIR)/$(MICROPY_HW_FLASH_TYPE)_config.c + SRC_HAL_C += $(BOARD_DIR)/$(MICROPY_HW_FLASH_TYPE)_config.c else - SRC_C += hal/$(MICROPY_HW_FLASH_TYPE)_config.c + SRC_HAL_C += hal/$(MICROPY_HW_FLASH_TYPE)_config.c endif else $(error Error: Unknown board flash type $(MICROPY_HW_FLASH_TYPE)) @@ -254,29 +253,7 @@ SRC_S += shared/runtime/gchelper_m3.s \ # ============================================================================= # List of sources for qstr extraction -SRC_QSTR += \ - extmod/modonewire.c \ - extmod/uos_dupterm.c \ - machine_adc.c \ - machine_i2s.c \ - machine_led.c \ - machine_pin.c \ - machine_pwm.c \ - machine_rtc.c \ - machine_sdcard.c \ - machine_spi.c \ - machine_timer.c \ - machine_uart.c \ - machine_wdt.c \ - mimxrt_flash.c \ - modmachine.c \ - modmimxrt.c \ - modutime.c \ - pin.c \ - shared/readline/readline.c \ - shared/runtime/mpirq.c \ - shared/runtime/sys_stdio_mphal.c \ - $(GEN_PINS_SRC) +SRC_QSTR += $(SRC_C) $(SHARED_SRC_C) $(GEN_PINS_SRC) # ============================================================================= # Compiler Flags @@ -413,12 +390,16 @@ ifeq ($(MICROPY_FLOAT_IMPL),double) $(LIBM_O): CFLAGS := $(filter-out -Wdouble-promotion -Wfloat-conversion, $(CFLAGS)) endif - OBJ += $(PY_O) OBJ += $(LIBM_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_SS:.S=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_TINYUSB_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_HAL_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_HAL_IMX_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_ETH_C:.c=.o)) OBJ += $(GEN_PINS_SRC:.c=.o) # Workaround for bug in older gcc, warning on "static usbd_device_t _usbd_dev = { 0 };" From a2aceb50074f625c0d9b08ab8902bef1557c1ec6 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sun, 9 Oct 2022 00:05:17 +1100 Subject: [PATCH 0540/1041] nrf/Makefile: Split up SRC_C variables. This improves clarity a bit, but also ensures that only the required files are added to SRC_QSTR. Signed-off-by: Jim Mussared --- ports/nrf/Makefile | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 4128404da4..a80a37e1fb 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -163,7 +163,7 @@ LIBS = \ ifeq ($(MCU_VARIANT), nrf52) -SRC_LIB += $(addprefix lib/,\ +SRC_LIB_C += $(addprefix lib/,\ libm/math.c \ libm/fmodf.c \ libm/nearbyintf.c \ @@ -197,7 +197,7 @@ endif ifeq ($(MCU_VARIANT), nrf91) -SRC_LIB += $(addprefix lib/,\ +SRC_LIB_C += $(addprefix lib/,\ libm/math.c \ libm/fmodf.c \ libm/nearbyintf.c \ @@ -236,7 +236,7 @@ include drivers/secureboot/secureboot.mk endif -SRC_LIB += $(addprefix shared/,\ +SRC_SHARED_C += $(addprefix shared/,\ libc/string0.c \ readline/readline.c \ runtime/pyexec.c \ @@ -247,7 +247,7 @@ SRC_LIB += $(addprefix shared/,\ ) ifeq ($(MICROPY_FATFS), 1) -SRC_LIB += $(addprefix lib/,\ +SRC_LIB_C += $(addprefix lib/,\ oofatfs/ff.c \ oofatfs/ffunicode.c \ ) @@ -362,7 +362,8 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_NRFX:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_NRFX_HAL:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SYSTEM_C_SRC:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_LIB_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_SHARED_C:.c=.o)) OBJ += $(GEN_PINS_SRC:.c=.o) $(BUILD)/$(OOFATFS_DIR)/ff.o: COPT += -Os @@ -518,7 +519,7 @@ $(BUILD)/$(OUTPUT_FILENAME).elf: $(OBJ) $(Q)$(SIZE) $@ # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_LIB) $(DRIVERS_SRC_C) $(SRC_BOARD_MODULES) +SRC_QSTR += $(SRC_C) $(SRC_SHARED_C) $(DRIVERS_SRC_C) $(SRC_BOARD_MODULES) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR From b25087fc6ff6460bf464dbd402febc86799068a9 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sun, 9 Oct 2022 00:05:26 +1100 Subject: [PATCH 0541/1041] samd/Makefile: Split up SRC_C variables. This improves clarity a bit, but also ensures that only the required files are added to SRC_QSTR. Signed-off-by: Jim Mussared --- ports/samd/Makefile | 66 +++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 2c5f6a1ab2..2f97b1993e 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -110,16 +110,8 @@ SRC_C += \ samd_isr.c \ samd_soc.c \ tusb_port.c \ - lib/asf4/$(MCU_SERIES_LOWER)/hal/src/hal_atomic.c \ - lib/asf4/$(MCU_SERIES_LOWER)/hal/src/hal_flash.c \ - lib/asf4/$(MCU_SERIES_LOWER)/hpl/nvmctrl/hpl_nvmctrl.c \ - lib/tinyusb/src/class/cdc/cdc_device.c \ - lib/tinyusb/src/common/tusb_fifo.c \ - lib/tinyusb/src/device/usbd.c \ - lib/tinyusb/src/device/usbd_control.c \ - lib/tinyusb/src/portable/microchip/samd/dcd_samd.c \ - lib/tinyusb/src/tusb.c \ - drivers/bus/softspi.c \ + +SHARED_SRC_C += \ shared/runtime/mpirq.c \ shared/libc/printf.c \ shared/libc/string0.c \ @@ -132,39 +124,43 @@ SRC_C += \ shared/runtime/sys_stdio_mphal.c \ shared/timeutils/timeutils.c \ -LIBM_SRC_C += \ - lib/libm/ef_sqrt.c \ - lib/libm/fmodf.c \ - lib/libm/math.c \ - lib/libm/nearbyintf.c \ +ASF4_SRC_C += $(addprefix lib/asf4/$(MCU_SERIES_LOWER)/,\ + hal/src/hal_atomic.c \ + hal/src/hal_flash.c \ + hpl/nvmctrl/hpl_nvmctrl.c \ + ) + +LIBM_SRC_C += $(addprefix lib/libm/,\ + ef_sqrt.c \ + fmodf.c \ + math.c \ + nearbyintf.c \ + ) + +TINYUSB_SRC_C += $(addprefix lib/tinyusb/src/,\ + class/cdc/cdc_device.c \ + common/tusb_fifo.c \ + device/usbd.c \ + device/usbd_control.c \ + portable/microchip/samd/dcd_samd.c \ + tusb.c \ + ) + +DRIVERS_SRC_C += \ + drivers/bus/softspi.c \ # List of sources for qstr extraction -SRC_QSTR += \ - machine_adc.c \ - machine_dac.c \ - machine_i2c.c \ - machine_led.c \ - machine_pin.c \ - machine_pwm.c \ - machine_spi.c \ - machine_timer.c \ - machine_uart.c \ - machine_wdt.c \ - modutime.c \ - modmachine.c \ - modsamd.c \ - samd_flash.c \ - shared/readline/readline.c \ - shared/runtime/mpirq.c \ - shared/runtime/sys_stdio_mphal.c \ - -SRC_QSTR += $(SRC_CXX) +SRC_QSTR += $(SRC_C) $(SHARED_SRC_C) $(SRC_CXX) $(GEN_PINS_SRC) OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) +OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(ASF4_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(LIBM_SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(TINYUSB_SRC_C:.c=.o)) OBJ += $(GEN_PINS_SRC:.c=.o) ifneq ($(FROZEN_MANIFEST),) From 92d911803812100fac109b6108ab005e7bbd4c82 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 7 Oct 2022 21:08:08 +0200 Subject: [PATCH 0542/1041] rp2/fatfs_port: Fix the modification date of files. It was off by 2000 % 128 == 80 years. Addresses issue #9535. --- ports/rp2/fatfs_port.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/rp2/fatfs_port.c b/ports/rp2/fatfs_port.c index 3821d6586c..9706b6fe7d 100644 --- a/ports/rp2/fatfs_port.c +++ b/ports/rp2/fatfs_port.c @@ -30,5 +30,5 @@ MP_WEAK DWORD get_fattime(void) { datetime_t t; rtc_get_datetime(&t); - return ((2000 + t.year - 1980) << 25) | ((t.month) << 21) | ((t.day) << 16) | ((t.hour) << 11) | ((t.min) << 5) | (t.sec / 2); + return ((t.year - 1980) << 25) | ((t.month) << 21) | ((t.day) << 16) | ((t.hour) << 11) | ((t.min) << 5) | (t.sec / 2); } From ab317a0d66005ea88f162994130f61d0d488db93 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 8 Oct 2022 17:32:22 -0500 Subject: [PATCH 0543/1041] py/misc: Remove use of bitfield from vstr_t. Since there is only one flag, we don't need to use a bitfield in vstr_t. Compilers emit extra instructions to access a bitfield, so this should reduce the binary size a small amount. Signed-off-by: David Lechner --- py/misc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/misc.h b/py/misc.h index 7350d2f9b0..32061a009e 100644 --- a/py/misc.h +++ b/py/misc.h @@ -179,7 +179,7 @@ typedef struct _vstr_t { size_t alloc; size_t len; char *buf; - bool fixed_buf : 1; + bool fixed_buf; } vstr_t; // convenience macro to declare a vstr with a fixed size buffer on the stack From 89b320737652829edbab921e86d7ad3962d86d9e Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 14 Oct 2022 14:36:17 +1100 Subject: [PATCH 0544/1041] unix/modffi: Move header includes inside MICROPY_PY_FFI guard. So ffi.h is not needed if this module is disabled. Signed-off-by: Damien George --- ports/unix/modffi.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/ports/unix/modffi.c b/ports/unix/modffi.c index 3df748b80d..bc585f8647 100644 --- a/ports/unix/modffi.c +++ b/ports/unix/modffi.c @@ -25,13 +25,6 @@ * THE SOFTWARE. */ -#include -#include -#include -#include -#include -#include - #include "py/runtime.h" #include "py/binary.h" #include "py/mperrno.h" @@ -40,6 +33,12 @@ #if MICROPY_PY_FFI +#include +#include +#include +#include +#include + /* * modffi uses character codes to encode a value type, based on "struct" * module type codes, with some extensions and overridings. From 815920c87f9bda6b3fb7ec24686154210c9e8774 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 14 Oct 2022 15:49:52 +1100 Subject: [PATCH 0545/1041] extmod/utime_mphal: Make ticks_add check for overflow of delta. Work done in collaboration with @jimmo. Signed-off-by: Damien George --- extmod/utime_mphal.c | 13 +++++++++++ tests/extmod/ticks_add.py | 42 +++++++++++++++++++++++++++++++++++ tests/extmod/ticks_add.py.exp | 36 ++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 tests/extmod/ticks_add.py create mode 100644 tests/extmod/ticks_add.py.exp diff --git a/extmod/utime_mphal.c b/extmod/utime_mphal.c index 3d1cdfd820..cd91c95530 100644 --- a/extmod/utime_mphal.c +++ b/extmod/utime_mphal.c @@ -95,6 +95,19 @@ STATIC mp_obj_t time_ticks_add(mp_obj_t ticks_in, mp_obj_t delta_in) { // we assume that first argument come from ticks_xx so is small int mp_uint_t ticks = MP_OBJ_SMALL_INT_VALUE(ticks_in); mp_uint_t delta = mp_obj_get_int(delta_in); + + // Check that delta does not overflow the range that ticks_diff can handle. + // This ensures the following: + // - ticks_diff(ticks_add(T, delta), T) == delta + // - ticks_diff(T, ticks_add(T, delta)) == -delta + // The latter requires excluding delta=-TICKS_PERIOD/2. + // + // This unsigned comparison is equivalent to a signed comparison of: + // delta <= TICKS_PERIOD/2 || delta >= TICKS_PERIOD/2 + if (delta + MICROPY_PY_UTIME_TICKS_PERIOD / 2 - 1 >= MICROPY_PY_UTIME_TICKS_PERIOD - 1) { + mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("ticks interval overflow")); + } + return MP_OBJ_NEW_SMALL_INT((ticks + delta) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1)); } MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj, time_ticks_add); diff --git a/tests/extmod/ticks_add.py b/tests/extmod/ticks_add.py new file mode 100644 index 0000000000..2f1ba6c810 --- /dev/null +++ b/tests/extmod/ticks_add.py @@ -0,0 +1,42 @@ +try: + from utime import ticks_diff, ticks_add +except ImportError: + print("SKIP") + raise SystemExit + +# Maximum value returned from ticks_add, ticks_ms, etc. +TICKS_MAX = ticks_add(0, -1) +# Maximum value returned from ticks_diff. +TICKS_INTERVAL_MAX = TICKS_MAX // 2 + +# Invariants: +# - ticks_diff(ticks_add(T, delta), T) == delta +# - ticks_diff(T, ticks_add(T, delta)) == -delta + +# Check actual values of ticks_add. +print(ticks_add(20, 12)) +print(ticks_add(20, -12)) + +# Check invariant. +print(ticks_diff(ticks_add(100, 123), 100)) +print(ticks_diff(ticks_add(100, -123), 100)) +print(ticks_diff(100, ticks_add(100, 123))) +print(ticks_diff(100, ticks_add(100, -123))) + +# Check limits. +for T in (0, 10, TICKS_MAX): + for delta in ( + -TICKS_INTERVAL_MAX - 1, + -TICKS_INTERVAL_MAX, + 0, + TICKS_INTERVAL_MAX, + TICKS_INTERVAL_MAX + 1, + ): + try: + print(ticks_diff(ticks_add(T, delta), T) == delta) + except OverflowError: + print("OverflowError") + try: + print(ticks_diff(T, ticks_add(T, delta)) == -delta) + except OverflowError: + print("OverflowError") diff --git a/tests/extmod/ticks_add.py.exp b/tests/extmod/ticks_add.py.exp new file mode 100644 index 0000000000..60dc6f5afd --- /dev/null +++ b/tests/extmod/ticks_add.py.exp @@ -0,0 +1,36 @@ +32 +8 +123 +-123 +-123 +123 +OverflowError +OverflowError +True +True +True +True +True +True +OverflowError +OverflowError +OverflowError +OverflowError +True +True +True +True +True +True +OverflowError +OverflowError +OverflowError +OverflowError +True +True +True +True +True +True +OverflowError +OverflowError From 965a87b53cd9da32a546b03cdd01042058080498 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 14 Oct 2022 16:10:38 +1100 Subject: [PATCH 0546/1041] tests/extmod: Add test for sleep_ms value that overflows ticks. Addresses #9516. Signed-off-by: Damien George --- tests/extmod/uasyncio_micropython.py | 6 ++++++ tests/extmod/uasyncio_micropython.py.exp | 1 + 2 files changed, 7 insertions(+) diff --git a/tests/extmod/uasyncio_micropython.py b/tests/extmod/uasyncio_micropython.py index 69e5fa3224..a6b65bb2a8 100644 --- a/tests/extmod/uasyncio_micropython.py +++ b/tests/extmod/uasyncio_micropython.py @@ -22,6 +22,12 @@ async def main(): await uasyncio.sleep_ms(1) print(utime.ticks_diff(utime.ticks_ms(), t0) < 100) + try: + # Sleep 1ms beyond maximum allowed sleep value + await uasyncio.sleep_ms(utime.ticks_add(0, -1) // 2 + 1) + except OverflowError: + print("OverflowError") + # When task finished before the timeout print(await uasyncio.wait_for_ms(task(1, 5), 50)) diff --git a/tests/extmod/uasyncio_micropython.py.exp b/tests/extmod/uasyncio_micropython.py.exp index f5be1dc75a..4d1c6d681f 100644 --- a/tests/extmod/uasyncio_micropython.py.exp +++ b/tests/extmod/uasyncio_micropython.py.exp @@ -1,4 +1,5 @@ True +OverflowError task start 1 task end 1 2 From af4ba6d1b4558e0ce1c81b8acd975f0bcbe83072 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Thu, 6 Oct 2022 19:48:07 +0200 Subject: [PATCH 0547/1041] stm32: Rename machine I2C and SPI types consistently across ports. This renames: - machine_hard_i2c_type -> machine_i2c_type - machine_hard_spi_type -> machine_spi_type --- ports/stm32/machine_i2c.c | 18 +++++++++--------- ports/stm32/machine_spi.c | 14 +++++++------- ports/stm32/modmachine.c | 4 ++-- ports/stm32/modmachine.h | 4 +++- ports/stm32/spi.c | 4 ++-- ports/stm32/spi.h | 2 +- 6 files changed, 24 insertions(+), 22 deletions(-) diff --git a/ports/stm32/machine_i2c.c b/ports/stm32/machine_i2c.c index 9a2d338f54..7718d1bfe0 100644 --- a/ports/stm32/machine_i2c.c +++ b/ports/stm32/machine_i2c.c @@ -49,16 +49,16 @@ typedef struct _machine_hard_i2c_obj_t { STATIC const machine_hard_i2c_obj_t machine_hard_i2c_obj[MICROPY_HW_MAX_I2C] = { #if defined(MICROPY_HW_I2C1_SCL) - [0] = {{&machine_hard_i2c_type}, I2C1, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA}, + [0] = {{&machine_i2c_type}, I2C1, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA}, #endif #if defined(MICROPY_HW_I2C2_SCL) - [1] = {{&machine_hard_i2c_type}, I2C2, MICROPY_HW_I2C2_SCL, MICROPY_HW_I2C2_SDA}, + [1] = {{&machine_i2c_type}, I2C2, MICROPY_HW_I2C2_SCL, MICROPY_HW_I2C2_SDA}, #endif #if defined(MICROPY_HW_I2C3_SCL) - [2] = {{&machine_hard_i2c_type}, I2C3, MICROPY_HW_I2C3_SCL, MICROPY_HW_I2C3_SDA}, + [2] = {{&machine_i2c_type}, I2C3, MICROPY_HW_I2C3_SCL, MICROPY_HW_I2C3_SDA}, #endif #if defined(MICROPY_HW_I2C4_SCL) - [3] = {{&machine_hard_i2c_type}, I2C4, MICROPY_HW_I2C4_SCL, MICROPY_HW_I2C4_SDA}, + [3] = {{&machine_i2c_type}, I2C4, MICROPY_HW_I2C4_SCL, MICROPY_HW_I2C4_SDA}, #endif }; @@ -140,16 +140,16 @@ typedef mp_machine_soft_i2c_obj_t machine_hard_i2c_obj_t; STATIC machine_hard_i2c_obj_t machine_hard_i2c_obj[MICROPY_HW_MAX_I2C] = { #if defined(MICROPY_HW_I2C1_SCL) - [0] = {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA}, + [0] = {{&machine_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA}, #endif #if defined(MICROPY_HW_I2C2_SCL) - [1] = {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C2_SCL, MICROPY_HW_I2C2_SDA}, + [1] = {{&machine_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C2_SCL, MICROPY_HW_I2C2_SDA}, #endif #if defined(MICROPY_HW_I2C3_SCL) - [2] = {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C3_SCL, MICROPY_HW_I2C3_SDA}, + [2] = {{&machine_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C3_SCL, MICROPY_HW_I2C3_SDA}, #endif #if defined(MICROPY_HW_I2C4_SCL) - [3] = {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C4_SCL, MICROPY_HW_I2C4_SDA}, + [3] = {{&machine_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C4_SCL, MICROPY_HW_I2C4_SDA}, #endif }; @@ -237,7 +237,7 @@ STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = { }; MP_DEFINE_CONST_OBJ_TYPE( - machine_hard_i2c_type, + machine_i2c_type, MP_QSTR_I2C, MP_TYPE_FLAG_NONE, make_new, machine_hard_i2c_make_new, diff --git a/ports/stm32/machine_spi.c b/ports/stm32/machine_spi.c index 718ae1af5e..7ccff75f1c 100644 --- a/ports/stm32/machine_spi.c +++ b/ports/stm32/machine_spi.c @@ -32,12 +32,12 @@ // Implementation of hard SPI for machine module STATIC const machine_hard_spi_obj_t machine_hard_spi_obj[] = { - {{&machine_hard_spi_type}, &spi_obj[0]}, - {{&machine_hard_spi_type}, &spi_obj[1]}, - {{&machine_hard_spi_type}, &spi_obj[2]}, - {{&machine_hard_spi_type}, &spi_obj[3]}, - {{&machine_hard_spi_type}, &spi_obj[4]}, - {{&machine_hard_spi_type}, &spi_obj[5]}, + {{&machine_spi_type}, &spi_obj[0]}, + {{&machine_spi_type}, &spi_obj[1]}, + {{&machine_spi_type}, &spi_obj[2]}, + {{&machine_spi_type}, &spi_obj[3]}, + {{&machine_spi_type}, &spi_obj[4]}, + {{&machine_spi_type}, &spi_obj[5]}, }; STATIC void machine_hard_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -136,7 +136,7 @@ STATIC const mp_machine_spi_p_t machine_hard_spi_p = { }; MP_DEFINE_CONST_OBJ_TYPE( - machine_hard_spi_type, + machine_spi_type, MP_QSTR_SPI, MP_TYPE_FLAG_NONE, make_new, machine_hard_spi_make_new, diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index e1796d1cf0..06fdd0e2c1 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -424,14 +424,14 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, #if MICROPY_PY_MACHINE_I2C #if MICROPY_HW_ENABLE_HW_I2C - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hard_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, #else { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, #endif { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, #endif #if MICROPY_PY_MACHINE_SPI - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_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) }, #endif #if MICROPY_HW_ENABLE_I2S diff --git a/ports/stm32/modmachine.h b/ports/stm32/modmachine.h index 9fa7851582..0c776280b4 100644 --- a/ports/stm32/modmachine.h +++ b/ports/stm32/modmachine.h @@ -30,8 +30,10 @@ extern const mp_obj_type_t machine_adc_type; extern const mp_obj_type_t machine_timer_type; -extern const mp_obj_type_t machine_hard_i2c_type; +extern const mp_obj_type_t machine_i2c_type; extern const mp_obj_type_t machine_i2s_type; +extern const mp_obj_type_t machine_spi_type; +extern const mp_obj_type_t machine_timer_type; void machine_init(void); void machine_deinit(void); diff --git a/ports/stm32/spi.c b/ports/stm32/spi.c index 9c031cad2e..e21ebcd02b 100644 --- a/ports/stm32/spi.c +++ b/ports/stm32/spi.c @@ -678,7 +678,7 @@ const spi_t *spi_from_mp_obj(mp_obj_t o) { if (mp_obj_is_type(o, &pyb_spi_type)) { pyb_spi_obj_t *self = MP_OBJ_TO_PTR(o); return self->spi; - } else if (mp_obj_is_type(o, &machine_hard_spi_type)) { + } else if (mp_obj_is_type(o, &machine_spi_type)) { machine_hard_spi_obj_t *self = MP_OBJ_TO_PTR(o); return self->spi; } else { @@ -687,7 +687,7 @@ const spi_t *spi_from_mp_obj(mp_obj_t o) { } mp_obj_base_t *mp_hal_get_spi_obj(mp_obj_t o) { - if (mp_obj_is_type(o, &machine_hard_spi_type)) { + if (mp_obj_is_type(o, &machine_spi_type)) { return MP_OBJ_TO_PTR(o); } #if MICROPY_PY_MACHINE_SOFTSPI diff --git a/ports/stm32/spi.h b/ports/stm32/spi.h index 17f1bf6c4a..ef3d718cdd 100644 --- a/ports/stm32/spi.h +++ b/ports/stm32/spi.h @@ -65,7 +65,7 @@ extern const spi_t spi_obj[6]; extern const mp_spi_proto_t spi_proto; extern const mp_obj_type_t pyb_spi_type; -extern const mp_obj_type_t machine_hard_spi_type; +extern const mp_obj_type_t machine_spi_type; // A transfer of "len" bytes should take len*8*1000/baudrate milliseconds. // To simplify the calculation we assume the baudrate is never less than 8kHz From 427670c21047585fb9295ddf35cdbdaa8265fbe1 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Thu, 6 Oct 2022 20:20:03 +0200 Subject: [PATCH 0548/1041] esp32: Rename machine I2C and SPI types consistently across ports. This renames: - machine_hw_i2c_type -> machine_i2c_type - machine_hw_spi_type -> machine_spi_type --- ports/esp32/machine_hw_spi.c | 4 ++-- ports/esp32/machine_i2c.c | 4 ++-- ports/esp32/modmachine.c | 4 ++-- ports/esp32/modmachine.h | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ports/esp32/machine_hw_spi.c b/ports/esp32/machine_hw_spi.c index 647874e17f..35ecc397b3 100644 --- a/ports/esp32/machine_hw_spi.c +++ b/ports/esp32/machine_hw_spi.c @@ -490,7 +490,7 @@ mp_obj_t machine_hw_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_ self = &machine_hw_spi_obj[1]; default_pins = &machine_hw_spi_default_pins[1]; } - self->base.type = &machine_hw_spi_type; + self->base.type = &machine_spi_type; int8_t sck, mosi, miso; @@ -540,7 +540,7 @@ STATIC const mp_machine_spi_p_t machine_hw_spi_p = { }; MP_DEFINE_CONST_OBJ_TYPE( - machine_hw_spi_type, + machine_spi_type, MP_QSTR_SPI, MP_TYPE_FLAG_NONE, make_new, machine_hw_spi_make_new, diff --git a/ports/esp32/machine_i2c.c b/ports/esp32/machine_i2c.c index 9244343dcf..17e98ffc5b 100644 --- a/ports/esp32/machine_i2c.c +++ b/ports/esp32/machine_i2c.c @@ -161,7 +161,7 @@ mp_obj_t machine_hw_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_ bool first_init = false; if (self->base.type == NULL) { // Created for the first time, set default pins - self->base.type = &machine_hw_i2c_type; + self->base.type = &machine_i2c_type; self->port = i2c_id; if (self->port == I2C_NUM_0) { self->scl = MICROPY_HW_I2C0_SCL; @@ -193,7 +193,7 @@ STATIC const mp_machine_i2c_p_t machine_hw_i2c_p = { }; MP_DEFINE_CONST_OBJ_TYPE( - machine_hw_i2c_type, + machine_i2c_type, MP_QSTR_I2C, MP_TYPE_FLAG_NONE, make_new, machine_hw_i2c_make_new, diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index a70f2fbedb..e24afd0403 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -315,14 +315,14 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { #if MICROPY_PY_MACHINE_DAC { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) }, #endif - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hw_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, #if MICROPY_PY_MACHINE_I2S { MP_ROM_QSTR(MP_QSTR_I2S), MP_ROM_PTR(&machine_i2s_type) }, #endif { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hw_spi_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) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, diff --git a/ports/esp32/modmachine.h b/ports/esp32/modmachine.h index 4d2ab9020d..138a89e9c3 100644 --- a/ports/esp32/modmachine.h +++ b/ports/esp32/modmachine.h @@ -16,8 +16,8 @@ extern const mp_obj_type_t machine_touchpad_type; extern const mp_obj_type_t machine_adc_type; 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_hw_i2c_type; -extern const mp_obj_type_t machine_hw_spi_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; From 22ad45fda649b754916883f246139e35ff20e126 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Thu, 6 Oct 2022 20:21:51 +0200 Subject: [PATCH 0549/1041] rp2: Rename machine I2C type consistently across ports. This renames: - machine_hw_i2c_type -> machine_i2c_type --- ports/rp2/machine_i2c.c | 6 +++--- ports/rp2/modmachine.c | 2 +- ports/rp2/modmachine.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ports/rp2/machine_i2c.c b/ports/rp2/machine_i2c.c index 00dc36a4e0..85d12c7713 100644 --- a/ports/rp2/machine_i2c.c +++ b/ports/rp2/machine_i2c.c @@ -68,8 +68,8 @@ typedef struct _machine_i2c_obj_t { } machine_i2c_obj_t; STATIC machine_i2c_obj_t machine_i2c_obj[] = { - {{&machine_hw_i2c_type}, i2c0, 0, MICROPY_HW_I2C0_SCL, MICROPY_HW_I2C0_SDA, 0}, - {{&machine_hw_i2c_type}, i2c1, 1, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA, 0}, + {{&machine_i2c_type}, i2c0, 0, MICROPY_HW_I2C0_SCL, MICROPY_HW_I2C0_SDA, 0}, + {{&machine_i2c_type}, i2c1, 1, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA, 0}, }; STATIC void machine_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -177,7 +177,7 @@ STATIC const mp_machine_i2c_p_t machine_i2c_p = { }; MP_DEFINE_CONST_OBJ_TYPE( - machine_hw_i2c_type, + machine_i2c_type, MP_QSTR_I2C, MP_TYPE_FLAG_NONE, make_new, machine_i2c_make_new, diff --git a/ports/rp2/modmachine.c b/ports/rp2/modmachine.c index 3c8922c417..8058189a92 100644 --- a/ports/rp2/modmachine.c +++ b/ports/rp2/modmachine.c @@ -239,7 +239,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hw_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_I2S), MP_ROM_PTR(&machine_i2s_type) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, diff --git a/ports/rp2/modmachine.h b/ports/rp2/modmachine.h index 503c1ca86c..6ea4def91d 100644 --- a/ports/rp2/modmachine.h +++ b/ports/rp2/modmachine.h @@ -4,7 +4,7 @@ #include "py/obj.h" extern const mp_obj_type_t machine_adc_type; -extern const mp_obj_type_t machine_hw_i2c_type; +extern const mp_obj_type_t machine_i2c_type; extern const mp_obj_type_t machine_i2s_type; extern const mp_obj_type_t machine_pin_type; extern const mp_obj_type_t machine_rtc_type; From e275a58ac12c72d8d8e99f8c558f6e4a1f6637c1 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Thu, 6 Oct 2022 20:22:57 +0200 Subject: [PATCH 0550/1041] samd: Rename machine I2C type consistently across ports. This renames: - machine_hw_i2c_type -> machine_i2c_type --- ports/samd/machine_i2c.c | 4 ++-- ports/samd/modmachine.c | 2 +- ports/samd/modmachine.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ports/samd/machine_i2c.c b/ports/samd/machine_i2c.c index 25dfa99340..0a8f5b94db 100644 --- a/ports/samd/machine_i2c.c +++ b/ports/samd/machine_i2c.c @@ -144,7 +144,7 @@ mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n } // Get the peripheral object. - machine_i2c_obj_t *self = mp_obj_malloc(machine_i2c_obj_t, &machine_hw_i2c_type); + machine_i2c_obj_t *self = mp_obj_malloc(machine_i2c_obj_t, &machine_i2c_type); self->id = id; self->instance = sercom_instance[self->id]; @@ -260,7 +260,7 @@ STATIC const mp_machine_i2c_p_t machine_i2c_p = { }; MP_DEFINE_CONST_OBJ_TYPE( - machine_hw_i2c_type, + machine_i2c_type, MP_QSTR_I2C, MP_TYPE_FLAG_NONE, make_new, machine_i2c_make_new, diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index f6cf7f8155..b9de026ed4 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -157,7 +157,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hw_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, diff --git a/ports/samd/modmachine.h b/ports/samd/modmachine.h index 6a745da067..e99ca990fb 100644 --- a/ports/samd/modmachine.h +++ b/ports/samd/modmachine.h @@ -30,7 +30,7 @@ extern const mp_obj_type_t machine_adc_type; extern const mp_obj_type_t machine_dac_type; -extern const mp_obj_type_t machine_hw_i2c_type; +extern const mp_obj_type_t machine_i2c_type; extern const mp_obj_type_t machine_led_type; extern const mp_obj_type_t machine_pin_type; extern const mp_obj_type_t machine_pwm_type; From bfa6f34404374bb7c7d892ca6cb32175e8dd19f6 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Thu, 6 Oct 2022 20:25:34 +0200 Subject: [PATCH 0551/1041] renesas-ra: Rename machine SPI type consistently across ports. This renames: - machine_hard_spi_type -> machine_spi_type --- ports/renesas-ra/machine_spi.c | 6 +++--- ports/renesas-ra/modmachine.c | 2 +- ports/renesas-ra/modmachine.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ports/renesas-ra/machine_spi.c b/ports/renesas-ra/machine_spi.c index b9f5b1ad1b..2c71c83b66 100644 --- a/ports/renesas-ra/machine_spi.c +++ b/ports/renesas-ra/machine_spi.c @@ -70,7 +70,7 @@ typedef struct _machine_hard_spi_obj_t { STATIC machine_hard_spi_obj_t machine_hard_spi_obj[] = { #if defined(MICROPY_HW_SPI0_RSPCK) { - {&machine_hard_spi_type}, 0, + {&machine_spi_type}, 0, DEFAULT_SPI_POLARITY, DEFAULT_SPI_PHASE, DEFAULT_SPI_BITS, DEFAULT_SPI_FIRSTBIT, DEFAULT_SPI_BAUDRATE, MICROPY_HW_SPI0_RSPCK, MICROPY_HW_SPI0_MOSI, MICROPY_HW_SPI0_MISO, @@ -78,7 +78,7 @@ STATIC machine_hard_spi_obj_t machine_hard_spi_obj[] = { #endif #if defined(MICROPY_HW_SPI1_RSPCK) { - {&machine_hard_spi_type}, 1, + {&machine_spi_type}, 1, DEFAULT_SPI_POLARITY, DEFAULT_SPI_PHASE, DEFAULT_SPI_BITS, DEFAULT_SPI_FIRSTBIT, DEFAULT_SPI_BAUDRATE, MICROPY_HW_SPI1_RSPCK, MICROPY_HW_SPI1_MOSI, MICROPY_HW_SPI1_MISO, @@ -298,7 +298,7 @@ STATIC const mp_machine_spi_p_t machine_hard_spi_p = { }; MP_DEFINE_CONST_OBJ_TYPE( - machine_hard_spi_type, + machine_spi_type, MP_QSTR_SPI, MP_TYPE_FLAG_NONE, make_new, machine_hard_spi_make_new, diff --git a/ports/renesas-ra/modmachine.c b/ports/renesas-ra/modmachine.c index e6f78747fd..7db36298db 100644 --- a/ports/renesas-ra/modmachine.c +++ b/ports/renesas-ra/modmachine.c @@ -286,7 +286,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, #endif #if MICROPY_PY_MACHINE_SPI - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_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) }, #endif { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, diff --git a/ports/renesas-ra/modmachine.h b/ports/renesas-ra/modmachine.h index de421c5db8..5dbda6bda8 100644 --- a/ports/renesas-ra/modmachine.h +++ b/ports/renesas-ra/modmachine.h @@ -37,7 +37,7 @@ extern const mp_obj_type_t machine_adc_type; 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_hard_spi_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; From 5e90ec233139e90b5dc022932b15b3bc9fd7865c Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Thu, 6 Oct 2022 20:28:31 +0200 Subject: [PATCH 0552/1041] zephyr: Rename machine I2C and SPI types consistently across ports. This renames: - machine_hard_i2c_type -> machine_i2c_type - machine_hard_spi_type -> machine_spi_type --- ports/zephyr/machine_i2c.c | 4 ++-- ports/zephyr/machine_spi.c | 4 ++-- ports/zephyr/modmachine.c | 4 ++-- ports/zephyr/modmachine.h | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ports/zephyr/machine_i2c.c b/ports/zephyr/machine_i2c.c index 8f0f25257b..c261ffad0d 100644 --- a/ports/zephyr/machine_i2c.c +++ b/ports/zephyr/machine_i2c.c @@ -84,7 +84,7 @@ mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz mp_raise_NotImplementedError(MP_ERROR_TEXT("explicit choice of timeout is not implemented")); } - machine_hard_i2c_obj_t *self = mp_obj_malloc(machine_hard_i2c_obj_t, &machine_hard_i2c_type); + machine_hard_i2c_obj_t *self = mp_obj_malloc(machine_hard_i2c_obj_t, &machine_i2c_type); self->dev = dev; self->restart = false; @@ -127,7 +127,7 @@ STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = { }; MP_DEFINE_CONST_OBJ_TYPE( - machine_hard_i2c_type, + machine_i2c_type, MP_QSTR_I2C, MP_TYPE_FLAG_NONE, make_new, machine_hard_i2c_make_new, diff --git a/ports/zephyr/machine_spi.c b/ports/zephyr/machine_spi.c index 19d4ae6dee..507d839c66 100644 --- a/ports/zephyr/machine_spi.c +++ b/ports/zephyr/machine_spi.c @@ -106,7 +106,7 @@ mp_obj_t machine_hard_spi_make_new(const mp_obj_type_t *type, size_t n_args, siz .cs = NULL }; - machine_hard_spi_obj_t *self = mp_obj_malloc(machine_hard_spi_obj_t, &machine_hard_spi_type); + machine_hard_spi_obj_t *self = mp_obj_malloc(machine_hard_spi_obj_t, &machine_spi_type); self->dev = dev; self->config = cfg; @@ -198,7 +198,7 @@ STATIC const mp_machine_spi_p_t machine_hard_spi_p = { }; MP_DEFINE_CONST_OBJ_TYPE( - machine_hard_spi_type, + machine_spi_type, MP_QSTR_SPI, MP_TYPE_FLAG_NONE, make_new, machine_hard_spi_make_new, diff --git a/ports/zephyr/modmachine.c b/ports/zephyr/modmachine.c index 63bd336989..95a66c5119 100644 --- a/ports/zephyr/modmachine.c +++ b/ports/zephyr/modmachine.c @@ -69,10 +69,10 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) }, #if MICROPY_PY_MACHINE_I2C - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hard_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, #endif #if MICROPY_PY_MACHINE_SPI - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_type) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, #endif { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, diff --git a/ports/zephyr/modmachine.h b/ports/zephyr/modmachine.h index a3cdd2b30f..a605ada0de 100644 --- a/ports/zephyr/modmachine.h +++ b/ports/zephyr/modmachine.h @@ -4,8 +4,8 @@ #include "py/obj.h" extern const mp_obj_type_t machine_pin_type; -extern const mp_obj_type_t machine_hard_i2c_type; -extern const mp_obj_type_t machine_hard_spi_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); From 93f3910fe7e43de5661ff0d6f961c6eccb8537e5 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Thu, 6 Oct 2022 20:27:09 +0200 Subject: [PATCH 0553/1041] nrf: Rename machine I2C, PWM, SPI, UART types consistently across ports. This renames: - machine_hard_i2c_type -> machine_i2c_type - machine_hard_pwm_type -> machine_pwm_type - machine_hard_spi_type -> machine_spi_type - machine_hard_uart_type -> machine_uart_type --- ports/nrf/main.c | 2 +- ports/nrf/modules/machine/i2c.c | 6 +++--- ports/nrf/modules/machine/i2c.h | 2 +- ports/nrf/modules/machine/modmachine.c | 8 ++++---- ports/nrf/modules/machine/pwm.c | 16 ++++++++-------- ports/nrf/modules/machine/pwm.h | 2 +- ports/nrf/modules/machine/spi.c | 14 +++++++------- ports/nrf/modules/machine/spi.h | 2 +- ports/nrf/modules/machine/uart.c | 4 ++-- ports/nrf/modules/machine/uart.h | 2 +- ports/nrf/modules/uos/moduos.c | 2 +- 11 files changed, 30 insertions(+), 30 deletions(-) diff --git a/ports/nrf/main.c b/ports/nrf/main.c index bcfaafd39c..989db58b3f 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -170,7 +170,7 @@ soft_reset: MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_NEW_SMALL_INT(115200), }; - MP_STATE_PORT(board_stdio_uart) = MP_OBJ_TYPE_GET_SLOT(&machine_hard_uart_type, make_new)((mp_obj_t)&machine_hard_uart_type, MP_ARRAY_SIZE(args), 0, args); + MP_STATE_PORT(board_stdio_uart) = MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, make_new)((mp_obj_t)&machine_uart_type, MP_ARRAY_SIZE(args), 0, args); } #endif diff --git a/ports/nrf/modules/machine/i2c.c b/ports/nrf/modules/machine/i2c.c index c16c3669ec..ac331b8d7a 100644 --- a/ports/nrf/modules/machine/i2c.c +++ b/ports/nrf/modules/machine/i2c.c @@ -69,8 +69,8 @@ typedef struct _machine_hard_i2c_obj_t { } machine_hard_i2c_obj_t; STATIC const machine_hard_i2c_obj_t machine_hard_i2c_obj[] = { - {{&machine_hard_i2c_type}, .p_twi = NRFX_TWI_INSTANCE(0)}, - {{&machine_hard_i2c_type}, .p_twi = NRFX_TWI_INSTANCE(1)}, + {{&machine_i2c_type}, .p_twi = NRFX_TWI_INSTANCE(0)}, + {{&machine_i2c_type}, .p_twi = NRFX_TWI_INSTANCE(1)}, }; void i2c_init0(void) { @@ -162,7 +162,7 @@ STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = { }; MP_DEFINE_CONST_OBJ_TYPE( - machine_hard_i2c_type, + machine_i2c_type, MP_QSTR_I2C, MP_TYPE_FLAG_NONE, make_new, machine_hard_i2c_make_new, diff --git a/ports/nrf/modules/machine/i2c.h b/ports/nrf/modules/machine/i2c.h index 1dfb1f077a..5c5befc285 100644 --- a/ports/nrf/modules/machine/i2c.h +++ b/ports/nrf/modules/machine/i2c.h @@ -29,7 +29,7 @@ #include "extmod/machine_i2c.h" -extern const mp_obj_type_t machine_hard_i2c_type; +extern const mp_obj_type_t machine_i2c_type; void i2c_init0(void); diff --git a/ports/nrf/modules/machine/modmachine.c b/ports/nrf/modules/machine/modmachine.c index d322e45067..d315582ae6 100644 --- a/ports/nrf/modules/machine/modmachine.c +++ b/ports/nrf/modules/machine/modmachine.c @@ -217,13 +217,13 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, #if MICROPY_PY_MACHINE_UART - { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_hard_uart_type) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, #endif #if MICROPY_PY_MACHINE_HW_SPI - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_type) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, #endif #if MICROPY_PY_MACHINE_I2C - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hard_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, #endif #if MICROPY_PY_MACHINE_ADC @@ -236,7 +236,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, #endif #if MICROPY_PY_MACHINE_HW_PWM - { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_hard_pwm_type) }, + { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, #endif #if MICROPY_PY_MACHINE_TEMP { MP_ROM_QSTR(MP_QSTR_Temp), MP_ROM_PTR(&machine_temp_type) }, diff --git a/ports/nrf/modules/machine/pwm.c b/ports/nrf/modules/machine/pwm.c index 862e1907cb..7c84a8c885 100644 --- a/ports/nrf/modules/machine/pwm.c +++ b/ports/nrf/modules/machine/pwm.c @@ -77,11 +77,11 @@ STATIC machine_pwm_config_t hard_configs[MP_ARRAY_SIZE(machine_hard_pwm_instance STATIC const machine_hard_pwm_obj_t machine_hard_pwm_obj[] = { #if defined(NRF52_SERIES) - {{&machine_hard_pwm_type}, .p_pwm = &machine_hard_pwm_instances[0], .p_config = &hard_configs[0]}, - {{&machine_hard_pwm_type}, .p_pwm = &machine_hard_pwm_instances[1], .p_config = &hard_configs[1]}, - {{&machine_hard_pwm_type}, .p_pwm = &machine_hard_pwm_instances[2], .p_config = &hard_configs[2]}, + {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[0], .p_config = &hard_configs[0]}, + {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[1], .p_config = &hard_configs[1]}, + {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[2], .p_config = &hard_configs[2]}, #if NRF52840 - {{&machine_hard_pwm_type}, .p_pwm = &machine_hard_pwm_instances[3], .p_config = &hard_configs[3]}, + {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[3], .p_config = &hard_configs[3]}, #endif #endif }; @@ -155,7 +155,7 @@ STATIC mp_obj_t machine_pwm_init(size_t n_args, const mp_obj_t *pos_args, mp_map mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // dispatch to specific implementation - if (mp_obj_get_type(self) == &machine_hard_pwm_type) { + if (mp_obj_get_type(self) == &machine_pwm_type) { machine_hard_pwm_init(self, args); } @@ -165,7 +165,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pwm_init_obj, 1, machine_pwm_init); STATIC mp_obj_t machine_pwm_deinit(mp_obj_t self) { // dispatch to specific implementation - if (mp_obj_get_type(self) == &machine_hard_pwm_type) { + if (mp_obj_get_type(self) == &machine_pwm_type) { machine_hard_pwm_deinit(self); } return mp_const_none; @@ -182,7 +182,7 @@ STATIC mp_obj_t machine_pwm_freq(size_t n_args, const mp_obj_t *pos_args, mp_map mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - if (mp_obj_get_type(self) == &machine_hard_pwm_type) { + if (mp_obj_get_type(self) == &machine_pwm_type) { machine_hard_pwm_freq(self, args); } else { // soft pwm @@ -340,7 +340,7 @@ STATIC mp_obj_t machine_hard_pwm_freq(mp_obj_t self_in, mp_arg_val_t *args) { } MP_DEFINE_CONST_OBJ_TYPE( - machine_hard_pwm_type, + machine_pwm_type, MP_QSTR_PWM, MP_TYPE_FLAG_NONE, make_new, machine_pwm_make_new, diff --git a/ports/nrf/modules/machine/pwm.h b/ports/nrf/modules/machine/pwm.h index 7a5b72e0e8..ab2d927fa4 100644 --- a/ports/nrf/modules/machine/pwm.h +++ b/ports/nrf/modules/machine/pwm.h @@ -26,4 +26,4 @@ void pwm_init0(void); -extern const mp_obj_type_t machine_hard_pwm_type; +extern const mp_obj_type_t machine_pwm_type; diff --git a/ports/nrf/modules/machine/spi.c b/ports/nrf/modules/machine/spi.c index fd7f7bb5bc..0dee20027b 100644 --- a/ports/nrf/modules/machine/spi.c +++ b/ports/nrf/modules/machine/spi.c @@ -117,12 +117,12 @@ STATIC const nrfx_spi_t machine_spi_instances[] = { STATIC nrfx_spi_config_t configs[MP_ARRAY_SIZE(machine_spi_instances)]; STATIC const machine_hard_spi_obj_t machine_hard_spi_obj[] = { - {{&machine_hard_spi_type}, .p_spi = &machine_spi_instances[0], .p_config = &configs[0]}, - {{&machine_hard_spi_type}, .p_spi = &machine_spi_instances[1], .p_config = &configs[1]}, + {{&machine_spi_type}, .p_spi = &machine_spi_instances[0], .p_config = &configs[0]}, + {{&machine_spi_type}, .p_spi = &machine_spi_instances[1], .p_config = &configs[1]}, #if defined(NRF52_SERIES) - {{&machine_hard_spi_type}, .p_spi = &machine_spi_instances[2], .p_config = &configs[2]}, + {{&machine_spi_type}, .p_spi = &machine_spi_instances[2], .p_config = &configs[2]}, #if defined(NRF52840_XXAA) && NRFX_SPIM_ENABLED - {{&machine_hard_spi_type}, .p_spi = &machine_spi_instances[3], .p_config = &configs[3]}, + {{&machine_spi_type}, .p_spi = &machine_spi_instances[3], .p_config = &configs[3]}, #endif // NRF52840_XXAA && NRFX_SPIM_ENABLED #endif // NRF52_SERIES }; @@ -235,7 +235,7 @@ STATIC mp_obj_t machine_spi_init(size_t n_args, const mp_obj_t *pos_args, mp_map mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // dispatch to specific implementation - if (mp_obj_get_type(self) == &machine_hard_spi_type) { + if (mp_obj_get_type(self) == &machine_spi_type) { machine_hard_spi_init(self, args); } @@ -245,7 +245,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_init_obj, 1, machine_spi_init); STATIC mp_obj_t machine_spi_deinit(mp_obj_t self) { // dispatch to specific implementation - if (mp_obj_get_type(self) == &machine_hard_spi_type) { + if (mp_obj_get_type(self) == &machine_spi_type) { machine_hard_spi_deinit(self); } return mp_const_none; @@ -428,7 +428,7 @@ STATIC const mp_machine_spi_p_t machine_hard_spi_p = { }; MP_DEFINE_CONST_OBJ_TYPE( - machine_hard_spi_type, + machine_spi_type, MP_QSTR_SPI, MP_TYPE_FLAG_NONE, make_new, machine_spi_make_new, diff --git a/ports/nrf/modules/machine/spi.h b/ports/nrf/modules/machine/spi.h index c6f64a19da..e1505781ac 100644 --- a/ports/nrf/modules/machine/spi.h +++ b/ports/nrf/modules/machine/spi.h @@ -27,7 +27,7 @@ #include "py/obj.h" typedef struct _machine_hard_spi_obj_t machine_hard_spi_obj_t; -extern const mp_obj_type_t machine_hard_spi_type; +extern const mp_obj_type_t machine_spi_type; void spi_init0(void); void spi_transfer(const machine_hard_spi_obj_t * self, diff --git a/ports/nrf/modules/machine/uart.c b/ports/nrf/modules/machine/uart.c index 035a30df9c..eee5b8b79e 100644 --- a/ports/nrf/modules/machine/uart.c +++ b/ports/nrf/modules/machine/uart.c @@ -106,7 +106,7 @@ static const nrfx_uart_t instance0 = NRFX_UART_INSTANCE(0); STATIC machine_hard_uart_buf_t machine_hard_uart_buf[1]; STATIC const machine_hard_uart_obj_t machine_hard_uart_obj[] = { - {{&machine_hard_uart_type}, .p_uart = &instance0, .buf = &machine_hard_uart_buf[0]}, + {{&machine_uart_type}, .p_uart = &instance0, .buf = &machine_hard_uart_buf[0]}, }; void uart_init0(void) { @@ -371,7 +371,7 @@ STATIC const mp_stream_p_t uart_stream_p = { }; MP_DEFINE_CONST_OBJ_TYPE( - machine_hard_uart_type, + machine_uart_type, MP_QSTR_UART, MP_TYPE_FLAG_ITER_IS_STREAM, make_new, machine_hard_uart_make_new, diff --git a/ports/nrf/modules/machine/uart.h b/ports/nrf/modules/machine/uart.h index 121f83cd39..d3e23645b9 100644 --- a/ports/nrf/modules/machine/uart.h +++ b/ports/nrf/modules/machine/uart.h @@ -32,7 +32,7 @@ #include "genhdr/pins.h" typedef struct _machine_hard_uart_obj_t machine_hard_uart_obj_t; -extern const mp_obj_type_t machine_hard_uart_type; +extern const mp_obj_type_t machine_uart_type; void uart_init0(void); void uart_deinit(void); diff --git a/ports/nrf/modules/uos/moduos.c b/ports/nrf/modules/uos/moduos.c index 3fdd8eb19e..402096aacd 100644 --- a/ports/nrf/modules/uos/moduos.c +++ b/ports/nrf/modules/uos/moduos.c @@ -126,7 +126,7 @@ STATIC mp_obj_t os_dupterm(mp_uint_t n_args, const mp_obj_t *args) { } else { if (args[0] == mp_const_none) { MP_STATE_PORT(board_stdio_uart) = NULL; - } else if (mp_obj_get_type(args[0]) == &machine_hard_uart_type) { + } else if (mp_obj_get_type(args[0]) == &machine_uart_type) { MP_STATE_PORT(board_stdio_uart) = args[0]; } else { mp_raise_ValueError(MP_ERROR_TEXT("need a UART object")); From 4f946ba963b452cb79524225e0a88134921f2ebb Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 8 Sep 2022 12:51:10 +1000 Subject: [PATCH 0554/1041] lib/btstack: Update to v1.5.3. Signed-off-by: Damien George --- lib/btstack | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/btstack b/lib/btstack index c8b9823f68..87087689bb 160000 --- a/lib/btstack +++ b/lib/btstack @@ -1 +1 @@ -Subproject commit c8b9823f68c6af0fa52e2c4e009aba4dbf257232 +Subproject commit 87087689bb0c37ff4b9b3e3ba670b7019c306ebd From 67f98ba10c3d894e737f275f0a508b7ccf4f1807 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 8 Sep 2022 12:51:19 +1000 Subject: [PATCH 0555/1041] extmod/btstack: Update BTstack bindings to work with latest BTstack. The following multi-tests pass (eg with PYBD_SF6+LEGO_HUB_NO6): ble_gap_advertise.py ble_gap_connect.py ble_gap_device_name.py ble_gattc_discover_services.py ble_gatt_data_transfer.py perf_gatt_char_write.py perf_gatt_notify.py stress_log_filesystem.py These are the same tests that passed prior to this BTstack update. Also tested on the unix port using H4 transport. Signed-off-by: Damien George --- extmod/btstack/btstack_config.h | 2 +- extmod/btstack/btstack_hci_uart.c | 6 ++++++ extmod/btstack/btstack_hci_uart.h | 2 +- extmod/btstack/modbluetooth_btstack.c | 28 ++++++++++++++++++++++----- ports/stm32/mpbtstackport.c | 11 +++-------- ports/unix/mpbtstackport_common.c | 8 +------- ports/unix/mpbtstackport_h4.c | 14 ++++++++------ ports/unix/mpbtstackport_usb.c | 1 + 8 files changed, 44 insertions(+), 28 deletions(-) diff --git a/extmod/btstack/btstack_config.h b/extmod/btstack/btstack_config.h index e56a84f94a..7de938cb6f 100644 --- a/extmod/btstack/btstack_config.h +++ b/extmod/btstack/btstack_config.h @@ -6,7 +6,7 @@ #define ENABLE_LE_PERIPHERAL #define ENABLE_LE_CENTRAL // #define ENABLE_CLASSIC -#define ENABLE_LE_DATA_CHANNELS +#define ENABLE_L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE // #define ENABLE_LOG_INFO // #define ENABLE_LOG_DEBUG #define ENABLE_LOG_ERROR diff --git a/extmod/btstack/btstack_hci_uart.c b/extmod/btstack/btstack_hci_uart.c index 83e865b71d..f945efc762 100644 --- a/extmod/btstack/btstack_hci_uart.c +++ b/extmod/btstack/btstack_hci_uart.c @@ -159,6 +159,12 @@ const btstack_uart_block_t mp_bluetooth_btstack_hci_uart_block = { &btstack_uart_get_supported_sleep_modes, &btstack_uart_set_sleep, &btstack_uart_set_wakeup_handler, + + // The following are needed for H5 mode only. + NULL, // set_frame_received + NULL, // set_frame_sent, + NULL, // receive_frame, + NULL, // send_frame, }; void mp_bluetooth_btstack_hci_uart_process(void) { diff --git a/extmod/btstack/btstack_hci_uart.h b/extmod/btstack/btstack_hci_uart.h index 8011e587de..74983808ec 100644 --- a/extmod/btstack/btstack_hci_uart.h +++ b/extmod/btstack/btstack_hci_uart.h @@ -28,7 +28,7 @@ #ifndef MICROPY_INCLUDED_EXTMOD_BTSTACK_HCI_UART_H #define MICROPY_INCLUDED_EXTMOD_BTSTACK_HCI_UART_H -#include "lib/btstack/src/btstack.h" +#include "lib/btstack/src/btstack_uart_block.h" // --- Used by the port to create the HCI transport --------------------------- extern const btstack_uart_block_t mp_bluetooth_btstack_hci_uart_block; diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c index b58be78a99..e9c0037394 100644 --- a/extmod/btstack/modbluetooth_btstack.c +++ b/extmod/btstack/modbluetooth_btstack.c @@ -368,7 +368,7 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t event_type == SM_EVENT_PAIRING_COMPLETE || // event_type == GAP_EVENT_DEDICATED_BONDING_COMPLETED || // No conn_handle event_type == HCI_EVENT_ENCRYPTION_CHANGE) { - DEBUG_printf(" --> enc/auth/pair/bond change\n", ); + DEBUG_printf(" --> enc/auth/pair/bond change\n"); #if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING uint16_t conn_handle; switch (event_type) { @@ -420,6 +420,11 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t mp_bluetooth_gap_on_scan_result(address_type, address, adv_event_type, rssi, data, length); #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE #if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT + } else if (event_type == GATT_EVENT_MTU) { + // This is triggered in client mode. + uint16_t conn_handle = gatt_event_mtu_get_handle(packet); + uint16_t mtu = gatt_event_mtu_get_MTU(packet); + mp_bluetooth_gatts_on_mtu_exchanged(conn_handle, mtu); } else if (event_type == GATT_EVENT_QUERY_COMPLETE) { uint16_t conn_handle = gatt_event_query_complete_get_handle(packet); uint16_t status = gatt_event_query_complete_get_att_status(packet); @@ -625,6 +630,19 @@ STATIC void set_random_address(void) { DEBUG_printf("set_random_address: Address loaded by controller\n"); } +STATIC void deinit_stack(void) { + mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_OFF; + + // Deinitialise BTstack components. + sm_deinit(); + l2cap_deinit(); + hci_deinit(); + btstack_memory_deinit(); + btstack_run_loop_deinit(); + + MP_STATE_PORT(bluetooth_btstack_root_pointers) = NULL; +} + int mp_bluetooth_init(void) { DEBUG_printf("mp_bluetooth_init\n"); @@ -702,8 +720,8 @@ int mp_bluetooth_init(void) { // Attempt a shutdown (may not do anything). mp_bluetooth_btstack_port_deinit(); - // Clean up. - MP_STATE_PORT(bluetooth_btstack_root_pointers) = NULL; + // Clean up BTstack. + deinit_stack(); return timeout ? MP_ETIMEDOUT : MP_EINVAL; } @@ -757,8 +775,8 @@ void mp_bluetooth_deinit(void) { } btstack_run_loop_remove_timer(&btstack_init_deinit_timeout); - mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_OFF; - MP_STATE_PORT(bluetooth_btstack_root_pointers) = NULL; + // Clean up BTstack. + deinit_stack(); DEBUG_printf("mp_bluetooth_deinit: complete\n"); } diff --git a/ports/stm32/mpbtstackport.c b/ports/stm32/mpbtstackport.c index 795534042e..301ac30e20 100644 --- a/ports/stm32/mpbtstackport.c +++ b/ports/stm32/mpbtstackport.c @@ -31,6 +31,7 @@ #if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK #include "lib/btstack/src/btstack.h" +#include "lib/btstack/src/hci_transport_h4.h" #include "extmod/mpbthci.h" #include "extmod/btstack/btstack_hci_uart.h" #include "extmod/btstack/modbluetooth_btstack.h" @@ -137,16 +138,10 @@ void mp_bluetooth_hci_poll(void) { } void mp_bluetooth_btstack_port_init(void) { - static bool run_loop_init = false; - if (!run_loop_init) { - run_loop_init = true; - btstack_run_loop_init(&mp_btstack_runloop_stm32); - } else { - mp_btstack_runloop_stm32.init(); - } + btstack_run_loop_init(&mp_btstack_runloop_stm32); // hci_dump_open(NULL, HCI_DUMP_STDOUT); - const hci_transport_t *transport = hci_transport_h4_instance(&mp_bluetooth_btstack_hci_uart_block); + const hci_transport_t *transport = hci_transport_h4_instance_for_uart(&mp_bluetooth_btstack_hci_uart_block); hci_init(transport, &hci_transport_config_uart); #ifdef MICROPY_HW_BLE_BTSTACK_CHIPSET_INSTANCE diff --git a/ports/unix/mpbtstackport_common.c b/ports/unix/mpbtstackport_common.c index ec40db65bc..66a3a0536a 100644 --- a/ports/unix/mpbtstackport_common.c +++ b/ports/unix/mpbtstackport_common.c @@ -79,13 +79,7 @@ uint32_t hal_time_ms(void) { } void mp_bluetooth_btstack_port_init(void) { - static bool run_loop_init = false; - if (!run_loop_init) { - run_loop_init = true; - btstack_run_loop_init(btstack_run_loop_embedded_get_instance()); - } else { - btstack_run_loop_embedded_get_instance()->init(); - } + btstack_run_loop_init(btstack_run_loop_embedded_get_instance()); // hci_dump_open(NULL, HCI_DUMP_STDOUT); diff --git a/ports/unix/mpbtstackport_h4.c b/ports/unix/mpbtstackport_h4.c index 4fdc20c22b..dacfff9a49 100644 --- a/ports/unix/mpbtstackport_h4.c +++ b/ports/unix/mpbtstackport_h4.c @@ -32,6 +32,7 @@ #if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK && MICROPY_BLUETOOTH_BTSTACK_H4 +#include "lib/btstack/src/hci_transport_h4.h" #include "lib/btstack/chipset/zephyr/btstack_chipset_zephyr.h" #include "extmod/btstack/btstack_hci_uart.h" @@ -42,11 +43,12 @@ #define DEBUG_printf(...) // printf(__VA_ARGS__) STATIC hci_transport_config_uart_t hci_transport_config_uart = { - HCI_TRANSPORT_CONFIG_UART, - 1000000, // initial baudrate - 0, // main baudrate - 1, // flow control - NULL, // device name + .type = HCI_TRANSPORT_CONFIG_UART, + .baudrate_init = 1000000, + .baudrate_main = 0, + .flowcontrol = 1, + .device_name = NULL, + .parity = BTSTACK_UART_PARITY_OFF, }; void mp_bluetooth_hci_poll_h4(void) { @@ -58,7 +60,7 @@ void mp_bluetooth_hci_poll_h4(void) { void mp_bluetooth_btstack_port_init_h4(void) { DEBUG_printf("mp_bluetooth_btstack_port_init_h4\n"); - const hci_transport_t *transport = hci_transport_h4_instance(&mp_bluetooth_btstack_hci_uart_block); + const hci_transport_t *transport = hci_transport_h4_instance_for_uart(&mp_bluetooth_btstack_hci_uart_block); hci_init(transport, &hci_transport_config_uart); hci_set_chipset(btstack_chipset_zephyr_instance()); diff --git a/ports/unix/mpbtstackport_usb.c b/ports/unix/mpbtstackport_usb.c index 28d2c8c543..b8c7b758d9 100644 --- a/ports/unix/mpbtstackport_usb.c +++ b/ports/unix/mpbtstackport_usb.c @@ -34,6 +34,7 @@ #if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK && MICROPY_BLUETOOTH_BTSTACK_USB #include "lib/btstack/src/btstack.h" +#include "lib/btstack/src/hci_transport_usb.h" #include "lib/btstack/platform/embedded/btstack_run_loop_embedded.h" #include "lib/btstack/platform/embedded/hal_cpu.h" #include "lib/btstack/platform/embedded/hal_time_ms.h" From b33767896430a36f163c0f9bb7020e688ccb9c5b Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 5 Oct 2022 10:46:11 +1100 Subject: [PATCH 0556/1041] extmod/mbedtls: Add common configuration file, and use it in all ports. This is a no-op change. Signed-off-by: Damien George --- extmod/mbedtls/mbedtls_config_common.h | 110 +++++++++++++++++++++++++ ports/mimxrt/mbedtls/mbedtls_config.h | 69 +--------------- ports/rp2/mbedtls/mbedtls_config.h | 73 ++-------------- ports/stm32/mbedtls/mbedtls_config.h | 69 +--------------- ports/unix/mbedtls/mbedtls_config.h | 58 +------------ 5 files changed, 125 insertions(+), 254 deletions(-) create mode 100644 extmod/mbedtls/mbedtls_config_common.h diff --git a/extmod/mbedtls/mbedtls_config_common.h b/extmod/mbedtls/mbedtls_config_common.h new file mode 100644 index 0000000000..6c9385dea5 --- /dev/null +++ b/extmod/mbedtls/mbedtls_config_common.h @@ -0,0 +1,110 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2022 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. + */ +#ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_COMMON_H +#define MICROPY_INCLUDED_MBEDTLS_CONFIG_COMMON_H + +// If you want to debug MBEDTLS uncomment the following and +// pass "3" to mbedtls_debug_set_threshold in socket_new. +// #define MBEDTLS_DEBUG_C + +// Set mbedtls configuration. +#define MBEDTLS_DEPRECATED_REMOVED +#define MBEDTLS_AES_ROM_TABLES +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#define MBEDTLS_NO_PLATFORM_ENTROPY +#define MBEDTLS_PKCS1_V15 +#define MBEDTLS_SHA256_SMALLER +#define MBEDTLS_SSL_PROTO_TLS1 +#define MBEDTLS_SSL_PROTO_TLS1_1 +#define MBEDTLS_SSL_PROTO_TLS1_2 +#define MBEDTLS_SSL_SERVER_NAME_INDICATION + +// Use a smaller output buffer to reduce size of SSL context. +#define MBEDTLS_SSL_MAX_CONTENT_LEN (16384) +#define MBEDTLS_SSL_IN_CONTENT_LEN (MBEDTLS_SSL_MAX_CONTENT_LEN) +#define MBEDTLS_SSL_OUT_CONTENT_LEN (4096) + +// Enable mbedtls modules. +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_ERROR_C +#define MBEDTLS_MD_C +#define MBEDTLS_MD5_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS5_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_RSA_C +#define MBEDTLS_SHA1_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SHA512_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_TLS_C +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_USE_C + +// A port may enable this option to select additional bare-metal configuration. +#if MICROPY_MBEDTLS_CONFIG_BARE_METAL + +// Bare-metal mbedtls configuration. +#define MBEDTLS_PLATFORM_MEMORY +#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#define MBEDTLS_ENTROPY_HARDWARE_ALT + +// Bare-metal memory allocation hooks. +#include +#include +void *m_tracked_calloc(size_t nmemb, size_t size); +void m_tracked_free(void *ptr); +#define MBEDTLS_PLATFORM_STD_CALLOC m_tracked_calloc +#define MBEDTLS_PLATFORM_STD_FREE m_tracked_free +#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf + +#endif + +// Include mbedtls configuration checker. +#include "mbedtls/check_config.h" + +#endif // MICROPY_INCLUDED_MBEDTLS_CONFIG_COMMON_H diff --git a/ports/mimxrt/mbedtls/mbedtls_config.h b/ports/mimxrt/mbedtls/mbedtls_config.h index 8e054ed517..cc71aa7ec1 100644 --- a/ports/mimxrt/mbedtls/mbedtls_config.h +++ b/ports/mimxrt/mbedtls/mbedtls_config.h @@ -26,74 +26,13 @@ #ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H #define MICROPY_INCLUDED_MBEDTLS_CONFIG_H -// Set mbedtls configuration -#define MBEDTLS_PLATFORM_MEMORY -#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS -#define MBEDTLS_DEPRECATED_REMOVED -#define MBEDTLS_ENTROPY_HARDWARE_ALT -#define MBEDTLS_AES_ROM_TABLES -#define MBEDTLS_CIPHER_MODE_CBC -#define MBEDTLS_ECP_DP_SECP192R1_ENABLED -#define MBEDTLS_ECP_DP_SECP224R1_ENABLED -#define MBEDTLS_ECP_DP_SECP256R1_ENABLED -#define MBEDTLS_ECP_DP_SECP384R1_ENABLED -#define MBEDTLS_ECP_DP_SECP521R1_ENABLED -#define MBEDTLS_ECP_DP_SECP192K1_ENABLED -#define MBEDTLS_ECP_DP_SECP224K1_ENABLED -#define MBEDTLS_ECP_DP_SECP256K1_ENABLED -#define MBEDTLS_ECP_DP_BP256R1_ENABLED -#define MBEDTLS_ECP_DP_BP384R1_ENABLED -#define MBEDTLS_ECP_DP_BP512R1_ENABLED -#define MBEDTLS_ECP_DP_CURVE25519_ENABLED -#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED -#define MBEDTLS_NO_PLATFORM_ENTROPY -#define MBEDTLS_PKCS1_V15 -#define MBEDTLS_SHA256_SMALLER -#define MBEDTLS_SSL_PROTO_TLS1 -#define MBEDTLS_SSL_PROTO_TLS1_1 -#define MBEDTLS_SSL_PROTO_TLS1_2 -#define MBEDTLS_SSL_SERVER_NAME_INDICATION - -// Use a smaller output buffer to reduce size of SSL context -#define MBEDTLS_SSL_MAX_CONTENT_LEN (16384) -#define MBEDTLS_SSL_IN_CONTENT_LEN (MBEDTLS_SSL_MAX_CONTENT_LEN) -#define MBEDTLS_SSL_OUT_CONTENT_LEN (4096) - // Enable mbedtls modules -#define MBEDTLS_AES_C -#define MBEDTLS_ASN1_PARSE_C -#define MBEDTLS_BIGNUM_C -#define MBEDTLS_CIPHER_C -#define MBEDTLS_CTR_DRBG_C // #define MBEDTLS_ECP_C -#define MBEDTLS_ENTROPY_C -#define MBEDTLS_ERROR_C -#define MBEDTLS_MD_C -#define MBEDTLS_MD5_C -#define MBEDTLS_OID_C -#define MBEDTLS_PKCS5_C -#define MBEDTLS_PK_C -#define MBEDTLS_PK_PARSE_C -#define MBEDTLS_PLATFORM_C -#define MBEDTLS_RSA_C -#define MBEDTLS_SHA1_C -#define MBEDTLS_SHA256_C -#define MBEDTLS_SHA512_C -#define MBEDTLS_SSL_CLI_C -#define MBEDTLS_SSL_SRV_C -#define MBEDTLS_SSL_TLS_C -#define MBEDTLS_X509_CRT_PARSE_C -#define MBEDTLS_X509_USE_C -// Memory allocation hooks -#include -#include -void *m_tracked_calloc(size_t nmemb, size_t size); -void m_tracked_free(void *ptr); -#define MBEDTLS_PLATFORM_STD_CALLOC m_tracked_calloc -#define MBEDTLS_PLATFORM_STD_FREE m_tracked_free -#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf +// Set MicroPython-specific options. +#define MICROPY_MBEDTLS_CONFIG_BARE_METAL (1) -#include "mbedtls/check_config.h" +// Include common mbedtls configuration. +#include "extmod/mbedtls/mbedtls_config_common.h" #endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_H */ diff --git a/ports/rp2/mbedtls/mbedtls_config.h b/ports/rp2/mbedtls/mbedtls_config.h index c80aa5bc18..61f622295f 100644 --- a/ports/rp2/mbedtls/mbedtls_config.h +++ b/ports/rp2/mbedtls/mbedtls_config.h @@ -26,90 +26,27 @@ #ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H #define MICROPY_INCLUDED_MBEDTLS_CONFIG_H -// If you want to debug MBEDTLS uncomment the following and -// Pass 3 to mbedtls_debug_set_threshold in socket_new -// #define MBEDTLS_DEBUG_C - // Set mbedtls configuration -#define MBEDTLS_PLATFORM_MEMORY -#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS -#define MBEDTLS_DEPRECATED_REMOVED -#define MBEDTLS_ENTROPY_HARDWARE_ALT -#define MBEDTLS_AES_ROM_TABLES -#define MBEDTLS_CIPHER_MODE_CBC -#define MBEDTLS_ECP_DP_SECP192R1_ENABLED -#define MBEDTLS_ECP_DP_SECP224R1_ENABLED -#define MBEDTLS_ECP_DP_SECP256R1_ENABLED -#define MBEDTLS_ECP_DP_SECP384R1_ENABLED -#define MBEDTLS_ECP_DP_SECP521R1_ENABLED -#define MBEDTLS_ECP_DP_SECP192K1_ENABLED -#define MBEDTLS_ECP_DP_SECP224K1_ENABLED -#define MBEDTLS_ECP_DP_SECP256K1_ENABLED -#define MBEDTLS_ECP_DP_BP256R1_ENABLED -#define MBEDTLS_ECP_DP_BP384R1_ENABLED -#define MBEDTLS_ECP_DP_BP512R1_ENABLED -#define MBEDTLS_ECP_DP_CURVE25519_ENABLED #define MBEDTLS_ECP_NIST_OPTIM #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED -#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED -#define MBEDTLS_NO_PLATFORM_ENTROPY -#define MBEDTLS_PKCS1_V15 -#define MBEDTLS_SHA256_SMALLER -#define MBEDTLS_SSL_PROTO_TLS1 -#define MBEDTLS_SSL_PROTO_TLS1_1 -#define MBEDTLS_SSL_PROTO_TLS1_2 -#define MBEDTLS_SSL_SERVER_NAME_INDICATION - -// Use a smaller output buffer to reduce size of SSL context -#define MBEDTLS_SSL_MAX_CONTENT_LEN (16384) -#define MBEDTLS_SSL_IN_CONTENT_LEN (MBEDTLS_SSL_MAX_CONTENT_LEN) -#define MBEDTLS_SSL_OUT_CONTENT_LEN (4096) // Enable mbedtls modules -#define MBEDTLS_AES_C -#define MBEDTLS_ASN1_PARSE_C -#define MBEDTLS_BIGNUM_C -#define MBEDTLS_CIPHER_C -#define MBEDTLS_CTR_DRBG_C #define MBEDTLS_ECDH_C #define MBEDTLS_ECP_C -#define MBEDTLS_ENTROPY_C -#define MBEDTLS_ERROR_C #define MBEDTLS_GCM_C -#define MBEDTLS_MD_C -#define MBEDTLS_MD5_C -#define MBEDTLS_OID_C -#define MBEDTLS_PKCS5_C -#define MBEDTLS_PK_C -#define MBEDTLS_PK_PARSE_C -#define MBEDTLS_PLATFORM_C -#define MBEDTLS_RSA_C -#define MBEDTLS_SHA1_C -#define MBEDTLS_SHA256_C -#define MBEDTLS_SHA512_C -#define MBEDTLS_SSL_CLI_C -#define MBEDTLS_SSL_SRV_C -#define MBEDTLS_SSL_TLS_C #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE -#define MBEDTLS_X509_CRT_PARSE_C -#define MBEDTLS_X509_USE_C #define MBEDTLS_HAVE_TIME #define MBEDTLS_HAVE_TIME_DATE -// Memory allocation hooks -#include -#include -void *m_tracked_calloc(size_t nmemb, size_t size); -void m_tracked_free(void *ptr); -#define MBEDTLS_PLATFORM_STD_CALLOC m_tracked_calloc -#define MBEDTLS_PLATFORM_STD_FREE m_tracked_free -#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf - // Time hook #include time_t rp2_rtctime_seconds(time_t *timer); #define MBEDTLS_PLATFORM_TIME_MACRO rp2_rtctime_seconds -#include "mbedtls/check_config.h" +// Set MicroPython-specific options. +#define MICROPY_MBEDTLS_CONFIG_BARE_METAL (1) + +// Include common mbedtls configuration. +#include "extmod/mbedtls/mbedtls_config_common.h" #endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_H */ diff --git a/ports/stm32/mbedtls/mbedtls_config.h b/ports/stm32/mbedtls/mbedtls_config.h index 2e0cb7651a..b8548866f1 100644 --- a/ports/stm32/mbedtls/mbedtls_config.h +++ b/ports/stm32/mbedtls/mbedtls_config.h @@ -26,75 +26,14 @@ #ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H #define MICROPY_INCLUDED_MBEDTLS_CONFIG_H -// Set mbedtls configuration -#define MBEDTLS_PLATFORM_MEMORY -#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS -#define MBEDTLS_DEPRECATED_REMOVED -#define MBEDTLS_ENTROPY_HARDWARE_ALT -#define MBEDTLS_AES_ROM_TABLES -#define MBEDTLS_CIPHER_MODE_CBC -#define MBEDTLS_ECP_DP_SECP192R1_ENABLED -#define MBEDTLS_ECP_DP_SECP224R1_ENABLED -#define MBEDTLS_ECP_DP_SECP256R1_ENABLED -#define MBEDTLS_ECP_DP_SECP384R1_ENABLED -#define MBEDTLS_ECP_DP_SECP521R1_ENABLED -#define MBEDTLS_ECP_DP_SECP192K1_ENABLED -#define MBEDTLS_ECP_DP_SECP224K1_ENABLED -#define MBEDTLS_ECP_DP_SECP256K1_ENABLED -#define MBEDTLS_ECP_DP_BP256R1_ENABLED -#define MBEDTLS_ECP_DP_BP384R1_ENABLED -#define MBEDTLS_ECP_DP_BP512R1_ENABLED -#define MBEDTLS_ECP_DP_CURVE25519_ENABLED -#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED -#define MBEDTLS_NO_PLATFORM_ENTROPY -#define MBEDTLS_PKCS1_V15 -#define MBEDTLS_SHA256_SMALLER -#define MBEDTLS_SSL_PROTO_TLS1 -#define MBEDTLS_SSL_PROTO_TLS1_1 -#define MBEDTLS_SSL_PROTO_TLS1_2 -#define MBEDTLS_SSL_SERVER_NAME_INDICATION - -// Use a smaller output buffer to reduce size of SSL context -#define MBEDTLS_SSL_MAX_CONTENT_LEN (16384) -#define MBEDTLS_SSL_IN_CONTENT_LEN (MBEDTLS_SSL_MAX_CONTENT_LEN) -#define MBEDTLS_SSL_OUT_CONTENT_LEN (4096) - // Enable mbedtls modules -#define MBEDTLS_AES_C -#define MBEDTLS_ASN1_PARSE_C -#define MBEDTLS_BIGNUM_C -#define MBEDTLS_CIPHER_C -#define MBEDTLS_CTR_DRBG_C // #define MBEDTLS_ECP_C -#define MBEDTLS_ENTROPY_C -#define MBEDTLS_ERROR_C -#define MBEDTLS_MD_C -#define MBEDTLS_MD5_C -#define MBEDTLS_OID_C -#define MBEDTLS_PKCS5_C -#define MBEDTLS_PK_C -#define MBEDTLS_PK_PARSE_C -#define MBEDTLS_PLATFORM_C -#define MBEDTLS_RSA_C -#define MBEDTLS_SHA1_C -#define MBEDTLS_SHA256_C -#define MBEDTLS_SHA512_C -#define MBEDTLS_SSL_CLI_C -#define MBEDTLS_SSL_SRV_C -#define MBEDTLS_SSL_TLS_C #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE -#define MBEDTLS_X509_CRT_PARSE_C -#define MBEDTLS_X509_USE_C -// Memory allocation hooks -#include -#include -void *m_tracked_calloc(size_t nmemb, size_t size); -void m_tracked_free(void *ptr); -#define MBEDTLS_PLATFORM_STD_CALLOC m_tracked_calloc -#define MBEDTLS_PLATFORM_STD_FREE m_tracked_free -#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf +// Set MicroPython-specific options. +#define MICROPY_MBEDTLS_CONFIG_BARE_METAL (1) -#include "mbedtls/check_config.h" +// Include common mbedtls configuration. +#include "extmod/mbedtls/mbedtls_config_common.h" #endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_H */ diff --git a/ports/unix/mbedtls/mbedtls_config.h b/ports/unix/mbedtls/mbedtls_config.h index b119d09092..c83f1c86f3 100644 --- a/ports/unix/mbedtls/mbedtls_config.h +++ b/ports/unix/mbedtls/mbedtls_config.h @@ -26,69 +26,15 @@ #ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H #define MICROPY_INCLUDED_MBEDTLS_CONFIG_H -// If you want to debug MBEDTLS uncomment the following and -// Pass 3 to mbedtls_debug_set_threshold in socket_new -// #define MBEDTLS_DEBUG_C - // Set mbedtls configuration -#define MBEDTLS_DEPRECATED_REMOVED -#define MBEDTLS_AES_ROM_TABLES -#define MBEDTLS_CIPHER_MODE_CBC #define MBEDTLS_CIPHER_MODE_CTR // needed for MICROPY_PY_UCRYPTOLIB_CTR -#define MBEDTLS_ECP_DP_SECP192R1_ENABLED -#define MBEDTLS_ECP_DP_SECP224R1_ENABLED -#define MBEDTLS_ECP_DP_SECP256R1_ENABLED -#define MBEDTLS_ECP_DP_SECP384R1_ENABLED -#define MBEDTLS_ECP_DP_SECP521R1_ENABLED -#define MBEDTLS_ECP_DP_SECP192K1_ENABLED -#define MBEDTLS_ECP_DP_SECP224K1_ENABLED -#define MBEDTLS_ECP_DP_SECP256K1_ENABLED -#define MBEDTLS_ECP_DP_BP256R1_ENABLED -#define MBEDTLS_ECP_DP_BP384R1_ENABLED -#define MBEDTLS_ECP_DP_BP512R1_ENABLED -#define MBEDTLS_ECP_DP_CURVE25519_ENABLED -#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED -#define MBEDTLS_NO_PLATFORM_ENTROPY -#define MBEDTLS_PKCS1_V15 -#define MBEDTLS_SHA256_SMALLER -#define MBEDTLS_SSL_PROTO_TLS1 -#define MBEDTLS_SSL_PROTO_TLS1_1 -#define MBEDTLS_SSL_PROTO_TLS1_2 -#define MBEDTLS_SSL_SERVER_NAME_INDICATION - -// Use a smaller output buffer to reduce size of SSL context -#define MBEDTLS_SSL_MAX_CONTENT_LEN (16384) -#define MBEDTLS_SSL_IN_CONTENT_LEN (MBEDTLS_SSL_MAX_CONTENT_LEN) -#define MBEDTLS_SSL_OUT_CONTENT_LEN (4096) // Enable mbedtls modules -#define MBEDTLS_AES_C -#define MBEDTLS_ASN1_PARSE_C -#define MBEDTLS_BIGNUM_C -#define MBEDTLS_CIPHER_C -#define MBEDTLS_CTR_DRBG_C -#define MBEDTLS_ENTROPY_C -#define MBEDTLS_ERROR_C #define MBEDTLS_HAVEGE_C -#define MBEDTLS_MD_C -#define MBEDTLS_MD5_C -#define MBEDTLS_OID_C -#define MBEDTLS_PKCS5_C -#define MBEDTLS_PK_C -#define MBEDTLS_PK_PARSE_C -#define MBEDTLS_PLATFORM_C -#define MBEDTLS_RSA_C -#define MBEDTLS_SHA1_C -#define MBEDTLS_SHA256_C -#define MBEDTLS_SHA512_C -#define MBEDTLS_SSL_CLI_C -#define MBEDTLS_SSL_SRV_C -#define MBEDTLS_SSL_TLS_C #define MBEDTLS_TIMING_C #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE -#define MBEDTLS_X509_CRT_PARSE_C -#define MBEDTLS_X509_USE_C -#include "mbedtls/check_config.h" +// Include common mbedtls configuration. +#include "extmod/mbedtls/mbedtls_config_common.h" #endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_H */ From 9347545f9ee66210a835cb2f1e9860949feb139f Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 5 Oct 2022 10:48:31 +1100 Subject: [PATCH 0557/1041] extmod/mbedtls: Enable MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE. This was already enabled on all ports except mimxrt. Now it's enabled on all of them. Signed-off-by: Damien George --- extmod/mbedtls/mbedtls_config_common.h | 1 + ports/rp2/mbedtls/mbedtls_config.h | 1 - ports/stm32/mbedtls/mbedtls_config.h | 1 - ports/unix/mbedtls/mbedtls_config.h | 1 - 4 files changed, 1 insertion(+), 3 deletions(-) diff --git a/extmod/mbedtls/mbedtls_config_common.h b/extmod/mbedtls/mbedtls_config_common.h index 6c9385dea5..4c2be6228a 100644 --- a/extmod/mbedtls/mbedtls_config_common.h +++ b/extmod/mbedtls/mbedtls_config_common.h @@ -82,6 +82,7 @@ #define MBEDTLS_SSL_CLI_C #define MBEDTLS_SSL_SRV_C #define MBEDTLS_SSL_TLS_C +#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE #define MBEDTLS_X509_CRT_PARSE_C #define MBEDTLS_X509_USE_C diff --git a/ports/rp2/mbedtls/mbedtls_config.h b/ports/rp2/mbedtls/mbedtls_config.h index 61f622295f..9c930b7d9c 100644 --- a/ports/rp2/mbedtls/mbedtls_config.h +++ b/ports/rp2/mbedtls/mbedtls_config.h @@ -34,7 +34,6 @@ #define MBEDTLS_ECDH_C #define MBEDTLS_ECP_C #define MBEDTLS_GCM_C -#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE #define MBEDTLS_HAVE_TIME #define MBEDTLS_HAVE_TIME_DATE diff --git a/ports/stm32/mbedtls/mbedtls_config.h b/ports/stm32/mbedtls/mbedtls_config.h index b8548866f1..cc71aa7ec1 100644 --- a/ports/stm32/mbedtls/mbedtls_config.h +++ b/ports/stm32/mbedtls/mbedtls_config.h @@ -28,7 +28,6 @@ // Enable mbedtls modules // #define MBEDTLS_ECP_C -#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE // Set MicroPython-specific options. #define MICROPY_MBEDTLS_CONFIG_BARE_METAL (1) diff --git a/ports/unix/mbedtls/mbedtls_config.h b/ports/unix/mbedtls/mbedtls_config.h index c83f1c86f3..c8ffab0832 100644 --- a/ports/unix/mbedtls/mbedtls_config.h +++ b/ports/unix/mbedtls/mbedtls_config.h @@ -32,7 +32,6 @@ // Enable mbedtls modules #define MBEDTLS_HAVEGE_C #define MBEDTLS_TIMING_C -#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE // Include common mbedtls configuration. #include "extmod/mbedtls/mbedtls_config_common.h" From 8874a09119e74bb0edf73a63495b559d983767b7 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 5 Oct 2022 11:02:47 +1100 Subject: [PATCH 0558/1041] extmod/mbedtls: Enable elliptic curve DH and DSA cryptography. This is necessary to access sites that only support these protocols. The rp2 port already has ECDH enabled, so this just adds ECDSA there. The other ports now gain both ECDH and ECDSA. The code size increase is: - rp2 (PICO_W): +2916 bytes flash, +24 bytes BSS - stm32 (PYBD_SF6): +20480 bytes flash, +32 bytes data, +48 bytes BSS - mimxrt (TEENSY41): +20708 bytes flash, +32 bytes data, +48 bytes BSS - unix (standard x86-64): +39344 executable, +1744 bytes data, +96 BSS This is obviously a large increase in code size. But there doesn't seem to be any other option because without elliptic curve cryptography devices are partially cut off from the internet. For use cases that require small firmware size, they'll need to build custom firmware with a custom mbedtls config. Signed-off-by: Damien George --- extmod/mbedtls/mbedtls_config_common.h | 6 ++++++ ports/mimxrt/mbedtls/mbedtls_config.h | 3 --- ports/rp2/mbedtls/mbedtls_config.h | 2 -- ports/stm32/mbedtls/mbedtls_config.h | 3 --- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/extmod/mbedtls/mbedtls_config_common.h b/extmod/mbedtls/mbedtls_config_common.h index 4c2be6228a..252f293e03 100644 --- a/extmod/mbedtls/mbedtls_config_common.h +++ b/extmod/mbedtls/mbedtls_config_common.h @@ -47,6 +47,8 @@ #define MBEDTLS_ECP_DP_BP512R1_ENABLED #define MBEDTLS_ECP_DP_CURVE25519_ENABLED #define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +// #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED // enabling this currently breaks ssl_data.py test +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED #define MBEDTLS_NO_PLATFORM_ENTROPY #define MBEDTLS_PKCS1_V15 #define MBEDTLS_SHA256_SMALLER @@ -63,9 +65,13 @@ // Enable mbedtls modules. #define MBEDTLS_AES_C #define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_CIPHER_C #define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_ECDH_C +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECP_C #define MBEDTLS_ENTROPY_C #define MBEDTLS_ERROR_C #define MBEDTLS_MD_C diff --git a/ports/mimxrt/mbedtls/mbedtls_config.h b/ports/mimxrt/mbedtls/mbedtls_config.h index cc71aa7ec1..4140bb5145 100644 --- a/ports/mimxrt/mbedtls/mbedtls_config.h +++ b/ports/mimxrt/mbedtls/mbedtls_config.h @@ -26,9 +26,6 @@ #ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H #define MICROPY_INCLUDED_MBEDTLS_CONFIG_H -// Enable mbedtls modules -// #define MBEDTLS_ECP_C - // Set MicroPython-specific options. #define MICROPY_MBEDTLS_CONFIG_BARE_METAL (1) diff --git a/ports/rp2/mbedtls/mbedtls_config.h b/ports/rp2/mbedtls/mbedtls_config.h index 9c930b7d9c..1b6d3dd43a 100644 --- a/ports/rp2/mbedtls/mbedtls_config.h +++ b/ports/rp2/mbedtls/mbedtls_config.h @@ -31,8 +31,6 @@ #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED // Enable mbedtls modules -#define MBEDTLS_ECDH_C -#define MBEDTLS_ECP_C #define MBEDTLS_GCM_C #define MBEDTLS_HAVE_TIME #define MBEDTLS_HAVE_TIME_DATE diff --git a/ports/stm32/mbedtls/mbedtls_config.h b/ports/stm32/mbedtls/mbedtls_config.h index cc71aa7ec1..4140bb5145 100644 --- a/ports/stm32/mbedtls/mbedtls_config.h +++ b/ports/stm32/mbedtls/mbedtls_config.h @@ -26,9 +26,6 @@ #ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H #define MICROPY_INCLUDED_MBEDTLS_CONFIG_H -// Enable mbedtls modules -// #define MBEDTLS_ECP_C - // Set MicroPython-specific options. #define MICROPY_MBEDTLS_CONFIG_BARE_METAL (1) From e24159dec9588d83fc532aa6fcc2f418aae9df85 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 11 Oct 2022 19:22:48 +1100 Subject: [PATCH 0559/1041] extmod/mbedtls: Remove MBEDTLS_ECP_DP_CURVE25519_ENABLED config. Curve25519 arithmetic is supported in mbedtls, but it's not used for TLS. So there's no need to have this option enabled. Reduces rp2 PICO_W firmware by 2440 bytes. Thanks to @Carglglz for the information. Signed-off-by: Damien George --- extmod/mbedtls/mbedtls_config_common.h | 1 - 1 file changed, 1 deletion(-) diff --git a/extmod/mbedtls/mbedtls_config_common.h b/extmod/mbedtls/mbedtls_config_common.h index 252f293e03..9ec2af8553 100644 --- a/extmod/mbedtls/mbedtls_config_common.h +++ b/extmod/mbedtls/mbedtls_config_common.h @@ -45,7 +45,6 @@ #define MBEDTLS_ECP_DP_BP256R1_ENABLED #define MBEDTLS_ECP_DP_BP384R1_ENABLED #define MBEDTLS_ECP_DP_BP512R1_ENABLED -#define MBEDTLS_ECP_DP_CURVE25519_ENABLED #define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED // #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED // enabling this currently breaks ssl_data.py test #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED From 68f166dae9ad6dfd94038d5f4394defbb44238af Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 11 Oct 2022 19:25:05 +1100 Subject: [PATCH 0560/1041] extmod/mbedtls: Remove brainpool curves from config. They are much slower than NIST (SECP) curves and shouldn't be needed. Reduces rp2 PICO_W firmware by 1328 bytes. Thanks to @Carglglz for the information. Signed-off-by: Damien George --- extmod/mbedtls/mbedtls_config_common.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/extmod/mbedtls/mbedtls_config_common.h b/extmod/mbedtls/mbedtls_config_common.h index 9ec2af8553..bfbc6f7ba2 100644 --- a/extmod/mbedtls/mbedtls_config_common.h +++ b/extmod/mbedtls/mbedtls_config_common.h @@ -42,9 +42,6 @@ #define MBEDTLS_ECP_DP_SECP192K1_ENABLED #define MBEDTLS_ECP_DP_SECP224K1_ENABLED #define MBEDTLS_ECP_DP_SECP256K1_ENABLED -#define MBEDTLS_ECP_DP_BP256R1_ENABLED -#define MBEDTLS_ECP_DP_BP384R1_ENABLED -#define MBEDTLS_ECP_DP_BP512R1_ENABLED #define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED // #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED // enabling this currently breaks ssl_data.py test #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED From b161abc574b8e4fb2b00ef76be2b9c8967e18584 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 18 Oct 2022 00:18:54 +1100 Subject: [PATCH 0561/1041] py/obj: Verify floating point type is correct for repr C. Prevents double-precision floats being enabled on 32-bit architectures where they will not fit into the mp_obj_t encoding. Signed-off-by: Jim Mussared --- py/obj.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/py/obj.h b/py/obj.h index 8aa5b0a8e6..8d62dd4f3c 100644 --- a/py/obj.h +++ b/py/obj.h @@ -173,6 +173,10 @@ static inline bool mp_obj_is_obj(mp_const_obj_t o) { #elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_NONE +#error "MICROPY_OBJ_REPR_C requires float to be enabled." +#endif + static inline bool mp_obj_is_small_int(mp_const_obj_t o) { return (((mp_int_t)(o)) & 1) != 0; } @@ -189,6 +193,9 @@ static inline bool mp_obj_is_small_int(mp_const_obj_t o) { #endif static inline bool mp_obj_is_float(mp_const_obj_t o) { + // Ensure that 32-bit arch can only use single precision. + MP_STATIC_ASSERT(sizeof(mp_float_t) <= sizeof(mp_obj_t)); + return (((mp_uint_t)(o)) & 3) == 2 && (((mp_uint_t)(o)) & 0xff800007) != 0x00000006; } static inline mp_float_t mp_obj_float_get(mp_const_obj_t o) { From 5ee1cb27711d3747747db3ecd7b761c2a064addf Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 18 Oct 2022 00:22:53 +1100 Subject: [PATCH 0562/1041] stm32/boards/ARDUINO_PORTENTA_H7: Revert to single-precision float. Using repr C is incompatible with double-precision floats on 32-bit arch. Signed-off-by: Jim Mussared --- ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.mk b/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.mk index e5b48d0644..7151a5abc5 100644 --- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.mk +++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.mk @@ -10,7 +10,7 @@ BOOTLOADER_DFU_USB_PID = 0x035b # MCU settings MCU_SERIES = h7 CMSIS_MCU = STM32H747xx -MICROPY_FLOAT_IMPL = double +MICROPY_FLOAT_IMPL = single AF_FILE = boards/stm32h743_af.csv LD_FILES = boards/ARDUINO_PORTENTA_H7/stm32h747.ld TEXT0_ADDR = 0x08040000 From 1ba0e8ff96334af986d2b7d90f6d86af27595d28 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 20 Oct 2022 13:14:25 +1100 Subject: [PATCH 0563/1041] py/persistentcode: Only emit sub-version if generated code has native. In order for v1.19.1 to load a .mpy, the formerly-feature-flags which are now used for the sub-version must be zero. The sub-version is only used to indicate a native version change, so it should be zero when emitting bytecode-only .mpy files. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared --- py/persistentcode.c | 7 ++----- tools/mpy-tool.py | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/py/persistentcode.c b/py/persistentcode.c index 67c8f327f0..5408f756cf 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -591,21 +591,18 @@ void mp_raw_code_save(mp_compiled_module_t *cm, mp_print_t *print) { // header contains: // byte 'M' // byte version - // byte feature flags + // byte native arch (and sub-version if native) // byte number of bits in a small int byte header[4] = { 'M', MPY_VERSION, - MPY_FEATURE_ENCODE_SUB_VERSION(MPY_SUB_VERSION), + cm->has_native ? MPY_FEATURE_ENCODE_SUB_VERSION(MPY_SUB_VERSION) | MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH_DYNAMIC) : 0, #if MICROPY_DYNAMIC_COMPILER mp_dynamic_compiler.small_int_bits, #else MP_SMALL_INT_BITS, #endif }; - if (cm->has_native) { - header[2] |= MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH_DYNAMIC); - } mp_print_bytes(print, header, sizeof(header)); // Number of entries in constant table. diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 8b644c137f..0b8a0403ca 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -1676,7 +1676,7 @@ def merge_mpy(compiled_modules, output_file): header = bytearray(4) header[0] = ord("M") header[1] = config.MPY_VERSION - header[2] = config.native_arch << 2 | config.MPY_SUB_VERSION + header[2] = config.native_arch << 2 | config.MPY_SUB_VERSION if config.native_arch else 0 header[3] = config.mp_small_int_bits merged_mpy.extend(header) From edc3f3d0d3c4099dc6bce5371df0e1c3c5a4aecb Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 29 Jun 2022 15:31:21 +0200 Subject: [PATCH 0564/1041] samd/clock_config: Extend the range of machine.freq(). The value given for machine.freq(f) is extend to the range of 1_000_000 to 200_000_000. Frequencies below 48 MHz will be forced to an integer fraction of 48 MHz. At frequencies below 8 MHz USB is switched off. The power consumption e.g. of ADAFRUIT_ITSYBITSY_M4_EXPRESS drops to about 1.5 mA at 1 MHz. Since the peripheral frequency is dropped as well, timing e.g. of PWM, UART, I2C and SPI is affected and frequency/baud rate has to set again after a frequency change below 48 MHz. --- ports/samd/mcu/samd51/clock_config.c | 68 ++++++++++++++++++++-------- ports/samd/modmachine.c | 4 +- ports/samd/samd_soc.c | 2 +- 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/ports/samd/mcu/samd51/clock_config.c b/ports/samd/mcu/samd51/clock_config.c index 31c8f5a865..9fb48705ad 100644 --- a/ports/samd/mcu/samd51/clock_config.c +++ b/ports/samd/mcu/samd51/clock_config.c @@ -54,35 +54,63 @@ uint32_t get_peripheral_freq(void) { } void set_cpu_freq(uint32_t cpu_freq_arg) { - cpu_freq = cpu_freq_arg; // Setup GCLK0 for 48MHz as default state to keep the MCU running during config change. GCLK->GENCTRL[0].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; while (GCLK->SYNCBUSY.bit.GENCTRL0) { } - // Setup DPLL0 for 120 MHz // first: disable DPLL0 in case it is running OSCCTRL->Dpll[0].DPLLCTRLA.bit.ENABLE = 0; while (OSCCTRL->Dpll[0].DPLLSYNCBUSY.bit.ENABLE == 1) { } - // Now configure the registers - OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(1) | OSCCTRL_DPLLCTRLB_LBYPASS | - OSCCTRL_DPLLCTRLB_REFCLK(0) | OSCCTRL_DPLLCTRLB_WUF | OSCCTRL_DPLLCTRLB_FILTER(0x01); + if (cpu_freq_arg > DFLL48M_FREQ) { - uint32_t div = cpu_freq / DPLLx_REF_FREQ; - uint32_t frac = (cpu_freq - div * DPLLx_REF_FREQ) / (DPLLx_REF_FREQ / 32); - OSCCTRL->Dpll[0].DPLLRATIO.reg = (frac << 16) + div - 1; - // enable it again - OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE | OSCCTRL_DPLLCTRLA_RUNSTDBY; + cpu_freq = cpu_freq_arg; + peripheral_freq = DFLL48M_FREQ; + // Now configure the registers + OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(1) | OSCCTRL_DPLLCTRLB_LBYPASS | + OSCCTRL_DPLLCTRLB_REFCLK(0) | OSCCTRL_DPLLCTRLB_WUF | OSCCTRL_DPLLCTRLB_FILTER(0x01); - // Per errata 2.13.1 - while (!(OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY == 1)) { + uint32_t div = cpu_freq / DPLLx_REF_FREQ; + uint32_t frac = (cpu_freq - div * DPLLx_REF_FREQ) / (DPLLx_REF_FREQ / 32); + OSCCTRL->Dpll[0].DPLLRATIO.reg = (frac << 16) + div - 1; + // enable it again + OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE | OSCCTRL_DPLLCTRLA_RUNSTDBY; + + // Per errata 2.13.1 + while (!(OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY == 1)) { + } + // Setup GCLK0 for DPLL0 output (48 or 48-200MHz) + GCLK->GENCTRL[0].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DPLL0; + while (GCLK->SYNCBUSY.bit.GENCTRL0) { + } + // Set GCLK 2 back to 48 MHz + GCLK->GENCTRL[2].reg = GCLK_GENCTRL_DIV(1) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; + while (GCLK->SYNCBUSY.bit.GENCTRL2) { + } + } else { + int div = DFLL48M_FREQ / cpu_freq_arg; + // Setup GCLK1 for the low freq + GCLK->GENCTRL[2].reg = GCLK_GENCTRL_DIV(div) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; + while (GCLK->SYNCBUSY.bit.GENCTRL2) { + } + GCLK->GENCTRL[0].reg = GCLK_GENCTRL_DIV(div) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; + while (GCLK->SYNCBUSY.bit.GENCTRL0) { + } + peripheral_freq = DFLL48M_FREQ / div; + cpu_freq = DFLL48M_FREQ / div; } - - // Setup GCLK0 for DPLL0 output (48 or 48-200MHz) - GCLK->GENCTRL[0].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DPLL0; - while (GCLK->SYNCBUSY.bit.GENCTRL0) { + if (cpu_freq >= 8000000) { + // Setup GCLK5 for DFLL48M output (48 MHz) + GCLK->GENCTRL[5].reg = GCLK_GENCTRL_DIV(1) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; + while (GCLK->SYNCBUSY.bit.GENCTRL5) { + } + } else { + // Setup GCLK5 off if CPU Clk < 8 MHz + GCLK->GENCTRL[5].reg = 0; + while (GCLK->SYNCBUSY.bit.GENCTRL5) { + } } } @@ -120,9 +148,10 @@ void init_clocks(uint32_t cpu_freq) { // SAMD51 clock settings // GCLK0: 48MHz from DFLL48M or 48 - 200 MHz from DPLL0 (SAMD51) // GCLK1: 32768 Hz from 32KULP or DFLL48M - // GCLK2: 48MHz from DFLL48M for Peripheral devices - // GCLK3: 16Mhz for the us-counter (TC0/TC1) + // GCLK2: 8-48MHz from DFLL48M for Peripheral devices + // GCLK3: 8Mhz for the us-counter (TC0/TC1) // GCLK4: 32kHz from crystal, if present + // GCLK5: 48MHz from DFLL48M for USB // DPLL0: 48 - 200 MHz // Steps to set up clocks: @@ -136,6 +165,7 @@ void init_clocks(uint32_t cpu_freq) { // Setup GCLK2 to 48MHz for Peripherals // Setup GCLK3 to 8MHz for TC0/TC1 // Setup GCLK4 to 32kHz crystal, if present + // Setup GCLK5 to 48 MHz // Setup GCLK0 for 48MHz as default state to keep the MCU running during config change. GCLK->GENCTRL[0].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; @@ -238,7 +268,7 @@ void init_clocks(uint32_t cpu_freq) { peripheral_freq = DFLL48M_FREQ; // To be changed if CPU_FREQ < 48M - // Setup GCLK2 for DPLL1 output (48 MHz) + // Setup GCLK2 for DFLL48M output (48 MHz), may be scaled down later by calls to set_cpu_freq GCLK->GENCTRL[2].reg = GCLK_GENCTRL_DIV(1) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; while (GCLK->SYNCBUSY.bit.GENCTRL2) { } diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index b9de026ed4..d16b660645 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -69,9 +69,9 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { } else { #if defined(MCU_SAMD51) uint32_t freq = mp_obj_get_int(args[0]); - if (freq >= 48000000 && freq <= 200000000) { + if (freq >= 1000000 && freq <= 200000000) { set_cpu_freq(freq); - SysTick_Config(freq / 1000); + SysTick_Config(get_cpu_freq() / 1000); } #endif return mp_const_none; diff --git a/ports/samd/samd_soc.c b/ports/samd/samd_soc.c index f4a27f3df7..113529aeea 100644 --- a/ports/samd/samd_soc.c +++ b/ports/samd/samd_soc.c @@ -46,7 +46,7 @@ static void usb_init(void) { PM->APBBMASK.bit.USB_ = 1; uint8_t alt = 6; // alt G, USB #elif defined(MCU_SAMD51) - GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK2; + GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK5; while (GCLK->PCHCTRL[USB_GCLK_ID].bit.CHEN == 0) { } MCLK->AHBMASK.bit.USB_ = 1; From 1c32cec7f11864a9bc67f988e39e7dfc7c33188e Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 29 Jun 2022 17:22:20 +0200 Subject: [PATCH 0565/1041] samd/clock_config: Support changing machine.freq() for SAMD21. The range is 1MHz - 48 MHz. Note that below 8 MHz there is no USB support. The frequency will be set to an integer fraction of 48 MHz. And after changing the frequency, the peripherals like PWM, UART, I2C, SPI have to be reconfigured. Current consumption e.g. of the Seeed Xiao board at 1 MHz is about 1.5 mA, mostly caused by the on-board LED (green LED with 1k resistor at 3.3V). --- ports/samd/mcu/samd21/clock_config.c | 43 +++++++++++++++++++++------- ports/samd/mcu/samd21/mpconfigmcu.h | 1 + ports/samd/mcu/samd51/mpconfigmcu.h | 1 + ports/samd/modmachine.c | 4 +-- ports/samd/samd_soc.c | 2 +- 5 files changed, 36 insertions(+), 15 deletions(-) diff --git a/ports/samd/mcu/samd21/clock_config.c b/ports/samd/mcu/samd21/clock_config.c index 2402ed2e31..204a5294f2 100644 --- a/ports/samd/mcu/samd21/clock_config.c +++ b/ports/samd/mcu/samd21/clock_config.c @@ -51,7 +51,36 @@ uint32_t get_peripheral_freq(void) { } void set_cpu_freq(uint32_t cpu_freq_arg) { - cpu_freq = cpu_freq_arg; + + // Set 1 waitstate to be safe + NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_MANW | NVMCTRL_CTRLB_RWS(1); + + int div = DFLL48M_FREQ / cpu_freq_arg; + peripheral_freq = cpu_freq = DFLL48M_FREQ / div; + + // Enable GCLK output: 48M on both CCLK0 and GCLK2 + GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) | GCLK_GENDIV_DIV(div); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(0); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + GCLK->GENDIV.reg = GCLK_GENDIV_ID(2) | GCLK_GENDIV_DIV(div); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(2); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + if (cpu_freq >= 8000000) { + // Enable GCLK output: 48MHz on GCLK5 for USB + GCLK->GENDIV.reg = GCLK_GENDIV_ID(5) | GCLK_GENDIV_DIV(1); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(5); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + } else { + // Disable GCLK output on GCLK5 for USB, since USB is not reliable below 8 Mhz. + GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(5); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + } + // Set 0 waitstates for slower CPU clock + NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_MANW | NVMCTRL_CTRLB_RWS(cpu_freq > 24000000 ? 1 : 0); } void check_usb_recovery_mode(void) { @@ -76,6 +105,7 @@ void init_clocks(uint32_t cpu_freq) { // GCLK2: 48MHz from DFLL for Peripherals // GCLK3: 1Mhz for the us-counter (TC4/TC5) // GCLK4: 32kHz from crystal, if present + // GCLK5: 48MHz from DFLL for USB // GCLK8: 1kHz clock for WDT NVMCTRL->CTRLB.bit.MANW = 1; // errata "Spurious Writes" @@ -180,15 +210,7 @@ void init_clocks(uint32_t cpu_freq) { #endif // MICROPY_HW_XOSC32K - // Enable GCLK output: 48M on both CCLK0 and GCLK2 - GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) | GCLK_GENDIV_DIV(1); - GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(0); - while (GCLK->STATUS.bit.SYNCBUSY) { - } - GCLK->GENDIV.reg = GCLK_GENDIV_ID(2) | GCLK_GENDIV_DIV(1); - GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(2); - while (GCLK->STATUS.bit.SYNCBUSY) { - } + set_cpu_freq(cpu_freq); // Enable GCLK output: 1MHz on GCLK3 for TC4 GCLK->GENDIV.reg = GCLK_GENDIV_ID(3) | GCLK_GENDIV_DIV(48); @@ -200,7 +222,6 @@ void init_clocks(uint32_t cpu_freq) { GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(8); while (GCLK->STATUS.bit.SYNCBUSY) { } - } void enable_sercom_clock(int id) { diff --git a/ports/samd/mcu/samd21/mpconfigmcu.h b/ports/samd/mcu/samd21/mpconfigmcu.h index a84b31276b..e0af60552b 100644 --- a/ports/samd/mcu/samd21/mpconfigmcu.h +++ b/ports/samd/mcu/samd21/mpconfigmcu.h @@ -19,6 +19,7 @@ #define CPU_FREQ (48000000) #define DFLL48M_FREQ (48000000) +#define MAX_CPU_FREQ (48000000) #define IRQ_PRI_PENDSV ((1 << __NVIC_PRIO_BITS) - 1) diff --git a/ports/samd/mcu/samd51/mpconfigmcu.h b/ports/samd/mcu/samd51/mpconfigmcu.h index 19193992f0..819bc1bb11 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.h +++ b/ports/samd/mcu/samd51/mpconfigmcu.h @@ -26,6 +26,7 @@ unsigned long trng_random_u32(void); #define CPU_FREQ (120000000) #define DFLL48M_FREQ (48000000) +#define MAX_CPU_FREQ (200000000) #define DPLLx_REF_FREQ (32768) #define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003) diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index d16b660645..21d700ac31 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -67,13 +67,11 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { return MP_OBJ_NEW_SMALL_INT(get_cpu_freq()); } else { - #if defined(MCU_SAMD51) uint32_t freq = mp_obj_get_int(args[0]); - if (freq >= 1000000 && freq <= 200000000) { + if (freq >= 1000000 && freq <= MAX_CPU_FREQ) { set_cpu_freq(freq); SysTick_Config(get_cpu_freq() / 1000); } - #endif return mp_const_none; } } diff --git a/ports/samd/samd_soc.c b/ports/samd/samd_soc.c index 113529aeea..6d8348ebcd 100644 --- a/ports/samd/samd_soc.c +++ b/ports/samd/samd_soc.c @@ -41,7 +41,7 @@ static void usb_init(void) { // Init USB clock #if defined(MCU_SAMD21) - GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_USB; + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK5 | GCLK_CLKCTRL_ID_USB; PM->AHBMASK.bit.USB_ = 1; PM->APBBMASK.bit.USB_ = 1; uint8_t alt = 6; // alt G, USB From 64e3c351de0959660d1a6b691ee7dbf2de565fbe Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 29 Jun 2022 14:09:57 +0200 Subject: [PATCH 0566/1041] samd/modmachine: Add machine.reset_cause(). --- ports/samd/modmachine.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index 21d700ac31..db3f159cc2 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -139,6 +139,17 @@ STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) { } MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq); +STATIC mp_obj_t machine_reset_cause(void) { + #if defined(MCU_SAMD21) + return MP_OBJ_NEW_SMALL_INT(PM->RCAUSE.reg); + #elif defined(MCU_SAMD51) + return MP_OBJ_NEW_SMALL_INT(RSTC->RCAUSE.reg); + #else + return MP_OBJ_NEW_SMALL_INT(0); + #endif +} +MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause); + STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, @@ -165,8 +176,18 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) }, + { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) }, { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, { MP_ROM_QSTR(MP_QSTR_bitstream), MP_ROM_PTR(&machine_bitstream_obj) }, + + // Class constants. + // Use numerical constants instead of the symbolic names, + // since the names differ between SAMD21 and SAMD51. + { MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(0x01) }, + { MP_ROM_QSTR(MP_QSTR_HARD_RESET), MP_ROM_INT(0x10) }, + { MP_ROM_QSTR(MP_QSTR_WDT_RESET), MP_ROM_INT(0x20) }, + { MP_ROM_QSTR(MP_QSTR_SOFT_RESET), MP_ROM_INT(0x40) }, + { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_ROM_INT(0x80) }, }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); From 0d3f0d7470586f9c328a047ac3043420df16d4ab Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 2 Jul 2022 18:12:55 +0200 Subject: [PATCH 0567/1041] samd/boards/SPARKFUN_SAMD51_THING_PLUS: Add board files for Thing Plus. That device uses an SAMD51J20 MCU with 256k RAM and 1024k flash. --- .../SPARKFUN_SAMD51_THING_PLUS/board.json | 21 ++++++++++ .../mpconfigboard.h | 4 ++ .../mpconfigboard.mk | 8 ++++ .../SPARKFUN_SAMD51_THING_PLUS/pins.csv | 42 +++++++++++++++++++ ports/samd/boards/samd51x20a.ld | 20 +++++++++ 5 files changed, 95 insertions(+) create mode 100644 ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json create mode 100644 ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h create mode 100644 ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk create mode 100644 ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/pins.csv create mode 100644 ports/samd/boards/samd51x20a.ld diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json new file mode 100644 index 0000000000..af643f5c5f --- /dev/null +++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json @@ -0,0 +1,21 @@ +{ + "deploy": [ + "../deploy.md" + ], + "docs": "", + "features": [ + "Battery Charging", + "Breadboard Friendly", + "Micro USB", + "QWIIC", + "SPI Flash" + ], + "images": [ + "sparkfun_samd51_thing_plus.jpg" + ], + "mcu": "samd51", + "product": "Sparkfun SAMD51 Thing Plus", + "thumbnail": "", + "url": "https://www.sparkfun.com/products/14713", + "vendor": "Sparkfun" +} diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h new file mode 100644 index 0000000000..e797ccca9d --- /dev/null +++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h @@ -0,0 +1,4 @@ +#define MICROPY_HW_BOARD_NAME "Sparkfun SAMD51 Thing Plus" +#define MICROPY_HW_MCU_NAME "SAMD51J20A" + +#define MICROPY_HW_XOSC32K (1) diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk new file mode 100644 index 0000000000..9e5cf887df --- /dev/null +++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk @@ -0,0 +1,8 @@ +MCU_SERIES = SAMD51 +CMSIS_MCU = SAMD51J20A +LD_FILES = boards/samd51x20a.ld sections.ld +TEXT0 = 0x4000 + +# The ?='s allow overriding in mpconfigboard.mk. +# MicroPython settings +MICROPY_VFS_LFS1 ?= 1 diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/pins.csv b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/pins.csv new file mode 100644 index 0000000000..b60fb90971 --- /dev/null +++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/pins.csv @@ -0,0 +1,42 @@ +# Pin rows contain Pin number and pin name. +# Pin rows start with PIN_ +# LED rows start with LED_ +# If the pin name is omitted, the pin number is added as name. +# Rows for empty entries have to start with '-' +# Empty lines and lines not starting with PIN_ or LED_ are ignored + +PIN_PA13,D0 +PIN_PA12,D1 +PIN_PB23,RXD +PIN_PB22,TXD +PIN_PA06,D4 +PIN_PA15,D5 +PIN_PA20,D6 +PIN_PA21,D7 +- +PIN_PA07,D9 +PIN_PA18,D10 +PIN_PA16,D11 +PIN_PA19,D12 +PIN_PA17,D13 +PIN_PA02,A0 +PIN_PB08,A1 +PIN_PB09,A2 +PIN_PA04,A3 +PIN_PA05,A4 +PIN_PB02,A5 +PIN_PA22,SDA +PIN_PA23,SCL +PIN_PB12,MOSI +PIN_PB11,MISO +PIN_PB13,SCK +PIN_PA08,FLASH_MOSI +PIN_PA09,FLASH_SCK +PIN_PA10,FLASH_CS +PIN_PA11,FLASH_MISO +PIN_PA30,SWDCLK +PIN_PA31,SWDIO + +LED_PA17,LED +LED_PB03,RXLED +LED_PA27,TXLED diff --git a/ports/samd/boards/samd51x20a.ld b/ports/samd/boards/samd51x20a.ld new file mode 100644 index 0000000000..f0d5e5c6ae --- /dev/null +++ b/ports/samd/boards/samd51x20a.ld @@ -0,0 +1,20 @@ +/* + GNU linker script for SAMD51x20 +*/ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00004000, LENGTH = 1024K - 16K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K +} + +/* Top end of the stack, with room for double-tap variable */ +_estack = ORIGIN(RAM) + LENGTH(RAM) - 8; +_sstack = _estack - 16K; + +_oflash_fs = ORIGIN(FLASH) + 384K - 16K; +_sflash_fs = LENGTH(FLASH) - 384K + 16K - 1; + +_sheap = _ebss; +_eheap = _sstack; From a7113e95d78583a47f8074965e17d1e0499e0494 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 7 Jul 2022 09:49:51 +0200 Subject: [PATCH 0568/1041] samd/modmachine: Add machine.dht_readinto and enable on SAMD51. --- ports/samd/mcu/samd51/mpconfigmcu.h | 1 + ports/samd/mcu/samd51/mpconfigmcu.mk | 2 ++ ports/samd/modmachine.c | 4 ++++ ports/samd/mphalport.h | 3 +++ 4 files changed, 10 insertions(+) diff --git a/ports/samd/mcu/samd51/mpconfigmcu.h b/ports/samd/mcu/samd51/mpconfigmcu.h index 819bc1bb11..a266adf93c 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.h +++ b/ports/samd/mcu/samd51/mpconfigmcu.h @@ -13,6 +13,7 @@ #define MP_NEED_LOG2 (1) #define MICROPY_PY_CMATH (0) +#define MICROPY_PY_MACHINE_DHT_READINTO (1) #define MICROPY_PY_UOS_URANDOM (1) #define MICROPY_PY_URANDOM_SEED_INIT_FUNC (trng_random_u32()) unsigned long trng_random_u32(void); diff --git a/ports/samd/mcu/samd51/mpconfigmcu.mk b/ports/samd/mcu/samd51/mpconfigmcu.mk index f8ed02f841..ed4df82c69 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.mk +++ b/ports/samd/mcu/samd51/mpconfigmcu.mk @@ -2,6 +2,8 @@ MICROPY_VFS_LFS2 ?= 1 SRC_S += shared/runtime/gchelper_m3.s +SRC_C += drivers/dht/dht.c \ + LIBM_SRC_C += $(addprefix lib/libm/,\ acoshf.c \ asinfacosf.c \ diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index db3f159cc2..14baf279d5 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -30,6 +30,7 @@ #include "extmod/machine_pulse.h" #include "extmod/machine_i2c.h" #include "extmod/machine_spi.h" +#include "drivers/dht/dht.h" #include "modmachine.h" #include "samd_soc.h" @@ -179,6 +180,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) }, { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, { MP_ROM_QSTR(MP_QSTR_bitstream), MP_ROM_PTR(&machine_bitstream_obj) }, + #if MICROPY_PY_MACHINE_DHT_READINTO + { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) }, + #endif // Class constants. // Use numerical constants instead of the symbolic names, diff --git a/ports/samd/mphalport.h b/ports/samd/mphalport.h index 6f4f838cfb..3879240f9a 100644 --- a/ports/samd/mphalport.h +++ b/ports/samd/mphalport.h @@ -99,6 +99,9 @@ static inline uint64_t mp_hal_time_ns(void) { #define MP_HAL_PIN_FMT "%u" #define mp_hal_pin_obj_t uint +#define mp_hal_quiet_timing_enter() MICROPY_BEGIN_ATOMIC_SECTION() +#define mp_hal_quiet_timing_exit(irq_state) MICROPY_END_ATOMIC_SECTION(irq_state) + extern uint32_t machine_pin_open_drain_mask[]; mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t pin_in); From fe31fca462011785cf78b4730bf34bb552e9a707 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 21 Jun 2022 14:27:20 +0200 Subject: [PATCH 0569/1041] samd/mcu/samd51: Enable onewire support for SAMD51. --- ports/samd/mcu/samd51/mpconfigmcu.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/samd/mcu/samd51/mpconfigmcu.h b/ports/samd/mcu/samd51/mpconfigmcu.h index a266adf93c..5735f512b5 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.h +++ b/ports/samd/mcu/samd51/mpconfigmcu.h @@ -14,6 +14,7 @@ #define MICROPY_PY_CMATH (0) #define MICROPY_PY_MACHINE_DHT_READINTO (1) +#define MICROPY_PY_ONEWIRE (1) #define MICROPY_PY_UOS_URANDOM (1) #define MICROPY_PY_URANDOM_SEED_INIT_FUNC (trng_random_u32()) unsigned long trng_random_u32(void); From 4c9e4c3310faff5ec05b183454df88d0f33f9e78 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 10 Jul 2022 12:04:14 +0200 Subject: [PATCH 0570/1041] samd/mcu/samd51: Enable FAT support for SAMD51. Tested with a SD card connected to a SAMD51 board. The SEEED WIO terminal has a SD-Card reader built-in. Also a side change to remove a few obsolete lines from Makefile. --- ports/samd/Makefile | 4 --- ports/samd/fatfs_port.c | 41 ++++++++++++++++++++++++++++ ports/samd/mcu/samd51/mpconfigmcu.h | 6 ++++ ports/samd/mcu/samd51/mpconfigmcu.mk | 5 +++- ports/samd/modutime.c | 2 +- 5 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 ports/samd/fatfs_port.c diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 2f97b1993e..abec4e83a5 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -61,7 +61,6 @@ CFLAGS_MCU_SAMD51 = -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-a CFLAGS += $(INC) -Wall -Werror -std=c99 -nostdlib -mthumb $(CFLAGS_MCU_$(MCU_SERIES)) -fsingle-precision-constant -Wdouble-promotion CFLAGS += -DMCU_$(MCU_SERIES) -D__$(CMSIS_MCU)__ CFLAGS += $(CFLAGS_EXTRA) -CFLAGS += -DMPCONFIG_MCU_H='' LDFLAGS += -nostdlib $(addprefix -T,$(LD_FILES)) -Map=$@.map --cref @@ -169,9 +168,6 @@ CFLAGS += -DMICROPY_MODULE_FROZEN_STR CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool endif -# Workaround for bug in older gcc, warning on "static usbd_device_t _usbd_dev = { 0 };" -$(BUILD)/lib/tinyusb/src/device/usbd.o: CFLAGS += -Wno-missing-braces - all: $(BUILD)/firmware.uf2 $(BUILD)/firmware.elf: $(OBJ) diff --git a/ports/samd/fatfs_port.c b/ports/samd/fatfs_port.c new file mode 100644 index 0000000000..9ee1764ebc --- /dev/null +++ b/ports/samd/fatfs_port.c @@ -0,0 +1,41 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2021 Robert Hammelrath + * + * 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 "mphalport.h" +#include "py/runtime.h" +#include "shared/timeutils/timeutils.h" +#include "lib/oofatfs/ff.h" + +extern uint32_t time_offset; + +MP_WEAK DWORD get_fattime(void) { + timeutils_struct_time_t tm; + + timeutils_seconds_since_epoch_to_struct_time(mp_hal_ticks_ms_64() / 1000 + time_offset, &tm); + return ((tm.tm_year - 1980) << 25) | ((tm.tm_mon) << 21) | ((tm.tm_mday) << 16) | + ((tm.tm_hour) << 11) | ((tm.tm_min) << 5) | (tm.tm_sec / 2); +} diff --git a/ports/samd/mcu/samd51/mpconfigmcu.h b/ports/samd/mcu/samd51/mpconfigmcu.h index 5735f512b5..686cfd6104 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.h +++ b/ports/samd/mcu/samd51/mpconfigmcu.h @@ -22,6 +22,12 @@ unsigned long trng_random_u32(void); // Due to a limitation in the TC counter for us, the ticks period is 2**29 #define MICROPY_PY_UTIME_TICKS_PERIOD (0x20000000) +// fatfs configuration used in ffconf.h +#define MICROPY_FATFS_ENABLE_LFN (1) +#define MICROPY_FATFS_RPATH (2) +#define MICROPY_FATFS_MAX_SS (4096) +#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ + #define VFS_BLOCK_SIZE_BYTES (1536) // #define MICROPY_HW_UART_TXBUF (1) diff --git a/ports/samd/mcu/samd51/mpconfigmcu.mk b/ports/samd/mcu/samd51/mpconfigmcu.mk index ed4df82c69..305e780b87 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.mk +++ b/ports/samd/mcu/samd51/mpconfigmcu.mk @@ -1,8 +1,11 @@ MICROPY_VFS_LFS2 ?= 1 +MICROPY_VFS_FAT ?= 1 SRC_S += shared/runtime/gchelper_m3.s -SRC_C += drivers/dht/dht.c \ +SRC_C += \ + fatfs_port.c \ + drivers/dht/dht.c \ LIBM_SRC_C += $(addprefix lib/libm/,\ acoshf.c \ diff --git a/ports/samd/modutime.c b/ports/samd/modutime.c index a54544e62c..4169c15d91 100644 --- a/ports/samd/modutime.c +++ b/ports/samd/modutime.c @@ -29,7 +29,7 @@ #include "shared/timeutils/timeutils.h" #include "mphalport.h" -static uint32_t time_offset = 0; +uint32_t time_offset = 0; // localtime([secs]) STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { From 03075a68399a6450fd0e238dd75314805f8365b7 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 1 Aug 2022 17:23:11 +0200 Subject: [PATCH 0571/1041] samd/modmachine: Implement machine.lightsleep(). Which just sets the CPU clock to 200kHz and switches the peripheral clock off. There are two modes: machine.lightsleep(duration_ms) and machine.lightsleep() In any mode any configured pin.irq() event will terminate the sleep. Current consumption in lightsleep for some boards: - 1.5 - 2.5 mA when supplied trough an active USB (Seeed XIAO w/o power LED, Adafruit ItsyBitsy) - 0.8 - 2 mA when supplied through Gnd/+5V (Vusb) (Seeed XIAO w/o power LED, Adafruit ItsyBitsy) - < 1 mA for SAMD51 when supplied trough a battery connector (Sparkfun Thing SAMD51 plus) Related change: move the calls to SysTick_Config() into set_cpu_freq(). It is required after each CPU freq change to have ticks_ms run at the proper rate. --- ports/samd/machine_pin.c | 3 ++ ports/samd/mcu/samd21/clock_config.c | 1 + ports/samd/mcu/samd51/clock_config.c | 1 + ports/samd/modmachine.c | 61 +++++++++++++++++++++++++++- ports/samd/samd_soc.c | 1 - 5 files changed, 65 insertions(+), 2 deletions(-) diff --git a/ports/samd/machine_pin.c b/ports/samd/machine_pin.c index fc72c8f756..2dc10f9b46 100644 --- a/ports/samd/machine_pin.c +++ b/ports/samd/machine_pin.c @@ -57,6 +57,8 @@ typedef struct _machine_pin_irq_obj_t { STATIC const mp_irq_methods_t machine_pin_irq_methods; +bool EIC_occured; + uint32_t machine_pin_open_drain_mask[4]; // Open drain behaviour is simulated. @@ -410,6 +412,7 @@ void EIC_Handler() { for (int eic_id = 0; eic_id < 16; eic_id++, mask <<= 1) { // Did the ISR fire? if (isr & mask) { + EIC_occured = true; EIC->INTFLAG.reg |= mask; // clear the ISR flag machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]); if (irq != NULL) { diff --git a/ports/samd/mcu/samd21/clock_config.c b/ports/samd/mcu/samd21/clock_config.c index 204a5294f2..a4011c05cb 100644 --- a/ports/samd/mcu/samd21/clock_config.c +++ b/ports/samd/mcu/samd21/clock_config.c @@ -81,6 +81,7 @@ void set_cpu_freq(uint32_t cpu_freq_arg) { } // Set 0 waitstates for slower CPU clock NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_MANW | NVMCTRL_CTRLB_RWS(cpu_freq > 24000000 ? 1 : 0); + SysTick_Config(cpu_freq / 1000); } void check_usb_recovery_mode(void) { diff --git a/ports/samd/mcu/samd51/clock_config.c b/ports/samd/mcu/samd51/clock_config.c index 9fb48705ad..f67d297e8e 100644 --- a/ports/samd/mcu/samd51/clock_config.c +++ b/ports/samd/mcu/samd51/clock_config.c @@ -112,6 +112,7 @@ void set_cpu_freq(uint32_t cpu_freq_arg) { while (GCLK->SYNCBUSY.bit.GENCTRL5) { } } + SysTick_Config(cpu_freq / 1000); } void check_usb_recovery_mode(void) { diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index 14baf279d5..2a8e34a966 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -50,6 +50,10 @@ #define DBL_TAP_MAGIC_LOADER 0xf01669ef #define DBL_TAP_MAGIC_RESET 0xf02669ef +#define LIGHTSLEEP_CPU_FREQ 200000 + +extern bool EIC_occured; + STATIC mp_obj_t machine_reset(void) { *DBL_TAP_ADDR = DBL_TAP_MAGIC_RESET; NVIC_SystemReset(); @@ -71,7 +75,6 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { uint32_t freq = mp_obj_get_int(args[0]); if (freq >= 1000000 && freq <= MAX_CPU_FREQ) { set_cpu_freq(freq); - SysTick_Config(get_cpu_freq() / 1000); } return mp_const_none; } @@ -151,6 +154,60 @@ STATIC mp_obj_t machine_reset_cause(void) { } MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause); +STATIC mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) { + int32_t duration = -1; + uint32_t freq = get_cpu_freq(); + if (n_args > 0) { + duration = mp_obj_get_int(args[0]); + } + EIC_occured = false; + // Slow down + set_cpu_freq(LIGHTSLEEP_CPU_FREQ); + #if defined(MCU_SAMD21) + // Switch the peripheral clock off + GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(2); + while (GCLK->STATUS.bit.SYNCBUSY) { + } + // Switch the EIC temporarily to GCLK3, since GCLK2 is off + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK3 | EIC_GCLK_ID; + if (duration > 0) { + uint32_t t0 = systick_ms; + while ((systick_ms - t0 < duration) && (EIC_occured == false)) { + __WFI(); + } + } else { + while (EIC_occured == false) { + __WFI(); + } + } + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | EIC_GCLK_ID; + + #elif defined(MCU_SAMD51) + // Switch the peripheral clock off + GCLK->GENCTRL[2].reg = 0; + while (GCLK->SYNCBUSY.bit.GENCTRL2) { + } + // Switch the EIC temporarily to GCLK3, since GCLK2 is off + GCLK->PCHCTRL[EIC_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK3; + if (duration > 0) { + uint32_t t0 = systick_ms; + while ((systick_ms - t0 < duration) && (EIC_occured == false)) { + __WFI(); + } + } else { + while (EIC_occured == false) { + __WFI(); + } + } + GCLK->PCHCTRL[EIC_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK2; + + #endif + // Speed up again + set_cpu_freq(freq); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lightsleep_obj, 0, 1, machine_lightsleep); + STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, @@ -179,6 +236,8 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) }, { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, + { MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) }, + { MP_ROM_QSTR(MP_QSTR_bitstream), MP_ROM_PTR(&machine_bitstream_obj) }, #if MICROPY_PY_MACHINE_DHT_READINTO { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) }, diff --git a/ports/samd/samd_soc.c b/ports/samd/samd_soc.c index 6d8348ebcd..3608306e87 100644 --- a/ports/samd/samd_soc.c +++ b/ports/samd/samd_soc.c @@ -108,7 +108,6 @@ void init_us_counter(void) { void samd_init(void) { init_clocks(get_cpu_freq()); - SysTick_Config(get_cpu_freq() / 1000); init_us_counter(); usb_init(); check_usb_recovery_mode(); From f0399d35e4f7ad4e48b22f02b80a7ee506c9ec64 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 11 Aug 2022 11:22:58 +0200 Subject: [PATCH 0572/1041] samd/modmachine: Get the bootloader magic address from the lib. Instead of being hard-coded, and then it works for all MCUs. That fits except for a Sparkfun SAMD51 Thing Plus (known) bug, which uses 192k - 4 as magic address. Therefore, that address is set as well to avoid a problem when this bug is fixed by Sparkfun. --- .../SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h | 6 ++++++ ports/samd/modmachine.c | 14 +++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h index e797ccca9d..a51b71c363 100644 --- a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h +++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h @@ -2,3 +2,9 @@ #define MICROPY_HW_MCU_NAME "SAMD51J20A" #define MICROPY_HW_XOSC32K (1) + +// There seems to be an inconsistency in the SAMD51 Thing bootloader in that +// the bootloader magic address is at the end of a 192k RAM area, instead of +// 256k. Since the SAMD51x20A has 256k RAM, the loader symbol is at that address +// and so there is a fix here using the previous definition. +#define DBL_TAP_ADDR_ALT ((volatile uint32_t *)(HSRAM_ADDR + HSRAM_SIZE - 0x10000 - 4)) diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index 2a8e34a966..ce5fef76f7 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -41,21 +41,26 @@ #include "hpl_pm_base.h" #if MICROPY_PY_MACHINE - #if defined(MCU_SAMD21) -#define DBL_TAP_ADDR ((volatile uint32_t *)(0x20000000 + 32 * 1024 - 4)) +#define DBL_TAP_ADDR ((volatile uint32_t *)(HMCRAMC0_ADDR + HMCRAMC0_SIZE - 4)) #elif defined(MCU_SAMD51) -#define DBL_TAP_ADDR ((volatile uint32_t *)(0x20000000 + 192 * 1024 - 4)) +#define DBL_TAP_ADDR ((volatile uint32_t *)(HSRAM_ADDR + HSRAM_SIZE - 4)) #endif +// A board may define a DPL_TAP_ADDR_ALT, which will be set as well +// Needed at the moment for Sparkfun SAMD51 Thing Plus #define DBL_TAP_MAGIC_LOADER 0xf01669ef #define DBL_TAP_MAGIC_RESET 0xf02669ef #define LIGHTSLEEP_CPU_FREQ 200000 extern bool EIC_occured; +extern uint32_t _dbl_tap_addr; STATIC mp_obj_t machine_reset(void) { *DBL_TAP_ADDR = DBL_TAP_MAGIC_RESET; + #ifdef DBL_TAP_ADDR_ALT + *DBL_TAP_ADDR_ALT = DBL_TAP_MAGIC_RESET; + #endif NVIC_SystemReset(); return mp_const_none; } @@ -63,6 +68,9 @@ MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset); STATIC mp_obj_t machine_bootloader(void) { *DBL_TAP_ADDR = DBL_TAP_MAGIC_LOADER; + #ifdef DBL_TAP_ADDR_ALT + *DBL_TAP_ADDR_ALT = DBL_TAP_MAGIC_LOADER; + #endif NVIC_SystemReset(); return mp_const_none; } From ddd41b8bbf6823ea730e781d508babbecdd41304 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 13 Aug 2022 17:33:04 +0200 Subject: [PATCH 0573/1041] samd/clock_config: Document the #defines use in init_clocks(). Which may be set in the respective mpconfigboard.h files. --- ports/samd/mcu/samd21/clock_config.c | 34 +++++++++++++++++++++++ ports/samd/mcu/samd51/clock_config.c | 40 ++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/ports/samd/mcu/samd21/clock_config.c b/ports/samd/mcu/samd21/clock_config.c index a4011c05cb..a195cb6920 100644 --- a/ports/samd/mcu/samd21/clock_config.c +++ b/ports/samd/mcu/samd21/clock_config.c @@ -96,6 +96,40 @@ void check_usb_recovery_mode(void) { #endif // MICROPY_HW_XOSC32K } +// Purpose of the #defines for the clock configuration. +// +// Both CPU and periperal devices are clocked by the DFLL48M clock. +// DFLL48M is either free running, or controlled by the 32kHz crystal, or +// Synchronized with the USB clock. +// +// #define MICROPY_HW_XOSC32K (0 | 1) +// +// If MICROPY_HW_XOSC32K = 1, the 32kHz crystal is used as input for GCLK 1, which +// serves as refernce clock source for the DFLL48M oscillator, +// The crystal is used, unless MICROPY_HW_MCU_OSC32KULP is set. +// In that case GCLK1 (and the CPU clock) is driven by the 32K Low power oscillator. +// The reason for offering this option is a design flaw of the Adafruit +// Feather boards, where the RGB Led and Debug signals interfere with the +// crystal, causing the CPU to fail if it is driven by the crystal. +// +// If MICROPY_HW_XOSC32K = 0, the 32kHz signal for GCLK1 (and the CPU) is +// created by dividing the 48MHz clock of DFLL48M, but not used otherwise. +// +// If MICROPY_HW_DFLL_USB_SYNC = 0, the DFLL48M oscillator is free running using +// the pre-configured trim values. In that mode, the peripheral clock is +// not exactly 48Mhz and has a substantional temperature drift. +// +// If MICROPY_HW_DFLL_USB_SYNC = 1, the DFLL48 is synchronized with the 1 kHz USB sync +// signal. If after boot there is no USB sync withing 500ms, the configuratuion falls +// back to a free running 48Mhz oscillator. +// +// In all modes, the 48MHz signal has a substantial jitter, largest when +// MICROPY_HW_DFLL_USB_SYNC is active. That is caused by the repective +// reference frequencies of 32kHz or 1 kHz being low. That affects most +// PWM. Std Dev at 1kHz 0.156Hz (w. Crystal) up to 0.4 Hz (with USB sync). +// +// If none of the mentioned defines is set, the device uses the internal oscillators. + void init_clocks(uint32_t cpu_freq) { dfll48m_calibration = 0; // please the compiler diff --git a/ports/samd/mcu/samd51/clock_config.c b/ports/samd/mcu/samd51/clock_config.c index f67d297e8e..3bc4616de9 100644 --- a/ports/samd/mcu/samd51/clock_config.c +++ b/ports/samd/mcu/samd51/clock_config.c @@ -142,6 +142,46 @@ void check_usb_recovery_mode(void) { #endif // MICROPY_HW_XOSC32K } +// Purpose of the #defines for the clock configuration. +// +// The CPU clock is generated by DPLL0, which takes 32768 Hz as reference frequency, +// supplied through GCLK1. +// +// DFLL48M is used for the peripheral clock, e.g. for PWM, UART, SPI, I2C. +// DFLL48M is either free running, or controlled by the 32kHz crystal, or +// Synchronized with the USB clock. +// +// GCLK1 takes it's input either from the 32kHz crystal, the internal low power +// RC oscillator or from DFLL48M. +// +// #define MICROPY_HW_XOSC32K (0 | 1) +// +// If MICROPY_HW_XOSC32K = 1, the 32kHz crystal is used for the DFLL48M oscillator +// and for GCLK1, feeding the CPU, unless MICROPY_HW_MCU_OSC32KULP is set. +// In that case GCLK1 (and the CPU clock) is driven by the 32K Low power oscillator. +// The reason for offering this option is a design flaw of the Adafruit +// Feather boards, where the RGB Led and Debug signals interfere with the +// crystal, causing the CPU to fail if it is driven by the crystal. The +// peripheral devices are affected as well, but continue it's operation. +// +// If MICROPY_HW_XOSC32K = 0, the 32kHz signal for GCLK1 (and the CPU) is +// created by dividing the 48MHz clock of DFLL48M. +// +// If MICROPY_HW_DFLL_USB_SYNC = 0, the DFLL48M oscillator is free running using +// the pre-configured trim values. In that mode, the peripheral clock is +// not exactly 48Mhz and has a substantional temperature drift. +// +// If MICROPY_HW_DFLL_USB_SYNC = 1, the DFLL48 is synchronized with the 1 kHz USB sync +// signal. If after boot there is no USB sync withing 500ms, the configuratuion falls +// back to a free running 48Mhz oscillator. +// +// In all modes, the 48MHz signal has a substantial jitter, largest when +// MICROPY_HW_DFLL_USB_SYNC is active. That is caused by the repective +// reference frequencies of 32kHz or 1 kHz being low. That affects most +// PWM. Std Dev at 1kHz 0.156Hz (w. Crystal) up to 0.4 Hz (with USB sync). +// +// If none of the mentioned defines is set, the device uses the internal oscillators. + void init_clocks(uint32_t cpu_freq) { dfll48m_calibration = 0; // please the compiler From 2251cb774b7b7db12323a32b339903fa27ff7b08 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 18 Aug 2022 11:58:09 +0200 Subject: [PATCH 0574/1041] samd/machine_uart: Implement uart.txdone() and uart.flush(). Using the stream method for uart.flush(). uart.txdone() returns True, if the uart not busy, False otherwise. uart.flush() waits until all bytes have been transmitted or a timeout triggers. The timeout is determined by the buffer size and the baud rate. Also fix two inconsistencies when not using txbuf: - Report in ioctl as being writeable if there is room in the tx buffer, only if it is configured. - Print the txbuf size if configured. --- ports/samd/machine_uart.c | 53 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/ports/samd/machine_uart.c b/ports/samd/machine_uart.c index 1031f26c26..76b564e874 100644 --- a/ports/samd/machine_uart.c +++ b/ports/samd/machine_uart.c @@ -116,9 +116,17 @@ void sercom_enable(Sercom *uart, int state) { STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, " - "timeout=%u, timeout_char=%u, rxbuf=%d)", + "timeout=%u, timeout_char=%u, rxbuf=%d" + #if MICROPY_HW_UART_TXBUF + ", txbuf=%d" + #endif + ")", self->id, self->baudrate, self->bits, _parity_name[self->parity], - self->stop + 1, self->timeout, self->timeout_char, self->read_buffer.size - 1); + self->stop + 1, self->timeout, self->timeout_char, self->read_buffer.size - 1 + #if MICROPY_HW_UART_TXBUF + , self->write_buffer.size - 1 + #endif + ); } 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) { @@ -385,6 +393,22 @@ STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { } 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); + void uart_deinit_all(void) { for (int i = 0; i < SERCOM_INST_NUM; i++) { if (uart_table[i] != NULL) { @@ -399,7 +423,9 @@ STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { { 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) }, @@ -414,7 +440,6 @@ STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t siz uint8_t *dest = buf_in; Sercom *uart = sercom_instance[self->id]; - // t.b.d. Cater timeout for timer wrap after 50 days. for (size_t i = 0; i < size; i++) { // Wait for the first/next character while (ringbuf_avail(&self->read_buffer) == 0) { @@ -488,9 +513,29 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint if ((flags & MP_STREAM_POLL_RD) && (uart->USART.INTFLAG.bit.RXC != 0 || ringbuf_avail(&self->read_buffer) > 0)) { ret |= MP_STREAM_POLL_RD; } - if ((flags & MP_STREAM_POLL_WR) && (uart->USART.INTFLAG.bit.DRE != 0)) { + if ((flags & MP_STREAM_POLL_WR) && (uart->USART.INTFLAG.bit.DRE != 0 + #if MICROPY_HW_UART_TXBUF + || ringbuf_avail(&self->write_buffer) > 0 + #endif + )) { ret |= MP_STREAM_POLL_WR; } + } else if (request == MP_STREAM_FLUSH) { + // The timeout is defined by the buffer size and the baudrate. + // Take the worst case assumtions at 13 bit symbol size times 2. + uint64_t timeout = mp_hal_ticks_ms_64() + (3 + #if MICROPY_HW_UART_TXBUF + + self->write_buffer.size + #endif + ) * 13000 * 2 / self->baudrate; + do { + if (machine_uart_txdone((mp_obj_t)self) == mp_const_true) { + return 0; + } + MICROPY_EVENT_POLL_HOOK + } while (mp_hal_ticks_ms_64() < timeout); + *errcode = MP_ETIMEDOUT; + ret = MP_STREAM_ERROR; } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; From be31fde012e0cf522ec9d70f50923a0a899f438c Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 8 Sep 2022 17:55:08 +0200 Subject: [PATCH 0575/1041] samd/mcu: Make some settings in mpconfigmcu.h conditional. And set the default for MICROPY_PY_MATH as 1 for both MCU types. --- ports/samd/mcu/samd21/mpconfigmcu.h | 13 ++++++++++++- ports/samd/mcu/samd21/mpconfigmcu.mk | 29 ++++++++++++++++++++++++++++ ports/samd/mcu/samd51/mpconfigmcu.h | 11 +++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/ports/samd/mcu/samd21/mpconfigmcu.h b/ports/samd/mcu/samd21/mpconfigmcu.h index e0af60552b..8d155f93ab 100644 --- a/ports/samd/mcu/samd21/mpconfigmcu.h +++ b/ports/samd/mcu/samd21/mpconfigmcu.h @@ -9,13 +9,24 @@ #define MICROPY_MODULE_BUILTIN_INIT (1) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) + +#ifndef MICROPY_PY_BUILTINS_COMPLEX #define MICROPY_PY_BUILTINS_COMPLEX (0) -#define MICROPY_PY_MATH (0) +#endif + +#ifndef MICROPY_PY_MATH +#define MICROPY_PY_MATH (1) +#endif + +#ifndef MICROPY_PY_CMATH #define MICROPY_PY_CMATH (0) +#endif #define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; +#ifndef MICROPY_HW_UART_TXBUF #define MICROPY_HW_UART_TXBUF (1) +#endif #define CPU_FREQ (48000000) #define DFLL48M_FREQ (48000000) diff --git a/ports/samd/mcu/samd21/mpconfigmcu.mk b/ports/samd/mcu/samd21/mpconfigmcu.mk index cc435da8cc..287d6d18be 100644 --- a/ports/samd/mcu/samd21/mpconfigmcu.mk +++ b/ports/samd/mcu/samd21/mpconfigmcu.mk @@ -1 +1,30 @@ SRC_S += shared/runtime/gchelper_m0.s + +LIBM_SRC_C += $(addprefix lib/libm/,\ + acoshf.c \ + asinfacosf.c \ + asinhf.c \ + atan2f.c \ + atanf.c \ + atanhf.c \ + ef_rem_pio2.c \ + erf_lgamma.c \ + fmodf.c \ + kf_cos.c \ + kf_rem_pio2.c \ + kf_sin.c \ + kf_tan.c \ + log1pf.c \ + math.c \ + nearbyintf.c \ + roundf.c \ + sf_cos.c \ + sf_erf.c \ + sf_frexp.c \ + sf_ldexp.c \ + sf_modf.c \ + sf_sin.c \ + sf_tan.c \ + wf_lgamma.c \ + wf_tgamma.c \ + ) diff --git a/ports/samd/mcu/samd51/mpconfigmcu.h b/ports/samd/mcu/samd51/mpconfigmcu.h index 686cfd6104..666370c983 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.h +++ b/ports/samd/mcu/samd51/mpconfigmcu.h @@ -8,10 +8,19 @@ #define MICROPY_EMIT_INLINE_THUMB (1) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) + +#ifndef MICROPY_PY_BUILTINS_COMPLEX #define MICROPY_PY_BUILTINS_COMPLEX (0) +#endif + +#ifndef MICROPY_PY_MATH #define MICROPY_PY_MATH (1) #define MP_NEED_LOG2 (1) +#endif + +#ifndef MICROPY_PY_CMATH #define MICROPY_PY_CMATH (0) +#endif #define MICROPY_PY_MACHINE_DHT_READINTO (1) #define MICROPY_PY_ONEWIRE (1) @@ -30,7 +39,9 @@ unsigned long trng_random_u32(void); #define VFS_BLOCK_SIZE_BYTES (1536) // +#ifndef MICROPY_HW_UART_TXBUF #define MICROPY_HW_UART_TXBUF (1) +#endif #define CPU_FREQ (120000000) #define DFLL48M_FREQ (48000000) From fc9d66fac64422a6a6ea4a79bfd8b2460cc8e9e8 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 15 Sep 2022 15:58:54 +0200 Subject: [PATCH 0576/1041] samd/machine_rtc: Add the machine.RTC class. Methods implemented are: - rtc.init(date) - rtc.datetime([new_date]) - rtc.calibration(value) The presence of this class can be controlled by MICROPY_PY_MACHINE_RTC. If the RTC module is used, the time module uses the RTC as well. For boards without a 32kHz crystal, using RTC makes no sense, since it will then use the ULP32K oscillator, which is not precise at all. Therefore, it will by default only be enabled for boards using a crystal, but can be enabled in the respective mpconfigboard.h. --- ports/samd/Makefile | 1 + ports/samd/fatfs_port.c | 6 +- ports/samd/machine_rtc.c | 181 +++++++++++++++++++++++++++ ports/samd/mcu/samd21/clock_config.c | 17 ++- ports/samd/mcu/samd21/mpconfigmcu.h | 6 + ports/samd/mcu/samd51/clock_config.c | 20 +-- ports/samd/mcu/samd51/mpconfigmcu.h | 6 + ports/samd/modmachine.c | 3 + ports/samd/modmachine.h | 3 + ports/samd/modutime.c | 30 ++++- ports/samd/samd_soc.c | 7 ++ 11 files changed, 263 insertions(+), 17 deletions(-) create mode 100644 ports/samd/machine_rtc.c diff --git a/ports/samd/Makefile b/ports/samd/Makefile index abec4e83a5..e6e592a035 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -94,6 +94,7 @@ SRC_C += \ machine_i2c.c \ machine_led.c \ machine_pin.c \ + machine_rtc.c \ machine_spi.c \ machine_timer.c \ machine_uart.c \ diff --git a/ports/samd/fatfs_port.c b/ports/samd/fatfs_port.c index 9ee1764ebc..a3e3f1b67b 100644 --- a/ports/samd/fatfs_port.c +++ b/ports/samd/fatfs_port.c @@ -33,9 +33,13 @@ extern uint32_t time_offset; MP_WEAK DWORD get_fattime(void) { + #if MICROPY_PY_MACHINE_RTC + return (RTC->MODE2.CLOCK.reg >> 1) + (20 << 25); + #else + extern void rtc_gettime(timeutils_struct_time_t *tm); timeutils_struct_time_t tm; - timeutils_seconds_since_epoch_to_struct_time(mp_hal_ticks_ms_64() / 1000 + time_offset, &tm); return ((tm.tm_year - 1980) << 25) | ((tm.tm_mon) << 21) | ((tm.tm_mday) << 16) | ((tm.tm_hour) << 11) | ((tm.tm_min) << 5) | (tm.tm_sec / 2); + #endif } diff --git a/ports/samd/machine_rtc.c b/ports/samd/machine_rtc.c new file mode 100644 index 0000000000..57bfa998e5 --- /dev/null +++ b/ports/samd/machine_rtc.c @@ -0,0 +1,181 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Damien P. George + * Copyright (c) 2022 "Robert Hammelrath" + * + * 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 "shared/timeutils/timeutils.h" +#include "modmachine.h" +#include "py/mphal.h" +#include "sam.h" + +#if MICROPY_PY_MACHINE_RTC + +typedef struct _machine_rtc_obj_t { + mp_obj_base_t base; + mp_obj_t callback; +} machine_rtc_obj_t; + +// Singleton RTC object. +STATIC const machine_rtc_obj_t machine_rtc_obj = {{&machine_rtc_type}}; + +// Start the RTC Timer. +void machine_rtc_start(bool force) { + #if defined(MCU_SAMD21) + + if (RTC->MODE2.CTRL.bit.ENABLE == 0 || force) { + // Enable the 1k Clock + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK8 | GCLK_CLKCTRL_ID_RTC; + + RTC->MODE2.CTRL.reg = RTC_MODE2_CTRL_SWRST; + while (RTC->MODE2.STATUS.bit.SYNCBUSY) { + } + RTC->MODE2.CTRL.reg = + RTC_MODE2_CTRL_MODE_CLOCK | + RTC_MODE2_CTRL_PRESCALER_DIV1024 | + RTC_MODE2_CTRL_ENABLE; + while (RTC->MODE2.STATUS.bit.SYNCBUSY) { + } + } + + #elif defined(MCU_SAMD51) + + if (RTC->MODE2.CTRLA.bit.ENABLE == 0 || force) { + RTC->MODE2.CTRLA.reg = RTC_MODE2_CTRLA_SWRST; + while (RTC->MODE2.SYNCBUSY.bit.SWRST) { + } + RTC->MODE2.CTRLA.reg = + RTC_MODE2_CTRLA_MODE_CLOCK | + RTC_MODE2_CTRLA_CLOCKSYNC | + RTC_MODE2_CTRLA_PRESCALER_DIV1024 | + RTC_MODE2_CTRLA_ENABLE; + while (RTC->MODE2.SYNCBUSY.bit.ENABLE) { + } + } + #endif +} + +// Get the time from the RTC and put it into a tm struct. +void rtc_gettime(timeutils_struct_time_t *tm) { + tm->tm_year = RTC->MODE2.CLOCK.bit.YEAR + 2000; + tm->tm_mon = RTC->MODE2.CLOCK.bit.MONTH; + tm->tm_mday = RTC->MODE2.CLOCK.bit.DAY; + tm->tm_hour = RTC->MODE2.CLOCK.bit.HOUR; + tm->tm_min = RTC->MODE2.CLOCK.bit.MINUTE; + tm->tm_sec = RTC->MODE2.CLOCK.bit.SECOND; +} + +STATIC mp_obj_t machine_rtc_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, 0, 0, false); + // RTC was already started at boot time. So nothing to do here. + // Return constant object. + return (mp_obj_t)&machine_rtc_obj; +} + +STATIC mp_obj_t machine_rtc_datetime_helper(size_t n_args, const mp_obj_t *args) { + // Rtc *rtc = RTC; + if (n_args == 1) { + // Get date and time. + timeutils_struct_time_t tm; + rtc_gettime(&tm); + + mp_obj_t tuple[8] = { + mp_obj_new_int(tm.tm_year), + mp_obj_new_int(tm.tm_mon), + mp_obj_new_int(tm.tm_mday), + mp_obj_new_int(timeutils_calc_weekday(tm.tm_year, tm.tm_mon, tm.tm_mday)), + mp_obj_new_int(tm.tm_hour), + mp_obj_new_int(tm.tm_min), + mp_obj_new_int(tm.tm_sec), + mp_obj_new_int(0), + }; + return mp_obj_new_tuple(8, tuple); + } else { + // Set date and time. + mp_obj_t *items; + mp_obj_get_array_fixed_n(args[1], 8, &items); + + uint32_t date = + RTC_MODE2_CLOCK_YEAR(mp_obj_get_int(items[0]) % 100) | + RTC_MODE2_CLOCK_MONTH(mp_obj_get_int(items[1])) | + RTC_MODE2_CLOCK_DAY(mp_obj_get_int(items[2])) | + RTC_MODE2_CLOCK_HOUR(mp_obj_get_int(items[4])) | + RTC_MODE2_CLOCK_MINUTE(mp_obj_get_int(items[5])) | + RTC_MODE2_CLOCK_SECOND(mp_obj_get_int(items[6])); + + RTC->MODE2.CLOCK.reg = date; + #if defined(MCU_SAMD21) + while (RTC->MODE2.STATUS.bit.SYNCBUSY) { + } + #elif defined(MCU_SAMD51) + while (RTC->MODE2.SYNCBUSY.bit.CLOCKSYNC) { + } + #endif + + return mp_const_none; + } +} + +STATIC mp_obj_t machine_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) { + return machine_rtc_datetime_helper(n_args, args); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_datetime_obj, 1, 2, machine_rtc_datetime); + +STATIC mp_obj_t machine_rtc_init(mp_obj_t self_in, mp_obj_t date) { + mp_obj_t args[2] = {self_in, date}; + machine_rtc_datetime_helper(2, args); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_init_obj, machine_rtc_init); + +// calibration(cal) +// When the argument is a number in the range [-16 to 15], set the calibration value. +STATIC mp_obj_t machine_rtc_calibration(mp_obj_t self_in, mp_obj_t cal_in) { + int8_t cal = 0; + // Make it negative for a "natural" behavior: + // value > 0: faster, value < 0: slower + cal = -mp_obj_get_int(cal_in); + RTC->MODE2.FREQCORR.reg = (uint8_t)cal; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_calibration_obj, machine_rtc_calibration); + +STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_rtc_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_datetime), MP_ROM_PTR(&machine_rtc_datetime_obj) }, + { MP_ROM_QSTR(MP_QSTR_calibration), MP_ROM_PTR(&machine_rtc_calibration_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + machine_rtc_type, + MP_QSTR_RTC, + MP_TYPE_FLAG_NONE, + make_new, machine_rtc_make_new, + locals_dict, &machine_rtc_locals_dict + ); + +#endif // MICROPY_PY_MACHINE_RTC diff --git a/ports/samd/mcu/samd21/clock_config.c b/ports/samd/mcu/samd21/clock_config.c index a195cb6920..00f743cc49 100644 --- a/ports/samd/mcu/samd21/clock_config.c +++ b/ports/samd/mcu/samd21/clock_config.c @@ -141,7 +141,7 @@ void init_clocks(uint32_t cpu_freq) { // GCLK3: 1Mhz for the us-counter (TC4/TC5) // GCLK4: 32kHz from crystal, if present // GCLK5: 48MHz from DFLL for USB - // GCLK8: 1kHz clock for WDT + // GCLK8: 1kHz clock for WDT and RTC NVMCTRL->CTRLB.bit.MANW = 1; // errata "Spurious Writes" NVMCTRL->CTRLB.bit.RWS = 1; // 1 read wait state for 48MHz @@ -203,6 +203,11 @@ void init_clocks(uint32_t cpu_freq) { SYSCTRL_DFLLCTRL_BPLCKC | SYSCTRL_DFLLCTRL_ENABLE; while (SYSCTRL->PCLKSR.bit.DFLLLCKF == 0) { } + // Set GCLK8 to 1 kHz. + GCLK->GENDIV.reg = GCLK_GENDIV_ID(8) | GCLK_GENDIV_DIV(32); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_ID(8); + while (GCLK->STATUS.bit.SYNCBUSY) { + } #else // MICROPY_HW_XOSC32K @@ -242,6 +247,11 @@ void init_clocks(uint32_t cpu_freq) { GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(1); while (GCLK->STATUS.bit.SYNCBUSY) { } + // Set GCLK8 to 1 kHz. + GCLK->GENDIV.reg = GCLK_GENDIV_ID(8) | GCLK_GENDIV_DIV(32); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(8); + while (GCLK->STATUS.bit.SYNCBUSY) { + } #endif // MICROPY_HW_XOSC32K @@ -252,11 +262,6 @@ void init_clocks(uint32_t cpu_freq) { GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(3); while (GCLK->STATUS.bit.SYNCBUSY) { } - // Set GCLK8 to 1 kHz. - GCLK->GENDIV.reg = GCLK_GENDIV_ID(8) | GCLK_GENDIV_DIV(32); - GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(8); - while (GCLK->STATUS.bit.SYNCBUSY) { - } } void enable_sercom_clock(int id) { diff --git a/ports/samd/mcu/samd21/mpconfigmcu.h b/ports/samd/mcu/samd21/mpconfigmcu.h index 8d155f93ab..331df8e213 100644 --- a/ports/samd/mcu/samd21/mpconfigmcu.h +++ b/ports/samd/mcu/samd21/mpconfigmcu.h @@ -28,6 +28,12 @@ #define MICROPY_HW_UART_TXBUF (1) #endif +#ifndef MICROPY_PY_MACHINE_RTC +#if MICROPY_HW_XOSC32K +#define MICROPY_PY_MACHINE_RTC (1) +#endif +#endif + #define CPU_FREQ (48000000) #define DFLL48M_FREQ (48000000) #define MAX_CPU_FREQ (48000000) diff --git a/ports/samd/mcu/samd51/clock_config.c b/ports/samd/mcu/samd51/clock_config.c index 3bc4616de9..c5f508cae8 100644 --- a/ports/samd/mcu/samd51/clock_config.c +++ b/ports/samd/mcu/samd51/clock_config.c @@ -215,16 +215,19 @@ void init_clocks(uint32_t cpu_freq) { #if MICROPY_HW_XOSC32K // OSCILLATOR CONTROL + // Enable the clock for RTC + OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC1K; // Setup XOSC32K OSC32KCTRL->INTFLAG.reg = OSC32KCTRL_INTFLAG_XOSC32KRDY | OSC32KCTRL_INTFLAG_XOSC32KFAIL; - OSC32KCTRL->XOSC32K.bit.CGM = OSC32KCTRL_XOSC32K_CGM_HS_Val; - OSC32KCTRL->XOSC32K.bit.XTALEN = 1; // 0: Generator 1: Crystal - OSC32KCTRL->XOSC32K.bit.EN32K = 1; - OSC32KCTRL->XOSC32K.bit.ONDEMAND = 0; - OSC32KCTRL->XOSC32K.bit.RUNSTDBY = 1; - OSC32KCTRL->XOSC32K.bit.STARTUP = 4; OSC32KCTRL->CFDCTRL.bit.CFDEN = 1; // Fall back to internal Osc on crystal fail - OSC32KCTRL->XOSC32K.bit.ENABLE = 1; + OSC32KCTRL->XOSC32K.reg = + OSC32KCTRL_XOSC32K_CGM_HS | + OSC32KCTRL_XOSC32K_XTALEN | + OSC32KCTRL_XOSC32K_EN32K | + OSC32KCTRL_XOSC32K_EN1K | + OSC32KCTRL_XOSC32K_RUNSTDBY | + OSC32KCTRL_XOSC32K_STARTUP(4) | + OSC32KCTRL_XOSC32K_ENABLE; // make sure osc32kcrtl is ready while (OSC32KCTRL->STATUS.bit.XOSC32KRDY == 0) { } @@ -270,6 +273,9 @@ void init_clocks(uint32_t cpu_freq) { #else // MICROPY_HW_XOSC32K + // Enable the clock for RTC + OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_ULP1K; + // Derive GCLK1 from DFLL48M at DPLL0_REF_FREQ as defined in mpconfigboard.h (e.g. 32768 Hz) GCLK->GENCTRL[1].reg = ((DFLL48M_FREQ + DPLLx_REF_FREQ / 2) / DPLLx_REF_FREQ) << GCLK_GENCTRL_DIV_Pos | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; diff --git a/ports/samd/mcu/samd51/mpconfigmcu.h b/ports/samd/mcu/samd51/mpconfigmcu.h index 666370c983..541fba9009 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.h +++ b/ports/samd/mcu/samd51/mpconfigmcu.h @@ -28,6 +28,12 @@ #define MICROPY_PY_URANDOM_SEED_INIT_FUNC (trng_random_u32()) unsigned long trng_random_u32(void); +#ifndef MICROPY_PY_MACHINE_RTC +#if MICROPY_HW_XOSC32K +#define MICROPY_PY_MACHINE_RTC (1) +#endif +#endif + // Due to a limitation in the TC counter for us, the ticks period is 2**29 #define MICROPY_PY_UTIME_TICKS_PERIOD (0x20000000) diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index ce5fef76f7..12e9f7c341 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -238,6 +238,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) }, + #if MICROPY_PY_MACHINE_RTC + { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, + #endif { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, diff --git a/ports/samd/modmachine.h b/ports/samd/modmachine.h index e99ca990fb..8f85e14989 100644 --- a/ports/samd/modmachine.h +++ b/ports/samd/modmachine.h @@ -38,5 +38,8 @@ 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; +#if MICROPY_PY_MACHINE_RTC +extern const mp_obj_type_t machine_rtc_type; +#endif #endif // MICROPY_INCLUDED_SAMD_MODMACHINE_H diff --git a/ports/samd/modutime.c b/ports/samd/modutime.c index 4169c15d91..6b04134497 100644 --- a/ports/samd/modutime.c +++ b/ports/samd/modutime.c @@ -29,20 +29,34 @@ #include "shared/timeutils/timeutils.h" #include "mphalport.h" +#if !MICROPY_PY_MACHINE_RTC uint32_t time_offset = 0; +#endif // !MICROPY_PY_MACHINE_RTC // localtime([secs]) STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { timeutils_struct_time_t tm; mp_int_t seconds; + + #if MICROPY_PY_MACHINE_RTC + extern void rtc_gettime(timeutils_struct_time_t *tm); + if (n_args == 0 || args[0] == mp_const_none) { + rtc_gettime(&tm); + } else { + seconds = mp_obj_get_int(args[0]); + timeutils_seconds_since_epoch_to_struct_time(seconds, &tm); + } + + #else if (n_args == 0 || args[0] == mp_const_none) { - // seconds = pyb_rtc_get_us_since_epoch() / 1000 / 1000; seconds = mp_hal_ticks_ms_64() / 1000 + time_offset; } else { seconds = mp_obj_get_int(args[0]); time_offset = seconds - mp_hal_ticks_ms_64() / 1000; } timeutils_seconds_since_epoch_to_struct_time(seconds, &tm); + + #endif // MICROPY_PY_MACHINE_RTC mp_obj_t tuple[8] = { tuple[0] = mp_obj_new_int(tm.tm_year), tuple[1] = mp_obj_new_int(tm.tm_mon), @@ -50,8 +64,8 @@ STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { tuple[3] = mp_obj_new_int(tm.tm_hour), tuple[4] = mp_obj_new_int(tm.tm_min), tuple[5] = mp_obj_new_int(tm.tm_sec), - tuple[6] = mp_obj_new_int(tm.tm_wday), - tuple[7] = mp_obj_new_int(tm.tm_yday), + tuple[6] = mp_obj_new_int(timeutils_calc_weekday(tm.tm_year, tm.tm_mon, tm.tm_mday)), + tuple[7] = mp_obj_new_int(timeutils_year_day(tm.tm_year, tm.tm_mon, tm.tm_mday)), }; return mp_obj_new_tuple(8, tuple); } @@ -76,7 +90,17 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime); // time() STATIC mp_obj_t time_time(void) { + #if MICROPY_PY_MACHINE_RTC + extern void rtc_gettime(timeutils_struct_time_t *tm); + timeutils_struct_time_t tm; + rtc_gettime(&tm); + return mp_obj_new_int_from_uint(timeutils_mktime( + tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec)); + + #else return mp_obj_new_int_from_uint(mp_hal_ticks_ms_64() / 1000 + time_offset); + + #endif // MICROPY_PY_MACHINE_RTC } STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time); diff --git a/ports/samd/samd_soc.c b/ports/samd/samd_soc.c index 3608306e87..bd3eea536f 100644 --- a/ports/samd/samd_soc.c +++ b/ports/samd/samd_soc.c @@ -38,6 +38,10 @@ #include "tusb.h" #include "mphalport.h" +#if MICROPY_PY_MACHINE_RTC +extern void machine_rtc_start(bool force); +#endif + static void usb_init(void) { // Init USB clock #if defined(MCU_SAMD21) @@ -114,4 +118,7 @@ void samd_init(void) { #if defined(MCU_SAMD51) mp_hal_ticks_cpu_enable(); #endif + #if MICROPY_PY_MACHINE_RTC + machine_rtc_start(false); + #endif } From e33db80a5958772095a16b0b3753ed3aa72d07b2 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 29 Sep 2022 16:13:23 +0200 Subject: [PATCH 0577/1041] samd/clock_config: Extend the SAMD51 us-counter to 60 bit. This removes the difference in the time.ticks_us() range between SAMD21 and SAMD51. The function mp_hal_ticks_us_64() is added and used for: - SAMD51's mp_hal_ticks_us and mp_hal_delay_us(). For SAMD21, keep the previous methods, which are faster. - mp_hal_ticks_ms() and mp_hal_tick_ms_64(), which saves some bytes and removes a potential race condition every 50 days. Also set the us-counter for SAMD51 to 16 MHz for a faster reading of the microsecond value. Note: With SAMD51, mp_hal_ticks_us_64() has a 60 bit range only, which is still a long time (~36000 years). --- ports/samd/mcu/samd51/clock_config.c | 8 +++--- ports/samd/mcu/samd51/mpconfigmcu.h | 3 --- ports/samd/mphalport.c | 40 ++++++++++++++++++++++++---- ports/samd/mphalport.h | 23 +++++----------- ports/samd/samd_isr.c | 24 ++++++++++++----- ports/samd/samd_soc.c | 8 +++++- 6 files changed, 71 insertions(+), 35 deletions(-) diff --git a/ports/samd/mcu/samd51/clock_config.c b/ports/samd/mcu/samd51/clock_config.c index c5f508cae8..b55419d24b 100644 --- a/ports/samd/mcu/samd51/clock_config.c +++ b/ports/samd/mcu/samd51/clock_config.c @@ -190,7 +190,7 @@ void init_clocks(uint32_t cpu_freq) { // GCLK0: 48MHz from DFLL48M or 48 - 200 MHz from DPLL0 (SAMD51) // GCLK1: 32768 Hz from 32KULP or DFLL48M // GCLK2: 8-48MHz from DFLL48M for Peripheral devices - // GCLK3: 8Mhz for the us-counter (TC0/TC1) + // GCLK3: 16Mhz for the us-counter (TC0/TC1) // GCLK4: 32kHz from crystal, if present // GCLK5: 48MHz from DFLL48M for USB // DPLL0: 48 - 200 MHz @@ -204,7 +204,7 @@ void init_clocks(uint32_t cpu_freq) { // Setup DPLL0 to 120MHz // Setup GCLK0 to 120MHz // Setup GCLK2 to 48MHz for Peripherals - // Setup GCLK3 to 8MHz for TC0/TC1 + // Setup GCLK3 to 16MHz for TC0/TC1 // Setup GCLK4 to 32kHz crystal, if present // Setup GCLK5 to 48 MHz @@ -320,8 +320,8 @@ void init_clocks(uint32_t cpu_freq) { while (GCLK->SYNCBUSY.bit.GENCTRL2) { } - // Setup GCLK3 for 8MHz, Used for TC0/1 counter - GCLK->GENCTRL[3].reg = GCLK_GENCTRL_DIV(6) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; + // Setup GCLK3 for 16MHz, Used for TC0/1 counter + GCLK->GENCTRL[3].reg = GCLK_GENCTRL_DIV(3) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; while (GCLK->SYNCBUSY.bit.GENCTRL3) { } } diff --git a/ports/samd/mcu/samd51/mpconfigmcu.h b/ports/samd/mcu/samd51/mpconfigmcu.h index 541fba9009..16b2c101f0 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.h +++ b/ports/samd/mcu/samd51/mpconfigmcu.h @@ -34,9 +34,6 @@ unsigned long trng_random_u32(void); #endif #endif -// Due to a limitation in the TC counter for us, the ticks period is 2**29 -#define MICROPY_PY_UTIME_TICKS_PERIOD (0x20000000) - // fatfs configuration used in ffconf.h #define MICROPY_FATFS_ENABLE_LFN (1) #define MICROPY_FATFS_RPATH (2) diff --git a/ports/samd/mphalport.c b/ports/samd/mphalport.c index ad3817768f..b60bada480 100644 --- a/ports/samd/mphalport.c +++ b/ports/samd/mphalport.c @@ -37,6 +37,8 @@ #define MICROPY_HW_STDIN_BUFFER_LEN 128 #endif +extern volatile uint32_t ticks_us64_upper; + STATIC uint8_t stdin_ringbuf_array[MICROPY_HW_STDIN_BUFFER_LEN]; ringbuf_t stdin_ringbuf = { stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0 }; @@ -111,19 +113,47 @@ void mp_hal_delay_ms(mp_uint_t ms) { void mp_hal_delay_us(mp_uint_t us) { if (us > 0) { - uint32_t start = mp_hal_ticks_us(); #if defined(MCU_SAMD21) - // SAMD21 counter has effective 32 bit width + uint32_t start = mp_hal_ticks_us(); while ((mp_hal_ticks_us() - start) < us) { } - #elif defined(MCU_SAMD51) - // SAMD51 counter has effective 29 bit width - while (((mp_hal_ticks_us() - start) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1)) < us) { + #else + uint64_t stop = mp_hal_ticks_us_64() + us; + while (mp_hal_ticks_us_64() < stop) { } #endif } } +uint64_t mp_hal_ticks_us_64(void) { + uint32_t us64_upper = ticks_us64_upper; + uint32_t us64_lower; + uint8_t intflag; + __disable_irq(); + #if defined(MCU_SAMD21) + us64_lower = REG_TC4_COUNT32_COUNT; + intflag = TC4->COUNT32.INTFLAG.reg; + #elif defined(MCU_SAMD51) + TC0->COUNT32.CTRLBSET.reg = TC_CTRLBSET_CMD_READSYNC; + while (TC0->COUNT32.CTRLBSET.reg != 0) { + } + us64_lower = REG_TC0_COUNT32_COUNT; + intflag = TC0->COUNT32.INTFLAG.reg; + #endif + __enable_irq(); + if ((intflag & TC_INTFLAG_OVF) && us64_lower < 0x10000000) { + // The timer counter overflowed before reading it but the IRQ handler + // has not yet been called, so perform the IRQ arithmetic now. + us64_upper++; + } + #if defined(MCU_SAMD21) + return ((uint64_t)us64_upper << 32) | us64_lower; + #elif defined(MCU_SAMD51) + return ((uint64_t)us64_upper << 28) | (us64_lower >> 4); + #endif + +} + uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { uintptr_t ret = 0; diff --git a/ports/samd/mphalport.h b/ports/samd/mphalport.h index 3879240f9a..2cbb3333f6 100644 --- a/ports/samd/mphalport.h +++ b/ports/samd/mphalport.h @@ -37,7 +37,7 @@ extern int mp_interrupt_char; extern volatile uint32_t systick_ms; -extern volatile uint32_t systick_ms_upper; +uint64_t mp_hal_ticks_us_64(void); void mp_hal_set_interrupt_char(int c); @@ -47,28 +47,19 @@ void mp_hal_set_interrupt_char(int c); #define mp_hal_delay_us_fast mp_hal_delay_us -static inline mp_uint_t mp_hal_ticks_ms(void) { - return systick_ms; +static inline uint64_t mp_hal_ticks_ms_64(void) { + return mp_hal_ticks_us_64() / 1000; } -static inline uint64_t mp_hal_ticks_ms_64(void) { - return ((uint64_t)systick_ms_upper << 32) + systick_ms; +static inline mp_uint_t mp_hal_ticks_ms(void) { + return (mp_uint_t)mp_hal_ticks_ms_64(); } static inline mp_uint_t mp_hal_ticks_us(void) { #if defined(MCU_SAMD21) - return REG_TC4_COUNT32_COUNT; - - #elif defined(MCU_SAMD51) - - TC0->COUNT32.CTRLBSET.reg = TC_CTRLBSET_CMD_READSYNC; - while (TC0->COUNT32.CTRLBSET.reg != 0) { - } - return REG_TC0_COUNT32_COUNT >> 3; - #else - return systick_ms * 1000; + return (mp_uint_t)mp_hal_ticks_us_64(); #endif } @@ -89,7 +80,7 @@ static inline mp_uint_t mp_hal_ticks_cpu(void) { #endif static inline uint64_t mp_hal_time_ns(void) { - return mp_hal_ticks_ms_64() * 1000000; + return mp_hal_ticks_us_64() * 1000; } // C-level pin HAL diff --git a/ports/samd/samd_isr.c b/ports/samd/samd_isr.c index b507d5d1aa..1d6febaaa2 100644 --- a/ports/samd/samd_isr.c +++ b/ports/samd/samd_isr.c @@ -41,7 +41,7 @@ extern void EIC_Handler(void); const ISR isr_vector[]; volatile uint32_t systick_ms; -volatile uint32_t systick_ms_upper; +volatile uint32_t ticks_us64_upper; void Reset_Handler(void) __attribute__((naked)); void Reset_Handler(void) { @@ -93,15 +93,27 @@ void Default_Handler(void) { void SysTick_Handler(void) { uint32_t next_tick = systick_ms + 1; systick_ms = next_tick; - if (systick_ms == 0) { - systick_ms_upper += 1; - } if (soft_timer_next == next_tick) { pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler); } } +void us_timer_IRQ(void) { + #if defined(MCU_SAMD21) + if (TC4->COUNT32.INTFLAG.reg & TC_INTFLAG_OVF) { + ticks_us64_upper++; + } + TC4->COUNT32.INTFLAG.reg = TC_INTFLAG_OVF; + #elif defined(MCU_SAMD51) + if (TC0->COUNT32.INTFLAG.reg & TC_INTFLAG_OVF) { + ticks_us64_upper++; + } + TC0->COUNT32.INTFLAG.reg = TC_INTFLAG_OVF; + #endif +} + +// Sercom IRQ handler support void (*sercom_irq_handler_table[SERCOM_INST_NUM])(int num) = {}; void sercom_register_irq(int sercom_id, void (*sercom_irq_handler)) { @@ -180,7 +192,7 @@ const ISR isr_vector[] __attribute__((section(".isr_vector"))) = { 0, // 16 Timer Counter Control 1 (TCC1) 0, // 17 Timer Counter Control 2 (TCC2) 0, // 18 Basic Timer Counter 3 (TC3) - 0, // 19 Basic Timer Counter 4 (TC4) + &us_timer_IRQ, // 19 Basic Timer Counter 4 (TC4) 0, // 20 Basic Timer Counter 5 (TC5) 0, // 21 Basic Timer Counter 6 (TC6) 0, // 22 Basic Timer Counter 7 (TC7) @@ -316,7 +328,7 @@ const ISR isr_vector[] __attribute__((section(".isr_vector"))) = { 0, // 104 Timer Counter Control 4 (TCC4): TCC4_CNT_A ... 0, // 105 Timer Counter Control 4 (TCC4): TCC4_MC_0 0, // 106 Timer Counter Control 4 (TCC4): TCC4_MC_1 - 0, // 107 Basic Timer Counter 0 (TC0) + &us_timer_IRQ, // 107 Basic Timer Counter 0 (TC0) 0, // 108 Basic Timer Counter 1 (TC1) 0, // 109 Basic Timer Counter 2 (TC2) 0, // 110 Basic Timer Counter 3 (TC3) diff --git a/ports/samd/samd_soc.c b/ports/samd/samd_soc.c index bd3eea536f..a81e7c6881 100644 --- a/ports/samd/samd_soc.c +++ b/ports/samd/samd_soc.c @@ -68,7 +68,7 @@ static void usb_init(void) { tusb_init(); } -// Initialize the microsecond counter on TC 0/1 +// Initialize the µs counter on TC 0/1 or TC4/5 void init_us_counter(void) { #if defined(MCU_SAMD21) @@ -89,6 +89,9 @@ void init_us_counter(void) { TC4->COUNT32.READREQ.reg = TC_READREQ_RREQ | TC_READREQ_RCONT | 0x10; while (TC4->COUNT32.STATUS.bit.SYNCBUSY) { } + // Enable the IRQ + TC4->COUNT32.INTENSET.reg = TC_INTENSET_OVF; + NVIC_EnableIRQ(TC4_IRQn); #elif defined(MCU_SAMD51) @@ -107,6 +110,9 @@ void init_us_counter(void) { while (TC0->COUNT32.SYNCBUSY.bit.ENABLE) { } + // Enable the IRQ + TC0->COUNT32.INTENSET.reg = TC_INTENSET_OVF; + NVIC_EnableIRQ(TC0_IRQn); #endif } From e7aa9700cad4ace55fb9100c98b2bbfa811870d2 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 4 Oct 2022 13:39:43 +0200 Subject: [PATCH 0578/1041] samd/boards/SEEED_WIO_TERMINAL: Declare more pins for SEEED WIO board. Defining all pins from the external 40 Pin connector, and some internal pins like the one for SD and LCD. --- ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv b/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv index 72da71224a..9bc57070d1 100644 --- a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv +++ b/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv @@ -22,9 +22,43 @@ PIN_PD20,SWITCH_U PIN_PC26,BUTTON_1 PIN_PC27,BUTTON_2 PIN_PC28,BUTTON_3 -PIN_PD11,BUZZER_CTR PIN_PC14,5V_ENABLE PIN_PC15,3V3_ENABLE +PIN_PB26,TX +PIN_PB27,RX +PIN_PA13,SDA0 +PIN_PA12,SCL0 +PIN_PA17,SDA1 +PIN_PA16,SCL1 +PIN_PB02,MOSI +PIN_PB00,MISO +PIN_PB03,SCK +PIN_PB01,CS +PIN_PB15,GPCLK0 +PIN_PB12,GPCLK1 +PIN_PB13,GPCLK2 +PIN_PC16,SD_MOSI +PIN_PC18,SD_MISO +PIN_PC17,SD_SCK +PIN_PC19,SD_CS +PIN_PD21,SD_DET +PIN_PA20,I2S_LRCLK +PIN_PA21,I2S_SDIN +PIN_PA22,I2S_SDOUT +PIN_PB16,I2C_BCLK +PIN_PB18,LCD_MISO +PIN_PB19,LCD_MOSI +PIN_PB20,LCD_SCK +PIN_PB21,LCD_CS +PIN_PC05,LCD_BACKLIGHT +PIN_PC06,LCD_D/C +PIN_PC07,LCD_RESET +PIN_PC10,LCD_XL +PIN_PC11,LCD_YU +PIN_PC12,LCD_XR +PIN_PC13,LCD_YD +PIN_PC30,MIC +PIN_PD11,BUZZER LED_PA15,LED_BLUE LED_PC05,LED_LCD From e5cf3fab951adf39e7d39c2a8600b61f84e517ce Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 17 Sep 2022 17:27:27 +0200 Subject: [PATCH 0579/1041] samd/machine_pin: Change the pin handling and naming/numbering. Pin numbers are now the MCU port numbers in the range: PA0..PA31: 0..31 PB0..PB31: 32..63 PC0..PC31: 64..95 PD0..PD31: 96..127 Pins can be denoted by the GPIO port number, the name as defined in pins.csv or a string in the form Pxnn, like "PA16" or "PD03". The pins.c and pins.h files are now obsolete. The pin objects are part of the AF table. As result of a simplification, the code now supports using pin names or numbers instead of pin objects for modules like UART, SPI, PWM, I2C, ADC, pininfo. --- ports/samd/Makefile | 26 +--- .../{make-pin-af.py => make-pin-table.py} | 54 +++++++- ports/samd/boards/make-pins.py | 128 ------------------ ports/samd/machine_adc.c | 4 +- ports/samd/machine_led.c | 27 ++-- ports/samd/machine_pin.c | 119 ++++++---------- ports/samd/machine_pwm.c | 4 +- ports/samd/modsamd.c | 60 ++++---- ports/samd/pin_af.c | 69 +++++++++- ports/samd/pin_af.h | 18 ++- 10 files changed, 221 insertions(+), 288 deletions(-) rename ports/samd/boards/{make-pin-af.py => make-pin-table.py} (59%) delete mode 100644 ports/samd/boards/make-pins.py diff --git a/ports/samd/Makefile b/ports/samd/Makefile index e6e592a035..f512fb0b2e 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -47,14 +47,10 @@ INC += -I$(TOP)/lib/asf4/$(MCU_SERIES_LOWER)/include INC += -I$(TOP)/lib/asf4/$(MCU_SERIES_LOWER)/include/pio INC += -I$(TOP)/lib/tinyusb/src -MAKE_PIN_AF = boards/make-pin-af.py +MAKE_PIN_AF = boards/make-pin-table.py PIN_AF_TABLE_CSV = mcu/$(MCU_SERIES_LOWER)/pin-af-table.csv -GEN_PIN_AF = pin_af_table.c - -MAKE_PINS = boards/make-pins.py BOARD_PINS = $(BOARD_DIR)/pins.csv -GEN_PINS_SRC = $(BUILD)/pins.c -GEN_PINS_HDR = $(BUILD)/pins.h +GEN_PIN_AF = pin_af_table.c CFLAGS_MCU_SAMD21 = -mtune=cortex-m0plus -mcpu=cortex-m0plus -msoft-float CFLAGS_MCU_SAMD51 = -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard @@ -150,7 +146,7 @@ DRIVERS_SRC_C += \ drivers/bus/softspi.c \ # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SHARED_SRC_C) $(SRC_CXX) $(GEN_PINS_SRC) +SRC_QSTR += $(SRC_C) $(SHARED_SRC_C) $(SRC_CXX) OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) @@ -161,7 +157,6 @@ OBJ += $(addprefix $(BUILD)/, $(ASF4_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(LIBM_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(TINYUSB_SRC_C:.c=.o)) -OBJ += $(GEN_PINS_SRC:.c=.o) ifneq ($(FROZEN_MANIFEST),) CFLAGS += -DMICROPY_MODULE_FROZEN_MPY @@ -182,19 +177,10 @@ $(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(BUILD)/firmware.uf2: $(BUILD)/firmware.bin $(Q)$(PYTHON) $(UF2CONV) -b $(TEXT0) -c -o $@ $< -pin_af.c: $(BUILD)/$(GEN_PIN_AF) +pin_af.c: $(BUILD)/$(GEN_PIN_AF) | $(HEADER_BUILD) -$(BUILD)/$(GEN_PIN_AF): $(PIN_AF_TABLE_CSV) | $(HEADER_BUILD) +$(BUILD)/$(GEN_PIN_AF): $(PIN_AF_TABLE_CSV) $(BOARD_PINS) | $(HEADER_BUILD) $(ECHO) "Create $@" - $(Q)$(PYTHON) $(MAKE_PIN_AF) --csv $(PIN_AF_TABLE_CSV) --table $(BUILD)/$(GEN_PIN_AF) --mcu $(MCU_SERIES) - -machine_led.c machine_pin.c modsamd.c: $(GEN_PINS_HDR) - -$(GEN_PINS_SRC) $(GEN_PINS_HDR): $(BOARD_PINS) | $(HEADER_BUILD) - $(ECHO) "Create $@" - $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --pins $(GEN_PINS_SRC) --inc $(GEN_PINS_HDR) - -$(GEN_PINS_SRC:.c=.o): $(GEN_PINS_SRC) - $(call compile_c) + $(Q)$(PYTHON) $(MAKE_PIN_AF) --csv $(PIN_AF_TABLE_CSV) --board $(BOARD_PINS) --table $(BUILD)/$(GEN_PIN_AF) --mcu $(MCU_SERIES) include $(TOP)/py/mkrules.mk diff --git a/ports/samd/boards/make-pin-af.py b/ports/samd/boards/make-pin-table.py similarity index 59% rename from ports/samd/boards/make-pin-af.py rename to ports/samd/boards/make-pin-table.py index d895ef9dd9..327478568a 100644 --- a/ports/samd/boards/make-pin-af.py +++ b/ports/samd/boards/make-pin-table.py @@ -16,6 +16,7 @@ table_header = """// This file was automatically generated by make-pin-cap.py class Pins: def __init__(self): self.board_pins = [] # list of pin objects + self.pin_names = {} def parse_csv_file(self, filename): with open(filename, "r") as csvfile: @@ -25,17 +26,43 @@ class Pins: if len(row) > 0 and row[0].strip().upper()[:2] in ("PA", "PB", "PC", "PD"): self.board_pins.append(row) + def parse_pin_file(self, filename): + with open(filename, "r") as csvfile: + rows = csv.reader(csvfile, skipinitialspace=True) + for row in rows: + # Pin numbers must start with "PIN_" + # LED numbers must start with "LED_" + if len(row) > 0: + # for compatibility, map LED_ to PIN_ + if row[0].startswith("LED_"): + row[0] = "PIN_" + row[0][4:] + if len(row) == 1: + self.pin_names[row[0]] = (row[0][4:], "{&machine_led_type}") + else: + self.pin_names[row[0]] = (row[1], "{&machine_led_type}") + elif row[0].startswith("PIN_"): + if len(row) == 1: + self.pin_names[row[0]] = (row[0][4:], "{&machine_pin_type}") + else: + self.pin_names[row[0]] = (row[1], "{&machine_pin_type}") + def print_table(self, table_filename, mcu_name): with open(table_filename, "wt") as table_file: table_file.write(table_header) - table_file.write("const pin_af_t pin_af_table[] = {\n") + table_file.write("const machine_pin_obj_t pin_af_table[] = {\n") if mcu_name == "SAMD21": for row in self.board_pins: pin = "PIN_" + row[0].upper() table_file.write(" #ifdef " + pin + "\n") eic = row[1] if row[1] else "0xff" adc = row[2] if row[2] else "0xff" - table_file.write(" {%s, %s, %s" % (pin, eic, adc)) + if pin in self.pin_names: + name = '"%s"' % self.pin_names[pin][0] + type = self.pin_names[pin][1] + else: + name = '"-"' + type = "{&machine_pin_type}" + table_file.write(" {%s, %s, %s, %s, %s" % (type, pin, name, eic, adc)) for cell in row[3:]: if cell: table_file.write( @@ -52,7 +79,15 @@ class Pins: eic = row[1] if row[1] else "0xff" adc0 = row[2] if row[2] else "0xff" adc1 = row[3] if row[3] else "0xff" - table_file.write(" {%s, %s, %s, %s" % (pin, eic, adc0, adc1)) + if pin in self.pin_names: + name = '"%s"' % self.pin_names[pin][0] + type = self.pin_names[pin][1] + else: + name = '"-"' + type = "{&machine_pin_type}" + table_file.write( + " {%s, %s, %s, %s, %s, %s" % (type, pin, name, eic, adc0, adc1) + ) for cell in row[4:]: if cell: table_file.write( @@ -67,7 +102,7 @@ class Pins: def main(): parser = argparse.ArgumentParser( - prog="make-pin-cap.py", + prog="make-pin-af.py", usage="%(prog)s [options] [command]", description="Generate MCU-specific pin cap table file", ) @@ -75,7 +110,13 @@ def main(): "-c", "--csv", dest="csv_filename", - help="Specifies the pin-mux-xxxx.csv filename", + help="Specifies the pin-af-table.csv filename", + ) + parser.add_argument( + "-b", + "--board", + dest="pin_filename", + help="Specifies the pins.csv filename", ) parser.add_argument( "-t", @@ -96,6 +137,9 @@ def main(): if args.csv_filename: pins.parse_csv_file(args.csv_filename) + if args.pin_filename: + pins.parse_pin_file(args.pin_filename) + if args.table_filename: pins.print_table(args.table_filename, args.mcu_name) diff --git a/ports/samd/boards/make-pins.py b/ports/samd/boards/make-pins.py deleted file mode 100644 index 679e2c9d19..0000000000 --- a/ports/samd/boards/make-pins.py +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/env python -"""Generates the pins file for the SAMD port.""" - -from __future__ import print_function - -import argparse -import sys -import csv - -pins_header_prefix = """// This file was automatically generated by make-pins.py -// -typedef struct _machine_pin_obj_t { - mp_obj_base_t base; - uint32_t id; - char *name; -} machine_pin_obj_t; - -int pin_find(mp_obj_t pin, const machine_pin_obj_t machine_pin_obj[], int table_size); - -""" - -led_header_prefix = """typedef struct _machine_led_obj_t { - mp_obj_base_t base; - uint32_t id; - char *name; -} machine_led_obj_t; - -""" - - -class Pins: - def __init__(self): - self.board_pins = [] # list of pin objects - self.board_leds = [] # list of led objects - - def parse_csv_file(self, filename): - with open(filename, "r") as csvfile: - rows = csv.reader(csvfile, skipinitialspace=True) - for row in rows: - # Pin numbers must start with "PIN_" - # LED numbers must start with "LED_" - if len(row) > 0: - if row[0].startswith("PIN_"): - if len(row) == 1: - self.board_pins.append([row[0], row[0][4:]]) - else: - self.board_pins.append([row[0], row[1]]) - elif row[0].startswith("LED_"): - self.board_leds.append(["PIN_" + row[0][4:], row[1]]) - elif row[0].startswith("-"): - self.board_pins.append(["-1", ""]) - - def print_pins(self, pins_filename): - with open(pins_filename, "wt") as pins_file: - pins_file.write("// This file was automatically generated by make-pins.py\n") - pins_file.write("//\n") - pins_file.write('#include "modmachine.h"\n') - pins_file.write('#include "sam.h"\n') - pins_file.write('#include "pins.h"\n\n') - - pins_file.write("const machine_pin_obj_t machine_pin_obj[] = {\n") - for pin in self.board_pins: - pins_file.write(" {{&machine_pin_type}, ") - pins_file.write(pin[0] + ', "' + pin[1]) - pins_file.write('"},\n') - pins_file.write("};\n") - - if self.board_leds: - pins_file.write("\nconst machine_led_obj_t machine_led_obj[] = {\n") - for pin in self.board_leds: - pins_file.write(" {{&machine_led_type}, ") - pins_file.write(pin[0] + ', "' + pin[1]) - pins_file.write('"},\n') - pins_file.write("};\n") - - def print_header(self, hdr_filename): - with open(hdr_filename, "wt") as hdr_file: - hdr_file.write(pins_header_prefix) - if self.board_leds: - hdr_file.write(led_header_prefix) - hdr_file.write( - "extern const machine_pin_obj_t machine_pin_obj[%d];\n" % len(self.board_pins) - ) - if self.board_leds: - hdr_file.write( - "extern const machine_led_obj_t machine_led_obj[%d];\n" % len(self.board_leds) - ) - - -def main(): - parser = argparse.ArgumentParser( - prog="make-pins.py", - usage="%(prog)s [options] [command]", - description="Generate board specific pin file", - ) - parser.add_argument( - "-b", - "--board", - dest="csv_filename", - help="Specifies the pins.csv filename", - ) - parser.add_argument( - "-p", - "--pins", - dest="pins_filename", - help="Specifies the name of the generated pins.c file", - ) - parser.add_argument( - "-i", - "--inc", - dest="hdr_filename", - help="Specifies name of generated pin header file", - ) - args = parser.parse_args(sys.argv[1:]) - - pins = Pins() - - if args.csv_filename: - pins.parse_csv_file(args.csv_filename) - - if args.pins_filename: - pins.print_pins(args.pins_filename) - - pins.print_header(args.hdr_filename) - - -if __name__ == "__main__": - main() diff --git a/ports/samd/machine_adc.c b/ports/samd/machine_adc.c index 97b6a14f17..efe0f041cd 100644 --- a/ports/samd/machine_adc.c +++ b/ports/samd/machine_adc.c @@ -66,8 +66,8 @@ STATIC void adc_obj_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t k (void)kind; machine_adc_obj_t *self = MP_OBJ_TO_PTR(o); - mp_printf(print, "ADC(P%c%02u, ADC%u, channel=%u, bits=%u, average=%u)", - "ABCD"[self->id / 32], self->id % 32, self->adc_config.device, + mp_printf(print, "ADC(%s, ADC%u, channel=%u, bits=%u, average=%u)", + pin_name(self->id), self->adc_config.device, self->adc_config.channel, self->bits, 1 << self->avg); } diff --git a/ports/samd/machine_led.c b/ports/samd/machine_led.c index 54c2cb18bc..c18bc052bd 100644 --- a/ports/samd/machine_led.c +++ b/ports/samd/machine_led.c @@ -30,7 +30,7 @@ #include "py/mphal.h" #include "extmod/virtpin.h" #include "modmachine.h" -#include "pins.h" +#include "pin_af.h" extern mp_obj_t machine_pin_low_obj; extern mp_obj_t machine_pin_high_obj; @@ -38,8 +38,10 @@ extern mp_obj_t machine_pin_toggle_obj; extern mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); STATIC void machine_led_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - machine_led_obj_t *self = self_in; - mp_printf(print, "LED(\"%s\")", self->name); + machine_pin_obj_t *self = self_in; + mp_printf(print, "LED(\"%s\", GPIO=P%c%02u)", + pin_name(self->pin_id), + "ABCD"[self->pin_id / 32], self->pin_id % 32); } // constructor(id, ...) @@ -47,23 +49,16 @@ mp_obj_t mp_led_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // get the wanted LED object - int wanted_led = pin_find(args[0], (const machine_pin_obj_t *)machine_led_obj, MP_ARRAY_SIZE(machine_led_obj)); - const machine_led_obj_t *self = NULL; - if (0 <= wanted_led && wanted_led < MP_ARRAY_SIZE(machine_led_obj)) { - self = (machine_led_obj_t *)&machine_led_obj[wanted_led]; - } - // the array could be padded with 'nulls' (see other Ports). - // Will also error if the asked for LED (index) is greater than the array row size. - if (self == NULL || self->base.type == NULL) { - mp_raise_ValueError(MP_ERROR_TEXT("invalid LED")); - } - mp_hal_pin_output(self->id); - mp_hal_pin_low(self->id); + const machine_pin_obj_t *self; + + self = pin_find(args[0], &machine_led_type); + + mp_hal_pin_output(self->pin_id); + mp_hal_pin_low(self->pin_id); return MP_OBJ_FROM_PTR(self); } - STATIC const mp_rom_map_elem_t machine_led_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&machine_pin_low_obj) }, diff --git a/ports/samd/machine_pin.c b/ports/samd/machine_pin.c index 2dc10f9b46..a7cd86d386 100644 --- a/ports/samd/machine_pin.c +++ b/ports/samd/machine_pin.c @@ -34,7 +34,6 @@ #include "extmod/virtpin.h" #include "modmachine.h" #include "samd_soc.h" -#include "pins.h" #include "pin_af.h" #include "hal_gpio.h" @@ -68,17 +67,17 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin machine_pin_obj_t *self = self_in; char *mode_str; char *pull_str[] = {"PULL_OFF", "PULL_UP", "PULL_DOWN"}; - if (GPIO_IS_OPEN_DRAIN(self->id)) { + if (GPIO_IS_OPEN_DRAIN(self->pin_id)) { mode_str = "OPEN_DRAIN"; } else { - mode_str = (mp_hal_get_pin_direction(self->id) == GPIO_DIRECTION_OUT) ? "OUT" : "IN"; + mode_str = (mp_hal_get_pin_direction(self->pin_id) == GPIO_DIRECTION_OUT) ? "OUT" : "IN"; } mp_printf(print, "Pin(\"%s\", mode=%s, pull=%s, GPIO=P%c%02u)", - self->name, + pin_name(self->pin_id), mode_str, - pull_str[mp_hal_get_pull_mode(self->id)], - "ABCD"[self->id / 32], self->id % 32); + pull_str[mp_hal_get_pull_mode(self->pin_id)], + "ABCD"[self->pin_id / 32], self->pin_id % 32); } STATIC void pin_validate_drive(bool strength) { @@ -87,25 +86,6 @@ STATIC void pin_validate_drive(bool strength) { } } -int pin_find(mp_obj_t pin, const machine_pin_obj_t machine_pin_obj[], int table_size) { - int wanted_pin = -1; - if (mp_obj_is_small_int(pin)) { - // Pin defined by the index of pin table - wanted_pin = mp_obj_get_int(pin); - } else if (mp_obj_is_str(pin)) { - // Search by name - size_t slen; - const char *s = mp_obj_str_get_data(pin, &slen); - for (wanted_pin = 0; wanted_pin < table_size; wanted_pin++) { - if (slen == strlen(machine_pin_obj[wanted_pin].name) && - strncmp(s, machine_pin_obj[wanted_pin].name, slen) == 0) { - break; - } - } - } - return wanted_pin; -} - // Pin.init(mode, pull=None, *, value=None, drive=0). No 'alt' yet. STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_pull, ARG_value, ARG_drive, ARG_alt }; @@ -120,32 +100,34 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + // clear any existing mux setting + mp_hal_clr_pin_mux(self->pin_id); // set initial value (do this before configuring mode/pull) if (args[ARG_value].u_obj != mp_const_none) { - mp_hal_pin_write(self->id, mp_obj_is_true(args[ARG_value].u_obj)); + mp_hal_pin_write(self->pin_id, mp_obj_is_true(args[ARG_value].u_obj)); } // configure mode if (args[ARG_mode].u_obj != mp_const_none) { mp_int_t mode = mp_obj_get_int(args[ARG_mode].u_obj); if (mode == GPIO_MODE_IN) { - mp_hal_pin_input(self->id); + mp_hal_pin_input(self->pin_id); } else if (mode == GPIO_MODE_OUT) { - mp_hal_pin_output(self->id); + mp_hal_pin_output(self->pin_id); } else if (mode == GPIO_MODE_OPEN_DRAIN) { - mp_hal_pin_open_drain(self->id); + mp_hal_pin_open_drain(self->pin_id); } else { - mp_hal_pin_input(self->id); // If no args are given, the Pin is 'input'. + mp_hal_pin_input(self->pin_id); // If no args are given, the Pin is 'input'. } } // configure pull. Only to be used with IN mode. The function sets the pin to INPUT. uint32_t pull = 0; - mp_int_t dir = mp_hal_get_pin_direction(self->id); + mp_int_t dir = mp_hal_get_pin_direction(self->pin_id); if (dir == GPIO_DIRECTION_OUT && args[ARG_pull].u_obj != mp_const_none) { mp_raise_ValueError(MP_ERROR_TEXT("OUT incompatible with pull")); } else if (args[ARG_pull].u_obj != mp_const_none) { pull = mp_obj_get_int(args[ARG_pull].u_obj); - gpio_set_pin_pull_mode(self->id, pull); // hal_gpio.h + gpio_set_pin_pull_mode(self->pin_id, pull); // hal_gpio.h } // get the strength @@ -158,18 +140,10 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_ // constructor(id, ...) mp_obj_t mp_pin_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); + const machine_pin_obj_t *self; // get the wanted pin object - int wanted_pin = pin_find(args[0], machine_pin_obj, MP_ARRAY_SIZE(machine_pin_obj)); - - const machine_pin_obj_t *self = NULL; - if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj)) { - self = (machine_pin_obj_t *)&machine_pin_obj[wanted_pin]; - } - - if (self == NULL || self->base.type == NULL) { - mp_raise_ValueError(MP_ERROR_TEXT("invalid pin")); - } + self = pin_find(args[0], &machine_pin_type); if (n_args > 1 || n_kw > 0) { // pin mode given, so configure this GPIO @@ -187,18 +161,18 @@ mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp machine_pin_obj_t *self = self_in; if (n_args == 0) { // get pin - return MP_OBJ_NEW_SMALL_INT(mp_hal_pin_read(self->id)); + return MP_OBJ_NEW_SMALL_INT(mp_hal_pin_read(self->pin_id)); } else { // set pin bool value = mp_obj_is_true(args[0]); - if (GPIO_IS_OPEN_DRAIN(self->id)) { + if (GPIO_IS_OPEN_DRAIN(self->pin_id)) { if (value == 0) { - mp_hal_pin_od_low(self->id); + mp_hal_pin_od_low(self->pin_id); } else { - mp_hal_pin_od_high(self->id); + mp_hal_pin_od_high(self->pin_id); } } else { - mp_hal_pin_write(self->id, value); + mp_hal_pin_write(self->pin_id, value); } return mp_const_none; } @@ -219,7 +193,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_ // Pin.disable(pin) STATIC mp_obj_t machine_pin_disable(mp_obj_t self_in) { machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); - gpio_set_pin_direction(self->id, GPIO_DIRECTION_OFF); // Disables the pin (low power state) + gpio_set_pin_direction(self->pin_id, GPIO_DIRECTION_OFF); // Disables the pin (low power state) return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_disable_obj, machine_pin_disable); @@ -227,10 +201,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_disable_obj, machine_pin_disable); // Pin.low() Totem-pole (push-pull) STATIC mp_obj_t machine_pin_low(mp_obj_t self_in) { machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (GPIO_IS_OPEN_DRAIN(self->id)) { - mp_hal_pin_od_low(self->id); + if (GPIO_IS_OPEN_DRAIN(self->pin_id)) { + mp_hal_pin_od_low(self->pin_id); } else { - mp_hal_pin_low(self->id); + mp_hal_pin_low(self->pin_id); } return mp_const_none; } @@ -239,10 +213,10 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_low_obj, machine_pin_low); // Pin.high() Totem-pole (push-pull) STATIC mp_obj_t machine_pin_high(mp_obj_t self_in) { machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (GPIO_IS_OPEN_DRAIN(self->id)) { - mp_hal_pin_od_high(self->id); + if (GPIO_IS_OPEN_DRAIN(self->pin_id)) { + mp_hal_pin_od_high(self->pin_id); } else { - mp_hal_pin_high(self->id); + mp_hal_pin_high(self->pin_id); } return mp_const_none; } @@ -255,16 +229,16 @@ STATIC mp_obj_t machine_pin_toggle(mp_obj_t self_in) { // Determine DIRECTION of PIN. bool pin_dir; - if (GPIO_IS_OPEN_DRAIN(self->id)) { - pin_dir = mp_hal_get_pin_direction(self->id); + if (GPIO_IS_OPEN_DRAIN(self->pin_id)) { + pin_dir = mp_hal_get_pin_direction(self->pin_id); if (pin_dir) { // Pin is output, thus low, switch to high - mp_hal_pin_od_high(self->id); + mp_hal_pin_od_high(self->pin_id); } else { - mp_hal_pin_od_low(self->id); + mp_hal_pin_od_low(self->pin_id); } } else { - gpio_toggle_pin_level(self->id); + gpio_toggle_pin_level(self->pin_id); } return mp_const_none; } @@ -280,8 +254,8 @@ STATIC mp_obj_t machine_pin_drive(size_t n_args, const mp_obj_t *args) { pin_validate_drive(strength); // Set the DRVSTR bit (ASF hri/hri_port_dxx.h hri_port_write_PINCFG_DRVSTR_bit(PORT, - (enum gpio_port)GPIO_PORT(self->id), - GPIO_PIN(self->id), + (enum gpio_port)GPIO_PORT(self->pin_id), + GPIO_PIN(self->pin_id), strength); return mp_const_none; } @@ -301,9 +275,9 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // Get the IRQ object. - uint8_t eic_id = get_pin_af_info(self->id)->eic; + uint8_t eic_id = get_pin_obj_ptr(self->pin_id)->eic; machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]); - if (irq != NULL && irq->pin_id != self->id) { + if (irq != NULL && irq->pin_id != self->pin_id) { mp_raise_ValueError(MP_ERROR_TEXT("IRQ already used")); } @@ -322,7 +296,7 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_ if (n_args > 1 || kw_args->used != 0) { // set the mux config of the pin. - mp_hal_set_pin_mux(self->id, ALT_FCT_EIC); + mp_hal_set_pin_mux(self->pin_id, ALT_FCT_EIC); // Configure IRQ. #if defined(MCU_SAMD21) @@ -362,7 +336,7 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_ irq->base.ishard = args[ARG_hard].u_bool; irq->flags = 0; irq->trigger = args[ARG_trigger].u_int; - irq->pin_id = self->id; + irq->pin_id = self->pin_id; // Enable IRQ if a handler is given. if (args[ARG_handler].u_obj != mp_const_none) { @@ -457,10 +431,10 @@ STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, i switch (request) { case MP_PIN_READ: { - return mp_hal_pin_read(self->id); + return mp_hal_pin_read(self->pin_id); } case MP_PIN_WRITE: { - mp_hal_pin_write(self->id, arg); + mp_hal_pin_write(self->pin_id, arg); return 0; } } @@ -494,7 +468,7 @@ static uint8_t find_eic_id(int pin) { STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); - uint8_t eic_id = find_eic_id(self->id); + uint8_t eic_id = find_eic_id(self->pin_id); if (eic_id != 0xff) { machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]); EIC->INTENCLR.reg |= (1 << eic_id); @@ -507,7 +481,7 @@ STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger STATIC mp_uint_t machine_pin_irq_info(mp_obj_t self_in, mp_uint_t info_type) { machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); - uint8_t eic_id = find_eic_id(self->id); + uint8_t eic_id = find_eic_id(self->pin_id); if (eic_id != 0xff) { machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]); if (info_type == MP_IRQ_INFO_FLAGS) { @@ -525,11 +499,8 @@ STATIC const mp_irq_methods_t machine_pin_irq_methods = { }; mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t obj) { - if (!mp_obj_is_type(obj, &machine_pin_type)) { - mp_raise_ValueError(MP_ERROR_TEXT("expecting a Pin")); - } - machine_pin_obj_t *pin = MP_OBJ_TO_PTR(obj); - return pin->id; + const machine_pin_obj_t *pin = pin_find(obj, &machine_pin_type); + return pin->pin_id; } MP_REGISTER_ROOT_POINTER(void *machine_pin_irq_objects[16]); diff --git a/ports/samd/machine_pwm.c b/ports/samd/machine_pwm.c index d987927d31..91982a6f74 100644 --- a/ports/samd/machine_pwm.c +++ b/ports/samd/machine_pwm.c @@ -107,8 +107,8 @@ STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "PWM P%c%02u device=%u channel=%u output=%u", - "ABCD"[self->pin_id / 32], self->pin_id % 32, self->device, self->channel, self->output); + mp_printf(print, "PWM %s device=%u channel=%u output=%u", + pin_name(self->pin_id), self->device, self->channel, self->output); } // PWM(pin) diff --git a/ports/samd/modsamd.c b/ports/samd/modsamd.c index 05ed69bad0..79e7b4cc35 100644 --- a/ports/samd/modsamd.c +++ b/ports/samd/modsamd.c @@ -30,42 +30,40 @@ #include "sam.h" #include "pin_af.h" -#include "pins.h" #include "samd_soc.h" extern const mp_obj_type_t samd_flash_type; STATIC mp_obj_t samd_pininfo(mp_obj_t pin_obj) { - mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_obj); - const pin_af_t *pin_af = get_pin_af_info(pin); - const char *name = ((machine_pin_obj_t *)MP_OBJ_TO_PTR(pin_obj))->name; - if (pin_af) { - #if defined(MCU_SAMD21) - mp_obj_t tuple[7] = { - tuple[0] = mp_obj_new_str(name, strlen(name)), - tuple[1] = mp_obj_new_int(pin_af->eic), - tuple[2] = mp_obj_new_int(pin_af->adc0), - tuple[3] = mp_obj_new_int(pin_af->sercom1), - tuple[4] = mp_obj_new_int(pin_af->sercom2), - tuple[5] = mp_obj_new_int(pin_af->tcc1), - tuple[6] = mp_obj_new_int(pin_af->tcc2), - }; - return mp_obj_new_tuple(7, tuple); - #elif defined(MCU_SAMD51) - mp_obj_t tuple[9] = { - tuple[0] = mp_obj_new_str(name, strlen(name)), - tuple[1] = mp_obj_new_int(pin_af->eic), - tuple[2] = mp_obj_new_int(pin_af->adc0), - tuple[3] = mp_obj_new_int(pin_af->adc1), - tuple[4] = mp_obj_new_int(pin_af->sercom1), - tuple[5] = mp_obj_new_int(pin_af->sercom2), - tuple[6] = mp_obj_new_int(pin_af->tc), - tuple[7] = mp_obj_new_int(pin_af->tcc1), - tuple[8] = mp_obj_new_int(pin_af->tcc2), - }; - return mp_obj_new_tuple(9, tuple); - #endif - } + const machine_pin_obj_t *pin_af = pin_find(pin_obj, NULL); + // Get the name, now that it is not in the pin object + const char *name = pin_af->name; + + #if defined(MCU_SAMD21) + mp_obj_t tuple[7] = { + tuple[0] = mp_obj_new_str(name, strlen(name)), + tuple[1] = mp_obj_new_int(pin_af->eic), + tuple[2] = mp_obj_new_int(pin_af->adc0), + tuple[3] = mp_obj_new_int(pin_af->sercom1), + tuple[4] = mp_obj_new_int(pin_af->sercom2), + tuple[5] = mp_obj_new_int(pin_af->tcc1), + tuple[6] = mp_obj_new_int(pin_af->tcc2), + }; + return mp_obj_new_tuple(7, tuple); + #elif defined(MCU_SAMD51) + mp_obj_t tuple[9] = { + tuple[0] = mp_obj_new_str(name, strlen(name)), + tuple[1] = mp_obj_new_int(pin_af->eic), + tuple[2] = mp_obj_new_int(pin_af->adc0), + tuple[3] = mp_obj_new_int(pin_af->adc1), + tuple[4] = mp_obj_new_int(pin_af->sercom1), + tuple[5] = mp_obj_new_int(pin_af->sercom2), + tuple[6] = mp_obj_new_int(pin_af->tc), + tuple[7] = mp_obj_new_int(pin_af->tcc1), + tuple[8] = mp_obj_new_int(pin_af->tcc2), + }; + return mp_obj_new_tuple(9, tuple); + #endif return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(samd_pininfo_obj, samd_pininfo); diff --git a/ports/samd/pin_af.c b/ports/samd/pin_af.c index 926c4ae0c2..fc2a0f3d54 100644 --- a/ports/samd/pin_af.c +++ b/ports/samd/pin_af.c @@ -29,7 +29,9 @@ */ #include +#include "string.h" +#include "modmachine.h" #include "py/runtime.h" #include "py/misc.h" #include "pin_af.h" @@ -43,13 +45,65 @@ extern const uint8_t tcc_channel_count[]; // Just look for an table entry for a given pin and raise an error // in case of no match (which should not happen). -const pin_af_t *get_pin_af_info(int pin_id) { +const machine_pin_obj_t *get_pin_obj_ptr(int pin_id) { for (int i = 0; i < MP_ARRAY_SIZE(pin_af_table); i++) { if (pin_af_table[i].pin_id == pin_id) { // Pin match return &pin_af_table[i]; } } - mp_raise_ValueError(MP_ERROR_TEXT("wrong pin")); + mp_raise_ValueError(MP_ERROR_TEXT("not a Pin")); +} + +const machine_pin_obj_t *pin_find(mp_obj_t pin, const mp_obj_type_t *type) { + const machine_pin_obj_t *self = NULL; + // Is already a object of the proper type + if (mp_obj_is_type(pin, type)) { + return pin; + } + if (mp_obj_is_small_int(pin)) { + // Pin defined by pin number for PAnn, PBnn, etc. + self = get_pin_obj_ptr(mp_obj_get_int(pin)); + } else if (mp_obj_is_str(pin)) { + // Search by name + size_t slen; + const char *s = mp_obj_str_get_data(pin, &slen); + // Check for a string like PA02 or PD12 + if (slen == 4 && s[0] == 'P' && strchr("ABCD", s[1]) != NULL && + strchr("0123456789", s[2]) != NULL && strchr("0123456789", s[2]) != NULL) { + int num = (s[1] - 'A') * 32 + (s[2] - '0') * 10 + (s[3] - '0'); + self = get_pin_obj_ptr(num); + } else { + for (int i = 0; i < MP_ARRAY_SIZE(pin_af_table); i++) { + if (slen == strlen(pin_af_table[i].name) && + strncmp(s, pin_af_table[i].name, slen) == 0) { + self = &pin_af_table[i]; + } + } + } + } + if (self != NULL && (type == NULL || mp_obj_is_type(self, type))) { + return self; + } else { + mp_raise_ValueError(MP_ERROR_TEXT("not a Pin")); + } +} + +const char *pin_name(int id) { + static char board_name[5] = "Pxnn"; + for (int i = 0; i < sizeof(pin_af_table); i++) { + if (pin_af_table[i].pin_id == id) { + if (pin_af_table[i].name[0] != '-') { + return pin_af_table[i].name; + } else { + board_name[1] = "ABCD"[id / 32]; + id %= 32; + board_name[2] = '0' + id / 10; + board_name[3] = '0' + id % 10; + return board_name; + } + } + } + return "-"; } // Test, wether the given pin is defined and has signals for sercom. @@ -57,7 +111,7 @@ const pin_af_t *get_pin_af_info(int pin_id) { // If not, an error will be raised. sercom_pad_config_t get_sercom_config(int pin_id, uint8_t sercom_nr) { - const pin_af_t *pct_ptr = get_pin_af_info(pin_id); + const machine_pin_obj_t *pct_ptr = get_pin_obj_ptr(pin_id); if ((pct_ptr->sercom1 >> 4) == sercom_nr) { return (sercom_pad_config_t) {ALT_FCT_SERCOM1, pct_ptr->sercom1 & 0x0f}; } else if ((pct_ptr->sercom2 >> 4) == sercom_nr) { @@ -72,7 +126,12 @@ sercom_pad_config_t get_sercom_config(int pin_id, uint8_t sercom_nr) { // If not, an error will be raised. adc_config_t get_adc_config(int pin_id, int32_t flag) { - const pin_af_t *pct_ptr = get_pin_af_info(pin_id); + const machine_pin_obj_t *pct_ptr = get_pin_obj_ptr(pin_id); + #if defined(MCU_SAMD51) + if (pct_ptr->adc1 != 0xff && (flag & (1 << (pct_ptr->adc1 + 16))) == 0) { + return (adc_config_t) {1, pct_ptr->adc1}; + } else + #endif if (pct_ptr->adc0 != 0xff && (flag & (1 << pct_ptr->adc0)) == 0) { return (adc_config_t) {0, pct_ptr->adc0}; #if defined(MUC_SAMD51) @@ -91,7 +150,7 @@ adc_config_t get_adc_config(int pin_id, int32_t flag) { // tries to provide an unused device, if available. pwm_config_t get_pwm_config(int pin_id, int wanted_dev, uint8_t device_status[]) { - const pin_af_t *pct_ptr = get_pin_af_info(pin_id); + const machine_pin_obj_t *pct_ptr = get_pin_obj_ptr(pin_id); uint8_t tcc1 = pct_ptr->tcc1; uint8_t tcc2 = pct_ptr->tcc2; diff --git a/ports/samd/pin_af.h b/ports/samd/pin_af.h index b75f4ddd02..5bb65a098a 100644 --- a/ports/samd/pin_af.h +++ b/ports/samd/pin_af.h @@ -30,15 +30,17 @@ #if defined(MCU_SAMD21) -typedef struct { +typedef struct _machine_pin_obj_t { + mp_obj_base_t base; uint8_t pin_id; + char *name; uint8_t eic; uint8_t adc0; uint8_t sercom1; uint8_t sercom2; uint8_t tcc1; uint8_t tcc2; -} pin_af_t; +} machine_pin_obj_t; #define ALT_FCT_TC 4 #define ALT_FCT_TCC1 4 @@ -46,8 +48,10 @@ typedef struct { #elif defined(MCU_SAMD51) -typedef struct { +typedef struct _machine_pin_obj_t { + mp_obj_base_t base; uint8_t pin_id; + char *name; uint8_t eic; uint8_t adc0; uint8_t adc1; @@ -56,7 +60,7 @@ typedef struct { uint8_t tc; uint8_t tcc1; uint8_t tcc2; -} pin_af_t; +} machine_pin_obj_t; #define ALT_FCT_TC 4 #define ALT_FCT_TCC1 5 @@ -85,7 +89,11 @@ typedef struct _pwm_config_t { #define ALT_FCT_SERCOM1 2 #define ALT_FCT_SERCOM2 3 +extern const machine_pin_obj_t pin_af_table[]; + sercom_pad_config_t get_sercom_config(int pin_id, uint8_t sercom); adc_config_t get_adc_config(int pin_id, int32_t flag); pwm_config_t get_pwm_config(int pin_id, int wanted_dev, uint8_t used_dev[]); -const pin_af_t *get_pin_af_info(int pin_id); +const machine_pin_obj_t *get_pin_obj_ptr(int pin_id); +const char *pin_name(int id); +const machine_pin_obj_t *pin_find(mp_obj_t pin, const mp_obj_type_t *type); From 4d38ab652ea57a60c6f2ff085547f72012ac7df6 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 7 Oct 2022 09:40:45 +0200 Subject: [PATCH 0580/1041] samd: Make ADC, DAC, PWM, SPI objects consistent in how they print out. All of ADC, DAC, Pin, PWM and SPI looked different before this change. --- ports/samd/machine_adc.c | 2 +- ports/samd/machine_dac.c | 2 +- ports/samd/machine_pwm.c | 2 +- ports/samd/machine_spi.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ports/samd/machine_adc.c b/ports/samd/machine_adc.c index efe0f041cd..8fd3e3bf4e 100644 --- a/ports/samd/machine_adc.c +++ b/ports/samd/machine_adc.c @@ -66,7 +66,7 @@ STATIC void adc_obj_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t k (void)kind; machine_adc_obj_t *self = MP_OBJ_TO_PTR(o); - mp_printf(print, "ADC(%s, ADC%u, channel=%u, bits=%u, average=%u)", + mp_printf(print, "ADC(%s, device=%u, channel=%u, bits=%u, average=%u)", pin_name(self->id), self->adc_config.device, self->adc_config.channel, self->bits, 1 << self->avg); } diff --git a/ports/samd/machine_dac.c b/ports/samd/machine_dac.c index 41c6784cce..53407c0d37 100644 --- a/ports/samd/machine_dac.c +++ b/ports/samd/machine_dac.c @@ -126,7 +126,7 @@ STATIC mp_obj_t dac_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ STATIC void dac_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { dac_obj_t *self = self_in; - mp_printf(print, "DAC(%u) PIN_PA%02u", self->id, self->gpio_id); + mp_printf(print, "DAC(%u, Pin=%s)", self->id, pin_name(self->gpio_id)); } STATIC mp_obj_t dac_write(mp_obj_t self_in, mp_obj_t value_in) { diff --git a/ports/samd/machine_pwm.c b/ports/samd/machine_pwm.c index 91982a6f74..2ae841a974 100644 --- a/ports/samd/machine_pwm.c +++ b/ports/samd/machine_pwm.c @@ -107,7 +107,7 @@ STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "PWM %s device=%u channel=%u output=%u", + mp_printf(print, "PWM(%s, device=%u, channel=%u, output=%u)", pin_name(self->pin_id), self->device, self->channel, self->output); } diff --git a/ports/samd/machine_spi.c b/ports/samd/machine_spi.c index 8321f19cf0..43150f67f1 100644 --- a/ports/samd/machine_spi.c +++ b/ports/samd/machine_spi.c @@ -82,7 +82,7 @@ void common_spi_irq_handler(int spi_id) { STATIC void machine_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "SPI(%u), baudrate=%u, firstbit=%u, polarity=%u, phase=%u, bits=8", + mp_printf(print, "SPI(%u, baudrate=%u, firstbit=%u, polarity=%u, phase=%u, bits=8)", self->id, self->baudrate, self->firstbit, self->polarity, self->phase); } From a6760bd4efa883ef463795036ff74d678ff65c7b Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 9 Oct 2022 10:56:29 +0200 Subject: [PATCH 0581/1041] samd/modmachine: Replace the LED class by the Signal class. It simplifies and improves the code. The LED_Pxxx lines of the board.csv lines can still be used, but will be taken as Pin definitions. --- ports/samd/Makefile | 1 - ports/samd/boards/make-pin-table.py | 6 +-- ports/samd/machine_led.c | 78 ----------------------------- ports/samd/machine_pin.c | 4 +- ports/samd/modmachine.c | 3 +- ports/samd/modmachine.h | 1 - ports/samd/modsamd.c | 2 +- ports/samd/mpconfigport.h | 1 + ports/samd/pin_af.c | 6 +-- ports/samd/pin_af.h | 2 +- 10 files changed, 11 insertions(+), 93 deletions(-) delete mode 100644 ports/samd/machine_led.c diff --git a/ports/samd/Makefile b/ports/samd/Makefile index f512fb0b2e..b2e84460ea 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -88,7 +88,6 @@ SRC_C += \ machine_bitstream.c \ machine_dac.c \ machine_i2c.c \ - machine_led.c \ machine_pin.c \ machine_rtc.c \ machine_spi.c \ diff --git a/ports/samd/boards/make-pin-table.py b/ports/samd/boards/make-pin-table.py index 327478568a..40bcd166dd 100644 --- a/ports/samd/boards/make-pin-table.py +++ b/ports/samd/boards/make-pin-table.py @@ -36,11 +36,7 @@ class Pins: # for compatibility, map LED_ to PIN_ if row[0].startswith("LED_"): row[0] = "PIN_" + row[0][4:] - if len(row) == 1: - self.pin_names[row[0]] = (row[0][4:], "{&machine_led_type}") - else: - self.pin_names[row[0]] = (row[1], "{&machine_led_type}") - elif row[0].startswith("PIN_"): + if row[0].startswith("PIN_"): if len(row) == 1: self.pin_names[row[0]] = (row[0][4:], "{&machine_pin_type}") else: diff --git a/ports/samd/machine_led.c b/ports/samd/machine_led.c deleted file mode 100644 index c18bc052bd..0000000000 --- a/ports/samd/machine_led.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * This is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016-2021 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. - * - * Uses pins.h & pins.c to create board (MCU package) specific 'machine_led_obj' array. - */ - -#include "py/runtime.h" -#include "py/mphal.h" -#include "extmod/virtpin.h" -#include "modmachine.h" -#include "pin_af.h" - -extern mp_obj_t machine_pin_low_obj; -extern mp_obj_t machine_pin_high_obj; -extern mp_obj_t machine_pin_toggle_obj; -extern mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); - -STATIC void machine_led_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - machine_pin_obj_t *self = self_in; - mp_printf(print, "LED(\"%s\", GPIO=P%c%02u)", - pin_name(self->pin_id), - "ABCD"[self->pin_id / 32], self->pin_id % 32); -} - -// constructor(id, ...) -mp_obj_t mp_led_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 the wanted LED object - const machine_pin_obj_t *self; - - self = pin_find(args[0], &machine_led_type); - - mp_hal_pin_output(self->pin_id); - mp_hal_pin_low(self->pin_id); - - return MP_OBJ_FROM_PTR(self); -} - -STATIC const mp_rom_map_elem_t machine_led_locals_dict_table[] = { - // instance methods - { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&machine_pin_low_obj) }, - { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_pin_high_obj) }, - { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&machine_pin_toggle_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(machine_led_locals_dict, machine_led_locals_dict_table); - -MP_DEFINE_CONST_OBJ_TYPE( - machine_led_type, - MP_QSTR_LED, - MP_TYPE_FLAG_NONE, - make_new, mp_led_make_new, - print, machine_led_print, - call, machine_pin_call, - locals_dict, &machine_led_locals_dict - ); diff --git a/ports/samd/machine_pin.c b/ports/samd/machine_pin.c index a7cd86d386..8768485832 100644 --- a/ports/samd/machine_pin.c +++ b/ports/samd/machine_pin.c @@ -143,7 +143,7 @@ mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const machine_pin_obj_t *self; // get the wanted pin object - self = pin_find(args[0], &machine_pin_type); + self = pin_find(args[0]); if (n_args > 1 || n_kw > 0) { // pin mode given, so configure this GPIO @@ -499,7 +499,7 @@ STATIC const mp_irq_methods_t machine_pin_irq_methods = { }; mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t obj) { - const machine_pin_obj_t *pin = pin_find(obj, &machine_pin_type); + const machine_pin_obj_t *pin = pin_find(obj); return pin->pin_id; } diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index 12e9f7c341..47fc03d824 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -29,6 +29,7 @@ #include "extmod/machine_mem.h" #include "extmod/machine_pulse.h" #include "extmod/machine_i2c.h" +#include "extmod/machine_signal.h" #include "extmod/machine_spi.h" #include "drivers/dht/dht.h" #include "modmachine.h" @@ -228,8 +229,8 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) }, - { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&machine_led_type) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, + { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, diff --git a/ports/samd/modmachine.h b/ports/samd/modmachine.h index 8f85e14989..792fca1b92 100644 --- a/ports/samd/modmachine.h +++ b/ports/samd/modmachine.h @@ -31,7 +31,6 @@ extern const mp_obj_type_t machine_adc_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_led_type; extern const mp_obj_type_t machine_pin_type; extern const mp_obj_type_t machine_pwm_type; extern const mp_obj_type_t machine_spi_type; diff --git a/ports/samd/modsamd.c b/ports/samd/modsamd.c index 79e7b4cc35..5a2cf4616d 100644 --- a/ports/samd/modsamd.c +++ b/ports/samd/modsamd.c @@ -35,7 +35,7 @@ extern const mp_obj_type_t samd_flash_type; STATIC mp_obj_t samd_pininfo(mp_obj_t pin_obj) { - const machine_pin_obj_t *pin_af = pin_find(pin_obj, NULL); + const machine_pin_obj_t *pin_af = pin_find(pin_obj); // Get the name, now that it is not in the pin object const char *name = pin_af->name; diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 8b8305f0b4..f03f8a11d7 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -100,6 +100,7 @@ #define MICROPY_PY_MACHINE_PWM_INIT (0) #define MICROPY_PY_MACHINE_PWM_DUTY_U16_NS (1) #define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/samd/machine_pwm.c" +#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new #define MP_STATE_PORT MP_STATE_VM diff --git a/ports/samd/pin_af.c b/ports/samd/pin_af.c index fc2a0f3d54..a7a72ac96a 100644 --- a/ports/samd/pin_af.c +++ b/ports/samd/pin_af.c @@ -54,10 +54,10 @@ const machine_pin_obj_t *get_pin_obj_ptr(int pin_id) { mp_raise_ValueError(MP_ERROR_TEXT("not a Pin")); } -const machine_pin_obj_t *pin_find(mp_obj_t pin, const mp_obj_type_t *type) { +const machine_pin_obj_t *pin_find(mp_obj_t pin) { const machine_pin_obj_t *self = NULL; // Is already a object of the proper type - if (mp_obj_is_type(pin, type)) { + if (mp_obj_is_type(pin, &machine_pin_type)) { return pin; } if (mp_obj_is_small_int(pin)) { @@ -81,7 +81,7 @@ const machine_pin_obj_t *pin_find(mp_obj_t pin, const mp_obj_type_t *type) { } } } - if (self != NULL && (type == NULL || mp_obj_is_type(self, type))) { + if (self != NULL) { return self; } else { mp_raise_ValueError(MP_ERROR_TEXT("not a Pin")); diff --git a/ports/samd/pin_af.h b/ports/samd/pin_af.h index 5bb65a098a..4b0c80250c 100644 --- a/ports/samd/pin_af.h +++ b/ports/samd/pin_af.h @@ -96,4 +96,4 @@ adc_config_t get_adc_config(int pin_id, int32_t flag); pwm_config_t get_pwm_config(int pin_id, int wanted_dev, uint8_t used_dev[]); const machine_pin_obj_t *get_pin_obj_ptr(int pin_id); const char *pin_name(int id); -const machine_pin_obj_t *pin_find(mp_obj_t pin, const mp_obj_type_t *type); +const machine_pin_obj_t *pin_find(mp_obj_t pin); From ac1e31267b0bf21caa31b8136208c116b1612789 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 8 Oct 2022 21:12:50 +0200 Subject: [PATCH 0582/1041] samd/boards: Rework the pins.csv files. Changes are: - Remove the LED_Pxxx definitions from pins.csv, now that the LED class is gone. - Remove the '-' lines. - Add default lines for USB and SWCLK, SWDIO. --- .../boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv | 11 ++++++++--- .../boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv | 10 ++++++---- .../boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv | 8 +++++--- .../boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv | 9 ++++++--- ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.csv | 8 +++++++- ports/samd/boards/MINISAM_M4/pins.csv | 9 ++++++++- ports/samd/boards/SAMD21_XPLAINED_PRO/pins.csv | 15 +++++++-------- ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv | 11 +++++++++-- ports/samd/boards/SEEED_XIAO/pins.csv | 12 +++++++++--- .../boards/SPARKFUN_SAMD51_THING_PLUS/pins.csv | 15 +++++++++------ 10 files changed, 74 insertions(+), 34 deletions(-) diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv index 0985ee1646..45b05c2694 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv @@ -5,6 +5,9 @@ # Rows for empty entries have to start with '-' # Empty lines and lines starting with # are ignored +PIN_PA27,LED_TX +PIN_PB03,LED_RX + PIN_PA11,D0 PIN_PA10,D1 PIN_PA14,D2 @@ -35,6 +38,8 @@ PIN_PB11,SCK PIN_PA06,NEOPIXEL PIN_PA13,FLASH_CS -LED_PA17,LED -LED_PA27,LED_TX -LED_PB03,LED_RX +PIN_PA24,USB_DM +PIN_PA25,USB_DP + +PIN_PA30,SWCLK +PIN_PA31,SWDIO diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv index 32daac3d0f..ca58a4be79 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv @@ -7,12 +7,9 @@ PIN_PB17,D0 PIN_PB16,D1 -- -- PIN_PA14,D4 PIN_PA16,D5 PIN_PA18,D6 -- PIN_PB03,D8 PIN_PA19,D9 PIN_PA20,D10 @@ -40,4 +37,9 @@ PIN_PA09,FLASH_MISO PIN_PA10,FLASH_WP PIN_PA11,FLASH_HOLD -LED_PA17,LED +PIN_PA24,USB_DM +PIN_PA25,USB_DP +PIN_PA26,USB_SOF + +PIN_PA30,SWCLK +PIN_PA31,SWDIO diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv index d7d59c2357..e93e00ab9c 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv @@ -11,9 +11,7 @@ PIN_PA14,D2 PIN_PA09,D3 PIN_PA08,D4 PIN_PA15,D5 -- PIN_PA21,D7 -- PIN_PA07,D9 PIN_PA18,D10 PIN_PA16,D11 @@ -37,4 +35,8 @@ PIN_PB03,FLASH_MISO PIN_PB23,FLASH_SCK PIN_PA27,FLASH_CS -LED_PA17,LED +PIN_PA24,USB_DM +PIN_PA25,USB_DP + +PIN_PA30,SWCLK +PIN_PA31,SWDIO diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv index ce760a269c..3dee9bf4c3 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv @@ -11,9 +11,7 @@ PIN_PA07,D2 PIN_PB22,D3 PIN_PA14,D4 PIN_PA15,D5 -- PIN_PA18,D7 -- PIN_PA19,D9 PIN_PA20,D10 PIN_PA21,D11 @@ -39,4 +37,9 @@ PIN_PA09,FLASH_MISO PIN_PA10,FLASH_WP PIN_PA11,FLASH_HOLD -LED_PA22,LED +PIN_PA24,USB_DM +PIN_PA25,USB_DP +PIN_PA26,USB_SOF + +PIN_PA30,SWCLK +PIN_PA31,SWDIO diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.csv b/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.csv index 797b3f70bb..95f76815f9 100644 --- a/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.csv +++ b/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.csv @@ -13,4 +13,10 @@ PIN_PA06,D4 PIN_PA00,DOTSTAR_DATA PIN_PA01,DOTSTAR_CLK -LED_PA10,LED +PIN_PA10,LED + +PIN_PA24,USB_DM +PIN_PA25,USB_DP + +PIN_PA30,SWCLK +PIN_PA31,SWDIO diff --git a/ports/samd/boards/MINISAM_M4/pins.csv b/ports/samd/boards/MINISAM_M4/pins.csv index cf9a3bd19b..f6d0ab657f 100644 --- a/ports/samd/boards/MINISAM_M4/pins.csv +++ b/ports/samd/boards/MINISAM_M4/pins.csv @@ -27,4 +27,11 @@ PIN_PA01,SCK PIN_PB03,DOTSTAR_DATA PIN_PB02,DOTSTAR_CLK -LED_PA15,LED +PIN_PA15,LED + +PIN_PA24,USB_DM +PIN_PA25,USB_DP +PIN_PA26,USB_SOF + +PIN_PA30,SWCLK +PIN_PA31,SWDIO diff --git a/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.csv b/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.csv index 438119d90c..bd0757d564 100644 --- a/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.csv +++ b/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.csv @@ -32,8 +32,6 @@ PIN_PB12,EXT2_PIN7 PIN_PB13,EXT2_PIN8 PIN_PB14,EXT2_PIN9 PIN_PB15,EXT2_PIN10 -- -- PIN_PB11,EXT2_PIN13 PIN_PB10,EXT2_PIN14 PIN_PA17,EXT2_PIN15 @@ -44,20 +42,21 @@ PIN_PA19,EXT2_PIN18 # EXT3 PIN_PA02,EXT3_PIN3 PIN_PA03,EXT3_PIN4 -- PIN_PA15,EXT3_PIN6 PIN_PA12,EXT3_PIN7 PIN_PA13,EXT3_PIN8 PIN_PA28,EXT3_PIN9 PIN_PA27,EXT3_PIN10 -- -- -- -- PIN_PB17,EXT3_PIN15 PIN_PB22,EXT3_PIN16 PIN_PB16,EXT3_PIN17 PIN_PB23,EXT3_PIN18 -LED_PB30,LED +PIN_PB30,LED + +PIN_PA24,USB_DM +PIN_PA25,USB_DP + +PIN_PA30,SWCLK +PIN_PA31,SWDIO diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv b/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv index 9bc57070d1..4a3d9e21ae 100644 --- a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv +++ b/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv @@ -60,5 +60,12 @@ PIN_PC13,LCD_YD PIN_PC30,MIC PIN_PD11,BUZZER -LED_PA15,LED_BLUE -LED_PC05,LED_LCD +PIN_PA15,LED_BLUE +PIN_PC05,LED_LCD + +PIN_PA24,USB_DM +PIN_PA25,USB_DP +PIN_PA26,USB_SOF + +PIN_PA30,SWCLK +PIN_PA31,SWDIO diff --git a/ports/samd/boards/SEEED_XIAO/pins.csv b/ports/samd/boards/SEEED_XIAO/pins.csv index 8a70a77145..a06d3ac6ac 100644 --- a/ports/samd/boards/SEEED_XIAO/pins.csv +++ b/ports/samd/boards/SEEED_XIAO/pins.csv @@ -17,6 +17,12 @@ PIN_PA07,A8_D8 PIN_PA05,A9_D9 PIN_PA06,A10_D10 -LED_PA17,USER_LED -LED_PA18,RX_LED -LED_PA19,TX_LED +PIN_PA17,USER_LED +PIN_PA18,RX_LED +PIN_PA19,TX_LED + +PIN_PA24,USB_DM +PIN_PA25,USB_DP + +PIN_PA30,SWCLK +PIN_PA31,SWDIO diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/pins.csv b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/pins.csv index b60fb90971..dfd6641333 100644 --- a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/pins.csv +++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/pins.csv @@ -13,7 +13,6 @@ PIN_PA06,D4 PIN_PA15,D5 PIN_PA20,D6 PIN_PA21,D7 -- PIN_PA07,D9 PIN_PA18,D10 PIN_PA16,D11 @@ -34,9 +33,13 @@ PIN_PA08,FLASH_MOSI PIN_PA09,FLASH_SCK PIN_PA10,FLASH_CS PIN_PA11,FLASH_MISO -PIN_PA30,SWDCLK -PIN_PA31,SWDIO -LED_PA17,LED -LED_PB03,RXLED -LED_PA27,TXLED +PIN_PB03,RXLED +PIN_PA27,TXLED + +PIN_PA24,USB_DM +PIN_PA25,USB_DP +PIN_PA26,USB_SOF + +PIN_PA30,SWCLK +PIN_PA31,SWDIO From 474233c250536612a5245231aff1ef3ad74ccf20 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 11 Oct 2022 10:05:01 +0200 Subject: [PATCH 0583/1041] samd/machine_pwm: Serialize fast update of PWM settings. Any update of freq or duty_cycle requires the previous PWM cycle to be finished. Otherwise the new settings are not accepted. Other changes in this commit: - Report the set duty cycles even when the PWM is not yet started. - pwm.freq(0) stops the pwm device, instead of raising an expception. - Clear the duty cycle value cache on soft reset. --- ports/samd/machine_pwm.c | 51 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/ports/samd/machine_pwm.c b/ports/samd/machine_pwm.c index 2ae841a974..f6b417631e 100644 --- a/ports/samd/machine_pwm.c +++ b/ports/samd/machine_pwm.c @@ -25,6 +25,7 @@ * THE SOFTWARE. */ +#include #include "py/runtime.h" #include "py/mphal.h" #include "modmachine.h" @@ -46,6 +47,8 @@ typedef struct _machine_pwm_obj_t { uint8_t output; uint16_t prescaler; uint32_t period; // full period count ticks + uint32_t duty_ns; // just for reporting + uint16_t duty_u16; // just for reporting } machine_pwm_obj_t; #define PWM_NOT_INIT (0) @@ -53,6 +56,7 @@ typedef struct _machine_pwm_obj_t { #define PWM_TCC_ENABLED (2) #define PWM_MASTER_CLK (get_peripheral_freq()) #define PWM_FULL_SCALE (65536) +#define PWM_UPDATE_TIMEOUT (2000) static Tcc *tcc_instance[] = TCC_INSTS; @@ -148,6 +152,7 @@ STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args self->output = config.device_channel & 0x0f; self->prescaler = 1; self->period = 1; // Use an invalid but safe value + self->duty_u16 = self->duty_ns = 0; put_duty_value(self->device, self->channel, 0); Tcc *tcc = self->instance; @@ -240,6 +245,7 @@ void pwm_deinit_all(void) { device_status[i] = PWM_NOT_INIT; duty_type_flags[i] = 0; output_active[i] = 0; + memset(pwm_duty_values, 0, sizeof(pwm_duty_values)); } } @@ -256,8 +262,25 @@ STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self) { } } +STATIC void wait_for_register_update(Tcc *tcc) { + // Wait for a period's end (may be long) to have the change settled + // Each loop cycle takes at least 1 ms, giving an implicit timeout. + for (int i = 0; i < PWM_UPDATE_TIMEOUT; i++) { + if (tcc->INTFLAG.reg & TCC_INTFLAG_OVF) { + break; + } + MICROPY_EVENT_POLL_HOOK + } + // Clear the flag, telling that a cycle has been handled. + tcc->INTFLAG.reg = TCC_INTFLAG_OVF; +} + STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) { - return MP_OBJ_NEW_SMALL_INT(PWM_MASTER_CLK / self->prescaler / self->period); + if (self->instance->CTRLA.reg & TCC_CTRLA_ENABLE) { + return MP_OBJ_NEW_SMALL_INT(PWM_MASTER_CLK / self->prescaler / self->period); + } else { + return MP_OBJ_NEW_SMALL_INT(0); + } } STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) { @@ -267,7 +290,8 @@ STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) { Tcc *tcc = self->instance; if (freq < 1) { - mp_raise_ValueError(MP_ERROR_TEXT("invalid freq")); + pwm_stop_device(self->device); + return; } // Get the actual settings of prescaler & period from the unit @@ -288,6 +312,11 @@ STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) { if (period < 2) { mp_raise_ValueError(MP_ERROR_TEXT("freq too large")); } + // If the PWM is running, ensure that a cycle has passed since the + // previous setting before setting a new frequency/duty value + if (tcc->CTRLA.reg & TCC_CTRLA_ENABLE) { + wait_for_register_update(tcc); + } // Check, if the prescaler has to be changed and stop the device if so. if (index != tcc->CTRLA.bit.PRESCALER) { // stop the device @@ -339,25 +368,37 @@ STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) { } STATIC mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self) { - return MP_OBJ_NEW_SMALL_INT(self->instance->CC[self->channel].reg * PWM_FULL_SCALE / (self->instance->PER.reg + 1)); + return MP_OBJ_NEW_SMALL_INT(self->duty_u16); } STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16) { + // Remember the values for update & reporting put_duty_value(self->device, self->channel, duty_u16); + self->duty_u16 = duty_u16; + self->duty_ns = 0; // If the device is enabled, than the period is set and we get a reasonable value for // the duty cycle, set to the CCBUF register. Otherwise, PWM does not start. if (self->instance->CTRLA.reg & TCC_CTRLA_ENABLE) { - self->instance->CCBUF[self->channel].reg = (uint64_t)duty_u16 * (self->instance->PER.reg + 1) / PWM_FULL_SCALE; + // Ensure that a cycle has passed updating the registers + // since the previous setting before setting a new duty value + wait_for_register_update(self->instance); + self->instance->CCBUF[self->channel].reg = (uint64_t)duty_u16 * (self->period) / PWM_FULL_SCALE; } duty_type_flags[self->device] |= 1 << self->channel; } STATIC mp_obj_t mp_machine_pwm_duty_get_ns(machine_pwm_obj_t *self) { - return MP_OBJ_NEW_SMALL_INT(1000000000ULL * self->instance->CC[self->channel].reg * self->prescaler / PWM_MASTER_CLK); + return MP_OBJ_NEW_SMALL_INT(self->duty_ns); } STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns) { + // Remember the values for update & reporting put_duty_value(self->device, self->channel, duty_ns); + self->duty_ns = duty_ns; + self->duty_u16 = 0; + // Ensure that a cycle has passed updating the registers + // since the previous setting before setting a new duty value + wait_for_register_update(self->instance); self->instance->CCBUF[self->channel].reg = (uint64_t)duty_ns * PWM_MASTER_CLK / self->prescaler / 1000000000ULL; duty_type_flags[self->device] &= ~(1 << self->channel); } From 9c2bc379f183ff9f3280842eb236e8f4b8635835 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 8 Oct 2022 12:32:55 +0200 Subject: [PATCH 0584/1041] samd/machine_uart: Use a finaliser to tidy up UART on soft reset. And use the common sercom_table, saving a few bytes of RAM. --- ports/samd/machine_uart.c | 22 ++++++++-------------- ports/samd/main.c | 2 -- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/ports/samd/machine_uart.c b/ports/samd/machine_uart.c index 76b564e874..2526b45093 100644 --- a/ports/samd/machine_uart.c +++ b/ports/samd/machine_uart.c @@ -59,7 +59,7 @@ typedef struct _machine_uart_obj_t { } machine_uart_obj_t; Sercom *sercom_instance[] = SERCOM_INSTS; -machine_uart_obj_t *uart_table[SERCOM_INST_NUM] = {}; +extern void *sercom_table[SERCOM_INST_NUM]; STATIC const char *_parity_name[] = {"None", "", "0", "1"}; // Is defined as 0, 2, 3 @@ -82,7 +82,7 @@ STATIC void uart_drain_rx_fifo(machine_uart_obj_t *self, Sercom *uart) { } void common_uart_irq_handler(int uart_id) { - machine_uart_obj_t *self = uart_table[uart_id]; + machine_uart_obj_t *self = sercom_table[uart_id]; // Handle IRQ if (self != NULL) { Sercom *uart = sercom_instance[self->id]; @@ -322,7 +322,8 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, } // Create the UART object and fill it with defaults. - machine_uart_obj_t *self = mp_obj_malloc(machine_uart_obj_t, &machine_uart_type); + machine_uart_obj_t *self = m_new_obj_with_finaliser(machine_uart_obj_t); + self->base.type = &machine_uart_type; self->id = uart_id; self->baudrate = DEFAULT_UART_BAUDRATE; self->bits = 8; @@ -332,7 +333,7 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, self->tx = 0xff; self->rx = 0xff; self->new = true; - uart_table[uart_id] = self; + sercom_table[uart_id] = self; mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); @@ -348,10 +349,10 @@ 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); Sercom *uart = sercom_instance[self->id]; - // clear table entry of uart - uart_table[self->id] = NULL; // Disable interrupts uart->USART.INTENCLR.reg = 0xff; + // clear table entry of uart + sercom_table[self->id] = NULL; MP_STATE_PORT(samd_uart_rx_buffer[self->id]) = NULL; #if MICROPY_HW_UART_TXBUF MP_STATE_PORT(samd_uart_tx_buffer[self->id]) = NULL; @@ -409,14 +410,6 @@ STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone); -void uart_deinit_all(void) { - for (int i = 0; i < SERCOM_INST_NUM; i++) { - if (uart_table[i] != NULL) { - machine_uart_deinit((mp_obj_t)uart_table[i]); - } - } -} - 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) }, @@ -430,6 +423,7 @@ STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { { 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___del__), MP_ROM_PTR(&machine_uart_deinit_obj) }, }; STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table); diff --git a/ports/samd/main.c b/ports/samd/main.c index 0f24e2382e..725fd651d0 100644 --- a/ports/samd/main.c +++ b/ports/samd/main.c @@ -39,7 +39,6 @@ extern void adc_deinit_all(void); extern void pin_irq_deinit_all(void); extern void pwm_deinit_all(void); extern void sercom_deinit_all(void); -extern void uart_deinit_all(void); void samd_main(void) { mp_stack_set_top(&_estack); @@ -86,7 +85,6 @@ void samd_main(void) { pin_irq_deinit_all(); pwm_deinit_all(); sercom_deinit_all(); - uart_deinit_all(); soft_timer_deinit(); gc_sweep_all(); mp_deinit(); From d74215a3137da5e9001aed92c8c1b06d828ff9d2 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 8 Oct 2022 12:34:45 +0200 Subject: [PATCH 0585/1041] samd/machine_spi: Implement spi.deinit() and simplify sercom_deinit_all. The sercom_deinit_all() function does not need the object pointers. --- ports/samd/machine_spi.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/ports/samd/machine_spi.c b/ports/samd/machine_spi.c index 43150f67f1..d4c7a05bb6 100644 --- a/ports/samd/machine_spi.c +++ b/ports/samd/machine_spi.c @@ -254,17 +254,23 @@ STATIC mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, s return self; } +STATIC void machine_sercom_deinit(mp_obj_base_t *self_in) { + machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); + Sercom *spi = sercom_instance[self->id]; + // Disable interrupts (if any) + spi->SPI.INTENCLR.reg = 0xff; + sercom_enable(spi, 0); + // clear table entry of spi + sercom_table[self->id] = NULL; +} + void sercom_deinit_all(void) { for (int i = 0; i < SERCOM_INST_NUM; i++) { - if (sercom_table[i] != NULL) { - machine_spi_obj_t *self = sercom_table[i]; - Sercom *spi = sercom_instance[self->id]; - // Disable interrupts (if any) - spi->SPI.INTENCLR.reg = 0xff; - // clear table entry of spi - sercom_table[i] = NULL; - sercom_enable(spi, 0); - } + Sercom *spi = sercom_instance[i]; + spi->SPI.INTENCLR.reg = 0xff; + sercom_register_irq(i, NULL); + sercom_enable(spi, 0); + sercom_table[i] = NULL; } } @@ -316,6 +322,7 @@ STATIC void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8 STATIC const mp_machine_spi_p_t machine_spi_p = { .init = machine_spi_init, + .deinit = machine_sercom_deinit, .transfer = machine_spi_transfer, }; From a1eebc507eda8f5ec052d0ef0450c52f2320e106 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 13 Oct 2022 19:04:37 +0200 Subject: [PATCH 0586/1041] samd/machine_spi: Register SerCom objects as root pointers. Protect SerCom (UART, SPI, I2C) objects from getting freed by the GC when they go out of scope without being deinitialized. Otherwise the ISR of a Sercom may access an invalid data structure. --- ports/samd/machine_i2c.c | 5 ++--- ports/samd/machine_spi.c | 10 +++++----- ports/samd/machine_uart.c | 7 +++---- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/ports/samd/machine_i2c.c b/ports/samd/machine_i2c.c index 0a8f5b94db..d943b6b2f4 100644 --- a/ports/samd/machine_i2c.c +++ b/ports/samd/machine_i2c.c @@ -69,7 +69,6 @@ typedef struct _machine_i2c_obj_t { } machine_i2c_obj_t; extern Sercom *sercom_instance[]; -extern void *sercom_table[SERCOM_INST_NUM]; STATIC void i2c_send_command(Sercom *i2c, uint8_t command) { i2c->I2CM.CTRLB.bit.CMD = command; @@ -79,7 +78,7 @@ STATIC void i2c_send_command(Sercom *i2c, uint8_t command) { void common_i2c_irq_handler(int i2c_id) { // handle Sercom I2C IRQ - machine_i2c_obj_t *self = sercom_table[i2c_id]; + machine_i2c_obj_t *self = MP_STATE_PORT(sercom_table[i2c_id]); // Handle IRQ if (self != NULL) { Sercom *i2c = self->instance; @@ -159,7 +158,7 @@ mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n if (sda_pad_config.pad_nr != 0 || scl_pad_config.pad_nr != 1) { mp_raise_ValueError(MP_ERROR_TEXT("invalid pin for sda or scl")); } - sercom_table[self->id] = self; + MP_STATE_PORT(sercom_table[self->id]) = self; self->freq = args[ARG_freq].u_int; // Configure the Pin mux. diff --git a/ports/samd/machine_spi.c b/ports/samd/machine_spi.c index d4c7a05bb6..4ffc7095cc 100644 --- a/ports/samd/machine_spi.c +++ b/ports/samd/machine_spi.c @@ -57,11 +57,11 @@ typedef struct _machine_spi_obj_t { } machine_spi_obj_t; extern Sercom *sercom_instance[]; -void *sercom_table[SERCOM_INST_NUM] = {}; +MP_REGISTER_ROOT_POINTER(void *sercom_table[SERCOM_INST_NUM]); void common_spi_irq_handler(int spi_id) { // handle Sercom IRQ RXC - machine_spi_obj_t *self = sercom_table[spi_id]; + machine_spi_obj_t *self = MP_STATE_PORT(sercom_table[spi_id]); // Handle IRQ if (self != NULL) { Sercom *spi = sercom_instance[self->id]; @@ -246,7 +246,7 @@ STATIC mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, s self->sck = 0xff; self->new = true; - sercom_table[spi_id] = self; + MP_STATE_PORT(sercom_table[spi_id]) = self; mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); @@ -261,7 +261,7 @@ STATIC void machine_sercom_deinit(mp_obj_base_t *self_in) { spi->SPI.INTENCLR.reg = 0xff; sercom_enable(spi, 0); // clear table entry of spi - sercom_table[self->id] = NULL; + MP_STATE_PORT(sercom_table[self->id]) = NULL; } void sercom_deinit_all(void) { @@ -270,7 +270,7 @@ void sercom_deinit_all(void) { spi->SPI.INTENCLR.reg = 0xff; sercom_register_irq(i, NULL); sercom_enable(spi, 0); - sercom_table[i] = NULL; + MP_STATE_PORT(sercom_table[i]) = NULL; } } diff --git a/ports/samd/machine_uart.c b/ports/samd/machine_uart.c index 2526b45093..4b8fa3b60d 100644 --- a/ports/samd/machine_uart.c +++ b/ports/samd/machine_uart.c @@ -59,7 +59,6 @@ typedef struct _machine_uart_obj_t { } machine_uart_obj_t; Sercom *sercom_instance[] = SERCOM_INSTS; -extern void *sercom_table[SERCOM_INST_NUM]; STATIC const char *_parity_name[] = {"None", "", "0", "1"}; // Is defined as 0, 2, 3 @@ -82,7 +81,7 @@ STATIC void uart_drain_rx_fifo(machine_uart_obj_t *self, Sercom *uart) { } void common_uart_irq_handler(int uart_id) { - machine_uart_obj_t *self = sercom_table[uart_id]; + machine_uart_obj_t *self = MP_STATE_PORT(sercom_table[uart_id]); // Handle IRQ if (self != NULL) { Sercom *uart = sercom_instance[self->id]; @@ -333,7 +332,7 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, self->tx = 0xff; self->rx = 0xff; self->new = true; - sercom_table[uart_id] = self; + MP_STATE_PORT(sercom_table[uart_id]) = self; mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); @@ -352,7 +351,7 @@ STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) { // Disable interrupts uart->USART.INTENCLR.reg = 0xff; // clear table entry of uart - sercom_table[self->id] = NULL; + MP_STATE_PORT(sercom_table[self->id]) = NULL; MP_STATE_PORT(samd_uart_rx_buffer[self->id]) = NULL; #if MICROPY_HW_UART_TXBUF MP_STATE_PORT(samd_uart_tx_buffer[self->id]) = NULL; From fcccfc176b225001b402ce2ced062344990789e0 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 17 Oct 2022 18:05:28 +0200 Subject: [PATCH 0587/1041] samd/modmachine: Add machine.softreset(). For consistency with other ports. --- ports/samd/modmachine.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c index 47fc03d824..8adc06f526 100644 --- a/ports/samd/modmachine.c +++ b/ports/samd/modmachine.c @@ -32,6 +32,7 @@ #include "extmod/machine_signal.h" #include "extmod/machine_spi.h" #include "drivers/dht/dht.h" +#include "shared/runtime/pyexec.h" #include "modmachine.h" #include "samd_soc.h" @@ -57,6 +58,12 @@ extern bool EIC_occured; extern uint32_t _dbl_tap_addr; +STATIC mp_obj_t machine_soft_reset(void) { + pyexec_system_exit = PYEXEC_FORCED_EXIT; + mp_raise_type(&mp_type_SystemExit); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset); + STATIC mp_obj_t machine_reset(void) { *DBL_TAP_ADDR = DBL_TAP_MAGIC_RESET; #ifdef DBL_TAP_ADDR_ALT @@ -219,6 +226,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lightsleep_obj, 0, 1, machine STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, + { MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&machine_soft_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) }, { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) }, From d75c7e822cbfe7014fede1420f996a0af04bb13c Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 21 Sep 2022 09:57:10 +1000 Subject: [PATCH 0588/1041] py/obj: Add comments explaining the slot index scheme. Signed-off-by: Jim Mussared --- py/obj.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/py/obj.h b/py/obj.h index 8d62dd4f3c..b5b855bad3 100644 --- a/py/obj.h +++ b/py/obj.h @@ -753,10 +753,16 @@ typedef struct _mp_obj_full_type_t { #define MP_DEFINE_CONST_OBJ_TYPE_NARGS_11(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, } } #define MP_DEFINE_CONST_OBJ_TYPE_NARGS_12(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11, f12, v12) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slot_index_##f12 = 12, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, } } +// Because the mp_obj_type_t instances are in (zero-initialised) ROM, we take +// slot_index_foo=0 to mean that the slot is unset. This also simplifies checking +// if the slot is set. That means that we need to store index+1 in slot_index_foo +// though and then access it as slots[slot_index_foo - 1]. This is an implementation +// detail, the user of these macros doesn't need to be aware of it, and when using +// MP_OBJ_TYPE_OFFSETOF_SLOT you should use zero-based indexing. #define MP_OBJ_TYPE_HAS_SLOT(t, f) ((t)->slot_index_##f) #define MP_OBJ_TYPE_GET_SLOT(t, f) (_MP_OBJ_TYPE_SLOT_TYPE_##f(t)->slots[(t)->slot_index_##f - 1]) #define MP_OBJ_TYPE_GET_SLOT_OR_NULL(t, f) (_MP_OBJ_TYPE_SLOT_TYPE_##f(MP_OBJ_TYPE_HAS_SLOT(t, f) ? MP_OBJ_TYPE_GET_SLOT(t, f) : NULL)) -#define MP_OBJ_TYPE_SET_SLOT(t, f, v, n) ((t)->slot_index_##f = (n) + 1, (t)->slots[(t)->slot_index_##f - 1] = (void *)v) +#define MP_OBJ_TYPE_SET_SLOT(t, f, v, n) ((t)->slot_index_##f = (n) + 1, (t)->slots[(n)] = (void *)v) #define MP_OBJ_TYPE_OFFSETOF_SLOT(f) (offsetof(mp_obj_type_t, slot_index_##f)) #define MP_OBJ_TYPE_HAS_SLOT_BY_OFFSET(t, offset) (*(uint8_t *)((char *)(t) + (offset)) != 0) From 64af916c111b61bce82c00f356a6b1cb81946d87 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 18 Oct 2022 16:24:33 +1100 Subject: [PATCH 0589/1041] docs/templates/layout.html: Indicate latest vs release docs. When looking at latest (the default for docs.micropython.org), make it clear that this isn't the release version. - Changes the version in the top-left to "latest". - Adds a message to the top of each page to explain. For future release versions, add a short message to link to the latest version. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared --- docs/conf.py | 3 ++- docs/templates/layout.html | 25 +++++++++++++++++++++++++ docs/templates/topindex.html | 3 +-- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 5533bf0191..ce5c037568 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -33,6 +33,7 @@ html_context = { 'downloads':[ ('PDF', url_pattern % micropy_version + '/micropython-docs.pdf'), ], + 'is_release': micropy_version != 'latest', } @@ -74,7 +75,7 @@ copyright = '- The MicroPython Documentation is Copyright © 2014-2022, Damien P # # We don't follow "The short X.Y version" vs "The full version, including alpha/beta/rc tags" # breakdown, so use the same version identifier for both to avoid confusion. -version = release = '1.19.1' +version = release = micropy_version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/templates/layout.html b/docs/templates/layout.html index a6caa0bc5a..8563f02af0 100644 --- a/docs/templates/layout.html +++ b/docs/templates/layout.html @@ -4,3 +4,28 @@ {# we change the master_doc variable so that links to the index page are to index.html instead of _index.html #} {% set master_doc = "index" %} + +{% block document %} + {% if is_release %} +
+

+ This is the v{{ release }} version of the MicroPython + documentation. The latest + development version of this page may be more current. +

+
+ {% else %} +
+

+ This is the documentation for the latest development branch of + MicroPython and may refer to features that are not available in released + versions. +

+

+ If you are looking for the documentation for a specific release, use + the drop-down menu on the left and select the desired version. +

+
+ {% endif %} + {{ super() }} +{% endblock %} diff --git a/docs/templates/topindex.html b/docs/templates/topindex.html index cfe3ad1516..4e163b6efe 100644 --- a/docs/templates/topindex.html +++ b/docs/templates/topindex.html @@ -5,8 +5,7 @@

MicroPython documentation

- {{ _('Welcome! This is the documentation for MicroPython') }} - v{{ release|e }}{% if last_updated %}, {{ _('last updated') }} {{ last_updated|e }}{% endif %}. + {{ _('Welcome! This is the documentation for MicroPython') }}{% if last_updated %}, {{ _('last updated') }} {{ last_updated|e }}{% endif %}.

From 11910e2fa1c8f5dc76cbc90598ff81526d1f6312 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 20 Jun 2022 14:02:30 +0200 Subject: [PATCH 0590/1041] docs/samd: Add documentation for the samd port. Includes a general overview, a quickref, pinout tables, and the beginnings of a tutorial. --- docs/index.rst | 1 + docs/samd/general.rst | 88 +++ docs/samd/img/itsybitsy_m4_express.jpg | Bin 0 -> 151296 bytes docs/samd/pinout.rst | 850 +++++++++++++++++++++++++ docs/samd/quickref.rst | 469 ++++++++++++++ docs/samd/tutorial/intro.rst | 84 +++ docs/templates/topindex.html | 4 + 7 files changed, 1496 insertions(+) create mode 100644 docs/samd/general.rst create mode 100644 docs/samd/img/itsybitsy_m4_express.jpg create mode 100644 docs/samd/pinout.rst create mode 100644 docs/samd/quickref.rst create mode 100644 docs/samd/tutorial/intro.rst diff --git a/docs/index.rst b/docs/index.rst index 9a021b3906..64b83618da 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -17,3 +17,4 @@ MicroPython documentation and references unix/quickref.rst zephyr/quickref.rst renesas-ra/quickref.rst + samd/quickref.rst diff --git a/docs/samd/general.rst b/docs/samd/general.rst new file mode 100644 index 0000000000..66e6d2a31f --- /dev/null +++ b/docs/samd/general.rst @@ -0,0 +1,88 @@ +.. _samd_general: + +General information about the SAMD port +======================================= + +The SAMD21/SAMD51 MCU family is a high performance family of devices made by MicroChip. +The SAMD21 devices are based on an ARM M0+ core, the SAMD51 device on ARM Cortex M4 core. +They provide many on-chip I/O units for building small to medium sized devices. + +Multitude of boards +------------------- + +There is a multitude of modules and boards from different sources which carry +an SAMD21/SAMD51 chip. MicroPython aims to provide a generic port which runs on +as many boards/modules as possible, but there may be limitations. The +Adafruit ItsyBitsy M0 Express, Adafruit Feather M4 Express and the Adafruit ItsyBitsy M4 Express +development boards are taken as reference for the port (for example, testing is performed on them). +For any board you are using please make sure you have a data sheet, schematics +and other reference materials so you can look up any board-specific functions. + +The following boards are at the moment supported by the port: + +- ADAFRUIT FEATHER M0 EXPRESS +- ADAFRUIT FEATHER M4 EXPRESS +- ADAFRUIT ITSYBITSY M0 EXPRESS +- ADAFRUIT ITSYBITSY M4 EXPRESS +- ADAFRUIT TRINKET M0 +- MINISAM M4 +- SAMD21 XPLAINED PRO +- SEEED WIO TERMINAL +- SEEED XIAO + +To make a generic SAMD port and support as many boards as possible the +following design and implementation decision were made: + +* GPIO pin numbering is based on the board numbering. + Please have the manual/pin diagram of your board at hand + to find correspondence between your board pins and actual SAMD21/SAMD51 pins. + For the boards listed above, the relation between the board pin number and + the GPIO number can be found at :ref:`samd_pinout`. +* The pins that can be used by MicroPython are limited to those listed + in the board definition files. + +Technical specifications and SoC data sheets +-------------------------------------------- + +The data sheets and other reference material for SAMD21/SAMD51 chip are available +from the vendor site: https://www.microchip.com/en-us/products/microcontrollers-and-microprocessors/32-bit-mcus/sam-32-bit-mcus +They are the primary reference for the chip technical specifications, capabilities, +operating modes, internal functioning, etc. + +For your convenience, a few technical specifications are provided below: + +SAMD21: + +* Architecture: ARM Cortex M0+ +* CPU frequency: up to 48MHz +* Total RAM available: up to 32 kB (see table) +* Internal FlashROM: up to 256 kB + Some boards provide additional external SPI flash. +* GPIO: up to 52 (GPIOs are multiplexed with other functions, including + external FlashROM, UART, etc.) +* UART: up to 6 serial devices, which can used for UART, SPI or I2C. +* I2S: 1 I2S interfaces +* ADC: One 12-bit SAR ADC converter with 16 channels. +* Programming: using BootROM bootloader from USB. + +SAMD51: + +* Architecture: ARM Cortex M4 +* CPU frequency: up to 120MHz +* Total RAM available: up to 256 kB +* Internal FlashROM: up to 1 MB + Some boards provide additional external SPI flash. +* GPIO: up to 99 (GPIOs are multiplexed with other functions, including + external FlashROM, UART, etc.) +* UART: up to 8 serial devices, which can used for UART, SPI or I2C. +* I2S: 1 I2S interfaces +* ADC: Dual 12-bit SAR ADC converter with 16 channels. +* Programming: using BootROM bootloader from USB. + + +For more information see the excellent SAMD21/SAMD51 data sheets or reference manuals. + +At the moment, the SAM21 port of MicroPython requires 256kB flash, of which 64kB is used +for a small file system. The SAM51 port requires 512 kB of flash, of which all flash beyond +384kB is used for a file system. Some boards have additional flash memory, which can be used +as additional file space. diff --git a/docs/samd/img/itsybitsy_m4_express.jpg b/docs/samd/img/itsybitsy_m4_express.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ea18b5c3899dee9a6668451c794d3d50ad0fa390 GIT binary patch literal 151296 zcmd42WmFtNxA!}^6WrY$26uO7a0@cHI{^Yg0>Rye06_;B+$FeMNC+;0;2wfITyoBH z*FEoD_rra^y){!a|LLl|yJ~l@Ro(m7^RoEz8-Sy#sGju34=zncw|Ix~?n*4ugmjCEi zQvfdW!JN>od!~eI>f3}XF5dX`6`K!Kut@e5jzOL3Zd|W^v7cYR9hnH8BM^KcP zhXx1~<>wIv0s+VXKr#vd@wM-3BM>g-zcm~@0sv6(pY1>%9=L-4XCLtY(f{Uv@E`qe z4*v==009o+zee!t_y5;S;Nbsz#PY8m;Qyly$^Xk4;N|}-!Ycr|*U|F0k- zAiyIaAtE6mAtE9oA)_E8A)z26A|j(9qoDpPNXTgDXsGD_e!RRo`RC!E)$1Ge)#|^x z{BM1{^a5~E0hWMJ1UNbXJT4ppF5Jr?fa+fq5dNJI|93%n9SkZO96Sm-;I&;G2LKO; z0RK8f1Y{({*C+#CV~vP}i;M!mqXnYk%jgi$S%vX>{zW4sqE9K5m8Z<&nH{hH~p7@ ze&b~sfQj&59dH3s0BH2jyzp(GvG?B3_$jk*+y-hbCL-8Xb}wS=&bQp+M|QV$_W7QI z+xRB3=OU;ISl+fv>0f=fx*Q3Kh`*Dx5P=&78Hxb>_Ys1>gJ)2}>H12_`!8Bqh2aeU zT5kIY9~_Mmkl?~u|*B9+?obHsqU0EpCChkRcw3J`iI-R(N1 z+^M5o^)*^oxLfawy?i}OQ>)9XJy0Afwn!Zr{VY=o#0!WlF}%tra5`~4wHVU__LcqP zvi>H0*;l4S*%^MU_!ncJkl6kJ!xn@hSn7=kjbt; zOlbdD#os7t(Y1k*+%@j;m!y&PQ+$gU%g6D@=)Z2CG090&*zc06Z60omE!u7U3|CMp zq~=P=UpJ!VlPW3-`N_sMAcCVLrUZIloKE{A_o`kU`g?%{a_{Cv1zYwp`>p1q6F_ea zkDM=U90FdaNi0TKC_h*!D?=_WyFeF8Cr^n%3ci@`>Jp7O?aNm*iK*BP`(0C-qs$D= z6ihUtR547LPUjW2gag4*w9)qLn zn%)ozFD-2piyz;Sf1(x-q^AN?NvM;-5&>Gb9f9%wQnrkd%Gzg2Gzdsp6^|Du3!$0B zT&dYMX&5u8n&b#G>r|iClXURX@{!)Yv$Nig?^dS&+$Nb9`rz3xLYB!nIbMhsc+O6w8>0~9$gh7{n0&gTGS$U*Z^B3AE3RL0^qVkv)L!)wo z-ref2P*U_@nM;HkF`J9VJl3oDP%o_fIuph)W*kBWQ3NP^tj~mXgy5b zDqmiq!U)}_CWu?J?fPWlP?#96J z2$P!u?qFHIA_)olWcOYt^R3ttHPUB&qJ|Y0^bn$e^@FBw5*~V>3THvD;Qu7Y;`H^+@yazwUz5sAd2CR;W#GZHDTZ(>~ z1nG?#>jYO6s!r(BWvhY~%$+icFPt&Hv4m|KZImi+@yN%o*?0yad=yp&fhUx`)p4Lv zFMwOKm4nhwkn8;R@o99|_MC5H&sjp$9m4|S>}Chs=LFY_vC2TFAfwU>mby}Ak#ukR za!{_}bLWqSeMf$gqB)|x4`o-BDYY$uIc%ci#?X?4HIco{a2Uy6EMaDTg@KaJR5HW^ zCiDAC=t=3XJfYY5dLG;eJW4qlowTCIF>N+O11nwcTaXk#X%07SjkX!gDgPjZs!&NP zBsXFH#^z$W*iiH8lyKGioafr;)^c|`az>T+3AFCo5wB+|fHfTWDb%>~@GVm&Y*~_y z#6CQC6Do~%`%cH~ob8j<=y9I7E*3K%DZ+UuvJROO(V?ZjBNr7(+mC<*712qUzQSmH z32c8KmF+0%ih*izME&Zdx00L=(Cx&E0I&-3V_xYg+Zjw=<;-zKbFZBdZ961CjX{5i ztm*jf-fDJ|QCS7*CeDGXss(ezUuNFR;j_)Fe1zduC11$HZDl)uLx2gMYBOcc8$j#V z7(zAF9tYnY6g_*U4xt(@(}@Hr+TTNS0MUxSw+qr4!)X=QYMT`4+m#l=3j^h!W~M-`VN7LPy33J~sAdt~=s z#p#=Vl>q08eQC3U$nnDEjES=u=wOs-1)WojZo1hO$;G1)eYtnY;c>APr&7L(4aDV0 zd0Ob3K(y&Tb$|PLjdOn{NNPiN`HCC+hp~$n|H``FBxB-*A{Pc`v$lW>+V*fLGvqsF zN%0uNC4OmZ_d*4isHt1!2~l3gY_s<4fzxMiIW2x-HNs%oG0#@V&%bo2;n_Y(IvjdD zPK~DVe#PdX?bJ*Fm-!%%9=YEK+05i9=}h-|%=+hug|G74@R`%cPRrR>er=q4KF<_} z#wsLB&b%AHNV~Zu2V+SvoJSd?itDHM^>4tK0V=;sj{qMR_+H&Rj|>tGl&VHsuCNh z-rrbhyEZg3--H&FEHoU<*T2`0tSk7)5Xb2XD|o|Jv1PQSy0L?VlCkCSS8uB@j%Blm2LUmMobP_dpL||ps7o1 zkm=za`0qi90AWblOpZZikZt|)ak1uHpRNW$W(S+7UZh(~n}G98mYl3meCL##fzThE3rxRH~I76B6ex;I|KLI{iap~M~qy2*X?Z@556TV zcHyf9&OXF62li;bt*E|tYpB@}@F*>8*ZabSdSD67EZed=*N|_dkBSwSwe*9{o2(D` zMXhNRuc&cVYecRMmv$NnVDEm3t7xP$npa_A;!sW~xW&8DLRYWY*%8^28;olCGhDl* z(LOIWvW2&wMgFI4`udj$wB>CoEby!AT6iW@<-oaex4g2PP=_T|G_odFeKNx(w)2Q= zz=-&pX@wBksakET$qPWY(k&`hG{_gTSyhrOhVY}+=f|9PQ{+(dB}jIb9cOnYS{3ZD zApbf?bIbIoXzEypKayp_Jb-dbfqg2s>)qS()r94>Uy_7(8&vtLe`=^=~L;4lZ1fe_^ zI8_9vA~LMcP&di|k78o-_`|C}$!F*PGMOoAI-&EtktLujc&%cq4yM;DZ6O+Y&w4|p* zg3d^giX8biAI~W1a7cIe3*fXjMfNuY{MIT|Wrta!=jP^jOqt(IOP-RPxkHa>IXBUr zUgdze)8Q6<;i!bD{d)W5#!z7^xwoL7Xkeh|iA62HzNnIx>ZLz~rI|B4PqjTNYO@9k z%i5-XWJ}fi?Imu5(AN@n_c8L5OB%D>KFa0elZ5b_jXX8p04NOts|1Nqw`gL|$;d}d z2lTcN7$I!@iC^af8-skYkJeg|A2YMdU0YP;%UVorssp3&f6mMPsCLaS>7$eR3)0}E z_^Ys^y9Lbtyi(l&_7Y5TJkb~9^H_RXpBHMcC8pGNnB3!l%Q{WNqcXV)i}D4LMYBmL_(7HILG~z# z8%2)_GS+3y({2iB@+b30rlUd*W=gD_0oX`c{=Z@_fhqloE>gTN!P%j}q=K&?e~2 zn~CqREj0etGDV#7Nx>k9KPZlt167>!D;hX zOP*nG88|p5!xIqa) zuQk`c0%}bc(;0)Okhn}TEdG~V3=EzU)UJ?j(gaW32)qrHQ+KBH^lIJ@?rB-8ZJzUD zq*v0={25UCOO_=;uTe;d1@L}qkqSZ-=e_)^_3uo*>6a4U=UFp>~wKj z4ig;B>?D z2SKV$s8a0}Qd5&AqsbGNa`NU%7(k&V$(Ah82A|Ryzp9)xeRrm)RpfDW#Q#u~bC)g=vrWc4w9>AxUD0rn;iOIX5&YN97je0qy%i+_J@ELkn~{fy^j z{4c3>X)}p>~6))D^2?PGVcnARee*{Y&HvR@qW(9>zEhf3|cd$APjwqz?xe< zaJU&67`kvdY;6cXo)5~HP+2=T_6_VmP9H<^rQoT00ib4hbcUG|6_!*Om-*Ql4LTil zhD_nx{++X3b;r9#PY~FOYT3@v`)--D_~D%{NQ=5(drc-?XTq3+C*3Y)PQKfOKZ(`@ z4qa=t2lM`Zp#A=5oV>%hYwm){)KR%plj6$y<+lEZ!5g-0T9b)6ecR3zNqLlV<)+fWPMW4u0-xP9(c!N*ZN%gnYp+XXacu*-3cCY~BP}ey=0~&> zVe$DcAL>q?RHhCNf9xSc$c?)}%`b`m!ugiI($)pd?@Ia|DT{xa^v?cJ#T6y1xoo#+ z&&&;(>R3iKh;|P<=Hz7ftCn0C1t1uZ z-TAWzWMd~4of;5x#qgRP(6mg{FER6@Nz$41dwyQ^Ct}FaMIdEUcCVnXqhFah7&ah8 z58HWb1_t<#SS_69=Tg{ENA|icaPW#A@*c5Q47vW5!@e0;xZNximu=s6wUx zV~wFw<#8bo{1zJSDFKuyG8Z%a8@4LDTfYg>qDd}o}r$(_#NG{{D*4$T}V|+ z0&=nWNwWxJlkIrjFiUcsy{Wz~%B?=5UNc7=BSTj{2gMm{OPcp(wT6P*3&3>>wp!i) zOH5;2bmA)0nGe?`X&~_3S(Gv}B{#J2v9Sb96YRACuBINqa%b{14 zN0gtFcj!2I`PK?U+<_EH*_oi`%lb~#KT|)3RYI5)*PQZ6}F50-eha;QqyAu3!G*n-iW zKSSWTEYE+Vn(b728~1H_clJ9@O@Y$qd}BNCH`-`h0oc#myp1+u$T&(5)agtk>95i8 z2j(TUuYz~2pMpb|BsPAU@YedA-s6q5zMkXNOnCH&PP0>F>Y~XS`W2VXY@_0uXtfF0i^zlM(R&%>^W^^cT+u9fs!<^v2 zIV)%)-?E}HuDqSGR{?`Tps=cnl!*x)9lq4_3Ho;XlrcLy#u(;EnG%GSA{B)%MIRMB2!a*-ubecp(P^DB=DH z_bTGnc}^87VtXg`)P8vTh)bv(0}$e^(_R-ci}w?j=(@e5VNzbgAnMbj?MO@Y;+vt= zLig+qK&5{(3CCPWwO(6GUMeLfVu``KcNp9Q?85^WUJ$Sqh_{ad0KYo?@9(d#e{)A9 zDjMABmg}U12Kqhse$Xnzh|&C=8!@FBAfh!X)BE@o{E0lf9S&(W5rVi?@B(l{%{kXj zj$|t1){01H6EV9_>^U3oo7O156sTz!D`7n$%W{S71pE<2z9+4^O5D0j11a}>YnkI= z#@9_odvv5Z7*Tb=GmF$WIEkV>mq>yWXunGp9#0ib&31$A^Cjlus)}@)ES-=kX}`hx z%319v_1>3qoPDZvl~YN{Szz92TKUq;aCryH;p}#b*eIRFIwwiWoUc4Hm0lN3^qH|% zbEV=q$B(J3wJ<=^-#)d-&ibvRjkSpiDFjmDrN&3Zkd{waTvD!wJ6uM6ohlj(xDscP zQLnd0YVVIo=223AbMl;PsF`L&8xEhAtCDKV9PLr4A7at3$4ar5_q>+t(lkNNsxuoO zip_WV-R)yYaM0g!9KO`8d_{`eDcK~bl+l)Ng0eKJu^|bfSLPLU?ca@NJ=0G_|(9O;DAIV%yD?~hLI7QJbg!B8r zKo5nNCBQ%Y^?wjUgG+`d_+J^MQyN8FO>GP&tz7(W6?DGx9FQz!W4d<1$L|m#Nkm^y4t(w!N(7E`KGQjWCGm_qPbiK zSCmMBGfdguP>r0lk#tc@29=R|lD^(i>>b>TiQ3Hb#ruFs_p^A+7PqG0flzMr?lYY7 zObsn(Mp~Q$J=K01BPP$LQwfFWnZ-^;h~r|L@Our6G$M|oJ}6hb5$a~II)#j=ou7bu z2t^dweG&b1=T~}9$gK5rmXoPj>UAy+?0$tuo!XiK?HnJOUM%?pAOC)T{C4LBz?kut zn93;Q>;WbhBgbXTT)jO-l<9#U^B6TItB4kL2Z7|*M7H<1gvS{N-s_a$#J3)@ekxB| zjiivxWVac0hnox?30QH6obw#3_lw@)oEcpT4A6M<;c1K)A5o2-JHiG-qVS^bJdCpK z5>CeJ54SF|YNC|RrVEqvZdGc3ACW9=ID%L@MInxjJ>i`@FX!!Ypc<}{U~Ci8;b`s< z5pN238MnWR91GU+wq3S3XA;DRD|YDtiqxA4bX#WA@!)aSAJ#Z4N3(?McU`VzrwM9V z{b=Whmnt01M38#A`Dg1~c%V_IMHji*#5LJ^s1nhgUhEi%1Ggw( zbKbJW_cro85y@`$N3DXL>mn_toYAmbC@QH)_Kp<26fPxa&kfP2m(d}Rgou2@(rOBd3y!}0_Od{*v;hA16=o8Kn*+C9HHcm)k8ESH9j(v})15wMh1*ZpO80W;Kzp zvCBtZqW&`4J~%RbZXiW^V=I5|>};%@p_h^Dxg_@7Jcg~nhPz#mD2Lk=vcUHM*+&>o zt9sj-K1$^cGSm3%Pl5#_Ol=)YG2;Il!NkGP7kNPIk)opcSX^Q_!diKj^R~kmIV9Ia zei}mqVw|j=^ShK?PrAAkUAyB$V>DmZAAdN*FUfY?T8Hj00N-ztqlR)+jpl+A0mStl ztR%X0@EF#lYxW_!-9Kz6DQppas&h3#7bHvI@e3!QGv&S@p)aYBC}(w|WT^$ogDQLL0p-Dny5u zq;$b;P-JoL@*wtZT*>JjQ?NR7O{a%33;P&m=o#?!#)DVkM>|4Kn&<+Is9>fY{CeAf z(?`+Hc;sF$@B*MhOTCttuCf#!bba1}&Q9iws#K6) z!{Z45=%T-gF5en3B5kUFCff4!xF+rW?yS(S3Ovl16blj7BgWRWbs*%WL+s+~jQ`I0 z0^q9Y&}tL)*0LqdEK(lXK0;rR>`x(PBbsH5i(w)s6KLfUlgIr2ke`}JEs`?%+c>`6 zlod>=XReF)NmZsc;Iyxrm4@VbL@0peQC$)23CZ?I=TvBxEXqoN5-ey~_`pD1_2>|W z0XeT!*2SmKf3)RZj~bk0p_$Ebc;oS$k?jMu>Q+_~c$JyeWD=j5b;lfAMV&kT(~bJz zA6?uF>f}MDD&21zhv41Mw1bbajD8FIN?eRQTwio;Ujv7Pi;E)`LWz1-zOC11!4X`Q zR6rN@YbnF2Fj0L`MK;dsjz~Q>{`7d+&Tp9#)@=4NLwZBq^L1D#nK3i{ z*Mc^@(cBxPu&xgODUaF{*sZ!h%}ZY2^&&A(vaNxtp{P$Kx*YB7G^ z*iiE4316EKo*=o!iKn{27|Jhwvq#yX$?a)f?e_)pw4q};)7hoUAAYe8 z!p_TZM79~Qo^Q^psFNq89*scB$eX4Nks*0E7fN7Di+NkvQiQ;9F0Vuh$ zpZbVa2;M76tEGHRAN}p2Iiopj&Epb8d+QQTH*Ma)gO_hTWsmL=L5?k@Mt@&CPlrKg z>(&B#iq$IBY>_)588p*%S~PzTk(7vSAi^{OAI2Dc*`-rx_gsal?HbV2x;firCkQ1} zJC11zG^8`#8JbA1-m!3I;8or7Ds7Wm|FfNDz>+XhD1!>eXh)IScJPYdiKT@YOXp4zwR|8WL#5( z06x-CHb&p6`R$e$YqY=BeY}r;2F^3E)dL!vrh7Gi=y+mttzkE#1UY&)eEjocna+}w zS6fHw$Sr4w1KlfoV_1mtbMW|dQYx9Pn~r|!d$bMKO?a_vwC7C}hui4=+&(MEhVxJK zm=GpVJXIvLDTbkwf> zQ?u3}=VWe7P<2T4c|Q{|V&IpxV1v#m)Y@i>{^>HOMbW|1v)RFVK}%z?neUSSi95#O!^Kom&c$3dgY*P1Z+f0mVSN--0X^$8|z@`{nrQwxt0|^7DQ4CYf zw>tO7h}*>MyA?c}cql*$oA3`-VrNN^WjgGPmBNUxpC@)tw%O8S6-%1^ew=zO++Z6Q zz@=DfjIA=i%cgz3V%X5(y84cmmaNK+!UdTo?nokiGLbC-Ws@UbiX2&vWMxrtK#N2-^B7}Zq zxNnj^>JnBVPcaD*OCd;C(VWJWm>$BWilg9y={Q>TdKSsXo|jIb6O2lNbji>6aHXiJ z$wvW89Yk*HtdlbwmF~Q6eI3-79f8R%VW}xhJT}t8W1j2j&!epm(XBC^T0=(tn)(Lh zV5aejfk=^uC8<_ZEVSzh%ji*5hTlT+TBv!uw!>EQ$DtNvOA{g(A-BaCt&F}JdmLG0 zP~|kfPNGd~KE7w5*yQ|p0)|h;kLKhF%aLDhp5+bSy|w1&RRW#AlX5#Pjv0R$bJHcy zJV*5LxKj(XAP;ZzakieNHs{IG+AJY%~o6i3P!$mN$mRF~k~7{rdEtSqShF1tUR|4?*^qEJ64AJideF zu)2!k7^3h%II`b%z4WBI{D?vd{|IYRAM=~|Ad;vwH_u3IXd+b#MwAlXT&h2nm`4g8 zCDeZ(DU+|A1O3FtB6B!X@`q7F2gw6ZlhE^TfaN@%RulmlnY_ZGJufL`FVw!-=Lcb0 z`q)n8qPBhoYaBYy$fEwc?InSNeq^TE(GpZ}%%CfN_s&Mmaw}wzNOH^3lFJB28(=i^ zNw{71=eYOD8(C!M>|8|YtTC-SEj8!qaW$4iA@yC4yX#U-FW`v*&jOGmWff};N}B9_ z-NGF2k-Z!e2pA{%r~>ZE3{j(a&6clujDn|}w!)%x1lybI#H4d6xRB{21(OmB2DW0C zJv$&%s_2n*nJ)mM!8)Ephiv03*?f*qF%9TM^nX!+_z%&gzTqeohG!6rVlU@!kyUeS zZA;wRbyc3$V`+RxOmC>4%Wsob^N*V>x#p*Yn9~bA*gr5$@Uv^!rgTeEwbPPju@p8k z;NpM=SnhZs@P2}iPs4d#DN{>*dDh`2oz5##4qK2ltk3Z!zi$Z77e%NC-Nj0JGMZ&e zS46{gOliV1Rv$1vVpk8AS}I|Pq%HBi6R9sFU4 zAqv&i)QO~C^b8X(T$ppT#D2pQCwAh@E8sZDL5yK+PjW>cev*asD`OQ)Dn4v9nei-p zOY8)fzDL?ZM94)O|YE6yB-b`?Gr8JOM#F zyCO3Fc;n@8PM_&_jLPA;WkQmj{qBoEUDIhV}J?dxqiegS1aOn&|P`A{_{BkJCd>j$8xj{m* z(HZKZTC`QYPyut?`SrehtDve^(%7oRO=jX6?H29##+#88Os(M`UwMt4_128*3uX>8QF7_+yte|>N@6^qaqLX7O{`H;_|g2 zZV|_+8HV?*>dT4?FIB0^wQUK%5%dK0)W%m>P)&33(gMi`ea+Dm+CDhVZC!}4qgQ=t zXXp0ZF$D0`+TIi~pu#yhqe|I$lTVIF*CbemxRYCNE~OZo2d_8<+b$IPDq&c=@arP9 zZbrhVQf!O3>7ukM*pX(%&AHkf9x~&5etAFBG}K@Eae$m0DH1ij2bb^@X?AErnQIXM zZ%7@=*7Buo??<8P(xSs+)dNP*pUFDQIqc}v*O>AO#;}ScK_Evb>#xveWQ%IN)kQy- z=PyNJ^t?JQE^#UB1%Moc&yg`0Vxz;@Gos;Q4vmjIW;?&3)~qIeYS0ZdIcn9wJw%VS zR1W%x*(yv+ve_-BeEL&8K}CZs%`cIeI8T2?1d*0-?30q?T2p@}sD*-IV2N{;rlcj| z1_H=w#dO)`%^GyHAxu=R&lq!QPr^5DBYqE{2}QRt!ovS$PosmQ)1wV)HH|XW0u5~( z@DVq3uTX|mfk6#kQbaX?U#+Ny^(l8ezgyScVq43AF946ehlNbeL<~V*Qo`fPF^38} zXmt?($7m=K_*NcDM<;wbyPPGMNd+2j^pWGuG^!Qya<)b1wdL|k_(quC$13pgqm-Qs z-WSMv0g@`}{^rSwe!^-W^NKd=gR~|CcH3g43BL@>yZh@zCrHeiB=!*aXfsPR6lVKm zbfnh3;%Xjvnr6iV_J10wBfgdIZ9w~a4&f}ZCgQ1U@e<%PYUZ3r)K~3tc5Mc^Wlu`i zQ0SoZCa2g;ChdH8{E|>GX^=Cap>9iPRViac%#{$Vq0LqkJqNBBosi)p;y zBrWn3pBIJW@G+A}H>pzeY4OaA(y|CSo!0iw!(!8H%ZqNW)16U@n*6(HHRg;)aeQm~ zk2|pdp#@?i2PZ@joyZ!4Iuf9fW|{EVf|kYT59s~C>@X84 z&S*3pJms_C;qqGrl1eh`j@m;^^Bgzw`e_hq8bm*^@L`{FEgvn_X8I z`f=F}i1K!azlmcpOW5D$qOLs6*@lBXCjD%g##)LB0=!!Ggrr=_x)QCCuF8+ZU-j8y0HdZ3%@V{F)V$)df0w@T z;FnNWZrh(cCym5Gg?xyRSoK@;ml$+5Icc8E0*Aj|bi7kfth6I+IQrO>YcD=ph_)pj zrSf?&@rP!Px&F=qXd9DAIdvm4xP-sOh6Uo2#_d9k8iT`mhZsNEJ0k71e5RilKLA$3 zu4<<6puIs}Oev5CM^BjJv56QBhEOj7+fJM0eFar|e^UIRYq-Mluj4YR_f#9 zSS8s*xbob#jcMq#Zw0Q84ejhYOG$;y>uqxRZx<#j=g`8gUb%?AetcbJivm=Tz|@uY z2ZD^$8%yMbptk-thSy9OQ@g1;1n{QDKbn*_m9xcoYMuO4LbyF)0IVO-bXa%v1Oe4F zPgmby(}Znn;8SsEu~_zMZQ+m)y7SHX8cy9>JM5h-3eF=&qF=2Q1-~=30qN2x4tlY; z3lcP7j($+X4v(oj;+pY0W7nI2<`$W4AO~77_jxTQWZ^0C0nd1qs4srJ;WBPECLOfl zj{L^Ll(9`#WQjuk-`IHQo;k0KffN(eYGoLKw~;hM8A34mg$sA`*T~L`@6RbLDWRBeg-thHSv~eO@1L$7mQ{y#VpWO(L!ljOj zW!aaj4Hdp$h1?RrCP*xac;Sl>s_zgu&URNZpSOxTYW>2)4JS`Pd5Egyonj=UaBV=P zO$v{30yWYepRY;t1yKEQEY4-!_HkE?t`#XSw<-$A5ulfIfnD}Qbs+ z92nTjSEk3#tD5Z4=;F`=bm00L$-VMx$fmy(O~|Npu(c>0*V--LE{J|>#k9mS#k3Nb z+T)^y-|6);Mjf1-jF9q-QN6q-O7)n-IY)si&=p(4FEJEa%T(e$q@uw+hG6V@akZ&5 zy9xpWh@(KVvxX00o#VyE@GW@7UXP=hUe!g+iR0?>A-Ht}taF!t@-V#`MZ>3<`klbM zJO(HyGDFRodXXY7L~L+#!KV68? z^#qe{e{N{5URys^7dric+ESHPi$ql>0tLw949U)phCp_HpnDml*zsOf*>XER7Su;3 zxZeL()ZgsxpMdvz-)7!$xl$g! z0DO`<FiWv7a=$2u&jADbR>8^UU3i_4n{f+iVhhPPoi_sE)#?J#LlIq3jH=311Y%slE2+XL?JQ3|HBMJR!EOcohB44DmmKZtxjxgNT#8 zf{hvd`SppVQyon{EUsE2u0C9vlN$N#VG2?NZN70Lju=bzFNaK`a3GkO%@S+~RPdk) zA{XSy=li1^j!v`>X2{mY9kf)oR7DOES~IKvYZFVGVY@=~O?a2<$#-Bl#RW~j*gPhA z3pL|ecT@=f_F8dkwJA3hRx|gIFdA6QE5_Afdj)M7MDi?V7T61)GQ`IjTV`U8_Zgsm z3~JEkF8wlOxj^LnG;lU&i=_qyq-J$?E3X_tgh?`DH?2b?0j*UCFq?BCFSPbg8oRvN z5qg#QnhIJtmmNknXlT~*>P7N7jcY?;CT=4Sdfp*o?=c+Q{O$RmY*u|O?#Q|T;bAMs$+>QF;qk88>I zo~qCm1IfDj)7W6}_?o^}dI(()NKXg<-1LLZWP`bB_G<7)+sOS5v$gw{10C3GVbXS; zN&Lnx4{}mJozeH>aMpw(WWF{%&&*T%ePfU_>ntzPam$<+Q~YFo&zzx4m!vHo*2tV{m#=(70?4`j0RCctvENLA?8G*bFi$_u+ZHwmGh=pU01Y z{;w%a{3L}m?LL0=cgg5T;i|OBbhvrHiL9Dl0OjNq#9Qpi({7C=U%q_4s)VMw%P~{q zv1MD;$%MNyauE;4z6*^H=^#678sFn5mqj8 zAmLBVmD|Lx`3r_NplgZ~0~J!QytPpF)$ocdC81~gm0mxzIkz;2xDqv%b(8#1-u2eg z$CJyN{!U*0^?{!clRmJ`{$@^YV`K5^RU$gV6i}A=SyEGB6>VJ;K{?Y{oPsLn?-Gpk z6W|X_mXWTkrn9$d=g}f~klMF9uYdJJW9<90ireoG7JLj@L;MirgEXy$VmrUfd*!HK zMt})2@NkM^8a`J!Ky{93_83{@%4!X_n*sZV#pXf%w+bTFp8Zd#9^kE9!Z7PE#yFzGBmG?_59Hl|q6v)$}l zV+E;dV%vtn`~4mm->J>345m- zsUYm=d9sOPZX$>?+fo`zmbDBxg`5;@Br(V!Vq#;Zi9)hEV=0L&tYzre_hKxrn~w8x z4{3Vghblec1zdehiJy^^5{Vhxrs#~-;m9{1me$e?bT|?tG+2q@B>L-644UkhC2|ul zh!8FJE|grywKei!LyC33dlZ+q7xw;&r+QXaPDDkaD=GBLVt+De&(9g?3y#}gi>*UD zmsQ#thUP%#t1DX&th%KHJNi~oL|=pqO9o_MLO0lAAsst7+;Xqi&AIflVj~vUZsfMn z2dTs+$Y8@66D9?`OoU8E-!VNdoQs+md-dIy!Qq`t?WT?^E|vye#byXn5i8;%FhsBH zo<#xkyi9d{P|7U*bG>f}f9{kSyET8@xW_ zQfA($M3h>hhtxYuG>nunb|zvyat5jOluV5Bo&NwYiELy7jf}M-xmxC@BD&zACQoEU z6fjUi25~D|dADI1SrbM!+-I(R)*7ZcKV;TaOKP2GaT5!9Z)Eyoi9r-X&QefoiGe5` zus3lYluwg)tk%K!)WpBNNN@5b5};Rbss1tWnbXX6oOvAw^Q5Y@r8OuWHL=%V-fe z8I6p{XXaz272T2$x1FPR8a5lf)Jqfv6I{k%8)-sNEMbd>k?*{ee8DWr_*2iDPT61A$0#b5n7L3G{oNv5O#Qrh+o^#MqUqkM(yeRks+r0pRb-^N%t*k# zUBuo-TagorCw@H#KWn8^Ljd4yTs@{AvEg!W+RB?b7%aH3Oau&Buz!f|Qy(QgFbm~h z3|Qn_zof8ewIaJ0T-qqd*d!O?liA+O0=P*_BaazAF%idkq^(ppl{{8$Rq?c}zRHt~ ztabrBBt_QkSTF-)B0U=jd~spz@8WvknYpG*L7AGl%x9?dn4mLr|5)bm3;$tx}yj6L5 z9BPj%I9qu7tFiaUNYrvd%!slHHQ^B~fg))Tvv~YY7q-ies;5&?+NJ2c$tF_$q#w)zePTRH1KQb%{=<%dj?Ej`x_Z3o>Gn=>ZmC&r$+9atzzJ{>reya# zmOt4%&SZ{4fAN9pXXDbWWz3a~vvOKlkz*Zv-&K_3Afg#2R~v&PxR<3z>jlY~ZzM$$ zFe15@boehJp1+dP=r&e;S4F44945c+1=p~(?1hLjN7PZsxl9zu@ra-P>DSv$d2LON zy^E_B(svtc-nnBWV9M0UgBvp~;;4;*W;<=lW1uO1M0FSOMUKv7KE*%-aj>44F3Q^PVqX>I~~CH4cx$Bz?_+n1Q1Nd@iDag(ycj8ir8$^nJl$X z$b=%0H7lY<$HIZc8x_A~6pYPPOaTgnrZ<`B2(IIBwBL9#C6jXMvVWHewPjAnwTy*U zVOektSSBc7*dr4g&+mQqk(fqhEvCL2mF#X3&A?bbrH@n?R5RjHY1@nxiEcv?5h6qX z05jD%huFh1m3#Q?;_RZ}+qR~TK*pVhL5RA;B{2}TLt%i4BI6JfKNA}}sV3~Y*)N=m z>^2V4mL&fGT}DX2kyrRw?knHoIYbuo`{)aL)vJS@sZz0yrKCh}xU6NOxAw+u<-gi| zEFyg&&KIyBDBdP!dV3ZsXAaG46|5dQqe|25*SwV2bt980TNMN+SOKsr6?}w%?Y7ak zR?`l{F=$qP#x*o7l`*SbqY#i&%midkQe-ebktsfLAKNjse9XJWEdgekRJdN{)%Lb( zG!> z3dv*rD-eO(=cjs!_b+30C1zK`VjX>zC{6r#{kXUUS}Gq|DhbmfL?pp35W(f}Qd2y` zzcq6og~n;jeoHft3bBwyOI9MZW9rG9j>IZSQgQvVo%WNGQBM0zZEa(MwLq(=Dr8ls zz-m5fs-Ej^DaPoKh+~%GASqmt0GP++6UH~*K!1+976xytF`Qlkr3(D56?Kb62Jqk8 zBFQN*PbnwF$M1INvHVl573_9$(;BfvuFj%~SY9F7)|4&chLEj_h*-n`hZrB2 zE|p^j=0eSPS*fLLSo^W|O~g#AA7IF&T(uc+G7%Y=hz>iLZSp?_6WHJ3bao!S7)rnH zD`TpvwmFJg>_HJ)VM4*vGSEL-qF8cF5-Es?fB{x!=1$(GqMbdMU$Q@tJa!(h@)mE> zG8tJBG@h24$#Cc;NU?mQ;sisYiw~Ncvx&~eQ#F!orYu>xWWt)0EeCrXm|n&ZDv>5H zU?v=l#E=xqJvxe?d0BUvZUt3hQ%cgFi3x)kf9J`gS_%$$Fd`WMBOeeW5cILh$mB0# zt>ISUdu?KIxcru2oRT>u!cMu`;8u_Vz;raCMqADzcM01mWE8r}tklL(jD{wq*Q;Tx zV=~JvqSdNe=mzl<7+|zFIsCbD8JXb`3$Kc)I4S$#Jd`pE6Pi(rBB|&rE4klB7Ms;J^ui*2;d`^ zIh#Kzma#_T%NviSR^BR`@zqM*^$fK{P$weOIARkqB_O%njRrH$s}z1MAwFxs`ISH>B%2O6udVY2}QB!05~xsG$xWWThrh{(GeUY)F!He495 zkCn+Vqz~E$WJicEi4-KjwplKDY;Yqu>b*6%*Gkn}8Wn|=4;M;SHZ0aCkp~B}`v!fJ z!Th3kSHwpMo{n92o7qnvU70ZTHoi))@q4O>zELwZ+_syX<|%L_L~#=z6CV@4BL=w& zUIAp+3Ru^xO5*aC;@29rpu*vak&Ty`lF?CeLL(rs`PwIW<+N2&op(8F$l{vUUYK!R zs$%x8VZ$VmQ41LOmNkG9CNQWOkcgR?n(?$M6dCF4HPqlvuoc!tQJNneDtWn{LJ z@# zf_l|IhO1)@WmKwUY||zprXeNny49=-NA7G45J%%A)Evy22QBA#+SkR`%n9alH5rXn z&sjU!L97Q8-6IAJhfJ3SMX_nMbN%xszyAP*)7662NN(vhVlU~)x|O+SGg_O(l%azv z^DeIr5IEa-g9A2B(aU+GQyzCqWN{3O*engY&oWzO2;PGteQKX^5JiBMM$<64_3+*c z=V$^)<7wru<<6UKnYHs4u+*wU@+;uTlC-sni&SOm30Xc&l%b9@128cii+I~ZlEE!` z+MxUAldEQpwwj(l5>K>o0Ma=rA(-AmMPau806iC99YZsvlaNoPnpp-*``D=~$72NI zRrfWHCz}FBxeP8p6DF6&#qu6U2;7dTt%%6|g{+j=#?bZI#>x!|c!UE@V!;U&sH+IX zM#~_bwwU+>=1V_}Oi*vqw!wDmW&cP=eO62zZw~}pTuhqn4 zX-2BaqaYS;*sPRWUP(~dXz+)9xjTspWhKPQ4mtj!CMHQW=WJL-yoN&xxqDXHwsM}9 zrWg?bwYEvKVo9;jW-O!prY3)VE2p2N<%+VF?^nyX?!C6C){tO|*f9#=qLxey!AGu3 zoD2zX`A0xZI5pbTDyHk2bvc^>73o>9R$Hik~l zDq0x|*GZPEBCOL&Yb9Z~gJ$|Oh`>WG)P*x&hurHnGmNdeu9XY=V`r?hQr#up zERH!C=hup;Fsd|N$e`uW$d=e#iE{n%k~8?;N@nO2r-lm%UZJg+w5Qiafqi*-VnnVq zWe}gnR#EuOj}ndNp7YD#LbCjZKR1uSXY*F_Rci&h)ddxw7F;l(VOU_SA)_K~DO))d zNI^``#=r_%dTf2Nms0?E62~s3+g0l_w-Shw2HI%>EYl`J9=)bxZT9@5p%I*|oCC<_ zUhI`h;M(<_ROOEQmWZy%wn;FaHM%;RPlGBJnvH2*+v-x9HhE~U~-0Rs0 ztk5L-%hpLgaw#KJluxXq{S}hw_PB#P76D^UG~c z8!!B}X4@%deIYSY!y3$$4oUg+DL_agDGB}lM=(ZP^WI~;0v6~_XmS}#PGka->V}nL zn8D=kPKhw$KwKuNPx!|vkL>xUB->@0(^Qd|$JGipjX>rSD*;_0{*9b&o^Sx=glrra z1iiN3Zh%#aRz99D5g&1W+`VEKau%K#=U!hKF>4G!Vp^z`04r(Q0KRsex_H_d3T}(I z+E+1JnJ;C#!H{Syh*-7pC)!x@4`h>B1fz~nX&H~kI&EcjahOTeSlhWO42ujvTddVq zLCFwvtUJdPSQv8$?o|+6M5C9?^$Kj)O0oG7z}W<)o|Qo&Z6xX{$a^lVgmykYs^b#b z0B5%^h@JM^p=O197HT^ihQ;Hu7ONI5 zCwVG(F{l^;2a;M0SVY*8FB432W&&RW;kJ7nAR-#qgc4s2_ zNo5$pO}5-gOveSw$%SE%78D}p&m_u!9z0{9U7SWkCXDti85CseDc29}h*mgU zy9FW(*x{sMC=n9$m#SxI;JN<*L$Nj2r(qeotj7uK1^vrrzB&n)oo+yXCIFoKTH^?k zU=Yjze17L}7L9z)XBBF$Ml!inS|?MQ>U)T9@Hh}+7Auc{;vgnd`<6t1zNeLXb+AY9 z(OXq2CdFfF4AWB6Vk9Tls`2*2T`dUQ4maZw{{W11$|*kHqP0rMB>@7}Tf|g3uZ^>1 zPm?Jck}|@D6@Z>R_c?%x_z~&~13HG4-6fNprMflRR4r4>T=csg0&pWRvIke0nU+te z%b0-%@ew1?2`}7s2HlM)tj!yFdX?T6ap{3`QB=w}*p6+6v)wTELpGD0w%_rMp8$m$ zv1+wVIU`}Qkrh&)+KmcSGOr#$j9S5bu8(unPn-j8;Qex;`ch!l1tRdr7d7K!1|3} z{bs=-t+x&lw12pO0?N}>dihM#F;p{nlNxC-vsyrs))c@f!U$G#AWUMl`7Ve? zEkxUOv1O*sm)vZ~9vRE_+CsSsYra6uD~M@(i}YnA1wZ)DMOJe%8LF8~HcJ(ev?p~{ z$nk-WTM8j^*8*PB-ngu0eQVjSP-ADUUrnMvGobr%de3{h8!OxmQ=H9M~~&!+nx5BQX&tx9)lp zu0pM>=~!Jh&Q3B0s{@^|!z$71#IfEbd%#EfjiATlbln@c``K&n#_B(L z9Yk7p+|xnTjw)z|>yaj#rpWmR^XDP%2Vt5*>Uj9dLU#`>ZdZ1t{WuJJxliy9qfCMB#Pf~;jC8a`l{7gSdX?#9PUCWC>OATV|~s_f6JyhoPKK=Ofg2c&P72r zD+prR$V4@#1tu$DL3-rIMf=9m;)saacV0Kn`>E2UO9*8*8tTf1Fd>Qs{{a3uICkU9 zYccDc;9x)Cx&f)vHYWB=v-nLrj|*nUxGC0a3CUn6)Z67F?Ng+H=W&uDA&HrY7>im? z=AdR7Ss>C8WLH|LKB|zKn~E)SJ20n7>RmcyLGKd<^AwWkVF>?lIlFBAFnBVNzc4%`Ws`2;lTq|J8 zjwjbiR#^d_v1U6rntoD`OA zhDgi-#c+-*6*di1EI>m^qRvM##v!Y!vf;%H@^cI*IYaGRtaPk%O@d%ULDDf|ISeeM z=6OcbGt$f@{{UURKbNPeGdBr=Ug9cE8C{dA;FYo$S`G+Sb6PnmQ5#5e{g+c>a6nmh zxbiJ8&)AZv#}MO%jDQq8tw@uUWakm7vQq>ro#$cL1HdwP3rV1=v88W=X7z$hBBk3F z1?M**(ATkMC(mhM%yW;&Z^xyWg1vH%7O+~cnaV_i>x*W^hgS!$*(UK4E-*Z1WCX+t z2!9{k%=I&MsbetIvDs6+ZQSyfT(~v1C5FKj4U0@C42(&ecG^#u#^b+2+^usZe#`O( zN^`DIsd;QAC9SI*5&{Oa5m~lEu`T70K$4B7AihAIRIq1MFgkYi#^*)VEb+FrSQCRL zk-#UPx0m(F2}#EhF^Guc)pK3is_jcRG|p{#D(Y@RjyoDHE0V>Dp5nn_jBEJW@xcj z>#GXE_T#H#rDVo0oD@ZrHce|OSxE7Z%Z~B-o`7Rg#!)vPk;mh373wo%w)I$#SP?#1 z66Mude?nFF0!x$R$v6@oA{|kcv1l>493ER6Lr-UC9EW{|P`yO}W+sLcB<4%p3zm_P z?-0&2`rE40Qm5VLbsk?jSZ7tJR%+ZDqPTpygey9f;Ko5i$JHzdf!~~e&pa!Lc#>m55Od;fOLjbji$$yFQ{YKpYRsbtTLiSG_)vTIBF1e4YR}j)e z50LuD*9!oZJdJ!N4kSusx7sVKp)|H2(PD7=Ck3bJ+%=~u_DD5d$Q5Rqz}XO}tj7C= zkiiLH$$Xs07!&^h>bG31j4CVYOd!;3I{0MlNm#1lSu1wIl*>rqfN=J+`i`CNky15v2KPQo~eC`~zKoXc3Lf0e2S@_2~O*iUT= zs!_m)tQsNiTTWKPk6Ol{4REhzi)e!BTB9ijW4S;uCCh-8k2L}M z)*H!=^E0$;%F3$cFJP$Mb?bM%w&bBQ@V}K%7&NVmfs(|qWip_HIGBhnqB&0Gp;`2X zR)#L@;Is1P*x_d*0##P+y|u%6nM-GnBI7?YTh8+{&I<)siMsQH`R}7(%96TUY^zDBdG|w&)E=o4i@6S zIhxj`fYGo-?oku-F){Ny?H;Yq{{W8WkD=V0)-P3e!?{|Mu(3)qSRg`ajqH9>95D#F zT!L3^8+w^0aU?`j6So+iv=QasgFXK74^nVaji3TBKyrS0{|J<;7ZG#d5~_CIE!pW_Dr=oJXvJe<_vB%zjZa zteH}%=!^v~>vhxPSCb6@WoaL+($*ia<>y}3niIaiV-n{xp{V}_t zD_HZoZsa-`JQ<*yYu_$A+RBjba>4r4BfR*|0Ga#jOpbMns|@KT-bx z_v_H7dpyYSKfvz?Gk;J20Hm9fh8BaLgH~4|; z(b6!hN)=^uEK+YUa+mY&d3DKBoTC~s{zaEk?iV|Cky^ca7WSq!sjaO{D20iG^bpJ_ zzZS9vSrZH3Qaf)w4yvB34Q-r7tes0XN~hjg#w@+b3HWjz!j*!!h!og>{>CWw{DXe8 zV_SVC{N>Ubb()7xcnSbAi5#78LFesbF@iToXy!8NiLo$o5m*+oIo>2nA|fI;xVdJo z*IjD&?G=^PWtk!}rqC9NIj~X^LZ4F^1S8H4PG{rdC#4QXD!xE&I-o`nm^T+&?%9u3 zxmt-}>b0dp=`mqX7esI=8JPUJPh4&`mOxg#s^apKHCd5kNhy!IQsx1s#v~WcWQTYm zBZC<^DU$feDpT>ZU2F?^-@ihbrDE$;2~#B&C4P$VErqzE2@NE=Hjz2_>ZUcg@*}Kl z7bdl^vYJ)GPO6tC#~S$&3b`<5A{8;hCSoE#+}eh7mYa*j7DkL=ODcx4jAUV~$=M)} zYu|AzkzvOnncwoC`Tcc5OH1U_R;E_9RAZ=HQDf+<6y!oD-bu6|4G38&p(8&VM3|Xv zyv)c1-@QPxxt7MAZ7jPkuCt}i6R+q9{?Oe;7C*@MIUU5NA}4ttg*5D2zgf8~ek)Mw zJTb}BUDlh;PU6AYfmno2XjdP3`e345!9t{Cz5DAKc+U7kcnw=Or| z+6!fIh6_I8!9He7h;bf8B|l+qipaB*JwKMKHE88|eVGNxsM|ob`k2;4aI|LD#K`eb z#Lm&Y^a9J06zbl>+rCT4Rk*ropel-Fg)eg}uK=+I4q#SPii#wHSW~{|JsWowm%2Er zH}s~x9AJu`RU(m%S|VW)E-PUK)TU-&SRh+E3yH+UbX`hW3+_5|doJut*Ynw=-8B6^7d&+~Zx!pphS67OY`n2nmA`u6ytOaX$hv3loleZ(^w{ z9fNjBZTnyqRU@$Il^iW^uC|zr!Zw2Zpae-##y)qV&NydT0VBJ*#1`tnjnq=lk0^}L(i8G&EK+vRDv}?17x0NGc!8+m* zT%}d(kRg?-D9AShy|Xj(gT@<(Da4;_pRvg0(lrw#oCKt}Nq8}GeWav1!6m{vnn&U)r7 z-o|Acp00G!_YSYIO_oW^+(Wvjf=7WwkNb((Tbg^8o61|u*4n%4HEDHqB&vc?z6!Hh z1th{%PIW-UBuGu3$cg>+UCL}uO?s8tD5Am{sxy#}yt1@R@nEU|#X~Ee5V?Vm#Qy+$ z$#esol`2pR6|>gqVV+-eBUYWaE6}J>$%2;K48MR&q5`h5fv!31t=4KG`Wx0gyPIzIUIQj+0PoahELJUPjqwBJyHv<7-N-{F5M$ zXof<#@;HzZh}@2L+{$E%m>ag+cRTl1@?y(O2x6opdN%IwS0N>olSMOL^X06lG71A-vA5yVf%-BUvWjD3uKWqUG6Kvt zfp9Q&*vR%sK@kMNaUaKMkBQt=DsesdAN;T3bs+|>+) z%oD7oAj_6v%gF#RA+1u+nM4dQKeP;awjDcfBt;!cf|$l-u4XG`ZB8UeB%9b3+!BSH^LyB zLbTn4DT%L;bGJ3$rT|{W`q2r68#}voauGYzyE*B8d|( zY;QYEbOd%Cl^ni59J{T>VeZx+v!hy(MbAJ8Po}iM{j5pzuMCFIIfYL1F$1(2TCPpp zJ|i|Wi6Co`WQs7PS5z9gFOtZT66Z0nF9?I)CMV!Wqb{bl0lC_^>w3cifLic_TOjlM zPrDLff|XsSB=Rw7k+7m-XX0jLW+IwaDrpK>&wuk+oiTj|N>LhCYOWC+!RwaD8dy>! z8%M!J?fQ;@<>%(*rA1jas_lBIv}m?g7&V%u#?Df`W(4%XbNonRWwKEaL~=pJo9fFm zA$t{+b~fbJb(;+1$@d_F5^DowK2;;k%!^>1`0e;~%%Cy$Ka#6~#5VCMVM$G^5eju-5yk?WF-!Vz`Ny6s*A4+tn@nFqfDXutPK50Q7n!({G*o96BD=2@+?tTvoVOvY8_LO!s9X2&fRK4HYS8g zn1YXh!6_sVfe{1zBxYtKmhvlU)Wy=Zl((s@;4IRKuqd^9QC_l&L>#g|WFcf?36WC@ zWY2Qr5?rJLG1`$gmsajXXl1BNCbLRTNpzABEB^qvgDuF3#v~*mF%nTRJMXa7(O)Fo zWl4jaoF!##^|EU*RY(*#{cUIngnMq3Nkn@O`vzuUVj#S&D_;ZPfo2}J2mIuSdA7ex+7s4&RFv` z*e`Nj4ie@Q%6Ey0=ml%3jK*WKj=>wW^jNF*`Fd|tM~g~TCh2T6WxR+XzVVIrARYez z2-y5KV7JGjf^%_zix7Cq*4Fo_6{p&XK4QXjK{2hE+@e1%_W7BZhM4+5@wf}O#@`DS zEl|jwJdjD|siLs5Q4dQMC^?XkDUjYjQPVn8cQQ6JH8q|gp4#>-lb?+mHC`)}GSgi8zj)iz6o+fTcCaWnu*f2gybL zqB<1fy=yE*+L$oCO5^j?(Od$-++%A*8|%1cMjZvlC9j?K1Bm|s-1O~O8ko^V?ACKK z=yjTyn*}UgRiOU>A8@8%%2+e)jpvW!6Z?*)%6f|dQk{zq#L&EChRYTU#^qu+nOf`f zf@2^VACbhzOuTe0i+rLr^ov|ocD#SyBiLG!mBF~TC zS8Z8tYVC}68wH8g8E~y~w{X8lrk1mQJlZ zxlBcuS7WVX8T@u3Bmmj4*qJqyE@D3zpYvo++x*Gla<)SO7Yi2pdVNBc6D_qa$62s2 zEE)7H2KOAz&kqb&rh^qy!he=D zeX@igy^;z{G_1plw+LBsi3y$ldMxZ)y4+4GDC6xSohxT*%+Wu!N{4A6H7LePCLjP{ zN7u+CqB%)*9Sl}SBm79*u@$o|=KN)3t;Jm>ArfwdECNZeB(KcMXW}D&j(`s#Tq(Zg zCx(4D6PA1l6f{_*J9uP|q89EG1WSdwOdwq#5$Tfy8&tn$VqQ&QmL1Q386+k8Yl*XUD`GD>- z9Jk(jk;z^notn8nZB(PxS$1)`FSAzf04#UfA%rosZ@=7N%WH5~|RR#sIFAME4@_&>QH~#EDjZ*XOY1IjAW;H;u9a^ z6VQ0}2lAKcRn2N`Eo!NK!f{om$=STtawdyxSRnzjGhmoZADM?o&+niUMug^$Bh}%y08IigA$C>8c}*)mHSrMTzGO8G^J5 zk6^#nQe#~_ibIf)%*x6(jiP0C9=2x-n$G0Q7CNTc%7$N$#wjhOU0@6R+zvO*frygk zGXpRqv~Lr<(`L>V-Ke*a$mOyJaa8hk*F_3#)sd8{%$%%Cav2z&Tg;G=OwTTWj+mn@ zj<$<+Fn23n`+>+N$UU_k1z~Fy?I6?>PA88dm@$Zn_=1U&XyZi&5}GvED@07wePvfH zbfz{7B`~=sgs_ZeV4_GquLcEaUANyrE$Rcgn1f5lwPW#I%?L_|MF7 z8UFx|y;OZLevS93Uc~u7=AMzm7FnhibjNSlxs+2NVG?ZRAb+i=$ALmjN&wwh&DK$3^np*WAGnnI4mUr_2zc?|*5zuL z%`Jnggwt4>I&%v}3!_Gr5EQC~b^ic@l(5)Ea6EX3#6%3lf3Aviq}UdW#gE*GP9yv$ zd5wmDaUUCh&q-dAdsKeb2mtUAiTID1pNRhe`}7A{*24MIw#3}P20?`X0kZU;AAvjtxb{3Y5R6cWPZuk5;6g}&lv{~>-RGg z5ddyy$&aKze0v1jJ=^+N_kT0k{ZgCF&9_aBgI$IZ2=b`6OGYIV1MyO0)I7>!H(_RBa<#z`Vnw`ASTB5Q;7otKohU6|qAz&>P75$LDU)d(Gf&5})QT}H6Ti{o2bT)?i zb9rTk*56SM>geq*#Oi+IW06L_OHXH5xNs70E&!_9KWOq4mg1vVIb_KXSaaU*8a}HZ zO5Wf1Lr(a^-)`h;zZr8CSxu|N^0Sc9wS#UaMQtfM=L04EspCJF{Eu1;!RjnVZiwJD zg?f{YZRT7?TCye@R#{`%=H$1CXf{cN!kzXl%4d0!p0MMdLgTUCH9JMwj75Ii*|v<1 zn$^`Z$+dFPQ4+}|$j|t|u04F`_EKdN`|Eq!*UFydcp>yW(q2IL^;bt^`kB(K>T~>#vguX;A_;|wFO0-a(bN9`PmiYdfY%+9(|%w1{{Wwy z_l_5>*TwetMy|+COSl$YJO)=}32qwhV!}~bOcs=>#LdHmb)A~8$d1l89pAAZbggqcB>tCGrXqE5LA1WHK#yF+ybpDXKiNp-3D?i*XsAqh&FL}I;)mpJ{KrW2RQ};@zP@DZ&{1tJ6Qb(K#`piBg z`E9>dJs+eiLhco+M`y#%Uu>_)v1?sPMyhI(SbwR7lyxLyRFCA@R^4VXPxmbSaxPFv z$FXw~aXT9$X#935{{WKTxv_a{UHe&k78Q-6%4l7+2_7~};;{O1OU9ZyJ#PgfTj@)={i_Q}M&kCyXm(5y&5-B^j>?@owgMm*0^?`2@ zw83?6YtN(Kj{W`Y_Nwo9)4R&eGvDht<@?JSX6-vN>EQ%uf>y$}NJx|ku1oX(04a%x ziw*Z&X|b;9)0Cclxc+1v9-g_KFN=;1DAviTw;6WDBCUtWAxpA?D&EVk1Fu<3mq7bM zCO$o=?7k0F zWN|rb)o@yd)26J_x_+QT0noE_C1MjMEs%}Bz>EI?a9vz$&)90KuC7l#Nww&NzaFay z2Gy=19K~XD=!)=X?374JY$f~JA}mmvlvJb2WJbpsH7@68VO4&zbgpXcTx)R^pD||B zD_O3`s$DIWBFHCmFLbF!8L&g_WS1O?X%XhAf(bDmTMR@ht6v)PtB|E-i^(x#kg3AOYPkk4d3$Hr z=1J95`a-d!i<2a$mhf>MGqYOWpU2Xtm3rGmZMjwxmQUCN+R1_Yt>oCxagd4bMX|ty z{{DK4H=f612U4?8UL3VKLK^uxsB%&km@-*R@3+7dT*lG4m!#8W zO&yQ8ue`+AdIRqBLsOE74hR~!k6f%EcZiY$`1zTZrpoHnxnaqjjPkCgS4jT=jD>qj z013@uIDK2FWqSw?+wUXuze{s1JUvONnaGYiC2|VFTasF0V#ypAs>)_r$!+Fr1TJ7> z;&zGNdODF@ub0eVsNNMy>>_KWllJpke-JAGu3S~bEH&~xW+&DKyv%$6)fcYjU8sqe z)m*7QyI#7G!TW&NzE^H$45M+Dl*I2OWgqLSNkcEWivbeK;aFndZLyK7ReUB(k+Nju zNVkaz{A8kMZRTgDkgK^SWX6B#{YO%z)vmqLyhLQ)V zSQXaK>J2_v+*OLo5dKfr)ZbsEL2|(~6dVbx_hRBAWTt=0N@NCsQ!+O$>O8#_E$o;| z7|V)6aw|2jnj_mVD;P@3WaDWem>KvOj-$s8HCP<3CnnLLt2H97GP1GrX0Q?+vf`{& zX+e7wO^;;EaoFc*<-Chy8IHj=&HTf%c691hUKNuob~Y8f*0W@rgpLJlY@{X!jIK?4 zZ4(`Gg`B>evvt@!J`*2r9|ZNS5zf`$YRKE@_d=A#@N7hY52TgBalEXC05c+Dh8{XH zjXYW#0cBOtwkU}^gb}pnBiS+jOW%FADWA`$831-xmMaf$4tWe>D<~CNbt}?c7@H74 z)IqtiSOAI&T!;c9`2PULC#y{>c45f>0H#YQ2UzOS^i{o54Tiy+5({6lJuxv1g5$Id ze15uw>foP|$o~KVPgB##Hn`g+uq*P&t#blGa&7*x_9(=pf64$Rf7d`#f=%JW!h!jjU*hRN0LWliA&}z+D}4%UT*-*~mn227%p43x;XMH)Gcu{k!G=FE zZo6)-#NEcGx@--ChKoUCB+-b7IEF!g`FwunSY@$zE-lk|=*NlKLdk3lywzBVkQ(5u z!9Yqt⋘EL=t5?>~Rq;L}|@jSXo`_AeupO*Rppe$h5>gvUV&meacYqYJhj&^M(Ha zh{Q+3s8+_k$~a-gV^vR+6K?VrF9(7ID&MgnMqp;KAq}QRQ9J&lU?j0^89P}$Lt`JC z$yT)QU1zz=G)sw$_lku;1f_&1HXw-Q``@UUl)rl3H0#bi*-I`Pva2|pEazFAtOKI5-lDv^R&bzvsWE; zVI;hsQ#D*r*&CIb`d9f6t+x27q5T82K&)fgJZ2_%z(fE=R9LLa1D%G1)PHHm-a$wgI$QZ&F42TFS zW*`6;5fKp`D!!`KG8$tR!N%dP-MR@ybwbmQ!^&X2PmF8>0vO3F5i-f=#hXvW{M<2? zrj1FKDtN|Wv+i^S>&}HbQ7n@_9)>PC3Bt&PL-B||kC~o;M`2V`Z4|QkFZzzv=04Ig z2*?te;$ujp!D0~r=@}9^=MsCy{{ZtZY0PQ(EI1giOprvb5OFi^AZGhczycv7w8Zo& zMmn)(a&>U3#A5MpCAzxW*jpkE_0P9OnwmoaXD6s%Mk-_zU5Th`qkEaC*;OPU5K^*CN9D9gg5&fN zwZzfNwacvR)yj=*mNK=>lrE^Iq3+U|SGrcoSFFDokIGy>`sf8YIeYBbW`4Bf*f_(@ zpb9}NWUdl29>`xWeTV|&Q4{|F)f2qW=p3SKUBueTzjped@=cR~c03jEZ$ z=kpu>Gray=%#`gqtJeM(7ke4^F{aX)F{ew2J0`J`DF!{HVOxMOW^(Ow_6We4vgtT ztX8LQB0E>B%s|B^iTLBjyTGJ2oxM@M&@mSKX}+FJa!++zSryTj4U}V;wn8MJ1WTOD zA|hf()>Avka{mC!sjb5OH>+fI4oYrKGfriRxL4@rtG&ONwir-*?L2*{CR*1TaM3R<|64XTnbIVLldoD@j@F){+hB43h=xI@ZkG`cJi zF)g8BT-PV^6A)O>v7W;?{HJY(K05lVO&hvaj1EsqsWRbu!jl4hL`3I$%|HT%!7*hc zzcC(r%)_QSX2ZS~sm5nbvp(vj_ZOP1vgM$7svP4@FM5NaUTtv(q#Qrl8)eREFP_b1GeuvYz&K2oJRl{viGn27oj15nOgz$j{ ztRagQ7v~UB5zAP`{q|cj%{P#1zS_PwA{STA#&uyL!iW{L3ag5E3^;!%g%I!Yw?#E} zF|NI*SB%GoaR`Zf>Y$RUX_6ptF}}hUL=hh3LQI({DVc(ffcWZJF}0ee{VkF~1FYSa zQ5zRhx`4naD6J$r3k>+5uz19(Cyw#dZ?8F9R;XuDjm2A4=xsP_cXi^h3=tKQObiny z2hH>OK}-(+0D$z*EF+V+%hc*-mqws)_acL?)>8KgF;LGElA zdoaVqB8ZiX!FMHOofgvusgke@f@zqN;y@V%JIDT`U@eRmpTg=2Q+rN#Ben5|70f{lQJS?q}f87EKxSVZ;AMb=>Gs#e&$(}lZ_l6 zl2Yv=08SBF`kZWHofce@Fj$v3h5q71r~d#hk{(8`0;~o*A%e)}j}*YHV`+xlEFj$3 zO-7y{;sXHBkIYYQfVf#kwS1*aOy=?8>glhPtwFZ!!|B#w66OB$Oj#X@S;V=@_mYjb z=ePiG({8ZJmMLRvGQvXrteaN1U#skh1~>45AW@48b;K~{#6cA88&^{n2apQ&>)v}Q zJY2YX5mahdV}w|?*pzUS00922zfwQ*(AdpIQmgFcPDU!sPw~J@iY?3&MnOm?r4a(B zF>^8@0&-Qrigtk52`YNW2!XXuu1^|+RjQbbo-gef#4ta&!||VFiOQTZWxqY=Xqexs ze$~}3F$u~(`{}NvF7QZ^-4!ZE1cZo%W-$>Hw%@3ox<4U5^!jqqk<(#TQjT|6{mFc;C*osnhr;9WwO^CV zswG> zQmxwiRhc0M(j|z%2*}6zMD9h=wd3t4DU8R^3-(&Cy=~yKvG6>cH|?>B4g$v zBxB+_0w_bB8BFY1W*w@$MtHi*GaITTyNf2l^86RFqi~KBGs|v7Q#bA}7pb)#tPD1h z!XrJX^UkYPRB5d4--q#l4ohq*M~T74@G}4~GX?XsO`!Wvt9zNOFukzt#*n?-ZCRL2 zVyCBJWX0M|m>G~Tk}wEd$0DDI^#c7*w`q-CV$Ff zc>e&7kyyCWINyFdelb7lKlRWRzQG$LjEKsAb3Z%vAFyC1c*K1F0LMWY$;?c|N5y<{; zOR3+H15!aF`<_ud@4U~){KU5zHX;n5f80d;bjN6kOCll|B?Kk@#((A~pe+vGcH6g| zsnaxcFKVwW>0QpBuDSHR{2#9I=v^oq!DEl)%7DOve)a%tUgT{{VBoCHZINmW=Tqx0UmG zJZ3|<;F>S*l=hhR4&sV^`j09FO~f_MCw;*J9YJ5MN>kTPZ1^kkO$76EodlxHAe z4TVPANlN6$c$oZuUpsZ8e?9()-HP&B)^A>RL3BGw-nJ?)SXCm5xNM-oL>q5aB9Pi3 z$|R%xOvc~6_G|S1@6Ua^`{L#!y53oKb4vCvxdVFjd$`PIRd*_~no1%p%SIwYa`vo( zf7)cfMICDg>QUzonC@-6o;hev;^y?GLuA5kvheLgiNBkA|&zm2_~^1)r0JYGvh*;f>fgU!SN9{$4)A4shVE9T$?5*;!c|h1GuaD90~V>73Rv^tFlmCc z*&v^WF|)q&9b~^_ygl!i)z`^CA$-r$I;B1`c)zH1qlXvV9JY;4ZzG(kUP858CYi&( z`s=E-WFL3emuwDoF+2V(6@IH9`PxKy{&FegxSyQ+Dp;ZyMdWzG) z1v76RDGOeGT24 zdbXA|{{UdsuIiwyQ<3{hYqPz0G5IBt#?iFI>2V*42MInIh_wflk2610AEpPHUSoNO zuKeWi%Kj6}4$C91a`0ve~*? znvG!bVI)8m1i9QDCoo(5?a~^*{{WH=jRSY@d};7!#*Gi-Wdo01BPT{_X7vU&X`XVw zSpB*g0%Ux6@*yaXpVv})hfv1PZM_I@Yw7!7@M(HITgNKBlJaX~xw=;|+HHNRJ87BK z{iyCB!&Z>Y=p9R2CxpsVH!dq&qi`gpkW%9x&SF&~BM}j{@nAK};ngVIRz}n6x=HK2 zr&zpcX`mA(06~P7nNu{~ zeN|?1c?xt;a}|d4gAIksMq(j`L;(vQ@d4^jr}c| z8saWtEZ(t%#{G<;$_N^Q{{Xp3)PXq-<-sFl6ibdZ;zf&+DJkJA>Wn^18+Mv;EXdf) zwbV++Ewut$0&bR$g6GH+rxfASV1%YH`fSH({06`$8dNNI+}Ik<9L{ zC%^VgM9Cf%V&oP>Pvf!IX(kM8fK{VdSPK!8hDy09gy>%F7?v^>yu=FNhDfdaJ*w82 z;>0mn>`Lj&g1zglsa3R%%k@-UHOyDfqQNGzvtdHL&({|oR-;`9? zuaP4v+b+Rcfi4PUv2bJYC;C1A066MvUw8Z~Gov<@i;gvyRZcHO&tv5a20Y{-1R;k1 z09<_Xj$7|P011*mutq-pHP;-%tnp>M)gl`h^$^0=s_uCRsgo=MAIEsyOP9{ja4jEp zc>=A7({_PEioX29Ui1MmTPThh$ewZxnUS5ikVpESp~hnIqghcyIb-bp_Qgw?YwKs) zvYLuTHERC=+?2pTK)hx+#F-StZxb>tmIVscomseFzprEtt=29<6Hm~{U6PZrJXl_$ z{RcQ9lHcc`CBi=uM<-g)ZRd{B%2?Y73}psbCa@PN3a_Z- z(Xma4_PHwGj>jCA#0n-O**j0=G19Dz3i2vOXWwTRkxe()q{-azKyWpeQ2zk1W(FYG z!2$S*Nl*It0hixt$gOu7a}}1-cV@a)$+e7B#h0n7*sQQvFysin1d1YH;vjxtHifu+ zE;|#HxqAq`4T;LiS@(}Ly@P!+xgxS=Y?Ukpkuofql9?$9{6KoD&NB~f>$nOK+P zF_-CIb`e!=D#J1Wx7r_Dn%g4+!5~ZRGK!b}7}Uxg<8L(`NCsxFthg6lsx1CKT|HnDvm!L`0VJ75iud zYf@RbMjr4(#wxAwcR0YiWw40cFd+jhCCtk|MFk%c<`;|&MOpaAzf0J1P%5i_wQA*U zX5jw#<+|bD)jO1okrwkMJM{>w7iP1wcQGi;P**6LGE;GYZzcO|k|0HbMX=1m{{XM! zm-!J-KpMnT%GtFWt*@YTXBVY%GX%m(Vq^2YUK)**FC%UBjZ0Gf5 z5=mK9iIWTDc4W-VOl=!+>he05=uV-`>A<>q&~kr~uAM-{6^h1j>=13Jh+^Q2etSt2 z{yY9L5CyG_&-*o9tw!90P}7W1&~5uwi}^dLkRtW9!bE#5p3xcQ5yA&(js9oAR?cHF zm9a*oX}Sxl#EdxK_FU|96q6#c?@OpeZtJDT_>k*Bs^|Wnr}P zFrUcI26*id0@^sq##gxv)cGu~E~{)tUH9f#@LU8j#|>myM<+=(R%#(G0zZsxyt@_Q z@%JYWf&T!b>7*jYJvVE?+O$oJONgI$Fp@7&)Q(Xf1Wft)o}vtu3|Z;yc4i%Yhy^7T zab}g@V>pZjk||iF3q)}lTt_ck84)`i$5JyOR<2;PkIkyCMh3q&KP<4W;cP>iblOwy zXFCAMh+ISt(GfiX7&7LO$K`3wn)UT8Dp_yS2{5A8O3GWgzDUG~%ukF@$d>;A@2axD z$6+!jiNnq$vQLgIe5-nv+_DD5*SEJ62JG4w8%z+C@AJ@0ubBHcQJTubGPR_-u2m$g zX%8y^r^P^QLkh_*&>vArRf2NathRU!cS@RUTzjAa^CZ?wCyB6!jDo>~F&w5NXxrt1R*$mA z*0W8qk4YP5qmo~I0`F9(gLV>OE7$Nl>@y`Xw8?c1X5?|1k@j2~b?a6K%Nap-SvICZ zWUbhi%os35Q|pc7WmKr& z$p=Y`;bn1f#BRwax#Ce3T^vOVQ9#7c<0ca`GFwbUIJB(JLm!B`b!nb* zgiU%OW7~C8=vdFE?i(^DW9*oTnA?m5N5pkid*IQ%iDj^T>UL#K3|JX9nx1e)HGxo5 zBvKNx_Lj>T-Ud0$$QO|Ev5&VEKFqAK^rO*M>d@a=ls?rp_MX>LO6P z&j!7>&NvHe6a?;5=@bVjo?gLZl>S{W2Sy($Q!!@|R^o8Zgx-C-1m>p8B>jjw;vz87 zlack57ZoTAeUE5%+(md@JZ-FYC~6IRG@0YKs;h z6K!q8GRhFpDVY4CsQSsGLSSd{BtTO?^E~JaK~&R;3_f;^qedSj_g6)l?Sqe6{j#fb zRl^c*mXc+1nS+?RWZxQvXzW=YSpq=Ode`JG3~oxz|{_w*qQW4z-<%p zB|UPt@wgheO;wK5tH%SCIU05Azk0Qnd{+yYv$KJQLnjLX_3T42^Ci&~#)VRaWikhS z#?UJhIFO&RnPavDN$>+HC@tbfeq(*-{Q*7vb}|juZU?9oHT^?k;{Msyl2zcjT!ljY zhD;_&&*WU=d7qA$V<-!2)hudiV=T6_Et1m^%Q;jic$&WIN>#rHOvdpAJb&YlNq{OU zDpkNW=%J8QQBhaBTIu9eUx`;Veo9Pj?>cVZ`_&>D{UFfd0G@E%kA*8 zDk9ooUnTj>>;VxYG7z>DPRGz6Y+-O1r3-NQ-B)svFZk@Mj;vOO0nhaj+Z7S*`sV_0 zGqg_I%*?vRB;8*3-DWA&!zGg@!B~}wibM?ZSuRFcGEDd~891N!v<}kPp+_5Tj#>3J zg0of4gHs_V?^78Jh+6*K<^pO28%hj9VE+JH&j^THlC2rF<+I4YZ!3;D$Wll0X)A~p zz(=s9fdFO71!O8M#v_bJ>u3Pmn2HN+NUNR6Y5SKfFVPhkoznsl1g8~{{ks1Et^?H^w~yTQ0Dv;Z z#?r}Czd(^{(5(2avPy{&KU{{&n2?c$Nkqg1PT!PIQ(U@NOYUR-_fXrdRajiBKP~nf2rrW z#POejj;P<=$Kw+vB!^C&%zj5C zbyU?>7_ut+XhQFR2i zyPwHk##05l6~YclQ({>J$%cUP9ik*=Hu#y4Hk1DV$NRf|fzci2)t$WVMjd#MA+=JI zPe)`~k6AXoTI=Ha%Z2ia>>)6dX7MI65MKa0dh~LNoC?!bi4j@Mp)f4r>te{VMw};eU4Z$8)sbbah90b+d75z+hXJO;J5FOr{FaRfUL*J={_R$k^aO zx0!>O>uVL_wWA8~0)hh=a#lQnq)m=oCO;t&GAQNx{r>>2fWe<7e6H=Eh}t%vcD#}9 zHC+*=a<@LiO=*mNIIQJ$9np!HO5{dP8eGSg^TGxPd5!*WuNi!}?BA96Jy&zK8Dpod zG{MxTt8|^#t(hG!YQjaTO_3Qbia>>tKk$G0+pKBwGwH70_W3c9^2WBb9Z9d}4^s<^ z#A@f8sOh@vS;-D26FgDuHp!WBgEA@RQye<-Yvs>zywdtp{Xz8?k{T-$sXG_0wQ_Ow zbrvviGm+E%%}sA&ld)G4gLLg6xS#BTiJjsmIs@N}gNYcXR@KA~#w9b$afzSb>*i)Q z{{YuO%82G<ut-#`C<)MoPn}wa}G3jOICi$3PAhVonc~j^F#}*FZw1MCW)C{{Vmg04|hj9R4Fo z;WPS^QaI@8%w9gmO6#FSQ|MT7J}^I#96;{^KQlA)@z$hp{{UFN!85+}J3HOJ+xH{K z96qEGXKy=!sck9RcT%*L5Eb%JsoxV|iK*EQ9f(+><@s^w4F3S~H@6+n?pB<`;yYE` zja{HK2*~@KtZ>$Ce9#g&eZD{)5_3`@*hDLs*rW|aGe4vKaerX~lOi0YgM91SD0j0klG(Xihy4`~B=Z`(G*8c#;_E%hES(Fa@ zYut^RV~?`eDqK2ZnhF>=m=Ks)F`!UqU|=C)xt9Ht`b1zcTC*+PKIr{GGF|1;f*i86 z^uKCqY5FWRM1c$P7cV|r&uNG#7~UdxkD1@OKC8c3KOg*L@#hn)bC^=qdgoNtKmPzt z`&&~dILw8WsLe5z%810BTzDO3a43P6h`?>cW3M_MCwWu#0P+UsXgq`Zk@u6!{@DFC zGI`vZ>9auL=MSduf|8~&j|zeo10JZfzx$`xY8fzN21K@O2e&^QHAii7_*v0?napPO z?jK4*@i@$lY&AS~KkU-6F~`&tEooa-2F_3;D}ats^26&Mexn~yZqa=;yHlqwXG)H| z@>f%nr?(mwjgnjP`30_EGI;_fY>aXw9&*ki4cm-F%uL3$e1-bPcp2gEZZTRfz3NyMj*NaxH}7?JGI`9+V^M6 z9`Sbq-;Lf6*3@?LTBo|RrN=Ll?hdE7WtK{wp2gbYrb!!C1h^Ri6fESXXJF_&_j0?f z-aP||?RRr~soyPe*lbHq#*xuFk1plIku5VEg^X(4bpp|Z%m_&O(*w9f5uDCO`K$Fi z@`K4P-1Z-`{lDxNj$S2pzqfh7&gfkmrs-L=Zlebu_D50fxMG*1*2cO*6}ZGN@+k<2 z!F@B`ZpZhBEpr=rIA0I@&QC4tv6dO5@{a!i@r~!%h$23Fao)b%V{h`^fMoAwyp!^? z#f>T5JrUxcfA!{s?e?q3v3cDsjIzr(>xyB48^*j0{e$2Gf!(XX%wdE2-+cJ`X=k)Q zkzQDK2eRG9(>L^OZ1wB&c8C2~+*Ut4k_I!`i?uK?a!hd)DZ|Z@J8wIV+Sbjhx;hUb zQxn|0GqF0d7&hv)#+IV-%Kc$=EKx0XM3%BxO4|z|35GA?WRmHe3j3LDi&3RV3^7fkpG^t{kzzP0EQEGQGh^%l+5IAVFj-7j<^xFCm_Dj2+ z#?YPX@)yl+(H;um7DKeztbKxo$#G~@EQLIC&c$|#gsq9NV=zS?&)i2*eKLIB@vp*e z-T7lzRQ9K|z5DNep0AD8U6jdcZ6brrBjydLpqv|5L?zA(* z#uY7Dox}C+*Se8=M zD$ngyzwRCqEv{1Nu~gVo44AC~QzH=_L)~rCt)oLvic+a3^)=_#OV`l!(388WqgRX_ z^WIOV$9?d=Heowqs=k*VHzPTwwC$Q$ZCl!2=DxP8r)2$bc5+H>d7Q%7!FMIGlQBEQ zM1Q>~hhqGNZ(?ls-&SZ%Z>YOAS-U!KC!4EsTsk);TZ}%QUb;u_RSwK@)=EE zid-_vX)JP8>AI+j;1>j>m2e}2ju8ZLGr0c%l4=j}3$M*U^+@vY(Ilk5aF@FS%!_rF-v|OUU6;^`ci|;6iOy3g*C=C5-JeADjy# z^Z6+KM092@!rPIrlcQrxUnH;s!);l!#%h!j;m|8+8I(sM+INATQ~u|r_;=x|7p0h* z4>wx-xy8`N*^$SaVmM!8h!^(X*td*xgEQeWMKLiD(rrp8R8~aUdbKvT)5VY?0EjMZ zY1>-Mn|G9KsQgF@Mq~HB4T-8d8g=U8A5$Q@3dxvJxeTx=Mc!%=Vw)bo_j=nS`Tl$l zX`VA3EPdj~Db2N6sJDw-gle=7IU820<#k}V0vRQ!6AlmY^vp!{bK0oPRXQhj=2>`5g+|=`EPV+^17hDuw*)C}N}2K^}k48hcDE;Dn&qG6c})`q+=-Bq9$ zU6)BIqXffLj9uBGXMb3Tflko_6UH}*k@2+IYW2NAmccr;7SSKOYhD$ZX=)J&8M7e* z1t;+aG0I^0@3+T5PkmLXyuXIP9xh1LQl&s8G*7sN_FPI?gt zw{GP&RKKZk#Mwe9O;Lso!vGQ$LK^v#mHR1BlXc~xr|`rt=PulhD#MhW7tao zOqxF=BH;f3;ROZAAbv}f&iuOI)zmDbmG$XbW`ea+u}x{2Uc&&%d`%NrnVoi6bEqlrSKO`4NnA{toa9jo=R_pXRQ84HfOEMkuh_>Xm`5FrT<;KsX;L++%Z%x0%{wW_e0@i*3c~yD>)6 z0?Ltbb-vQ#$uct}h=)2zTQb;akcQB4ynazVDKVvldh@ob*rAsDyEav4@7--CVXzq? z%xn(B5fQnMwsx43k>e1|G3^ zRqKd-W&>tMMODDXClaBO4lxB2&{$VwacIP@oojhIHy2YUMfOP)O3cb+`MvE8>=1*N zQUMXn8E17J7RAe2F5wTVI|B3 zM(@*_QzEjM+9UP=wdh@=kkhql;_YMcT*;_FW5v&@5$q3GDR2^PI|V=3UjQDhr~Vcz zIg_VGu1(f7mBmp86Oxn)+)QD&oY-@cTzE}`T(8*^5HmY$TgaSgIxyGU)jHYoW#{OgL zCVy%I2xEAd{qz8}*|iLf&102buBuz)&9)8&5co?LB%)hc2NASKDcGmxCL$s?4$w|U z#InA1mowzVG!>2-svL4_pTIyA46$Uj7{ozu{blj-)MG~n_jyd1(#GHymY=ug_8fXs zVW47hGrUV8B*$@$h9-aJdZ9MmF^jI|=WeNxPEgpkb|Rzg&L1HRi$wl6iJ2eM7LjWdYz&SC3x-)NbJAd?rgy4N zNpY~p%)RVXqb)vPraN<_#1${O$6Y4;um<*MI!Hrp{m; z(Z>7Cqv~IfN|tPzE=mA68mtVoL$f+BWaLz#4VE( zz{y3(n-dVwb0hLHnfRJDZN833+o?4LV&3pwo07P+u#;In889$p8%Uf)Y{-a@n2vzE zv1U}MsOe|%*d#nb(G@|ytDk_6+z6?g1e^>>48#{MQ!(?r^Q&tMrZ8C)+sb8oZBt!X zwP4;k3c&j?VLNRFHONI}@xQKPly4vEW3F@uTI4Rmarm5%-2VVEh&vG5mKTY<-*7Mb z!N+1rtM@O}UP1?9*oHQZzF%Xq+M0#S(~84gx15I#>bEt$b(qc)R(XjlgX5V=Dgt16 zMDm$3h!am?#~LS(3zt zbJb@XNG;4nwh7L#2_WDzESQ-h-F#$XBY2*G4w`NP&Ym|7BBRI_CZSkKF-WZ>WZ|*% zv@e-^1#$SnPbm4Bo`lHLxp{~JU~}Y6eLTNX^#A$Mp5w*w*5zuvyr=ChW@3>)v;;k zNOFh}$B3-Rq8gBaU_`=X6*D^-bN>L`ZUxPVO`5Kg(@b76gyki70ShI*5=2545OXIX z3tXp&1OmtBh{VZmsnl?n@}ZKwQ~5dxIHuUkHGmdMCD9feU3G-OMpgt;CA7;o{mjgy zdM@R$>BrcNrao6oA9Q}l8dr+8FxM>v%SBLjl2TK=9Lx(nk+r*ki;i-1xi{YF$aDGgKwdoR*k7Rq_;si2**Q2&`58oVf|l4g)h0 z`AY;C-R$NoJg%Vg=+`z+RWz5Hq2 zxhf;BO>52SPxLF)UeaQwNdEu{FIkj?Nd7y>9)~(%0RF`(xdcmbg8}9YZqvoE5%4kBsLc`H0n}A7Zp(< zAHsG356C|m+x~a!^O@4!l+~U_TZ&m&+aH+ zfBm3k#F)_q$ixJUaUmlqi$}*ltEbdk>2sFU{ww)6PrG`@8;PwLmT3)Q!~X!Pv@M}2 zbx@&k&{1NmVRN)Ab&}js9~JEojy|5z1O9+TAB@q)mN+M<>{{UNU8-MCQ&69u4i!}nVIJsOh*3z z^AjKIpc&b=zD9Q#Uu6X{<2dEd{vZZ_^51>u{x;|@wOqIE9~7!Iq)T%d{3N~xA_MZ; zcKv>%=6~N$Z7!XMteyw=QTYr<_>BJm%t!j@Tfo|DJ6`mtrVNU9nJ6Dw4?Vx~+E^ct z{!(1y+PnX8BmZ{dcYSt@N)0mqAOF!cqzVEipwh4)t zSHTzVHuJyTKGOI904?I5c6&9c`{kpxZ7Z}YVGmGhtZL6E6jKEh11WWX7TmYj1|m>1 zyCygMf@iNszF1}GJ3tP#?q06PXsjb4X~AQ`v;2v{>M$4|_bI)0j`KuXwd5Z2qL3kjdw5>OSD;cIR@KeBMsAaCpdBWqOSY%R{UB=9tV6 z+pQmr3nQv~-`sxY`H9>`_m8`p`?T1lyB?fwlhRs$5qR)=8&AUH?eMtD%UVN#1p5r) z1WbvW$HeuSr;5jYIJF0mo;Uq6yur=uPZxF4gCVI8BYM6*YUNAemFZqKEUT2F5VK;} z5@RqkGsYq{x2*L40C`iE(mHcPc<PpC{lvNX zEw`BXfHtl4y70%rk05k!k{$c5N+sAhUR^T;$hRbMeMH){&6mnT=!~|6AF@&eC(beH1 zV9)`4HRJ8viX&IGGgo^_uj=IcKis^=12%{!FC$MF+73a-$t~!Tj%z98GO{C%5F$U; zAR-5FBDiG1pz9dMGuC9#X_T?Z*o0IO`iP%t1dMGHFjFzPPWJAr?QW6RDU5ci!&iKb zeW|z`5oKQxJBY{jJ+NDVswM_`#Gdd2w`*yB=Js>Db`bqkdUvtC(4BvR7|j)>?Nn+y2&Kl~&$wSX!qiiUms+B2_J@ zxMVCoc|yP=c1*e*Bs)i0QpX^{%^$9Nwd2kxbe?Zd2asMfRxz`b!`-Pi+ox2=LRmF! z56w61iCmiGR73?5Gx<#A_PEv>GrS{$?T3jN{e7f+MU<_L%PSLZ{{Y-)^$uoH0}XKm z7qr#}wJb|;P{fe!EG^CNhNY!|?M`>Ly`s`qv|ndkj&to-%U)RI^z z3ns#0@U6rPW+=GG%yoqy-UoMT-=nvjz8v_$qPzEJLH4t``cpHeS5H~s4uH`cNmG8-`ro-r|Ki7ydvx_qh5;DS_e`2lWo}CFK#r`vsCKY$>#Dc8cJ=1 zF_9%%P))MYkoCwUcb|>p8hl9btF%5M_QMb4r7(>;@N-J& z8lA`QACg{1>#XsA7egDTvKFv9Zt;{l(=m0;aIjEIn!^0Hu<2x!Ov!KC-VZyr`lDI* zPf2(?tbFs)ZL>+*&sAr;p`e(a-Q}~cu`jb)Y2Qj2PTZ4J!(KE-v?zi^$&&86XS#Zy zTK8+Zc`oKoQ(froO-9Jn!&b&swMBYhP$e~MrpiZvHes%FN0dQB2Y8;X9{SMwy!m_D zTi8y@_p>8+waZ7?-ox0TTLX7l3TZfT)m(h7?y3 zf`W-a`%9Yc8aERND|Hr(C8m$e9>5$jc*mh>kl?&T%ud{jc(`#iQ?kfL>pB7tW5w zVbXaF*J8WXng0N(nfCSKTWY>G?V>A~EZ8JqtFR15^4Mp2Ih|a24fGW9L&?7PcMHl- zr&oWxdGkZFoyp8QRt8emtsHhs23A;46y1Pf!3ueZ#D}co{C#1@H`>>S{e$gC{{S8D z6Z_%Ze9mTXDi(xh^uNWa%Xycr?A`Z)dv+*&Drr)m}e&0zKXB*1Xe{dxMP8 zxnl-r^a`L3LcT@HlUo=qCn^k%8wRtPkI|P+VeMn}0FEA=n-A3{#$BsK%33!}MQ1h8 z!8v0YJfF%r4;h%4+DdoC%tb3HJGncxG4!)G>>an)ssqBSh@_8~0Es9AIoOEzoumCk zb)P;VcDuxm>S@m7Pm`WoYM&kQlf7*tR-bP&S&DZ}VkX>%Ledb#Dy*`29eFWi`iYb9 zLBH4()G5ZLStv?N%jfb%J;O6}$8h?jDvF^X0$!L?$za)|wg zP!^oB|fhtg+eGK@nHMSC&b|by8#MdjF%uW-(|!_ z@7$i#cOS7;sCQQ-tS}wh@!u(Kak_uGUADbnGo@n8Pcc!HkGB(VbB4-nhaiUp^O!h@ z>p{uTu$viHWv=0dl`=Knan>sIAz?gOVW{8(zWV@=_7^Eb>WVY8J5GUFn<{k{I;Fsq9w{Dm2S{E!|D}UxWQf8 z_)uJMVK!y}hnXn~14>F5F~&JEVj@VUN;P4|EZ5Vt%C;qDzqux|t)Yblr4s4Z6_J9F zP;4?EiH=_}@f|j+fLU5hUeWb%**c`(N~+nII&y@H%v|#sQ@yK!I7v?55j%YKlLG0x zIyS8vj2Oq?xoMW^%jeJ+GMuIl*dH=zo=g}p*<}hHqj8y^l^c?&XAzwoWn7i2b!~y% zYV6v$LTR-E9Dt%sB%r1_Z?NtDqB@fekb%qOY}BoZoW@306i z;#mr@$%z((!=e@-BfvI+lG;CeOhh%0wYKY&hbxB5&`ABf*yjpBANC2fMix*;rnEl; znV-*p_tJLTsZbKUjqG@5Dr4G*rBJujs>zsVt_TT44k#tg>j~o=VhiJ80-G+mZ_#nN ziKUgckgoiIS0=Q=NXkgfyYt)tHlOwWx{|$IRF*W7?%&E~m2Ejkkp@)&vH79L&KK&-`>+!x3CEdRm?_ zk5wX@ill{zCdW2B7h$TBVx$(xY{c?{h?x9hHkklhbTRW+BU2YR^-)SvU_QP8vl%-ztgBG!wVSAR?AvKx-N@N@$<$KIQL`?58KkjR-82$0X=gtz`km1OU`PE5A+vCQ8XP!U^pWGWm_jf7d`!mBf1mmA=ZN-gfz|lp(7fjX{kTuXz=wwQ(g$#2CV)_uGBrV(D-4 zvxcui+cRNexGgCA<`E^L!WbmB0M-$?5ttf4eSd@&`;m0vb2xjbp?3!Ru$L;sW>p}w zCd|Pf89#=MLkVqI{vSMMCTE}kxmk6aht1>iOSkun`{iCbgzEJM3RVLuSP+SC%V9X? zBpko|dN$5eEV7}PyOho3T9q>&TCJ-jqfJ#B=04kPn_=ccMoQtd2?W7R%)~9Lj>cok z7mC8U)UNw%)3o|c$12#Z^9wkSRIUO>fBOnKu>F%WJI74LYsnr!GP-XTR*_^Y9!}L# zhuxzOTUr3~AR^o4VH5HB94Ijma~?p5oOri1}__K!wR#?{e)V^3~p=P7LXF5 znQ_E|wl)-mNlXa9jgoEacxc2U6F3Zd%C*Zig25qFE6H<6ngq$7<_jl^;&=xGo-rhI zD(`18I$DadSMU}w*$4jsNJA8Xu;#4PWU`YYHWF9FQT2|kkM5feVaFH zpV&7fD}qHBV^}9U&4M>rHOk~z*^^(~97Mzy$OmMyF1=~FuYNw1pRnn-D%8_$=7~a- zEo#ViD1bSI98T*c&i??G(HvG?%v`>?f7A75P2bE^Sf=y1l*9i3wg|YyZ2~6~AB=6c z$5Ag6ZZZv>H(vg6q`}3y2BU8bs&mk9fZnING{!r^l}wk{9J)9Ld+Xh zP$wfXAJ-hF1} zlTKEev9wxpu}b(fNyN|!=94AQ9y^plPV*D+0aWW;Wvf;WrZ+!IrD?FbnI(!+q#qa_ zRhC3d8Cfc1H{;Kjzx3BR7V$T zh_f8ABDCv>J1|$RU$!!GyG|Ct2}-?7Ul){w19ljV%X4xV`*x~^Un7L2kir!;z}I!h zSzNU2l9g<$B<31099tt10TIF=V~0l89W_R6TD6+P0*e>+4(Hh5XbW-ysdf+1Eh4FsRQ>MDjV7bgOsd5Fu?>-pop(X@ZZzyam%u5#G# zeOq};tFXg0RhK%;R%TEU3k|2zOBI;&J>#5?(E}YUt!Ld@*wnLs4@~5fL@Xo;wFnkv z=>)Dxvt@s7qgj;f8;p+9JM_~XIM{YG6+-Ts3|gx_Vhds>^@st5i`qm@mvNQJ3GLZUbBwDP#y*$VlUn1SF-thn~X6tZW1=47P5+)q$&`>NEXRqnxAy48K+6CXVh zDhE1+Y8bVi4zduIRtpDN4zV#3wpU;rnTSI@&JvxNWwgY|@6ZcrN8VYO0{7laA4>EI$#Xm|~!dJ`EU3gM4h^<9tmzgAeW_-j% zE6kk70vY)ZUpvP@SjS#opstLQbsdIMl})N=aQ14>%tt?5l$ps2g`6gMaWVMbXL{)1 zGMbxEVzfqwz~*(9ztp#@N7!RRr}AvbxPrZTA}Ik7AT&gK4`7P&QMB#Tp9WO1$!s=X zOsL~>v}t7%khmDp8U{+o@rOou0HEXxtP2w=omj3|tOI5QJzTIPM+bOD=Se&|=R)MAKD6&k5ZzmK?$V%dKA)UyqtFfXzMJMO1l&w%vjSJGEB1hO{;JZ zC|YC)P$V!j8_32W_p<}s4A-1U^JldE^!jvo;oREV+1jriqxHR?yvM;Y3a-^;(M3%J zWM*r_PV`8+9M(qh#7ccB_6zC_qIMOLLb zY}S%vp)%DfAXn@I4Y=+hw*LU{tO)RH%g(~+uITw8;AXh)h8IkCOSf9?^y97E%a!X6 zr+YT#*Q@H7;E1gNP)G^lAZnS2gZbY?J0nvUWHU5vBQZ6my?mVtK&Qe8W@3KXts6>+y3HN64jF?9Ynyr@K*)w99!bT6SzsTiBVT@()FJCqriYp{??oivE^U)~a~?ZZ2=$w{A!T7hMaF?P)S(LU{_J z0EnaUlIzBI)EDavp8@;D+TR;{D8Aln>-e?P9{6f1Qrirq2FVh|C6)et)s|smNI6FC zf&Gl_nYx3^9^Cy!@ZJ{qXW@@>bT^Ql(#~od+Vi-2qLH|0Xe}R)uIjUEAhxY%7m1fE zg3~ZujtY1F$)14h9~3nvqx1XDjd9%$`qECj?ayi@`4h%_M$SBMw#x$@PmswA?F&KP z&9+cNcZi81BF2xZ-_@g2XPc}1Y4Dr9ou{$no>NqxZ#5>W4Cn)Nt(S)gr-Z4znZZeL zo1wUYiETW9y6rEkzPi&NMGvMlb{EH7mZsFcL3b-9lf{;y9DM!JS(?jT{Lx5!A+;(^ z6jqJkSM1n!*t+x0+7AdjXW&ke)7ooVVefa#>glRcM#hW5X)RXj)ckN4uu6tb{zjW+ zS2OP?AQPS>p&=H;y=b_aGSrLb*sg~Z-db4XVsf??rCe3x?SIGY1xhha;Ikc&SL_~=W#WNE#B^^Jxh<+~3 zdzzaah|)RyimRDmk!PA~Ta-k$SI?XZ34+OvXA%N%F%ciW=kjm88fP1)ZRj0grLnr> z%#3cPw%qq{0Zgd;Rxv~?99`H+i00nV^;u=t5uHDC045?f>f!811U!*zdlo?$|QPBdsDWaQ258KJ4KZ3caR!B&5s+j?kg8#7o+uFMw#ktS?t>O-=gw#D#b@*s({xo zw|}kC9HWfy6F4$?x7U6)+|hV!&b92GV&8K+XH{osP*Qam9OjlUXDMa8f50}b;9|S= zW6=;t%r_a{2eQppk&u6k&uyG zPSePvtTXcm=+&+>z1#19eHB9Aj{U8@rf+wHP8V*pHKb{ubuu`9F(+DmSca`&OVk|OoNhMIz1x&`m7mRQD z*M9NIj@(;2h|KX=b*SH}htm7Q?-zTQqw?Mo_|xQ0sn;62Jg{wyUF(P2p4keFUgj|? z0vB9=={06$Bx59Tyze_r@%zYcEHeHi;Ox7{g7MR~x}_CQ0jR8GV=FxdTx{{X3ushWpX#-01MgkF7oGH%O9obBCo^MlCOf|`TH1M+9cM)`}Zay^Ic z-nYZQAKH%iWL5m`KObt!CatQuB->LNUnariE5FPbn1Wakf`_j`SZ}FzXI=I;unMKv zc4%(wU=y6tmIp4~f`5+{S51UB^Y$&0hLBGvor`FQi221&B)*TBOs<&nlUVlCQRQ_v zd^J9MQac~piumaMJ(rE>`#QEP*mv94T{^_`TF{|%&4?a+cnIlhx_#IBfp*JDFSmIP z{de<3U^M1fvlaC2V%XS$G zT~W5Yg=*=vpJUVK)BgaGjEv0eW)r^u z0FTG&dfp#!`^~5ON0!jtj_ih*!rr}U^{{A77Cklb3m|DFNF|K(n2?e0`%TW1{;dukrf6j=0y2$6&PHHnuz2Wc2<=_{nRl|tp=T?tX#42U*aTsqg(mQxm2gbACE)L&aLe?hgy&7*XBN?`il1}9op>+rF8`A z3}&3l*L`E|m7t?ptpz$_BK0(iRzGX83;D=Q6b8eR{kHE=zGZZ5lcLtMgOn@0ExSK6Nwm&?0LakMoj%>{FL!0RO*}E zmGA?wJ)Y7y3ObH68uz+=x=`tywxq}e7&4wU`1PmnE3Qf*uVW=lYK&qgRU}#kJu#KU z=5hLlH9fB4QOFTh44vDJW@5OQ%x`s$_LY>Ete}nxB7aQ$?vDX2+Wt1xH=LhM5WbFKqoq>Pks4d-w1+pCh#{{Sg}CA7WW^p}U8GU&d? z8tJmOj*FbEs+jR7HXRHEOv>PPRH|kQN_YIWjj8zW*!C+}cjs96E8-4_$$cMnrUe>X zRN#A;+_p&_q>z@B#L1+-CSKL{3Lh@b+7*N_y_a=@pHYlaehhE`igd^ zTO|p~$6_){x09&qyvRgo*{Ftn-8eL~A+vp|XRP82;$l8~)K*n%Urtw1b6jDioGfy< z>|As^yBJYwuQKuXGq1h<#qo=`J)ZHy>jBwb)M7NRX8V~qdHT4r~FJ`)ZRZhi4 zxAiQuxj>SOkdLT%1^|ziYay%LGKG%+#E42OK`epbn-rm`1JX|a|D%iJP z7m;z#H=ScR2NNbHCT4olM|1p1&uN_w?;(2~Z&i6C;-()U+SfG^U>%IrS_1l$66|KD z!|wrAfel+BwZu~~u|#r{nU~YGt4qB6tyMI=4-I=-l%6LX9V1^emC9AaUzTJoV5;9> zCfv5UJLEoPDmfw{Siy zlG|pyaa)e6*Jx%b0v^IF+T+{+7J5rYYUCi00OpO~GxVUWt@$ZOkfQl@xUkc%#idK$TP zlHd^$_U25U1TCLqS<7}F(E%efCL<+M=(NC{*p79%x{{YwsrkW~O$l0$9{nf8C;B z;w4Vw3V?#1B;ws>dDSlIsj5t&Dg1ZY3;; zF*WT;%a?4?PZ&TCZ+od#GpgKRhr)tJHib{5fO)FQuh4&nei zPx|O=g2N>1K7nGWsHG^2mftF`O`H$h;FuCF1jY|Pn359Ppevv9i=0=$0ESf1TLusQSD&#R6jL+|u z{{X%Ex^crtBPgqnoQ>fzw_P@|wSj^hKtV50+i+!Yh*5+KCSc+wCMG&e>NeL^xa>YR zF?TIx)ki9%6C&NXiHTpaY2vs5fFdyxfgm6qw+ZMEnB*C|?$c1{wyl*W_wf{kSt(BO z5}M=dnS4(;iDZ_;5%ILd^n4sx$7BaNNA0letz=kFwsgzh4WOb(z%$3-+3oFU3F|*u6FT?)0f(+) zo%iXjX5}xp6>`W|t1)Rr;zeY*auN&LS?w8N9Em`aRm^1liJ6V|nI^TJLrgAT#8*zA z$yFseizPyZ3~MGn=hrMN4SDS4$Fq4{iEXzj+yzS(U(jb)pzVT3mgOoUaRSWRt|B5; z#KnXJGaJC1PbrevLYai6s8z)84B7H1y*LlVJ(+GBpM z!NVP~$Xr!h`7G3ue&DCtm$fj;^8&S3A^ww?WRMrZ@-5Vdo{R!=cgCyPzG6^2Nb z*_jw=3<}~PpwfW>;L4*Cz7R7z@|frYa+!-L`&#eC*s_X9S}UbiAm*Hr$EMi2%RXiy zU?*C4iHYCzdqV7*LACAG$uk|D$i=$~vI@luZQF4!8^NFbkoi}$@!RkLC=rO`Jszug z>QozwT9J~$z8z)@AuU`XrqXBqko~-Xi4lG=ylwmFU%a(zFHR`rkwwc&>9VoF-)^3R zddkN&Dn$PPwPz6p5w_-k@?8NYYH}3HaQ4w@R%>NM8aMs*(^X~dg^Xj;Ff4O2*v2 zIIA>qE;e6%u}MQ}3?;s`kNBVDD;bda_?X^jueB#TfJ9a!p^T(!`)RfJPWIa)XgrKm z*d@=YGw_p`h}&_9nVx`GZMAW?u29qk+{!r>5RAZJzT}%626?oKXJ$;y?lC)jZ~K|+ zon6?BY7ZQoeww4*+L&rAeMHVNv`Kb0ah$z{Wo|iRB>j`IK>l&C#P2iCfaNELFv(+auW2&O)%P z5W*OW;-&<}L)nH>Nr5AYWKYLHw#zEn#9RJ2G1+=ohP?oJFcnz>qcgm!s6RlIPdOlT zOiZ+AZTbeArS!4ZF^-Kxt1Z$jp$)(%#ygMY3|}wDoGpxrf!pNx#BUt{(N(bvJe*mv zhYWhJy{*MWwMxpS7_s+r<@lU%4nK^j*Bfo{T~!XuWW6`gjYmwtBO<4&@U4`1S5Xjs zz^qgQJMte^+X;+s@zj|nQNiW0v0ApM$K)8FWoA`Xkc2GP#eSOu644zJ8cz-#hVvvW$`t}#p4L8%G@rdMzF47h7jO@KZuSXLpw}N#QgOPebsjz<_Lwy zB5E0(B?_)EQLqfKR!}TT*s~KIq9^sV@7B8BInswVm*?78L4bmsb?3073yVThe4Z ze%f$dzv2(-qCH}m$~@I>ivnHp0JJ0Swc?+*=u&M>K)bpDF?AP?LrLZ{mNR+W9Y_-V7iRh(?$;koO2>&Bk@qC)|fp9^#Ssg z-I%wgYw5b$rpT3gmr}&pCYX`dQkMjuS+;D4=3EyMGXoM+GYO>X+LhhZtSY_vhVA%K z$Foa^_av^Yt*w-$6^t~o_x%rTy|(aw#opNH+(wMX_8+x9#;5jZZJf4W0vSuW_7nii z;f5q&4d)^w1;7Dev`1b@{zylQ+EWji-ATF?+S@BY z&mjY*UvA;E$C9SW#1w5kb?zJLpXR2O&{j0okj?iSAEWWfVi8*roVzvXE>1Y0UbFlZ zKZrr3f(9aD1|m0|?D!ktmtZuPd9)@6&fPnvyod8+xE-^~>y103?&;-ZG*+C!dr%f> z)^p*4%$p+Gy_TM1$!!6T@cg)Fy&tJix^?TzgEu;byQQ)BI{U*PCqAyfPK*9G_DkwC zU8wSt#T{deQQ*6*I^loFX(!;2nyNA`AK^=7MC4|u0E|_QheWh*{wWW z@LOFTpVQe)aZak#HL?R=DXQvwWSfe^*&T+GVoq4oiH1M!2qWSrebL4*!>-BplHZL! zQ})z6X7T?3R|{8<&|3b*Jf@hbYw{ybBKVzzSCN4CDx7eDA(8-zXI>&Z>6Yz}YijrV zG1y#=U%36B)2hqmv_4Nbgru_rTxKh=paTTOi8P>jf3!hu9~0Npw>FYxM=Ntnv4Hrm z2D{bd-;g>>#6KVVbD7t@>xdQ}4eC1U(DjDEkzLGh@l`M`A{B|r7x~O?$cgs3^ga4g zm(x$Xz1z=YwMIX=xAGc3h7&WYZ71z(WuNz=*FK{6_Z?_8nxYOTazRe}PTg$l>5t=2 zYCBi-{{Zoi51_IX^_CAYrEz+*P--!7+HSGR+(O*hbNLZC1)B#GnUVC2Ohk`a->C9> zSGJmOEvz-|yjCwrV{0<)`|nH|Xs9+JGl-6H^T}WVytKa!z9W1a7?a*#9(zl#Eo#kG z-%jDLIj6DsOqz3+uB{(qgT%JApL|1z1PTeSLp@~#Qb7eXI}Y9^{+eDA_kX?lEeC<| z`$puomu+!6hZ%ab@e^qYueNFq#sr*9i z*KIqa$^2MAy&L78i=(0ZXz@q79yNETDLC@(CvkQ5pQ(w?U;?2OhANbUi0!=Pg|P{G`0+3G z9BvP%_tpzL+gyf&?eBW@-;cej@l&^&XHaQGSg)l;RWpNE4BK~WKPbW|Je`|Mq}vNu z^)_CqE=MOlc~z_`Pv(2z^~&kehrq*4ng_+b%w$OlGV$`s)_aVePK#wZOjpvk}ep*twrsZ$F6yj?gjj6CG>w zw;p8c?Lnw>m9>_e$M+XZaeOj!zQUk>@sQ#>Cm3{#hIE{`!({DDmLWKHqs~+P>o-X*9RgOUM0J z-{aC%arjL?+-yEp-F;b#!K%v~IQ*KL-LqKUOmvVz`!<;p+yo*oKR5hK?aqHr_M^J~ zG3NW*<#v?r0nSf1t@MtNt%}isL=aUIfqDgua&t*=dy6LWKv!H=n3fjeI@rhFxu|nk z?H{MGx2)#w*o3B;l##`OB7r4;s_Tf6J$yzlmp$6@u(r>En_PR-fx zJ;1vIiq;9QNsu_WLkcUrz1$=3q)C7z&s@aB^~lM8{W|-}t~_1t?u+sV${cTC`}N~f zGI#r3ceu*dwL?}@vqGB=7nsBQ7*{L=goJxxWYC4W7ZAWR$$vk7qh0m-sOEIvhCT!7 zJyoZ>7pRu1uE^vm9VchY@tA#rAI7}}Zla3Cx7-jiHkcTQ)1Q(Z-_~8;)VOaQ^gfL2 z7B96rPdMD}oYB3m$5{*>CjFK2esbmOYKwV1q<}?VylF~+6#}@4_DOc%fgWa3`fhm> zpYELZBejM6QkJjKm1yJNUq5z{$yT{uEReM?s7*Rltk|Z)_C%1HI>Qh zSI92>d0*mRg}vPGUXn(a)%lGV+lL*T4x_5YTCJF^PyjM@=1ykC6ZN^Uoug>@h}t^x zTlDwsA9*#`a5WFqOUV4^k<`2Ws4_ugKxa!P+*KE0NC+?4wxO7`#YX5=JbK7N1!pB3 zN+Yex`LFem@H4&LlEmNbH(@mnt?%xm$=9ov$7;t2v`6_NBE3HM$r+~Yg*AN zTvKtP_R02S=7*`PR;MMDjYf6@x;@tH{;bI5G`f?l5u0pIrp8=*UuRKSo+TD6Gx9Y$ zBtQFyc^DB~PxbZNo@4gk!k;4hMXfD)58B;*rMtx#_T63lEy4a;g#jS3X3aa^ft#M8 z5-F)>3QT!N&nTGh?)iA_p!{eGdY?mOt!q5R!}e9utJ+R^e~p^Q6YSs-8%O2G;G!e< z){8u#^6w$r?5BK3vf67?c{k;*vBl%C_3*lX-fYr2Hr`cQD7Rd9l1rfOgsdib%yO9g z_nHq(UFtS>io&~cURz(>y=(T`Rpqn2wp)M6tPbe-gGa{AecImsc2m7Nhd-e;em1^u zw_VvCBXdmu062#!jf!?Hy?<-`kVR4>s{sQb2ru^=Y>%@409hY3J6G79bJ)!1b-Mwt z`?Y&0HT17?4+^|>igl!AOgj|Tp|6m=5IaLkAZAW?-*1dc^WVx}D7)*1@%vQy6XO?i zd?N7`L6F4uhe2d9&bKEji~N!9lW0_UxjY&c29lncRya_ z^BS92Yx2nVmi4-M432kF$Tr4W+C5;K7D-XYWJN&&xtZWG8*RTJIqbz}m{;bl#s# zd%fDe-uBNh>8g3XYhaGPotaOvMhz#h^PUkK$m~*6J8!>R(Co*9IbWv!s_o_ruo_W5 zPyIrBtBtplcX{rs)uOvcq3f^;{hFCZ!Ga~JIDlsvYYov8JYoc}Wb+5A^bWt#nzJ{c z^*3#G1`l0g?2+emKA^2 zx!Oxjc(LI&h0)QIF3{s`q_N%3)Ya@L7f&$gN_NMrEFGA}NW!eRNSsdMAUgN&zj5z< zT6=e=^Bsch2CB|^W7>^*V@c=q?Y!lUbFDRYloY{M%MNB%h0({wmtHWg$UalZgr*KU z)IPadbmqFqcH6wE)IGfJ=A5*;k^H3#Sd7M>f2)@51_+si#LPoribh*I7Sj<2&v1Kq z?zRITmen5nCTe))H={Q2_dU3c3xe>dAkH57FIp6$-9lmao>M8Po&iz|;>?J>42wn}&27$RTe z)-GyYL#uUuTNiJ-Izj0~i9jxjOwzgyw@pm%4!-a36P{+V;&N0Faa&2sZq@qA=KF!c!e~}X64rT;**gw+0>HVX;c=3z6eol95 z#a&h951blDKYVnjZ1Yr-8GRig3RNnIMb0%=%P`NoW=?m3Qv-o>QO8}k=8t;2r}U}u zFSi}?ua4~(ZoIcwTg$_ZfBsLlg+5fleg zY3}!AqO#-b+5O3V6H#`xJ|pgVMfxT8ht5qw=hu%tv++Y)cc)W!>dvOeSl75~IXkb@ zzx4O8qTT$3X0+4yDM-ht<6@SE@ep4nwy&%wlDf0Ber|bx*^e9htCG$Ll~+b;h2o85*T1R)N=KfGyT}>AlOul$b2z-7!vtJ&ih8w^ByjJG5(y^bgnn*8|Bw| zvVKrphznY8v{o-xZkJP6Ji&#JNmwMrq`x9$4F3S2_}+6L3)HkfsPD%IooXe3B+$Ezw|g52csnP1?*W$Yi}|)r?1Mm9>1;$n2oy|lk|`-J zoL02FMXVM*)+dR$^eu89a6` z8=ES=h^brdjZz-TC>_m0hzKH*fc4CYNf!SAKNfXUdvfsm5Uwprrd*ifv1%+08?|YK zTNT}$g~gj}+B%`@3f|R{=12O0zd=>1S8*^8&@N1JDJQ-xD^}kt!YPce%)3U z;aEn>*^DUSsDXC!G7&$nJ62w`+r37zvl>q)yesbPI%Mh(s74(4G|HGH69dE}@faBY z09`h(S?bAHN*AcDSvNMS-IK?>M>Hl2V=TJc5LxN$nZHSb!uDh3E*ebN3?GrT|?U3X3DINOD&^Xxlb z);VfhzU0S*O|D2Jz%n8YP%{&>0e)YU#8p`|Cr(~V5r?pxVkN!sQiq-B=UP9iUPF9?P=qL&~{rk6pT2hky6#)Xm zCd5RX#`F5=wm#MAsgK8|uCl9c)8igBe$uPmQN)H31;DEyNdkabZ?ut5XF zs}oIO?=VZZA!H?s0fB-j8Dz+U_LUTKmlWI@@%i^;j^j>cpcaVjGQy9YyOo#fu-OD| zX4w*0x>!bkrA7~g%PU^oYgyPCt!U24ivuH?RLHs~_C z+Oi++g{4y~O5N>LiGF1p@3_eI_O055S=BW@r6y%2xALI3EhG|$ek?k^*oL}5$L1RZ zz8jSy<;TYe4^%S4C|3f%aoe)Sf!PSK2+00t%>+t&!hFkhJJZ` zToxbvj%4X%&aI728_(I-x}j+R%##rgBlRTa3IwCoClVheF)*UH!mV0uuVuo)a96BS z*UtqH6PT6Al)wyrfOdk??cuKEis!1)(4vGlaesd#)YAaP_rb!Q>$IrX+fj16lO zxVg|ji4x#O3P>aTW@bwl;}(}@GEc~R?pKz5v!m=UTyVhx>^iV#DP-%trqJhR_AUSGVcZj=!F@ht|t|#xBpV7xxaXpfs$4 z1fkP0JR~MyzG7x$ZMN&3eaGXn7i)hfRXAsjrZL3xze;}Qd64rMu-R-5!x0c)@z**7 zuEgr)Q;CQ+W?M4O6yk~5ganBCL5qNgFg`+e`3NDIkC>j5<{~Q4xjK&XZU?DqSq@*= zkjMkX+SiFD8}A6=FjEB~yli{?L&~_9KOL4&>Pl!~~hh8RDD zZ?^M0{PY!T56xw6{{SC{##zTo`9(_$QkOLf85RnV3c!PYDK0aUU?4oNX+X>U7nKuU3sn3V`bC zl+u})l32MgFwh<3cH7|LgZhZ;;>6CbHJFoo;i4w$HCiCr01HsVIF7?#_P`+xkKm?f zVvefI4mR`bShY_}tqRC4y6Y~zs+G}KXc=M4g`VJvo#IDff{Bpt ztwxZ!maK`BM#k(hfQYbMLM9?2I7}AN{{S0w4NOgW$P4V(t!P6Y%d9F7Y_sj+83L89 zp7o3u;7ZZYul*m*h!d!&!BwOsskN487 zgyHDrb7f+!}b4((wtE+AqGf~OF|=oDkeT-dGu4`r<`6geM5VDlhf6$WM?-45uDLl zqP1%oOe&n5Dv-cx{_D{sd{cyRkrE?#LS}IH2>qexa^B03!{#pHTex;rD z#pio_l)t6CW77hH2d_k9%@-sNc931?LrxONA`;+nynf^7dAI(X-%o7kl%3GT;c<8@ zMpISTtj$Al`M6!`S~7&SllSgJq5~mr!$IH+coM^alzho`-M&V6OgaMfoS$c|J6UKz zCQ9*^p0&FiX9dIf>#T{F0Z4I_JLF_Oe;zw_C(|>@PSSSAxE@OQ&)*EzsqA)+?=FlD z6&nTYGVXFdC!=$#S}wG{ zlRP`ahWaXat*YsEN6J4SJNJ~=jHIUB%LZ2K@z_sr6dIlUU`1Lihz?$#n1D6!@wZg> z>%+d#c2^bKZ#%nxuXXBt#nr=SX)j*iMoIcs*5HbN%v5NVyd2s9Ced!{_7CJA zjBTjgZ~p)r@2P$dR34M<;=FF|Uv3TV9A9veto?MHt_2IY`tSteV2qUT6NsJTedO|UQF+fpu|5`fk>c*P(Or?z*%xFq z)`zd2wVu6h)EP{7-hV$5Ai988Q+voUWU9S`kv?x-T1?+yDjEVk)7C1rnix^mZz(1W=|+N znyhHUu@tYI4AhbkAM7~buzB&AnJ&J^I%_WyPF|T`-Jd(elgv9E9gXvIPW?N3$KL+V zcn?F!M)Tudkg>60Pmqo6L=pZE{{SJF ziSnpTEHilFa{HN=^wz`UypOltZzFr*-JNZzbge6Nu4(Ai*;?5O*&0i(Ufb4w*hEHE z2vj5yvXYNLw^6NzRgI)Mdt+b`?(OkkS50~s5;;Q2HS8TCCT*B5d7{($c$x~op zTC(8pbN(cxLNaW*R`*q7|^oqF6_H>Jv&KCR~KK3J_|cpc;VacC-eC2F_-P@^F77J(^_LwV(k9_ z7m&tNGl7-cy|?s%1T;j>NvZ>gT#qihkLsC@>@S0!D0uDIzZ1K4g6)5EGl6b&MxM`h z)mpa?Qo2RukmQSiN%mShfO6A`Hb?_Y{{R{5Xx+B0*uN5V4Rfohmz&SUf4+*DE-1(y zs5l2$wj~qnkHAEBo;wcFAHKZteQP|A$@f1^c;Auk0(F%gIU3VYV&^7>#d@@+)mqS> z?>&SVP`!j^VkcqSsm_(r>)BeyH6@nFuBg^1-dyjc93*O6wjL{Z1Kpn0=ua9v)T^t$ zp5Aw|+m)w$fUlM;rUPH(EU>J~^#bMJ_O?CKE06INgf3vCX^yuu^n?0K_Qy%-{{T9* zXVfn_+79??Zr&K+akFwP9*5d4A*__oi7nJTscROg6V=sBYF<=`NrXUiU{8GB;8G#ZmGqF!rYpMJ=sZHS! zG@#`qk>fWP-Ok2$LqThP>gnKDW&0^#Cv}#y)_ESJ%Hd}q@uiML4)AZXBC-44B&_%dIqrlRkR(^BJY|jyXY{?H`Vh^&jx{=U`TQRMm}^`^@?EDT|Oy zE0k<YwXV|Z$ZXd|r?RWdaUmA5Ub9{@y(6f~7w_~*~ulsE;V^E-om46oOfC53s z1YWhiW>p~)90;Jg+Aq;Fy8cFYuPgNs%6V~@)Y>!8td66qfXC`QbksdNf}C7M3b@)c zF+XEg+pWtH^{J&n3!UWPj!2J@?E)i;UDo*J_}i7@qO#p9l?EyIXbHQ_sgA%dlpPmn;clCNRmaS@{iAy_0m2W`7PyNo4woc z{{X`R!)p%sSL{!B4_WGOBF8v+DmluS#kva{IRUCku-hY$Qs!Z+I5k_rIvKn}mTVbjiZ!txqYh0Y>y!Alz?uaSn5 zx7Z+h^<1wB^)Hgz7g^;s4kx-jf$y#-Qe^Gm?dCyMs%7b-_oki4Cal7jHYry~kZr#x zVNbzNUUvS!{oT@fzv`dcp7!|N+>YI7Zu$0e7lgpl)f9C)U2gVZEwdnW3W_X49)v3L z*5%Ab@nNAcv`lrl52vrz559hG*30%6%U`GOa5YX^l`55W7P9St{{SPV-(ki-ZSCge zvXcyf^DCJmQ1G4hK8{!h7=3Fz!N+(LA&zl~9c!8{YyQl2xJa2HcXLYm{ROI`ojk8^- zn3b}%fMrcM14x-Qw&rYQxiOJq`p>*S)7!L~m%EkzslQWwABXKGzRo7@pV6JN)EaS@ z^p|YYL2X7n^Xr3W+)G78W?;5d!-78<{ac?uPjwaSLPq9L{BT8&MP&tbu57VDBD6Wi3}G#C#yLmK%*^%L z{%-lz+@CwO_6ptX9wW5ETbVG&KB#x0ZY>^p?$VLF5Mo3~z=kkc1{{Y|4Q|AYrj1dXRo9JGrOrCOdq3A?J z)gC)ZM)Dw2BQqOJ{=fcxW)F;BZg*qFVbyvjt|LSFLD@X+ogFOgA>2m)04q&+h-~{Q z)=9mJsF5a{j-WuT)5DO=j7(zI4?*Ph0p#uIy-TLGbu3%zCnlO!9kb%l%Q4gY4(rQ>&D2OBvFX|BzAIQkQ;Gjx(jkoI{_P^R6H#|A= zCqe4HSE4(|*iOUtYR7Mn72NqBevH?8a#LK_Ld6$XXpmD_0g6O+fZ%cyJcuI)bDg{F z7uDy*jXmC58pFKa$A2_ls$BkjKB@B)?S5$H`3f zr4JH(=k8aBQ{5~beH+`p^LArg)QnEJ(mC5xMl+-9a#l;pM9EfxO8`9}JR|a$`8n$` z^#1_WBfVYq)V-zgLj~Qr`eFEOV-Va#YA)8`X4`bH5D}(`$yyj-2{bHoa<={NzWekC zR^Ivtd52fY>)nQq;`Ue7XG&ys9-P(57hIvKEY+})Z5Gv624k&BIHFr-PO(5pEJ%Q& zbq(CF7W}*MC&*dtex%ctdnw$Eb&PJWW^*}!MWDvor*TfLdl8r&rpzCY6OHos=PMDX**4O`@Yja}Wuq( zkcdPVE&5Np-Zl8!^&#>1P59A6xZX&IivB%!954l}?p{`7Q}>S0<93XG4?k&~=4H2( z62ae`*HnB!M;1Y^Y;V_Jx7zbFj`Ckr_%Dgn9!y{~wS6xg*1fKqS5I81vTG;TjR76i zEwJ;N@-zN>@3igKlRSy?L%Kd+_ai0cCzX25wvp|MxPeOKN9~7s8rZ~4{{TfHpIONa zM7Bw=Tk-3%{L=8}UU-Mx4Lb2o2zGAWFYgLa@Qe414 zsJXb*@HmkH>khI%$S&SDxqZZ=Sh5?$X`M3__yXM|d~H}j{0hP${EeK8RQzWTWFSH-^d`Ay&L zE!#~8O9he)>u53Mr{9&2f`N=UiH^4d67r%t3DHnEd1 zmdCjmE9S@1AIQ%%{FCnQnBDrDtLNWKFRTX}sI-IFfP=^6QvPr&RB!zzjcx~HEqThQ@ zTDVD5?Ox=U96S8ycCpLS#o(^-MpIGX>+gj zmJf0}ORxI{r|`YO)ftT;-|oY=FC(VAkK63P<#fe}-BTzV110<$xRS{0FaV8b5>i5O z5n@hKxXrB9d$?rl0i|6VR8)*3ir4OWTK@p+aFLW0K*r=FG5Q$mexa=UO|QIC@xSX2 z;`fhq`+Y}UX0ZBuyd9RSQ8R?@t}f14u??);bc|MgwAke8_8PMx2L2`S)`0wi$Z6~^ zke%n!_}?9McZs-EXFlT>p)+qQ7WAkuiq^pPC1*KYPkxQMil(|YWg4n}hm>3w3 z!g{saG<|PeXH2hTl60-S#7actoJ@W}1;ipz{(Hp1#Bctim>m8y8Vnq3bh&5jwl7($ zR+p~18kzwDV+AntBRBGio%n+OHW=#Wh{v*qI@NlbwsAR?s2=_LzK)D1Waua(JrfJCQDm%=pix>u19|zW%j|~ zK>`O{rfad%B$yU_KmhJLOqTOhn|3DdTLiY`bEoYFDOH9N#{r7i*+CIRknq@l+(3@e z5w_qdXujT8DV(EUBbsAt)g;D5CKQ{8C{nj#)dWB%7H64m&Mf0I#v(eY?8~tQiTmo= za&nB;x}ZT)ZHz<|St5}#s|O5`kRD`YaWgRy5k^G?PGRb@+@_Pq+lqB9WYqPNSu+Mp zXXPX#CkYi0`~>@U+m!F|QCkOszk$b&GKZ$XjqH2WN_ny(2HB9#>Uw3H!1CYxcmDu= z08N^;^7N-THj#unz!ia{n_Tfu4ie9{s7zZGCC}q;#ztf2cbI{xR2a?M_2lw4EFqyY z?X@+?5^}}^SPPaBoRwn)hBpc8K_x+ir_K%?Q8&%CCCP|jfR8^`HTda?Ip{2 znfxPZOCN}={GDZE!x~mBv8`&>o+?ubg1KupDJAT=f-nh)g4_K}bOjahR0_>(P_FT2 zM(k7j2??~-t_)RaW<>sWQ!6EeaxYnNA=~15gzGEq>Lr&)H<2MAu~N->uJ^tmR-_`B ziyCN+-Y3FmDsiEJ`O5&r;e!sqVx!N44HkMo%w zhwq{f5Rq-1a3Th|HoNW>pTFY^1qy;#Ek{35`v|61b2A0M&p@inY$cE~;jy3i~+>BtokJa43Tx$z=n=LN?wfds?Du zYbeX!vl^kGwGF$`_W@;z4pHcfKJbQuec-u*{D*iy_@02cav0qVGgBjw?beyqcW!Pw8Td`sk9ijq4HjTRHKv=ad&9cT*RjRL`yFq2uXyUEWe+Y?-YyLrFC|EJD6EHCnQgai$ zZP6J>ER`41y^G0v24%M7@5+~nf|4(YKU};976ZQfavAB<+UqK-OmH?aY*8+?y0!>Q z_@VX-9B-}*YFcnd7CuYhTpL74?>4>Aq&T`XZ0B*A`(z?)wsw_fEfj#V7H?usSkr;1Xc+H4sBr(#8oH(i7A<{DG$T8ja<%ZlwG=&O)#?4 zHSrntjFQ-rQkIp0j3^*RcMYTCqcV%RQH*70w&vkjTa;>?B%RENWMP{~&+Lt;fn;)# z-}9L01r{yf={CNoQ=WQ#b!Al_S#R}17|4&h18DldT`MEmbG(d?&f7#4l&aU@?qlrP z%W51|_;YPU33J@(~4P-YqE9+BdKxO2ANQ6!zJtra!pD>CYs6FmKZYGgJDU4%zmS7 z!0OEIl}@LtZ!edZ;`JF@DvU}BVKvmLh5Hg>N^2mIDw31k5-<@FxEEMi+}_G%@Y&op zv+c&A$!R@zfOJ{K+0$8t6|6$Vhr(;xTSV4!J3E&ACR-yBxX)V`p-^pMvLjPb)XRV^ z*00-(r3{77Ax8zFa}4z-j7r(O%#h6g0IrKIB8kD*TvZXLD5z{jFq;QE+EXphGYcdJ_^eJ06G0n z`0qP6?yrnpqVi8dVf9`j_MO!D3-ti;daF*}uE@Tx%Zfmq1@{6|Cj^#kaTCAlW3NB` z*X(61qOz3TR>oBofWfis0W*AXh4NfR)3nLSpX{PwW@n6b(Y=oEXOi9mYjewXBT>#{ zw@t}&&1o!>8tfiju@Z1cUT69wq)mR+#C!n!{B?xXc?Q9IjoRM!c1>9wCxhIjO&O5G>P&!Z%!2dSn~zg+GMiFGk^qQj z$(Q6~u*`2W{>DGoTT|>uoBlfak%#_29Jh9#ypE=GkgoPTXQFj^X&>V;^HKp4Yb>mBUHBWr(tI2(iEIR9|8wmQltxT>k*XM0|1EYFid| zq@S^^Otpq=#QT-wZ_=B?j~+bU@-wp4{D$&-x=BOy9+fCkak^TAP`6X6l{82Z0FzOh z6#_&|nEwFAI_iHL{{ZwUA{8!L_PQR-MZoAYPOGn*V=sx6WFd56>ghF^F@ZvU~ ztO;x8wa9vbK^yw^i`TF{w*LU*&EU6j^uK>FUDWb_&W`hAUaX#y#$@!n=Dr&uke&?t zNvBr3Eeyn;z2<(hg^+ARzh5oB>H4#+C3go_PEQ!&f7N?q%VplvP_l)e!)xm{EA=(b#Jh6N$y(zWOXL3x)>CsV#Yq($=x;bL2OZHfA#o4c;%}6vedng$Z8)iyN8E7KWy~&12bz0 zO9zTjkE0`c!iXVLCp(e9mdfC@M18|~VDFGP-E;Kf*PbNy>q_^_wz`M8di3%XdxxC7 zR?A2;JxBPot|;YlaM@LY+?>dQ6^y%xz{G9V$$RtUho3!`)19xpdOfZVo|t z-2VV%Eec<%>;i--BPnT5T;lPfTqWL+*oGr{nA#&@{%LA&r~Zua>lxh-F*{q?Uh?QW zdSI|RcShrF#$O9@a@j9V8B-FZykpfYyr35R3`y*@#Cqx0qjmLL&N7PhM=3^hp4PBp zw|n#5#maW0w7ye!-$&}v?X^l`8j6o^sMXZDeP>}7+O$>2SEk70Rnrh`E#eP(XTx22_IZcPSYJl z=Z}|t)$?myBe~t^v5~Q+ai#&IG+sIzZyBe9gu|a*V6!`y-z4aZ6A;*d7~UX9Z$#kQ zNgPwdM`PLW{-4yt%I@)bD~jx1it)$6y*FmD-Nb3Sg_pIHvsZ&Fv`~VT*UVW{)BS3Q z5KPxE^I^>TckQ=%>1$0RjlJ8Pu0J#w%E3|kOH!1W=_=LcA|oSc;#ixKCp)Wo8G;St z_tusEn%-mfN5bCSYEH-Z`qz8>FYX?o)|o9)qSdanCPN>jvz66eve8XfTrv!@!4WxT z!!gKqoyTssF{trz-5%d#^j?4ts`8zr+Eq%$+wc*f1%l^&Td&)I(y9DtiFis#=bt&`I+?o?5~#kj;1>u zl*Z;r5Sc|QK`m0Oih^R`wHF_6xKg9#`(RsqL4M`fs>2 zb2{-Fr%YO={I(XY_e+BnX8f64zfm!~Cd-ykyC-Z!q6cW#6^lKR)5+9_+xtD0!|P$B z`z*udwG*xCNLUGx&mf4bla;K7Mj{y-!T$i|9e$dm-o)qlkCE1=7{8;jbm@I%jnx|I zNzk39(cSd#9!oB)ap%{HuFSSuGiJh-xTb7KS#cZ0*zJpXou+0(uU9?@cC+dc^wGq3 zvtQ@@Tg3Stqjd>m3qRZb-)lT`GMG%l$WCsuq^Lw4D{_RA1v^5-xBQ}dQQXZ9^wRBT zjNeR7;`uk&>G4ln1w2ly?T>YPQ;KD({j{(%R?63y%X68!wi}78i%VjpjNoIONp-Vs z^7%UN4SaCz&wc!l?sF$EI-!}0Z0%JHbwzjPELAh8R+hk$Lj7e}p3vB$0AxyIXpN3X zUH59vAH=;|to;4%r;}az?f(Fd`p%V@)%}O=7929J)VUd|0Ge3PGcl^T85PU`$nhB& zou}i;*OcB%>OUxZ#c#U0pGxQs*y!4{=NG0l=9tAQm0Tti2a;+wQn7~G-OPzS{sVyg zKty#1l|EH>m(C9L=6l`VYx4Wmt+O46rKjth*3%WGto2i%OrKel%M6)d$Jxk=d2J)s zHCD-_{>7fElEj>_MiF3#)>ed|Rxl)>-`yc45fd{7{(xByh|GyYOhx5rmzneC>w*Urjf^jB}0oXw)GaJOo%>QE(wqGY>rfCD)Z zfr8v;)?XjKj>7i8SnAy=8r^p^)m<}>QyS^Dm<2`^>*cx}qfnbn;KZOJCMIS+f8!%{ zK4(T%(RA?`jUSBE9y;D;IgGoctTMKCwsKG__u2_DlCdWN0TTqCA;uyI&u}kX27=PK zOddZMOGfCr)t6lti!*k88N5Y^^cF)SYbh=U0|o_PHPIfnti*nID2!XyUFg*MpCNA< zs5KTm^qIJFb-#$ITqh#H5`? zmrEWa>vWl#Qn?WriGlR*w-(RF#q#wUS1)Akgc?5A*X(3Z zBPf`jBM}1;96AHLJYn)9yZ$5V9@zf?`ah_39v`xLdd1the$_hbs%gDYqFk;~cBr^P z#C)1WMg%9sB6s7~{X0$OH;W!)X-XZ!(Kfq7;m)A#jui^*-)MWAk)uaPVsm9^rTVJA zCmuYq7DL;@k{J?0^*F#nTP%+`T8Ba0(>YAe8ir>Zn8gBO%v7sd!cK%pkJ~ozY$mlF zLxHVo*qD{b?-LU< zJpt=Sy`C74b8$J{J@ppv{&VV8tF$Rq);beFX}oqnM{25gD@2r7%;hUVEZ9nH+SxE( zp;8n0^D>UKVdX#57hZNOyQSpUh}yRy=XZ~EG7iE}%;A7+UC=KA-PJEu36rzv_6I8q z+judF5s}-h9{gJImqB?GuKVHNO#sJgom-=OM}E1ZSLUrg8Fjjo zGAlZWtdjePDzI?VfLzG@k3e}$##y(E&S5cHHz{{fciz*A%;zcEl-Sd=5;AjIz!1Kt z9$dfCZzc2kh|KR8{5=@TxP3mL@pOt zK}wHoDgd0;mpPr|tUm3|sq()WOTw`E*S#K+{*AjMv$?(w(fkY+@qC z7~U0z1i`{RQOfo=Z(GG!ms|Q@#hh#ry%?`oM1cDwPfwFlVaGz+J+{`02vgI zvLFYJ5L^0O{{Zp*)V=$}X-V$qmtC&zwY^G=Gy4f{$EAgLm@;uY-KNHhJ_T}Wx$7|v zgtm^mcd(u_V}70mqJE@)S@vSiu<~J{)u6C~>WtZ_;wz35^^1hEq{jGp71Lw>+ z9>ygxBi1W+`?Q_Z`rQ3MyOpnpxY{GPb#l~aRON1piS{&>3Y4auA)x`mcAdnP5>q>a zIZr5=->AF2B9&RXu1#mY4|S#edNJDudPML33$y)|?VoNti{vJl$9T)(k8AQ+eM5lJ zbfp#UYRu&$hGOa}m2)JjqFilkrX~%qpJ9v$f%WCLzrEq}C+lP6@#TAE*({yN!{eDt zPhjg*gdkW}3nBQgo8$@jr*K>VHJYnwU6UIKk`B{te<52nY;+CJi zV?}A)j-tnwFC(I@d)$d^1ByxKHfhabVF$m~06e8)y@~QuxP9UAQ|LkBhP?0+)$Bei zxY?UlJJZ~aFIvpyv5k_IoW+Eny1a~s+iwyx3rNI3#@$2THKtIEEaIN$-d&S^S=QPz zx~!DsX7qR)-JKufj*INidp?gHyVhDi4B)oyVcMSTEW3&p&0=;hguc8L*H0gs&1`|h z2<<P-Un8k_unt<&WjSD#kV4X!_K zTkit}44J?$rPq_bb!i_jyE&lzJ?>|Cb@nGy>nu&JS)~<~Jf#e-ENz5Zv3S@=_IoKz zB7Y%qK}gTQ#{QOmvc5rg6T&|4rBZq&Il` zy`tiV(L^=}c!`LgnEgMfZe83cTqw09`(-rOs_lYPRMBbMtf!ZQM>=~sjm%ocuNzHy zRo=&jO0+?|YuFZ3Nyo+vfEyp&{nBK_M#aJYTJYOKRW$jR^ zuoHv?7ZWq=mGYS~jrNF$$9+F{DUxmX0O%H^}ZvwzD#JY>2_yP-9TPW8r}tUzml&56X~Z3n3u4*GkvBu zB^LY4Pgl1nq>^3==5rLt?$@U4Id|mfe+CuO%0^KOuj~}?CW9)iMIOC^0178~BW~Zh z-K`YS&ZeS1%7mD+WYvLXh1WzXedbdt_Cb#n3_2%&jvx4R9x>NOYvn6t0?m6C%vRIL ztzhJvSGd232?M1t&DcNW&xx6lo{ME$bnnc+3~j~w)b2R~TUfg5i3pNVjLY0+D`O5% zb{jbqNkq)x)Q3)ED(Wi~kt$W|Mj;_mx+Gg;b|yE5@QH=Y!+@4iGFu+|!EMy0yK`Xi z*_&A>Vyf6{fQRl7nQ2TJ1R^WIt#c3}L^Jtun4i~Q8k`)CKE6Jct5_epmm+ex6unGR zECqjbp5{>IelFT)lu5@)@f7P-qLtOTcA=uE)T+W^y_N-SXEJG~MaBL_6Uerhh>n0~ zVL054yS0jf=O=MxoM5LCRwe}{AB{p7l@Kl(w!pk*CSdlDj*;bZ40^0iTK0X`f+r!2 zviS!Ig4nnw6hJS5yz7y{aFA4_2xpW|*JbQNLM(9pCY~XI7Hwr6hi{{GaW%q$Wd^<@ z4;ftl0GF_L-+qa`TFokhXDLMK;T&sC2tGHxrc6rbl>Y$yHu^pxOo=7_Q@+KwKwD3v zcq&$5zdKynOsmziSR61g1p@ZP@5h`F&;I~y#`3~+?>o;`i*aTS$BIFQ50@Cj?ElZPNL6zlbZ>wmRnxtoGiJg!4 z^V1{4=j~1%rG&)|V=y|k#f1@3Cb>8`m@U)8efN#0efj}M+1z73!MKcCa@<_kSoAZC zp4%cawN|jL zTMB*(C#RHX(9P2nQonO5x0I#PiS)?DIB=n>fMBp}gqvVw}#ejFZF;s42UaxH$HU8Q? zEorP+-bAKLK*~l4B|Jt4*Z$^uyK)zD4$R9+&2}P;u#{Go+;y~s89*VD;FVWIOiVy= zmKM@dQw0$PqOmHIiu}>QV6v21Mn=2?APP+jU3IzxoTdN^dEzijWJevoI$wVDQ>S{J zikeR$r|eYSa>(@6u*I%8rI6~|M9WUJC>AhVn?Eg&pgQY0kJ9;Z!#@2jABVOS;YTm3 z=o?!w<`}7OtCHd-0tg3&>zIl7n2vSan0+;F&1P4}BQ21rRg+v96lOovAIBaW$M$a% zF*C+v=lw@I1FJFAYh&Ky#KtCt$FJ4tve{jlbfDN#3o&4UnD5Vo#K-3!@$pSrOs^!7 z$S)U-4@G7@HrCjLeY0oPe31?Q;$)&hkiTN!ra8n!L^j4_*H)@sq+-gb6UQA=)o1{v zNvs&*Xc+_T2###rcK-mvC;jvb2DUkv!^pQLwO6TWB{;Op8Ipyv6xXQaR$^ragWHV5 z221jvn1DWDzSA1IMUh^X(Pe#7yt=H{KX$^-2H#_h_h2z=fRO=`Sxjva`=MCr%-YCR zW3S>Ty~L18ARyso0#a+< zW(W^`_xA7mnVBq842D}L{Cl6B#Gve%jf-G1z=N1*tZJHxL>|5&?BpCEXa4{x=mwv4 zV;f@}7)!^FkF^0s++twC>e@L~8wpvg9xy8@11LBWT+hUhOJx^tVro;UL1Ng}u`Z`> zpr|WBIvT@cVUWUj$f>2kBw6hrnV6W0s@Qfps>?=Ftqn}20|5fsrUONcfSUfV$#O<5 z35Jj5xF7!jj{QrFE&l-N>e*`9#?w-2yPb>T~O!mEetqg&&d3NG5Qi=;Zc7$3(m1nd-iti5oJD8mCF_?|we{($ntd8n-3WD$B z9f^Jq6{($Cs*LhhT~2Gtpht@$QaUb{gs}$K@QRI=|f%%}iMf)Iix_2!`?#J3x#? zbC~}CbI~AgKV4}a%6UQC94@}o7qr%}(-|~N@H&$STiLGBkA=F(PxO}_6DT zwWk?wK(Axs37E|MOm1NM{{RaG?Z!pCdBn+l{<_|ujXzMH!g*Cfk8bte0*7aN?E1vI zcnrg(HL}i+f{J-U{82qJ3pPss0226_0iX39D*DoWK)m3y=Wl*{8{A&x_kYL!+i47= zaoP__>FmYa1zS{i*fK@-LZuqk3O*)HR0z*b5I zAV-`V7R581EM{K4y_;=6BQw=+sWhthH6vO$l8W==+@H`jUz5z|9HTEk`0aPE%ReQ& zaq=q{=AKJb_ix4I%}h>^)!P040CG93b4Bx(qT7y+SsK-q_T>(2NUY6*Gx%*9%<*Ty zUn)GqU0Lz}0JnMU{{Uz4t;pl>8m~}f+l|5F@yBhk{{Zdw4hgbS5(ZGQ*x=%Rck6FH zBl$Drf7Tzo7Cd~`+GDop+cY?z0s06Ttp6z^|q7xK2Yy9eKFq;tNy?4Czfk$ z;*V3C8-9u{GGYp--t;~KSvw4e+>B2cKCf8Ib6OzmM6!|0|9y`O$~xsQ)I!!WiBQ+ z72c5CLSi^2V7U#5&w1HXl#`6oe}C$E9Od-Ro9FAQZlzVc>e;%92^!H}%(IY$ZeEdzSU9Cm5omxkX}A0V~wYdo{; ze|r0&+56ZWQ}J{=g{!PD(cC;*C5KZTmV$|~n6553Qr%(>7Cy)rh>71^9p>-Ge_MCY zxVq1}x|heE;`bLZs4^7tI`$7 zFI0Q$>Q(ATWS<91WAuiIr-H@dGzPU4mR_`@FVIW;}UfL0F#~z_{lx{?S7h04_GHBpp}0mX8~PN%OQxrSs!!3townKsho+D z*(lkO6Xk-&snc4j<8j&A_=Cuh#082qRgbc%jiN#s06xL|W8!D^5g(|IvV+6!@9U2k zyphoz=umR zUD5JGT(ih7`D;wiclFjyCe&MFMRh`~85C2cN7hXW=q611B%^tq;y+W>?b?h-j@B`m zi+$y}o?XS+l;YER)xFtBk^RR=YlJpz6MaH4Zb}sZTz2I>0gu-GN`6KwgHxzXDw!s^ znX<~k69&2WG7e-RV1C%1GrUB6g!Fb6&{otq%>5+e+?C|icCAYmURY$0D9< z7gH@$9g9LN8C$n`5H}-fOfc6RnIH{_DEW!~d`B3bfXxkc++=B<<7Cy9*4a%?Kgqq7 za@uyuD*gl62E^B8Q(%rjW0%MjPXQ>}f7EnUZDX&yr;)LzuP;jyaiRQ+>FNADRGQ&C z`&bCCFl@5PS`C9GJ4h_2^%K&qNtnp$&0C+;nuKurXD(i*sL)UqO`rs&EioY_U^WqH z$rjTM5!>+Vv2@n9{{W%S0L)@24fl#1TXTUZ8RG#l_;dn* z&uRQFHlblg?uc28(`?eWYNeuh2fAw-M52AACoVQ``Fr-6nThMGbq1@->I%v&MvTpy zkxh=PR25;6p=>X4I3tiKk=kUZ=6BkET^Xx&7NFHxq-AwwgQsYbEUk`1mW*Z{kP!_~ zizL9efhqlR*#7|c)sITPJQr%Ro}5lNm^D!|TWMgfHIs*2_ z==|nrYgNNzk(6T=^wTPDQWro(Mq4hEF&X0%UIB13v>P^`%44qZO0(E3Y}T)hR*%h0 zhEC;&9a`mzwmZ$7imk2)?N@BJMT&DcL=15a`AqedTDbiio71_?F`dI26}`NDi!~t+ zL$;A9_><&Y#K?~E$CmLCzVh!6k;kqoWRZc=`hrnp^42hFN7y>)Zzn8sY!O9<#Hh*! z20}O7eEXp|R`*lBUU749Dn+tT6^4)Flwbr+DEL69O_@&8La6 zbW?WC%b7;u?b{w=U}zB%EzOhoku%w_42*0)hWl^4&uRB==8M0nE??7_{Y|HV4whus zmwT5q8pfCg#T;b05EKvx;l>7k-1XC!H2U9lc5#@fc>ze*$Z>Azj%)Tvn`UIT39wMX z*p&mg%x};PZsU_^{{Xigjm~|s@hV`1fMdjF2nMh_p0LPiy#tfKjLlq@87~t2vOlL9oBbV;aZhJ?O)wzJv^)KoGYVq@J!Z1{lYEikq!xCILwkRTJu;e&IWS@ET z=bkVW4QLq9?gw#nF1=0sw{zD@-O0pbG|Q2R=bN5} zM6E#*2UmSbbdHSe7j)=$>$V-1*PXuc{{UO#XEM!N?9cM~-E}oDGMcO|!-gePkk88A zIa>o}6xoU9J7I<$7>iac>blyEIjkEDNl&QrZF|gc`=UvcyeeXMVFMygIYdnHfQZ@` zk+{8WqU!jA*srTkcy+&u-TKF9`#H|ocLta6+07e@v3oDItg?KBMn8ghp2#b4KP<6ma@7);7$P(oqRSOVwG@<*H%>lm7r6q{@29 zKc}B%d>`{a1N8>co!-}Yy*uSjgkT;QQDdw)V?}BI0JK?ExsIeI2y6wfXd0p*OOVFV zGxO0O{A;^A*iR?)51DMcTw{nSrp9P&|W9Mnv zyx{lv09qaV1>@Si308;OxqWoFb-b82g*Zn!JGZl13x5sB^DML~%XI~_x->$O; zPol+>;p{2lAQC%FM_sqr-t2dWz<)M80qn1wRJ(2CJn5Y?sjxNk+7AO=VcZ-e%^7QPak(76oYPRHSFd9|6xFqQu_sZjCZ<95ohJn)u=UoOn_Ot08oW)@zfum~cke~` z%UfG%bmaBcgVbHRx}7!L?NDif{{XYo{{V2C*zApl^8;;TAvghJR9l&rmb_8_0OV2R zcVM;tgwlRXUDN&B@!J@L;xf%$`u6p9BA=~eUAAm0Al}gdQ8SrIn;_(i<|nJS>V=!` zN1i@R_B&Vj%jI`(eB{vj)y$!yJ5xCl|Us#zp@C$OF5YA5G-Z*&hUaR_wmB$$?nQW$C?+OI;$k87g$^RU(Kf zJ<07TncN6w1CeQ8x?SAWec{&n(fVqUrxUs`)}dDdbQ_tJTKB7QF)7{^;59g>(r^c1U_eaE>bF|-a2esD%+cVi|uaK7H zD&lHch&BKrYIN7KT%e4_akmKSJLD+Prz(`And5`AtvR%+b}`?zKTh7%c(0(eN0Yx% z&p8?4HlqZmJ*PCbmbo=`UJxW_)hA>|EF#P-rZ_Gp26;~Vkw;qy#`boHmEDcWWc)Yt z`w{h4?I4n^G<_J+$mrgz~eqoy^G6>}GpXJ4og?Qp*>%-a{oqWJ5#h2jE8%So2=Rs^PS*}ac zYvidd$Vk{TGaJV#%Ff638@hi~FQ_ki`{US56@J}zy3cSf>$}>=QBqs6T5B0LA)C2O zGFi63B3Z_EjszRTK=0OFd7s>m1ANQ#BMaK@$Lh}>d`r_>TODb7)4f@+j71%7d^o~W zQy7p6%z<&sBGHr-^5g#i@W+3nSXF-l5~#Mz%JH9ORBFOInu)7rA(b-inNymiZVmlhn7{{Xao$O8y`%3Q%44=9k75G6|>--_k{q9c@b zA-XMab5ihI_XdnuU8`Y0Eu6a4CnW?Eki85cK-Ym;?-4d4dCt+Ymm5c}IyT-i&}Ao4 zS*P}mvR`pv_=mDA5lnjm)K}zgl7cxIFVRH*0Od0z1MSchUBy+@ly5q}+0C@USW65@ zWWcQ-vcbS_#$C=iapSk)yp4DGYBs23veRJkRBc2y+-cUSb=MGLuu%~K!eq*0oDb}0 z=i}o*E`5r1Xpip?ig1ZL#YnuN6uy`?YBkNg=f&4^4{{Zi4j;o_b3c_pg7_4{l z7xD#NSt3M&?w-XgG6lrM@c|fuk=uBkzu!;kV;<_Z=L|Uex6q_lTp@~o;Br&$B*{s$ zX(Rstx#i9$@&5qAI{1t|6AXebrkt;m@wJAH=_{*ndl@T#u_i=6oSAOV>;^zgY!T1^ z1k|?~`;_is@02PlO+?wW>MRBbgsUSKfK*7Bm^nlN2H*wrKcv|DH3ir)w~x7$surzF zL+vhBR#E(6a&Yj87MVcC(tr5vAFiggh{DyJb~4^3{lZ;Eoy>I=v4egMp~XuTHGgao zuyG)W;U3tHx1O7n*~{dzc}!9)=e268%O6FQh(QH5tXEP}p=_DJgg1*zc^L)FeutnT z$;D;5+V3w9lCracSUqxoe{G~3k|wl&m;!^D7x_etO#E#hGI;8=n5?yIUE3JDga|9S z7Dyt48E!u{l<<#o;cyc>d?|q&?K^bm4MAvIZfQ4W@mNqW8a3&Q5Nxhq!gRbzezSlQ z2{fEckx3uSpGzPyKX0cQg{6q7!>2T^+^Oh}v=eR7lX@*ZEwBiY^|*xMTG(lGm5gwhf`-7z>^~-rv}1EuYgrtX7B11;unV^e zyKCVTDBh>YLggCfUvSoGN}NY948v-Xu%+Chc|b%)(J{9`L-vS70*0+= z#y|vP%{p?^0P8@+2HWw7+i4krjysIc`<}Veyk+Z@XjdE%WGuruGUbaEUedE`l);<~ z@g+yZ53IMCk(u9Oh>mmzS;{g^vy#kKPx7j=ixA1r)%&(q{$vbhXqaF*KJ3d*?z*J)1G#Z8Um&)**5Ap;IEw(wIT zt=Wu)``2t|v5U2_4Ty_%0INV$zp2JLpnx(y{QaabFeLq$&SewBgbc>>_R4FfY+Szl zYw8lt6@6DhV3~vBYxce;+NFC6PPxR$`+(Q6OwUabcHL|BKH6ODEnjEYsI8S-HPEpU zHdPlkETrN9b|@{}xhdXYraAx?-l>>|*|f>jw3?O?qQ!y+sW1RFi+Fdk7w9F=B}@zX zloWgyUoTBY(Onz4Csfmi6K(a(Vw_6VxX47*E^-qD5eSLqdu&^b4^*Qwi_>jIY@TNI zHq>J>MJO4H>X6_c*Cs~AvQLrn34w_?+Be>1o8;YQi|u1?P)&na0F*)KO(Tv zD3{L`PQ^Qn98dmT0G24Cjvp9{C=N9B;vtU-=kh@t0V!OT`zY*P_11IkPD`Iw1a{8XIBc?mh?w3dsm^HQ#*MoR)0Wp3iO++mxdkd%3*UPwkqDilHi_l< z@4w7+0Fv5Np)kgMwE#`F-E>N3y$FU0JdY1h+1-nAt78y|hX{_-$Ts+h-=G1Qs*mA~ zH!EW>^ehya=7sGXQ1Xd$0#X7FIEzXiCG#P?PsDA|HuTjy>9}<=nOcQzs@rjxl9*C` zV4`b%9HdGcBD0A90LB}(-5ZXm!LByJH#F^lvNV;CqE49}5Fo=YKt9Qxlyk_o+D~tp zo|}`V`zz3Xpu1C3jekNARpAH}@?!U3RcGsXQ98zoJa#YXX2sKl#wS3D2O1stK&R-kb z?;^3fi^z`B(*qUfYeSDw=|u0w0oDozZ`FYzm=^Lcf*tk{h}||o{C4vrJ+s#d* z`-`C83K+=af+$HqphY$~gAVhMQ{ zIfgoY{6-id3-y!^`^4;D@rhM*{{VRWc-L8e;P~;X^SB*m$Qw*$Rs@czqXazDW~7v@ z=NwF?XJU?XG5g=FVH+&I4?~@X@28gk089M0b+spAbjNNrew^18>SLc{H;!wWii(qB zQu_Y40kQ^c6zoGI1v5Xnp1U{cgPgD5ZySE3z7tUIMjy0ZPxo0L&S||%V#s6u`qKts zhy#d&0+x&8*Syab%>45C!LJg&sGX?pZTx>|{Di<)?H6{O=1@xSu>Syn%S#F;jTSka zYrkeMl1?BunA(3Sh|G@ocpauSy$RR)2KGxw>dbk=hAAMI37Pqa`q0Ug%*P-5n#4b^ z)J#mzmitfnntuy+4X9O>396Cj2B@^h{{S8T0IRlNS5IYcc*TIiQ%KD#8p9*0sKx|p z@|Zg?BG_|ChCllF$o?Zgxt_gKC&ygxXS`(bW9YxzO=CmIp6h2R(W~5@MRu&+si*XK zUuCE!ZDFdw&@wB~O`c|lB!Lqv?qMt%k-uSQ+#@(agL0=}1h!ScJre%Ii1b`vwFD&{oG ze~9CMQDmROy-S&AK2F7_fC|lywI6w~h{%Z?PUA8$zJokP z?ibP*$HU9_uelN3-yl2Fjnug;Rwqnd!30sYj4MzTavx$l*MI%Ef%}=eJ)YQ@{ZCdu zceTHaKTFQi_NU0dIQv_f^N;Eq-dc>+7`z6iZ{1@t$}>q5FEO6kV2qh?Y>7m#g5n|< z9Zli))qCmh=ihL9f8t-4Ur&C`_D8sy!Lf_N>ODABryr5awc83|)vG4mCKwoO!Xh4H zJI?bxd36q^QAtLVlp^1^-wVmD4GOHODR}igBzYC(){F7y$BVvcr(J6t-Xk}qsbhOr zpjSw7&2~o8(br7 z(HC`}kNM42s8LiqXN$IGyH>7Uum>doY6=r-cWMwz6bwt51*8u=dxPb^wDQxq#pVsF z`p>&Ktb#Pr=;5pPk*5$sED9L9h?Ya^8mv~a?NCeK4+b~(Jy`56<8w+is4PX173n%M z*(Z}4t#?l+m)3bs-FIINp>5Nw(ri|vs6#Cn(Ld~6c3nY}1-_|T{n0%AfX(M^y4{b` z%gQeWJZ{7Hd$gVM?PZ?J>n`Eav4<}1w%v@iXX7m{6d3CxY6$V@f?<(Lb_Ps|6z?3O z9~gd)8m|T04A*%4jH9H!pT0Iy^jOMMuY!vjhd*58V3gX#O*(+@V1TZDZd~qOk>>V>MH(JYMg?nN9pV(=iF|k#;??NU6)gse4VBx7zp zdy`nllY(APJYD1LTl;;kyr;|f>30FH{4ecYyjGsh_YwK@7MRo*;VNX}>D+raw`?ZL ziV}_5KQqsX4&57y&Qa8r^A|%Ij>aysmloG)AvIP_DdS>gjh4ZFi`TsJf(f7BS%KXT z6#MDh-7DCS6+EczpMEP~AFp%EWh*>E>vN$LQgp9`+ z+oL;}oi*Ja+xeUI3houH8RHj?I%`=EXZtDHy&sOP{O(I7Q7D?#3{|i&6;}0o7Hqeh zT;{SQqE;OYmc^#&>esCTBOJB?Ap&n^(z%jcak9cA2FoP(gvR0{A@S7p8AZ-pZv~5Y zZ9XNhxm}UMeNhL`)DmqOG35s{#%4C#ao?&nrj_pxj=HZwX&(M*JYI#(WVGHdR$y^& zyqDd=V(-B=t6f;w;jHm$nX)bJ$Re5iMpxBe%GbzNX;c-elo=x_aZIr-bK4Nf6XHKwLLGn0jildvJAOdd^`{Ru?>0KTn+T#EupDpQriSO?gwk*vd1 z?y-j$AX*X-sUSERiRCl?_UXuGtsXA3u2rJOopP4hpjG3QW8OfNz01`+Vs{<)i8B8H zpO6`48=K4`&3vv3lCZ0Fd1gihiaN3EV&v*ATbT@$5EO($%s_r8=XH4uUMi7AwM}%; zO3U40myOSwLPD~XEs(Fba~J>+BqSgra})WLbsSv2M}n`6b1Pi9(6L>05H=^%5yWb} zWU>K+h#8Xq0Ky_BI=T-Zhqe~(BK}T=fd-P;-cG3H2$&pKDOj*u4KN*wV?V2~Ut#x;W5pS%PTRym35psbvzZ}K#7C?8qvLs=t=(aPsiv9(i?%9Rs!Gb( z^uSV>-}>9?nFD76f|DJhVVh6PPWSG2ESyc-l<`>~}@i)Huyo3?`~X8&*dcx4Lh*pHKe)E;NsBe9Y}9bM$qN z<#?stuH56n`h!a58pn+|h5-$~XDV<{uBSKzQ^sV#xQ_RJlU^cr15M;HzEAfbzdg3| zlgr$oVQMnv{LtlHr9ny+S4uJ$LVcO^&1n9Xv1L{S)UaGkn=oU+j0TDNC3!`oJ16BY zZaWmr{md;qhCf`ZR9m#(++rGsebzk~=}DWdv5Vn05Xggu4)H&iEv{X zVf!E5?$!A1q`&DcL6NVC$ zrwfs9il0;N$m*PLYIS3+KSXQW8208dFKmPpn_BOxY~eC1IA`=k&jH~eat0$FQG2i5 zZ422u`jfH$080!`W4S&A1`6H_ROoK!WiRRqTJIpyWV29WYFh?IF3JV<#2r`C))jf@ z8wk%?E9J-3-^iaUJ73uj&1!v3qI+MZbiNB3TA9B4w=z1vHl-vY?W~(ph_6|YY9dDx zBPl5(C@2xup;*Kn^)oj~nj=@jk?FrrVW*RP3``ScdkM!WBaQz6P*Knu5dQ$z z+Z@-H-Hh(ozhPn-OC2Kr2|K#%2TrZ z%T(#RT93USO1kguhnTvlH8RJF(dny_c)eySi-Co)CL*8{_7g4=!PuhDB#VW?;H`?Q|6 z)7XsWpT3{5xr)oBcBooWPv$KNi35*_pP1Wu`HlDKehV3f(sb~;BT4C8ewx!5dR*#K zt5Ha)K_XKEq=@i^{<%bs(>wnF>!3e9533K;%g4{9$8kFWV+D-Q`B&cV>eI04!D0xo z@3on(Yk*>gxqGIgO@uHJ6B8*dbH~1pM zoKChpB|NGx-?-2>i>k!AlU5X(>k}x66J?E}B&4Su{9XF4`1$6)Yx}+957Z|>_ov5B z@Z85){#3MvS?a@Ubj{JT_BgVJjH%qEU;f-t=&%IE%ueMU0h!)1eO0>~*uNolwvE?) zvDTf}?bfZdtZt$5_dxd2Yhks{tHmt|$QD5~QpNqPSvtxaz%scH^~61swap*cF8KG~ z$t*9HzDVlrGfzZl>vxse9SPh0S8^IQ=J4*)P3EZz}pLg4!sn6}jA7s8%jF{(8)^16E+ zc2u*Fw_ccis$L@H8A8>#3j^nEqBhItXVi z=5)LDZ*VZ(x5{2B+M=Q?DGFVeSS6@K*ujZ(544AHnc^c6b?d*a57WcNyTRHY1iqKO zitl%9aCRpH8rNRtDjls&Dk)Q2MMk>~^&hBAUF;Y#BG@Bs%YArX5j&aKPV{)G^$_qo z!(5J$)Y{`tT1R{PGgneo$I_>Zwv<@sKx{(RoPu8he{L`!*pG-3f+^A7ulhZGAv}=R z+M8SW>Ge?3UMcCzSsN3P?WU=ziu=7cbXrkjkj0y6a4lpcAQGm)Z7>HR0wYV-=*iUm zs``DsKO%oh`BcAZXRl-RH;?{gcv;-9sBhD|witgK`_ZGm={?Wv)vRy7M(fnnP+hr% z%390HzPmnn5r<9*hzSw7UZ;DyG1u(?oyOEZP#i??Z zo$RrW(-mw7w#_IQ1cL0$LA7t%BxGiLCsB9f>BIEi@TVvA`|z8(nuouZ^;Pz(xEjX} zp|vz=+=M4Dlx3NTuG>XTYpj)TCb1IYQ3vyxn&-;zr=BZW=&vKSCy_dL%(O9bE77d{kkc%}Qf?vFO38dW5n zGSy<2P^@ zp39^{wInVUye$>S6x2%B13NA^+@>UrlEayvU12?~Dcv0fggani3_#dTX`p5|KHg7#53~jU0A-M6Ux;7|mY-V+PFW&A&FAsnW_OLQBW-N4TDLTAQWbj2@&$ZN zlM0Ab{xU&agWEhx3JiCj)NQ}ff7!04YSiSiRv|*=GSy#51L0g53P8^jiI;zYMDjIH z?~H7)EUO!NxOHN2@XG@v`ojZWM{h&m2-Oi1ZBYb|?}rvdZM^j$aZfy>;&Fu?dDK35$u?aw;1VV*4VKPZO7ERiyVh5N&6r{#Hoe?F)3=@Vh(0L4hScV7tGA{ zRZJEnY0}1)BRO;1U|Do2s6erU_W?5xU>r;t$cV&oA_$rJ{PySrs^gUGi|Jmj+rf^C zOvo)+IoVj=EFfi-`e19gSjBEXEg_i_nHU&~Dpku3%1W*(P31TPD?;tUIO7o{78mMR z2}HJk$A5uZqyGRA+L+9vA^d$?HLl%INxH)f6=5~bW=bR~H-kzQ0MVG8!U_d{mESCS(X!7;KU6AgnXFUxu3KLRlTLZ=l|u|mD;)Q%#ZaYf^r zmB^TKuxKDiiGlo8mhGpwRlIGeeime9#$ubcYi_}oKOvFJ(@=l-qb#7zv%sQ0u zc|2=ZsVQ-7i%KQF&M8dfQe|XfAy$cUgw2`U!Xt+JM%@4Y>EhyzT0g-bhD}VXO{mpAA1DF;B zOz@eKf|)7bXy-sD3KNtn_GqEjs->zHQU*l6#LGW5iZ_XZGi0(X48%YgM11nzoA}B! zYmvC_SGQ*I)W_9WHOFmNQ zHe;Y2(yfxSmyxS-?b5AgCexngHh`&QR0<}4?k!su zEFjECg<>3`ez~8S=qv2Bwv`oT^K^46uBEEOE^x*zk|J;mw94=%Mlk~`5#hW{{>pj* z(ye4OCN?oMgTIYA`wDohVr-D94q);jut|bZ@kvhWIE{{CBlo&2g}|+ru*`LbWiHk> zJ*#uT5mY_X#DYkKAxQv9Lgamfa(_E<*vk@(qH}7@{eV`Y#b!2iyCmADxa}!m$SB`4 zB?7-(@QtP?^4c9@*=6}f*9Pi~^y7O<_g6Nic$~~I<{$-Z7+}N((<3py{{WZ30UgRz za!Xc2F{Cqkg8h%bY0g)qa|=kB%%WN|6FhfOPVvSjM`DSasTS%AY}2^7!Q?@f`7Zj@GA-u>3Q7lwEH(g zTVaYQC`DL0fEFc^g{DJ{n$|-QdlU=>VQis$Bb>XO&p54DTuoL|6*2aP0v&CJCQKCw z408OxBAAJf$Dr$0pfQk)eOsmXjgp8!mQuA=k;H*lkX%PLuh;E{G9`YXDgDIs0d{QF zU7XGjCUcIY7dssG9Bm!-)-+W1J z>;9RY;si<}AfjXlNU1fbrtUj24rI%%@?+O47O-IDDHW8qBxE9gLLfVSx&gf*s(8#> zvKEt--+$K-5OoR&h$ z#EGk-y1~Y5E<|VBAAujUoH954&i!2%@@%C~5k|P#!dEodZ??^&tka)Uwg_ZQkgWI= zOz+BLai55eplsz!{_3_NxSFvf+-lJ#xLM6|g?+SGQzezvCPWhkAqGw2BRq(J!T#g+ zFA1u!?2HaaN$Tu2M!k8(RdvFus|zNm4A;2)gqXXB>LYm=h}-9|d}#CM%0C41*i9R# z>*o96*vfpYr%&V?Gn&)!G70C6y)!1jA79ORm|Vu+AC&c$`8YpK!L~Z5DrWGEnOUUE z%gVxH1`Gu@0%`0~8b2%W3uG?ew!d{{G@RRMT8L%b&^%VR z494Un&r=uanI3%RTaxZ)YkV7Z)1A`shtAz6sQZPXH6|ZBZd1=KO4U%Qk;d3jPbFGN z#1(eTkntt%6Y)R3T{H3XxjKWxN}bQ`M{~P*s63MKCs}FRI$tG-qmw4*^mZ1?**0fS zuERdXh7!PeDgY$qQ?&2DUTkdWJxSZGbEf;T+Kp+S?WVk}`xa?sXtYoJM95Mm!8bs` zOBhC&Fc^p*!arrS9~M5S`d;Qo726*xa2U?hYL=UEi`3P{hl9`L1|Vdti4nzX4uj-m z96*GEcHT;7XE@7@C-*g0?>sykSnf}a9y5Ja{AcWz1HC=g?jDEM-Jiw(0MXh<$SoPB zo2Yc|r@*dY5*d0yKFU{;Dp)$TgAxY8x(kEDtCPY%rnl2az`pz7d%3N=#npaxd1-+^ zztOr=NNA?D_=hsP7Q3T@pcfd+yKpr+(-M^wLHtNbO|z-{RhR9?wxQ%_iT&5g_G7%w zRd$wNOp|y-iF#8}cEh-xvF#4A?v2c@ zQzlyLQw`zBW!%>OEx3xqAabOV5U82pDN0l^0v1UuPn8;e)?InIF z5?JpXPp>(CKkC1zw{g6#?mwPBF?M6T57(K!L6XWk+O(SPV#bYwg~m0Eu?s}*w54Cv z$ZQJ0zr=&9%e5MJ%0H;rm)-~KkEniQS>?MIueAZH4~;M_({|r}d8U zi^?AreBAB!jP6E*)99&$Zn;)Ay+!I*+FPV%P(08%I^Lx)n5l`_mU~3cBGq=4`keV2 zqx@m+hl5?)$@aU*UfxLE(VBlN+!YPnrkP@GO)+(6u;v$?< zc{y8LMMk_idsoua?9=f5QRCEfg>3gJen#Uw=kqhLYVeo19v5k!DRpPm1Gze;`mgE@ zdzG}0x53QYNs!Yz!V9en6#gkxY!JzqFVAT6af|Lgi^%s^v>LToe23WST~mwH8Y>)( zJ8st0d8&4n;izgI##ZSWHtZX-f6hua+b;YT@GHJPb(O2#sJWx`uVC@HFW~h~yUXUP znsAB$1~GN%je%pV3ar(cHjJ)He|yC3>aW5-q<@OO1ZVqy+)lyhYaQe74oacX$aiB} zWk&6cE+tbWOU73sBvTV3Wd8t2!Eq)*5k$a^iE>3oSv*?nzVl}^COhgq-#+H{i&XcE z>Tlir<~K^Y^&fdWR%dB^n8A2u z+6_sl{F(9}O!n@Uf4liS79m4{(>V#KPqKvC-W3Q1MOkB+GLs|V0xc8Y(Fd2EtL@j- zJIGG+_hzSh{891W$Bh$WG!OFG`qJF*a4Z3X8*fa*cr6B~SOwD0pfUlp-1Pq~a7bE;(6sh_q{ z1b}e}mBQnZ0>q+sBMpe=N+rZ2iGndSO+8&fp;hAh3oA^@|PdCU;Nx-P#{2r&VI|J%`nm(Q8E2&eCNp zhIQj$Q+Bm+B7!ri5ClwI5@eWMN`86**2X@{L!Mgy0P>GIj2mTPFSxdBqksy)0!0!f zv~ih%jsrV&K2sr3#>E;~ym{iQUm9fmi-ro+ixP6RETRoX$`5#fnD~#GpNO>S1${w` zTkzL&*@~fHjkUHRe$yZ@3|TANx$IxsGqA+(`!CZQceE2nOPaZG|0A%$^v&O z+i1P}Y1!+ZS!=|2`PmI$pzyupW|YY0v3hS*0`x_%Vfh_#elN|LKD0x?p|q{cQV0fJ=h z9FAuvwfAWJgYI@N_tNve{e{!|yXrOCZA+)E_8Yw&tTf{va{^?$9-CPdv2B{dmvaWp zZi6C$m>`+x1)Zn8VO_)QpK*LV>`!z2Ec)4Y!&Xx5hj9CIg;d+acS9VSye`{ZNH&-p zF?3?!^MDy*-L#uv=YIXH?3ZXhkoBtfce_2V?$>j>*WN+Y*==F2yK#&xly=p;Me~co z)~=pY4m&nMj)@j~6$QM&FOF{ae_!?owtCyOzAfc@tK1(A{K(YWP%)Zcy7hF&^4Pog z@-|T0b!+8vYp{!V-s%gMwDxK6RFTgBh}YMC{;2)u`epVjR(OTqk0|tCe?Fr3a(1#9 z?DbU@v}o)Ffe5Q_GLu-QZAY!;6+$F7CCo?9$QvQo9kB6>$bSU^{rAwzi#Ms0lCZPXIUYh^caX=V;VhUV_=19w4l(|sI-|3F&F{~Ln)f5!j}yC#f$iR> z%HLi_>?;}<^xm@}mMTX%jUg#Wk1~<4BP0aFnA&%l19qN9_DjIOr8kV)lS(tS*v~Qi z%I@wk9}U&E-D4G|=?urOApDeUR7^lcV&ssygpdL*3K;85SPI%dxHxL~ZrxsdYH?9N zDcY?^ZC}i%fD9eHBaNP%ok4+y5GnJJ2$>^PgsMw?U8MS@_|N4=gR3kDj|1updrO0z78#Li~ry>h*brZb=!g z(P-;9V|6T9?zvW4)XYlZswPNBG3F8zF+Z2U9(1%VjcaQ&r|=!5%AT`~&OsQ=ektx> zy>^(vO36lH5Nei5M3DgS^~`O`B#YfY)3@ofg7C{tR@FVgZ65G>A(8pJ1YtYG?Y~(+n!S#~WAl0aK)QHpbfE0svt(MquC$4AvnFE!!Ub_L z0~-$Wx6IF80e+mHR1W!grRGhX*1e^vyQ|wwr62lxRaLEyD|t5rnL4lW@_(DJIlk4Y z5W!sR(r({@b+qiq)d$G`048f|4JX`vci7I(>Fl0n&ANI6M{2YyJ69Rs>jK&)x3yp0B-|Q{Zl@k+CxtcyUBTT*@k0n0oIAe*k(oc7*Hj`YAAP)fti@w z{m=aM;_cd%MGn%XpdF+@_X`DYETdmAj0JSd5Lyo>g5(64r|tP)7M=@P$a6 zL`Nt-yIafe33TQM#+^;xj>KxR(Ov%l()MmP_L0u%M`d*8u%hcT73Ujbu#JopD=46g znaCKB%KrogO z`4n~RQ|Tq2&Kih~LTRbqtc9(X0rr5&mXidAOo+ZBS@G6x{UEf@Vle*z zQ|`}qUtHvLH)p$#r}3E_t|tpu0dpag)b<`Fk5zJAc=S>N`=Vf+#1Rl}KLR^-sl_~v z`*}T0YySYJr(`^X?w+6WU&wXnzTNlB8>){#p|AGn*`u%Hxq^Tdk;v9@KQWRt)#6Sv z6`**CEH)x6PmiWQkbWrV{GswM!%re|_>TA$o4Ms))sXDf)?$mz%pMmJb153;?Rv$F)09$htFELG;!(B~tGS*`{ZTwl?`CVjuKadO$6mqejBZOwX>CW4z+~U7G5G{qYF^83`+==h zHWBvBOu$PZ90k1c7>KJ%Rc74ZW6NuO8qQJk9uGD@QV*$qs``N7yHDHgM~K(jTAqZ% zzY(vncuh~W9Nwr^s>5>d*rY(KRp11;7TPp5B|J_+`NRpIrAjXlbZ z0i=*s^IFT(Ud9^JED!@PzS8$H7BRqE$#R09pY=1iY%kW8wX}cI`JKPSc?E~c_PFWd z`-z3V)ls3`Y+>NpMT((VEE6xV9~7RZJ$nhs%ug-nuWNDr>@0a_vJh{GqcS`b@OSBh z=2P)@wAYVV4Kb^G39qvHM_FOx4{daH(~<12jZgDJ=?N=(7qk zM9S2D)hHI&ApwYk)os=F2~wcrC+WM;_1gZ*YIP&QtlA%6KdSDL*O^}+hs%d*Yb~u0 zc9d>DrL8>`%EI_o3Z8%zmmW%oE+L$tqn6PfdVllrxGyGtpS~w~v#q;jW3#>a)|jkr zH!F>yXCFfS+-693w~zbmfU$C^6djWGN47zHBlbOOYeV_#^fJAxt9Oq~{Tn&=%?ym6 z*w?K=ntvaAesg98h7~|YU`w3UR}%Pz#E&A|XN_7fzn@p_XNU4r$_yr-?6-*Z_Q&YX z*RK{CCF;&ov$D6WxMmh$r3G}jA|_yn26+5+S6T(*sZMH^#TjQQuHKw-SnqXfdWmgV z;PYdIEXF(dyryFws%k7%eN6SfPMk4V?OncZV0+^{%c55v26K zo6f4ChpMIMrC^0%KC^-f=`45>)i7N7349E7uj^R~mNNPE;j#Y!$KSsR$F+e>t{cb= zLd9BGlD%BwTqIKkKBEAVkr){IJgRP+Y^LpMPmTiZ-+7aA6w|0GHMW#X`zBO44TM(- zstk9m*$NOTYl43vou_#CUg|2TW~IA`wUK3id!pYO%dpi8M|Mew?CTr)j#x7T%050u zXQCHA`d9Kf2j9U~w^5hi!RD0X-VB9$%FF{}+8*#|EQ_28PSFuDyvwFp3c0uA5NyWH z(n*+II}{ol4<;0d$2GJ?W$KNfXXkI8hQ%&^M$5GxKPH^9<)vQBHY{1Jy9Z$5qJ#Nt zL7R9C1T;-v#T>@R%6fLS*~(fg*yJ|;k7dYm)m++5tl4wkxa=ff;S(-xy>O%?uc6NG{5xee*EEE^t#5GZVBd&Hn%c=%rgRozFnzDU}q0 z6<(_|m7?rSl9lX~E;t+r&luc(KU;JK=Z>MAH90Y>ZdGcULcq6KFKiUgKgjDDkHj2C z#XR6qq}Cgdq4v~k>a50@6s2pLYqyR_svu*I%Q!I^;lqDiz)5nQx00FXKw2!j zr?QV6b|+K=uG8F~?W|XARA{io-(+E>z?@KGU!N_4CS&F%SYX$3m|Mo_+BI&n>lf+A z>DM6=*#ag>wY#xm10yplDE54O{Bi4)Uy@cj^^B!ExqU+oQP_(XJvHgDzw+h&$|sRb zN5;hy{^y`>4jV0qy%+OI$Wv1vVm7$8g>x1DM_p+ja6xY)$bKeZzux@-PN35s=KY>x zwpE94L=#zcH+DqKM7Ytd2oZr8+CAaMVqmtOg|+GksLXw=F`+aVy0kKu+zPAd9t5;1 zE6=ZfaS;Ywq{PegQ9TouuFB4R?2etn;B@mIc-0GT!fmpn2u1_c@Dde_M(|J*Ka|HQ z+h{A6e@s%HIF;YQ(`oZrT!hw!R8^IaI+qSce<&yjA&uvR#{U2tKnae3!gUpj*NXmS zmFlT;3T@(f3@&(A1uA|Ey1(Gq+IYKKszOCT-fZzF+pfqbMrM zfMgcow(|ua`1MUP#~sX)DdVg%hCuJH&pv60Q#oE`Z0k z2MltZd1sHiWajN%`G5Y(j!ESre*|$GZ99C-$OT&|tzMODR-2Gg+BPcWT){PDnI!~m zP`EwIYT!5vWA-eN-)-Ziu%_gq&I=cc%w1>OTgSeoTMeMeZ#1*lKB4t43RN*G9in)_ zOm18B-Jr$d>{+tv)-@b+uodbZYWGJVy#y7Vt#A;J$xQK?`t>SUL~!ErE4E%zub$fin5edD3B z>C9HGm9LM^;<0{(vm}@-pW6!wwZof9W9}&75FzUl78wCSM$j`SWE(Us&OWJFeH4IE znvqo3V}~M@fEft-cHfkLu@V^HZK42Qk$v{o3V8%3l};-mIueb+j2c@^Kcj|!)1@V{uTt|!F3 z2p};unG}RLz5+m`MkjfY5b5?B>|3pk1=n>eZ(T~2D$SzxNEu1BRhcNU%kD@;zaQfx z5wJ$|WN}mgXkzkM)m?R}ED`=v$MfnjxFaOJH@o@--Fh-3tq61B?WLt>KYt}riPt69h6GK#@dXEws94q_iQGTARL88~C2E10I36Pt zGbR53Jr{2@oSR*UTC#lFaMjZ&v0>Dwi1IS80Hv9cJdPS-K?EF!@`>uD{{T6YJJ{u@ z;-MK^i}tG(%C`fM%HTnZg{=o3s4ETJK#P)~Obn(QH%`6Q&ZVrX2t|=ctn#OmV;wTM zT(Q+p+X+m8tXyR*C<34Hk?0Dtxc1%4)V9p7I>mcH%HnLb_iVRZN+pYeOP1m&TaskR zkHeq&Ps~Ok_j9lzs4;qq@z8*Eg(Bfimeycfl+ckC{irX|CHW}EciqMR0NJ?){bluP zv~F9;+r;0~*(w&K)0A~eO0p+iJj{JcHid|;GAbCEiJn~glIn2zYPSi%Ml_HW7$CVU}c@Y+vP)b1B&7UV_!8I#Jj$Bd2; z5;ZM}l+!Lk$&|#x_c)Noo_y$Qiql!ij^Y@wa`-I8M2=R8%BNwqULrl! zhF3Ed74tE)ZMbjNvo)7&boHD~i;u5_yLq+`IJmuHs11VJAc*R=eb(Q!2J7FB&@&&G zF0gmFy@%F#9es|}UA@j~4F}y^V!i3k<8oyA$FgP}61IWKEM;wgBoRpn%#8jLG0~xe z(NA%-cbmPB?L_vcwB5rUN7|}+>N=-LV)BcNR&+*AozJ)&j+e;0^Qp{bwb+AX0j-82 zAJ}}eefs0WKREj|epdPQ;(vo(;qKmz!Yc!(R!;A`oXxPA&z}z*uJybP?jZ( zu4YU~#CnUZ8F-ELoylnHxbE2b)HrYnv{mWr%wUTtkn#xOYNQPCA><`2kC=iV*4=Fr z$bT8T7vzqb!1pV+Ry4)^Uj}aso-$$4c@W-nC}a-IDdh#iNLdpzKkhp6-q_Qx#F5^G zdX(O2yfVb^pVmt=k?i~X6W||=xDThlXzip7GE~=AmSH}{E+y3JW1v+^-x!eg#QUT; z?=ce{Ya_=$9=oaKCw6LfU$FhJ(0b>%wpQDAuG+$5`PE4}dELs|V91b6nH&j3nVg>U zJvP*Rj@0;VccpZWtJHWN-RT^rckJD(ER$1+`xjx7W|LZ2)^Yy;BQXvB1bW~9 z0AM^`?q7@jsQRk-uj013PNee7J%Pt-ZqMrmf@`l|X_sQQRN~D7pQd4adFz3 zH14>>*vQeTM&OwH@DFR^RE?Ix1T-eJ$E<`@GCa@o|nX!tMu~U7_(m4cR+{>VRrRK)si(A6>Uc88m{%s&#%TOY35+Hi zn+%t|ry|MXGc71s%ulFxz`Wi^QC-Kec`U}U%}zNpYZSYdtlWy5ffD#Bt%yv-5k$)5 zM0o8H6Tbe6exKDohF&%Hx3S&N?#F$xK23LDH<7Dk#{L!d)ueJTpd)3xYCVe+Q(3p& zJ9C(j+x#Q1sC`O4FyH6=id&_Owb;QO74&@X@0k6Bt#h=!y{|*J+0)1?FPhf4Mq+Q| zqPW7Vx|v)UoA#SBVu*x_6YGf+gCdBuvfbb9E~4_gMt2kHVcBh6se3=;k8CaI{@C_& zPE}=kmGuo4s3yKjvf6XIE1(U`nBd*k1hND`m#q8U;`*KGIv!l)Y<4@e8vg*gnY~o3 zZ;tfz)}v$bnGHJw{h3_PwqaF4KJs*&oJ-iySFdEO%U)ff`Z4$0UiZCS=kEUik=?oM zk8x?GIR;bh;|DF9tC8a%+qSG;AGcW?lNM`O6nfSJ$hYGfnx202XM!F0)qRWctI3Oa zu*vu9y;;2GuG4xCOwpH8?aqOfd&ei0Vq@Bn9hQIqPp^QiKVm{Qzh(PxOIX~-_eaQl zELQN#x7v#lhVK4F8jtwVz^LRGWzb52eTT{a0AQs<2QeiCJ5SGYc_ux>?Pr>rr#+)Q zvdU|I=jd#raJqB3x?rOpHPN*5#|jbwRcZMFb!5yW;sbb|uH|ZPHNLAJNa)_pYP{~A z*123&lgq6XG{|E#<^;|pEoZYUOv*~}$Gkn;bC8jU_?@H)G^cI*iJ0yWbpDTCGxv|O ze^Ac@JJPzj&fjG<$UTqkP1|ZaHykWTLn>OPy3=55u2%#OS-^`L!Rv5d7Ljl5N7G|c9tv(pE=1_EXaj6lJ4v(FOy38#D* z(Vdv>M{I8PyF06HU~)RoTH`U*3nQp|hhP$<1F-j>Z3;*Tkx%v!M8OmQ$0IJa!}WCf zk)y}H>_=t01=ze+z3*K<-(-URsdjaTTeqc{Yd-qBFm(2;?2i#sNw88=EgnTbJAqG| zA6A+k9`^4~c5|@V{@CijDf9G$HJ72Jvq;q1OS8zX*;HCg5Xd5KKtwL7ekzzV;xK!k znT#%k@~_A)=<06b;yaPs#po)IZmsV2v+e>h)@rdYbgB;}kYJOmw8&9LnkoMPX-gI9 z;p;MvzwK|1z4Fz$%^9dWapes5FU5Tly0<%-sQJj$!Bcgq37dGRnH;WB@b*c7sOc`%&XAnzmU?9+-2v<#i5EnF}=reakuiOETVELS|;R zHAGa9A?R$F7_peYcSdO~Fxu8L8kGyj@>jmAQn%P?NdOYgA&J~cL~EV+l*~-b#Px4# z%$8FOj9q+gS3=;9h0r{uoW@GE3M_M#ESg9+7xpydV`vD1iP~hoV{Z9cZHyJ^vtvD<@1Wjh=Yi3>NM{7d)q z)@*p0^(*po!)e{Y|d3)m$@#(|ma9Iq@t3RZ1L2Yg*t7<+RfaYxVmh5bi0ZfR5 zMiRz99bV=mMd^GlcMXqSW##NYGbIly^ApO+ZwmW^DJ}UYaO1=M^6Ni7nOYaKJ<$4u z_A|1b*~aPa<}RK$EvuWS?d24Tb|#&Dt4*nbD3CTXCKTwNM6dlvKyMSs&pvK><)^UP zJF+?tUTHr9GNn@1rZ!u%rFA!ZX_TxRimJ-O7BLuk2n4q15W3``>I6W0IpAN_Yrt=( zhig1w(SBZb63uSHcY6Lq2O590bu8rQ&v5;2QX@~rRN05)1J$^jl>)ISi7kkTi)VgN zXMAe${{UY0&sg}v{dcUqjMRB!#!>A?2ODDI>?KwdyVq`31+BQ+wE_x#t07x`P%#Cu zPg>FKFJ`-!OAVQ`gI0^9nzbs!8>;=o5_f%nac|PLEi%(0 zGL=sA@f{tI)0$F?@d(rS3{DSBfmfB9F^pAqaflfZW0NNg_56Fk+!o*JddxpIyDy#b z_sp$lrM!YuG!~HVC967Y>HY~`-;QqyuJ0?WJHJ>oCyU_DATe$NIzP0% z=bcNadn=jC*urD8=bm%3x>mHZ3wQ|Q{DlY$8xmt;ts6EcX^p)NtLgLN=X71`?q_Im zc}A}_XDa%bEm3m<+c~DE(l0x8IEAYSSSx@qr{KAM*i$}9^*?Cy9$9%m*`Eu%LZzD4 z*^_llZb`Q&s2rHKnEpp2krhW21XdL&250>r{{Woz`cY{v)ArNHwI?N=%ck0KHK`#F zu(IBwlf?r2MH4=-<_-19NP)=|O!Nnh?>qjQUF-1gO{2){j;C*sJ&?r0>gMxU3|vlE zw@xw{N8V$bEc?{N8ojR{@{*oW@e?@p^uh1WtMOa9`h<1nn$~^W$#)-GFFT{Vr=+yO zYAb56g+wnKZkQ>S!l)cA(4n7Lk?tcBGd+8L#rXx8cBb!sE51Fx)7o#c*sLx($z-#6 zs_hKYY$*0q(I8c(!=zWbfrJ2}Ud71BW6U3gK4|z;*gvVqo&EXAXq`#g&mP}{tERL) z+;$pk(!gFvvAHOxR!S#(4YBJ@jsi0(F^z|P`cr)Jaju(O9mDm(@^cNSdq1VTLeo8_ z??#uz>z!B`&2^}C4ua0jIRW9Cb&OeDS|9C`fB;yj|+RF z-7eL6I?&YKF83OkBRiPVMUiXtZb?(>L!45THbILLS(><*N|I6W$E~{dBhNn5cdx@N zFKzqN*#7`3{-ODtUZJ;lTGTxaH*IM=bX>IBR_`{l#deqrk=xNE@{u_$q9SKoe_Vde zXn!Aj)7m^gVe4tE&Xv^qU7728Gg@kUXdN!)*i;KfqucD+;8GD?k@%Wf{{S=AYIefx zZBCBqEsHF?JkI+2=sxpM@?*puHRAR!xLz~Z(J#X3T-L3~wYPHFO6v%(a^*V%Gd2B& zlL&6-CZA-^k_UKTZE7^jF%acpN-~b zcVV6KQ^238SBQO(@iXdO+?`?B9{uQaDz2XI9yb`)(7eK`w6%u97?n##x`nk*@i|Z# zPUZ1b>P;@C#W>0lZa-pYORY+cY*tuE?JpC*`84MHtKRK7*>5R4O~zsLHm=N6!KXi` zvvzVx#}%h3NDKJeYHU4Z&uH@kh#1>pjizM})(7cyP4C}tu$~z9=Dn;jJ zgz3x(S;6UilNM5o*OyT&6&hk8fHo{CFkDFE;tF?L*)G@XZy~kLTgyJ{R@Hr>&~DQ< zG?t$2&+?f3g{#yPl{eYRW%6}Q$83d^02&lhEL3{Wki^GO8a9gIbsCB;IP=*O+Rfz& z<}{acL%&N;qiy|fjniG%@4ssEx^uHEU3`WwPh`XG@*3YFCA3`5{$&fJ5Q11%oy7fP zGCNF9S#9-;`q*OpD#m2|KJbb(#;5YXA&yyRGRlCnitSww(qQE=!I>x(gf6)634vL} z2^{a$Us|uN#SX&b@_r-uNvts$uO)$VM^tM>HFJ#Z;EMfZuyjPJ_sB>EY6zG}dS*76 zn2$AHJb3QPknLTo@HX`}p=L!_8G9#p*>5Ld@h0ofXZ}v+Qc_d-L_o&>03Ce}FiK6L zqvXAN8$(hurJUZR&+5G1r@C&+b{5}|@NETqB;cuWk4!E7_W@e4B;+IdKw zVU&#dyAzLO(XE!g%yaR!rJMp+X@pQO+9&ZJh#4KfbJca~D&ad1jkl%Z)TM!CV`u;j z#(1M}l#u%8@%-X<-aqvn5r|$o)nkfS+Ba8H)K|$S%cCh=>@U+C8pGmb62}z5a43!c z0Dl`m!A(S4_nUJ01Xy*hb3)xaZ2N>ngu%Vf0F~HqALGV%l7oo-b@r^@xrnBe)2UNW zaP-p>%6*}z-@}TF-5}b*>-UJlIH-03jiw4ZAMA!}_()#`xXAm z=h|^J*#(Nm5Rnzfu4ZNn+U9H`uYrxXl@~G7X4PzUL|ZJ4eUO?~Yu8-K{sL+>@648B zBl#vGCvCs+=-DbM5Xzx5-)BC1l?d8WCe*QtLQpR{d+V&HPt6^7k!qo;K zaS;Nh=ZA)F~0KYE(!aZ zl<(v#A(Bm9%Qfw`E)tmo#cw3ZK30xWJjw(>wiu6{)+trUGT7?*6J9W)xay?LFrpzU72sI~ z)%CWRepJjwUA&JMS^m?6Kvs?4w*ioBmA|Wgm3qs8!oFZ;K4Jh}OAUW9U9Ku9%4V#r;OsK{P`_9xiW-l)kz)i#7*It&n@4Z| z0EZhze;*m|TPfxjmR3gK+*(;;s@_x>!UV*`69^kB`)KyT2}A*o(YMJ}=M7Cb%NDV= zB&sY0HEvg)5Nj3?7)rz)XoQ|bE}4;;nHc#A>YK$G72YqhHVetv`*6u+GE{@h?d8gA zcq|EpBM}3NQ7eTbkIxHg_Hm=tm3a0+L(CSoF4J3#(Cc+5x4^)qYa z#nhPL}gJBJMkVr5gjt8dgf;_e-~?1>H1b&^y9(! z&QUh3scTzJprZb}L6eW6Y??R)BJx+uQ+sd6$UA$6{IIrWL|AVck# zfSCMZci;2q39f%`Q7{O#HwPs7CtIuPs(ilfbG=267K+KnawR+@;Zw(OiRz4=cD>|g z+gX(tjHFYKnyt$rtf&DbOKq8x<6arcOwVa&=K~u|bs!@w>-HaE6G*|VWDY)4?3D5; zc&R8v!7?Y(-)}gE6Qp+BCT6rt+Le|?_psRI$i-}~MpC;JY>7jm&S5lvw02+;xJ<~m zjLgLGfEDL!VB+>a4VB1fd&-DVDoHk6IPdFQ=U`0Frf1*rxx~oGl*i}Lbtu=OwXzeY zviNW|J;|{3OMMdJn1F&JFYJ^Eeo-Y5F~7veOmNod<0#?c3n6+L_R!h6yc?kF!Lgix zb`<+0<^~EsTWz#QP4SFl5Jx!t)}&of3&~_rST5l6fhZ!EarEwC{&C7=cb|?u0K4ug z4fDM;v3TllvV}EwE3K`{TbKbOe=ZR2Br>5E2|&uEqJJ-leaCvd=C9;4&(*I$TFNv9 z7aUDjuVmi z4l^{WUG!(#77Z?`Li~FJ(u)NmV6TeH<5Z{E1~Q?Mn2+wBRMt(`*)gYk8s&k57W7qs znU7SEvKXduV8F-(O2#4#88aN@=4xdOZR)phR-C-1pZj#J^%IWw)=e_rMj>$UX)pm$GYsYleCoZh=A;>#$5(!8aCNoA!4&G zWSi}V9Fjrx>n^zrqw-^kaM3222RN7znPF+QtXeDp<8jrr{4A}my>yBc1qA?eX1VS_ z=K&KZ=17WU{{ZvpIx1bi{I*F;EOlUO1!+t)0TtIGuzQ=!osa8MqBq`0gl)Fb&<+B? zry-S!LkzEMYeOyDVpSGBWe}vUv>&dOiHY_~=3wR-6EpcoNwc~=?zmR-T%U}rEF#5? zP+mfJd2HpdnAnywN>wr>F(R1!W9DSrc$`pTax}4}pULRL^_2QCqSCQkWC&PIGJ;_H zN!xB*hvt4a>8%X4ikA_Np+h2Ai#JjsM-(X~nfqturf-))3~W>RKw1^uM&(mr@j2KwNh-xu9e9f7GBO^(;xpnINKP}6yF6n(e+(EHl?Q3cbjzJ?Ts>H0u%DF+ABo)FzN|4w| z@KGGgZ`||-et66E9_(+MH8Z`r?nV&P-0L!R^Ey)XaGZnBj6pFhAceJ2$fNTwX50S& zu03}(uNAdNW_6cud&Ag^daJowb4y%yYZauIta3P&(nIHKVTH9(vdndx1OPvt$YT}x z1pLhTx9?Alxg6!DYg~1GMTORMEL;04=whq64c$h$MYuH?LgR56<1rgdL40i)t>Qn` z$GJW>W~pfpCh=L_ccM~ZU3$q9r(LG9*kCdhNN3nFGs<1_Gq}d{#x~2J4K7Mtx3m%@0(-R~vw{r>eQN3pmPq2Li(pT1 zi76=}F0>QgZs+%tzuNhI+42*(n$Nj<{iF6Hn951QC{z~_vbH@Ezg0?$IezI}K+m)0 zKQ6aHtF#AVJl4}V9d)C%4jMCeYsyiVq{TDb!jjpn{{YEzJmh45_5T3AvFEX!n(@1` zJ<{$*gZheg!&7Sh-RcYltsSOyy>!k`4WX{vgHtjVv7q<>5ihC>KFN!^=@gGfj<@Gw(+NVNxYfy~c(Ap~*~0vrhL0x~rzD zvN+d(ayquvQ7%)q+*r#A+9g}fnc?UE02(g#_M^SJ1HayN_p`A5x9nzs&f~R@uSw+W zy4HH_Qx^~1+HeADS5p|!nH|_s6aJtkK3{bz^Z1pns!kO$@RH$rV~%oMEu(1~S#Rnx zksfIMMSMc~oc5o_Uo5=F(D!sIDbu4GlUCzvBL%B;CmYFw zXZ`OudDvYYV^??2wp114*1PhHO<-)lIiAqC7-8AV;Smuw7qW&uYnWum5;zud<0CtK z{ToP?$H+px;!vNSS1ZGB!+wQU=VYeTIbYoEe-^w~@?*?Bcc!~{;}30Y>TE_kD;Uhy zrD@8r`ZavbjhCBm*V z)lQ`U0Hv>?qrwiQigo>dt1e^$L{w1G^suI89UJ#wmmS~n)3!ct_|w}@H#qI#}%)s&wROs(p<`IYGtT5hj}0*pnkrFd55n z_>h6)I#$x!Q!A_UI@h|o&$`*vX#`wd-F>Sv>@1$9O}h{2~fr66RARVNg z`0(q0pIMISRPF9o_m2K(c9XYWOKKfSi)NBfc~WjYPer7}xz2!GKVdw2*FEX(9S+R) z!y8*Q-J3|OkviE7n84$)cFsn{>n7&M+a)RpWRBY(#76V+74~Ds9`t!3lXi;iT`f6~ z*3iZyBb3QFDB^p6LKV&VT#bep?g*~#lx?I=@LX1$jgGL{V!UO;NWz#RLE0%4Ly23&ndJhkn1zwxiJo+Eg_de4!T zdo51IMfX1SRU|boVyzMop^FJ(&9&j541%9ieQS@(0w=EB`WE<&;(wLBxy$PQ$9Ze6 zvYpPSt2F)I^yzI?pzC6@>_8b=wTn9muuoziX(>QkhRoMe3_wHJP+A=A)*^dNrw;zP z)|zipYF5;&i)_Oq*;<&a7aW%{_&LnpVn=PFB!B0w>e4y=ZKAW0-+d3>F6nsV+$JK- zSIcQ^h*ZiRFl5|ul7mrKAPGnUK~n#(&ozID7O@^7`Vq&wB7 zyH(ts8>-w*t)TUVy2pOesj#@nV)taZmRAR`wGuB>FrrKSb*W5m{{S4%rJlI8hRoH$ zd2goh^Tm$SSnlFleOn)~B`#i~e8(b@lJ4XtoKLgTdNkJs|- zORL~CR%;|zDCzv8ZhhNw_}2S`it9NbWC)?KDPG$|4_n8>cDqz*tUkHadS?lztLj>H z*=G`rW!n~ikd&@rRfe^ofu$uNzEC{MOr)igyg=@jR!tmm%zN>Z!M_SVn%X}lQ^yX( zXimmmy^iIS%MzycRn&kWd0)u7C8Q!-%pyuv%%r%%5lr0L+f8==0J^#>C*7YSimhKA zu=VFrT*PY%ri4o?49MKb2E-3piiqIkNGFYDs9@ofA!tomb0LoIe}4R^!7sEur^C&A z7`mB>B6FJL1)CN)8JxOFtW8C#1M~ZG2!i+?vDZ`UIv#L#X5&Wm{w@!UT z&$u3GcqiW7SKOZGYOwD~)g`ac0)mNH@!k$(=dIdyueLhd zQc~1@Q29C7KOH=L^3I-^w}r;{9}@Ix8@SACjijQp0+oopKZLMBtWiw10h|biJj(fj zceQ>TyfK}>@*`aLx9Vw=%qLQ7-tTE$OJ^BYk{_{u9xJZtLqMUBQC#OMo zFiJiEKi>Q7E59Ag`a*pnHBk2Rx!tkV-g|kom`rMIOLqP;uAs`;J0wl}%V&Ff^<>y5 zFcUu5ji!DGXRQ|a;ot1vjNVjskIFH`Th_X#PwE)WX6s}ME#Ati-DWD|C5O2>(Tm($ zjPDZxJMY%i{O|fm=#Q)a0CaO6e|sxZR)O}jwftGr=eP)VP zSWPDrJcdt^dwQYuowVxBL!X4#zkhsqEL}Y-Wi+lH5t=?a>p!EX)}yz&%MII}&*S?G z-%U428`EW zcQaovUn@s3Ui%Hhu9Z;1r!Gtpl|HyrWB$=QabtNhXOu)o^sNfiujLvqG@~oZ zBgEwTvwpUJU28g9SLggK@F%%zUvt~X9j?2viIm%3jS~Zd$Ks@R_T>md1&xW_5JLh` zP*Was{ATQm=vPK(Az}8iPnob6F96#U6ZSOhHRlp+B4do&B{R&+=Y6BErImqijGjJe zs)}BFIj7f^%gxxxoy?c9>{*M_PRJ9bf+5a%M)MMUp_4N(QPy*tD2^zyv|5>MCx0HG zY)coIywVVnCMcwa3|G9k=aBN5nf$(1W1C&rtBuF~nb%zumDrl1aWT$AgcD8#m}IFx zRE)$7ujlm;AUGlUdspk`FfH_*W;m-@Td$$YX9=;wSh86(ePl5^Yy-Idra&Uw8jxKC zUDCo0T?j1B+XZn*A`e1QL@f=fa3!j zK<(5O?_Mi5!x+nUk!q7BnM;fwuj~^M;>1LO3`Bs;Z!r-Qzt2E8Wyjwvc2euWYwj|P zYKpR!L{AW3^NHjUuA0)@XbH*w>Iv2P=F?OXU& zg(=o4nR?pStfZsVLcUWaGDjp^{^NM4jn!gl3mfX9G@WKL$5e%N)-W82h^iaO9JU}? zGs}3N_>QJkXT7bqtY}rn(y?4^I@N=;mQ*-csMcsSnE~*w0r5V$7LNOTL~_zvvv|D4 zC1vjW$o4wN?r--%>;k??6p1cCM2nvlj`6o1fFjf59~k@u-lux$umx$j5-YBI{{TzB z30v5?!#jVPg?2z5uPD)ra1GpdTx;nl~ zD6E*SogA=$laA=ttrjJ&BjfP3oRn}Kr+xnb@+jN)y%%zrrQfXkO?XqQ40^p zDG8Eu*%4AVbU{}b+{H07yloHzDp#9^Zc#Y4>SZam*Uzbvb8{SRXNfKuKl2A_Ff2bez(H4>6{0q~VT3AG_)(0%bOc1rQ|-+GYuD-{You%rmRB zot>>}l2(UVw9X2FeYFSX*}8^IEO^5TC1bmbk1h6&fEX=fF?nma<zQlcJP0}F`Hxok>fb~S#IF)yEIBPp3Fo~}!lE8{YT zWH~%*kec@Fr5M?Js=0G8xi86JQ8P0F$Qd!%qn6PT03fww8Z@XGVzM@fQ(#lTB!>4)w6e1R|)+v2ak5uo80|mF+FI=R2S}_+zPujBDLd zAuJ!b`=Y$RQyU_YF;rJ$ASPD@1q3ieQ@rmn02x~|TOW!}P0tJX7aD6&q*%tJ43=Rl zPXUsNIb@qA7+*4QTYT>`>ZBr#*E;n~ecXkH6aeJVsI5}bxWCrMA?la=VirPYGI2i< z6Vc8FH&IenLm`dH!}iS6k^KoeNh~yc~Aab6p6}(czvBl$)|8u^``DX ztQvsY0+-0xuOMbZvKSbSAUi~D^Uwj+6<*15$WyPIsaaJf#fxs3iuk2Ui0!#ZAu5Tk z_XNTmCk&IB800fO1x%=Dm_aAKaHNU>3sI;$kLDC1o=+KN70& z-DQzHJ}Whs6ROt{doD6>pAoCS+j^8P*jW)IvXu!$^4Ru@*f`rOqft2OnTFL~FxQ8s zYq;I_A7I#AtUyQ$f0=?VFdvlsL;?3HUX6^sXl|WFo0Tja*?rocp}l9>B-u+?fKsL+ zS1{QA$tWo0u*5*^vZhT8quFBpwb*5P7sbk~vbHnqS`OOgTFz44r1yxKkC^`el8Vdb zqMcarS=#9`Tdqt!wXx<3TZpWQ2`*$}%S+-nBa#0AV;xsXcN3RkS1m96MI2kC2?6hm zY@RGxegLu=VhCiQxAqhemhd}33*#QYv}PpF(tI~4w*&O>y> zuQa^nEUnLa)Awtx`jFC7K#Cb)C!t`2`Gndt`z2UE;6Lm&AxE+G0ma2!Ka%Y0|z4%P682F1X0+1nVAR&I}9$eH@zWepP ze-FN>y_@nh3$@+b)7Y-x_oTqS=LMd=DXiwJ*1?K*8MwH4L=+2mK4CvU1GWq5y$OoV zvRzd;?9ryq)uQ^1wp?LhWh)jF1%iktHeh$*xgW;zU15)N{CC7!jCr#eiqsjYE$ihN z{{Xf+?<)&G>$a(qQ3OoDiB9pn&*-|^oUrl_RP?(Iu6sR_$#+M^3cbG8dJj6T%={Zi+$ttBi8ycFYzPl2ixGxX>86DQRVGHSFe<<9-Gw~APj|j zpm?ChOZ+Bd;v@cJt*Xy=j!mN{lxaV(U6joE9pBE(`1_|UMxMQ_bzMy_V=?O~ua4q_ zeTf$c!24BQRzI#LW(op-)NQq2H2$sH2k9x@y<6b-(^JQ8#8%E}*;0L5L`mB7x_|A~?)-c4T{#-VYOeVZin)Tz26(>_2Vuzy6{2XSsR{9+hOY z-lj6 zoX&{GhN9D2jp}!--gYV~z#+3V-2_eqFvs&So_yIu>a9AZYKl{Xl{|P^=k3Nxy%MFg zCnZ=@;P;t6I)Cy5%y(PF4>0^*(fSj~3>KZ8M}gM5RAOF~3lM{~PWeaNR5*2&l&lCw zVh8s#J6rv(`qX#B#rF?mJb>|Yv;IW+P1=hW`*Ekcp>rz;vlZ(f+RV6OlU}klED5X| z0q&BRA>4TrPSkk=^o;sRcI&xl@DBE-^4H64K|#3ddXFPg!y3j;#HC%nH+|^pMEtA!nrrn)s+#LQ$@7}ba3wCqa2E3SFpcv-enasqe^#>hv z=}kJl3bLx!$}Mpgu=DEI?*4{#yP8v$+B~yz`e(NN@bcQGH|rJU=XLa+x$(mT+-zkX zMWXTweTJ45Srw&~@atb78er@E{@8*f%4`uv#~b?O&1!D%+&c``fw0B`wT27WqmbxT-Ak(0=P^V&$DHmK+J6uVz<>Ts?=~(TfINtwo?%* zpG@-}ONk~CYA;N9rR5&2?)~2!>2?D%+J7anr(xQ>`;&rVbZ2k0+J&I~MBI=^+h0i- zm)kO|h%lG5gbrw!RLZ^#cLI|q^N-lXui#9F$ORCXM)absI& zaB!+wF8AhvfUrAtY7ez|br_H;gd9Vsmo@D%C9ZENalQ2H*K>P`*^M#U4H>9BfTIdmdbtiz?nCrv+YbII7Y8xRK2+zw@fF+3-$?*ZUvl)8(s+Iz}B zEwNZV8R2C-)-@WgbnZo!@;ctFtctPqEu~fpAyfCac`j3;GqmI!e;O(y|RfoOq>x?x;kUG^)q8S1G^Y+yV4r_CuW#}?LYCBt0`VdLtf_73Ehwq zGHl<^WcXX(?-ftB{nh$$>g{WU*1DAN8+KSha6UW0`H4JRUx}VM7O! zguY4+N+DjjpIjeK?=bQ{Uv~Q|rM1UsHD`Quz zroOqkWr+^nXiSxn!r^ZyprLsQGT7RqA`u<9!l6?iGdt|#>eclG@*~5a9`bn~8#Jy1 zJ>G;}$7uIt^#zmrWaMt2uDRebCOhgJy0(*=OEHBBrLBSji0c|V$>$~u=qLP|Ge#EcF4F>4;> zZfSQtEcn~lzUWY?gYIXQ`U@|B?CuK}Pd|#GsWm6_*~RBL6YS=7ay@>wTUnBsTB=Ek zq$?j>0m*IDJ=yFRlf94Z{%bwsCvg0+^54jg@arUGtn0icqx%g%r?JFp;>n{ni8YfI z#8C|pmTnXI3<$?vf#R>3o-X+bs5`5!`ww$Sc=h!P);N{av4qxHSC%_8`u_m^O+`i6 z6vk*bI-;S zju_O5GDWGZlT|XFU_hpyw~wx8@sR0P(BHnDuI)dOo!{+_x5?Ji`u_l4;wqy~%U1$RDA9)gQCH?$UYe5zZ-3;w8j+g71nk3VY73H0G;=lp1oWBGdm@o`YwGib?kY&uCR3V zc4Jgz^&)hoT!`MBWs8(6)lLS2VoDoe*pFjGBaY4)o#qRqA4or?CA}$|(Vk%WLsqc& zWtQKY)0!pX45_0zw3rrcn8XV$LfAZDqjbQG#K!$`=!>g~RI6_}%5>w|%Rj5`dG(r9 zbC~kco4-mA9XyiJ9fi{g@?jcl8<=VW)*lF*FfTh5$T=x`k0HyA=1iQk*6}$Ah0gx~ z5fQ21t+&?uBZtfCU#EY7db-`t=D_~|1>BD1;|N4>Mq#@#SZ2t_w;5sO|7jHEt4si8A%VjVkQAF_aZTD?=dmfZJOCp&Rn|{6lsXD zk4TRYV1WpSI3ilYct*lMluq;h)Wn2Uw?YUo-4{iJLZV`wsIFw$sr(Fu5#>Qz*)6y6VXdYX+NTZZR`HvL>}7 zu}nlne`fMuGaLRrNCSGEdhE#D$g%LRu&66>QbX*)2NPR(lp#OZ-(W`2TqAg%g10a^ z8ddT$UZxNR%SA59>?XA~1d34A7qL=v1|Fe_XEsO7M?h0sCYwbI7G>n}Bt-V09-uBj z44X#Hy@IlsUjG1|^E{@1d&@T>+ybp5CxOG!t1Pxxg0kUGXx8~sJ?vn}PS70qa+wK_ z(8orIYNuZG9u%>aqTu7w^trPXmLVr8dOd3eqIjsGQ@ldhxczMrZz&3=Svd+=#bOx3 zuCi5ragMM=O(!MO5Wuf7Bt$$S3-gWsHs}iIXNB{8vH4b_@dNDe_bIYzS-~<6O=5h4 z3OGQ15xnvFlIXE^Pb3(u)ISktFm`LYnNXnX_(u7nq_QW zLz|Mvj-$j2D1FY^33(-F?NCaIpAyI|;$!1!;|w@upaC0Jo{ z8TNegnB-F%f15r8W;oA4eVlzJ&AXOt{iZ>7AqbJQOH~IM%$ieGEHgQf^&FWN-`No{ z`0p$TV=-376c>_CMw)@~kG>ymT_+Ypec$YX5a9$+sEL*nb}65TkBGHtL5QWOFnQEC z?ER&t*$-0Lz{7g=1#KT(%mBnhL_~`uN@Th24A*_CAIjsL@{wXLMOwbF&FaoDN+6-4P7=0sZ+S(3}Gxoo9C5*B87y2loW)I=kqbV z?;_?a)BZ-GTy8qfNi|Vuitz9G6jp2Dt zLD*GRRtm=RFduT|fGnF0CQ0l(c7U1ro}Q+zK(9Ksp5Zw;CeijTlJh>R?^A>sSlW3F@#Lsa1K zcArHUJx8dQ3~chn<^3wFFv1y81!Cg`xXJ!smlGfLw_NB2-iq-2b!=y+6L>1GDDO>Y zgDN3bLH`^J@LWIvmIB?YzAO8(fE4CeyI0qwl6`j`2h=O!dmKQTRhy3)0A`8Pe^ z%KNG)o|PM}t7tF6ZSWzkOx;@^`@{)v@jU>M>BQj~jXK}-&}C~|?rVvwTdFJZ8RDseB8Zup z9iTV6DT=vkEQDn2@H1eh$u5|!+(2b8w#XvGB)zA|L)QZUWBCzvH5gu1b@FbzR*G6h zj~kSUYCaNT$uJQH6G-J_2M|ybD-zp(nF6{NzV4kH%RGW{n2;+2RweaE*kVH@$%T-% zumD+-1(X?;k`j(F8_@OE%AHWE`t))*>8{$<6;cI)P#hG#A+!hxe{87#04a$r{x*(^ zW+L{WLh^Ph4pGRw*B#Z3iE>nBCS-1r6>i>J665FNdEb77en~}-$=A7ttek`HMf8N# z^{TXlGGKt^g$HQh+Azr1Y)$7X<(1#0yD&~;EG3xn=hyoE zbj5cy4J>8KtFuiATbvdyR=7u78()wVp$6fP&URPz2<^yspWnjoc6%mY^&VED&buPQ zYMw+#*G>bA3cwk}z_Vr<0?Ijr#LQ33b@l{qzPd41F{JkcVwJk|EEAAK5^J>&Sqj6D z1352lMnw}l?;QZ{%~e>dnZZ_h1Jw09Ab?;d!@!r#5+N#wvxqFGkgy z78yuIOiky1T=A@h39t!k^vJRZNAj46iHVt=6^jxymySBk8Z}L+YY;E3d+~5ggaCX= z7W)wt6zvoL029>qpHT$r`kM`r(=2^k3teT_Gi87Y^_^%VhWfXL35V+r&X0kX|o!* zuuG~z3R0@0oE3tDYJ|ojA|)nK^E1-4W9?kAT-k`y+1iXHxfPC|1~dNvD#}~l9>z;y zNfTiFM2E-D{Zo2{Govymi>HB6So>!t-J`0ROMOvbz(a+=fjN-_C}B8cr{V&701J5K z(X(q2l4bmz%ymaCiME8}tEK9ZVu1@_^WGlNh=xIg0m#Ju;w~#FbBYr@7gkVUyNL6F_o& zCy2TX*itPa2qB+bPgM``)k1NY2GCGFh~bDUCl&+Ja8m^l_zQ|mrWjk9Z!x^YM^{qv z{;QU9RchL+dZmbU7K}^nD#IHqg^D9-GbrN_b2|s5rZ)NL3s)zSikRpvOO?JCn|`~6 z%(iebjgMm53^Tg$CDhl_)N9Lax_k#YY3!a4$D$7Ev7tS0nQ`xh9iY!q8{ zBQ`@u4YF&Mf}&6V00@p}!+887rT0-YNlnV+GDyXj9Mt1$-dsfrya|&p6a?(X!eP81ig*NUE!+NMpe4u>n`3N~BKny&ifLnAR4loo z&^Qo5Ghh;7#6*V^0Z|lB<0K1 zLbTl~=wiW~NMfs?xqZ6VSjfZIJf_(M%)~@M9S5yDOM}&T`-oNp_#0Lk47yjGiVjGf zgY-&SD}Y4$;d}}sgcP6qlIswtXzuiQ-P|U32gfaUsdRRud5AK{^$29Pu-KpEYpx*< z2o+2V0CwI;w%m$mXSVIO!YC;K>Od90m9FHiigs-WR5?`cGJ1}a{Dlxi-s}Tf{5WCZ)Br@Nk=V|TSn9W0R45CTK@pY4(#@|ea+2y zU*273*+JD+imsx@U~ zyPYr?wB%SUYSPXdG5{Er#1zTK#S^)HqvB@r>=)Em$$tm(G&DzX^O>&uc=DDIO>5Ft za=4)rkXWtX{{RpNjK>yy{{H|`w_7L1A7HY(9lxsd9&<>i0wYZ zDKP=B&P*Cif*2$CiIFdljpudWPp=X?kK#XhJjU)vd^;_O*4|b2qq0={kK0`rZqnLU zS#R(7+DR@X2-aBjSCAi-lQxZ|olB#8nc}aWy{E_L^lq@zSxX7@Lkg|3R!)VIk(k_7 zBGols$oP-MVq#LU&OuDH`$Wst+OhQCf& z5vZ{xD?`OiV7(_KVtc~)#p-smySJ4Za>S*^eZ3CW^|nn)Ybf%=t^TK;cXxld+1~u? zuQB|9(f!M1nOT($Q*#}UzzochRSZgu239aInO6_WV5VYub?kdx>fY#ing0OC@~@IU zYG{mSWxMaEFk!Crc54*a#@xo;sb~Wmk*gyD$}h7pd#Q3WFfl**^>z1)R{c6OXKk(h zLG}Ltf?rP$Dy_dS>Y<#_?y9WbrOA_Lb36`8n9X}(GrNKBdq;7YVGjWvHvK}rsJ-#? zn-7ldz0DDa@&5qFL|UAPX?hl!X6~hJbf2nnb{GT7wRw=3sIE&R5ZY&qK+|7N+*Yik zwbI)p^ZKRi%VwdjTU3fvpa`}e1~+7`Y82dwXEFk^JT zs=bJc(6>y&s!Q!L(;=}NB4oGXGZ|U*weTOaxC}>+-cxxYIL%n?Tary))b^hrV6Rrx z7ly=%WilH{e?m{%att3-L~lPc0$RZE)4^{3dE>10E|%>DO);l5#vA)JMy%9~YUyDP ze>mPEWaaV^21^);4ttUQQxUq47JityUeEU{QELAH0RE~ygtO#k9}jCEnhJVf9hhD@ zF4{;Aq+4^7xhglASNOme@2h67)Rwl=aITuhIf`;$nOLJ|Qf;-^+=rQ-17SS&?+0$N zz4FyHw6|*X9TjAZ^rhp)YRtZEkX$GEWXwMwjaLa|0*WPvGrUZ3p0RJgH}l=L?pAM5 z`5WTSu<{4O8Y4k^TfJ0HGTMU>E34{tZB>m#4cqvSa4_QW^Oea-ltghT55iw2JD-8_ zI>&$>XJ}0y+dk-{O8)@W3Dk+y(DZlC&)j-K#cL-%#;jJPuhP=wzf7(I075#0UiW7+ z;fAJvpPy8oIJiHL zVF4=F%rZT*5gcM-VkSts@+dx2Y8?SbR``$Q{{U}$JLOk^v@-d89UVOOsC8bN#rru^ zEIpcM#TG$acSvv^97ZNL`0Bj_uY9iZTf2D<%=qnZxJ+)f)Ry%qXgxccu$?QTRemSh zRAeGbhB;#s4F$*p8xP!Pd70;z{v~%$>GRwjFWSEG-qCIxj>#rQ{>b+rCBa5R{HDPKfqqWMm7Y9zGfQj!{r4hq_^o57H7=DcMW^)b zjD1FmHBFLPOR>$WE3IC#f;VZKL-bP}YY*wQ+OH-x-;q=)_ygR{UD!Qa6xVxF>PlbV zrfB15kjpLN+DA#=(g}fF2QF)a+9o1;-6w4OZR5vv{-@0BJA8rfhkx;UClOayWU=^s zYAE1o>hxL?WajUzL++W%2EtP_JSB$%KaTQC9gSz4aCx5c8?)Y1Wby~z?(cUGU19sh ztkE~AcN@9by9j=F@q(`GWp@GBrBPwIs&>T>$K9o#HVEGHDjSLM|VHQsl4E$7^~8_WbzNnU1Xgz+TA&a%J&|W zCo8EnP5Xsk7obGuVNh1Uh~nP>8G%7Tj{E#X?>l=(&?~r&$49Tre$r&Sgkt98aN(t% z)SH_;q~gHZ_L&yYMA;5gJIwF5R_9@JUG2bs@!Rf}XX(*m{hutt-g)`I;Na&ePb68g zP2XHZK@HHyF07%EJfLDECL$xR68dvj_m@)lx-;FHj^Wz#3iZ@~5bZv^ja^MSf|RTp z_9&p{+>mbWb1N@o6z)WO{Qm$@)UN7QsY(@gsQ&;C79Xomx-I%HhZ^*qNjx>{$-U1q zd@S#`i5jk^k?)=d*M`X0A;)H@SvKSH(-2V$_R4or%&&e2GEuP3{{S)7-`YQ^SJZR0 zb#WcN?SGYB>(r58QHsT3FJkIyi?YH25L#Pqvkam>2jrpvMmC7wt^0jX8LqOwNUqgs z&i!dEMXY?z%GT02x;WYZg1p^q`pWyEkb(7r;vl7^5wiV)T(_RC@1$SSQyb$0Yxxh~ ze1dfskn@d%20EAoM$}YLva64XIl7E;O?)zUsw^h2i%_MW6Oc*=zDg4GX(<8nRkqFZH1gb z0mKZ%@}84@Z~nS@jbWSA-U59-wT-E|1pHTWJDq@%SmMG?d1ElFndc4SW9+!H{N=OR)^L>c#79wp?qNnGpyV5~p!8X7dv<)vlZ%pVF{K zlX&OY99E6RW12aQIV;9Xjd$tWi1iGMjFM9j-(*bsSWrb1E#*9ZAg4A|>a>xND$RCA z$jRF)sX2F{iwN~g26#vjPqbj92qHiJa~&_5>#j?yl&6VpDr~Xt#bn1p%5b9F&_Qs=YzmN8Uql%5}Ann3yf{B zKz@g4pqh+^YNbSAEZS|jRj^_!B!`4cWMI$%5*2s*n3-|UGYH&&2%dni608im;$2WF zE2@@w6+kU2r&sBMVC;ORZolV*b&WV;&R7h(jvGgs6nYr@Y7K8x(#K zJqvNgX45gL3Raq=zaI;#+bv<7t|VUJA^f+HIT$D@9p-oZx&X{>BNdRO>~=!UT-t%= z54s9nrwDB(9@$`|y>T%k!UUk;VkTw=AXsBlmOGfoR80$|Rc3Jv0Tw#J2uO&4Hbi1Y zqy1ZPh>`yQ-%?((YR~<(U*$3O3gm!7n#VpKsVN>SFG;{mGDZw{AA%U4iHKZP{Wy%0 zOAcd=cu2H~LtVJ&7Qs*b#IU%@6zwqsCA198?Y6)`>?<*BsZAW~oIB0pU3qJ_&BGg$F$YVU33yz%wiGIFr?`rHJn&}uW2l9jQOF%uI%<BlbnMPG47EJdozhCNVCwP8T8_WIWa_z(D)#{U4ggH#!7IJn2-X;S_-C14Ve zWkNOD0+ug&;zzWP=O@L&K@t#A8}HBp->Z8fG*M>Vxv(ix+m0Ru>U2Rw#}(}Z8!QTD zKPjKz>N+m97|B?}hFLVSxUgzlQ~4Zgms%oKAi?=59y=^{f{%&Zzu!aDxrATwI7+!9 z%zdoHVdA>d&w4?z&T1r95^i4NWKsA?u%bR-`Zj4|ot|Zb!qyzA6{E_**{=aq$jfIO z$qNZ)ArS-f#y=SNjk*F1XymbJWlUZZU7Dcejd;wAEhsIcVB7|I&mI%Xes&>`(8pZr z)5?YxBO4cOVko=q_l4fb)l@)9oR6d0L`0pYA`5-Df{ni(xzG_AshAX@xrn2RzSLBy zTCMud8Zj?c!RnD=OwQy5%l$-0`swc+<;T-q%yxFB8m*;6BBMRTjf?^&!`KTEX+#*$ z0hxsmM=hslS9>Oj#7(KSQRuut%1uT&s;6aw(w3@<_uf>q`;JSPfin@Er)Zvv^-){t zwpmjLeXk10EQ6-2PP~3VDNro`0K9@%Jf>sjWsS#G5UsZL$dt&;M?jsXRm{;V*;0&)19idOrCaUC*oY%rW(sS}r04$L zCOvZo5%C>S_OH6ic&ivVaa=F#$L6>So}?b|wR;vyH<3kn4j~2-Coo@@(BSSVnNPRN zMfy2lY%$g{aIsvnN(q2w`B_XL%;SUs2?-9xJM16qHo~K1gB#wg?9!$mZo^BXLhfa%ohx7B|i{54%-h(7mx;5yy&dBeJBP! zbX^Q$9%4<7JBQn(VhoFq{{UnWvSxND=n3lGx_`&7AC|#Vx;3iSuY|?}S!&wYKEvYW zNd$yTB;aNsMh|F+i0P_o>I*0u6#?s%Fy`obp0-ywn1p|46^kQzX>o`siH-N(XJ!>L zSnQD5#$w$3eAu@6Qt|6eBZP$UU048~4g%UnV77x85t!Ixr7C_t4cVRScvrk0M zn-)|+da?&ar+Aj|koh3?gBcO>sV|s_35fWOx;pytwttcgmNVGkw51h#+-N5g24G^@ zYZzv601+OTiGh!p{{SiI1(>D@p3=cL6j%zaX17)HfD$TklZ91w{vBaF)DefloP+-6;d)cO1~vTEmD z(BP^w&7u(19dU67y!IiOnTcM)$%*C>wZu)%s~Kv|dl>cPUQ7dn$qi)FS#fU^u%EW( z1bak>D1#OR!I95EDjL{;4CO4AqNXIqrp1Y*145|*%!$^te%+RQqPzosV1GFH`RYd0 z%LZb_x_JziM^@4}Haw`o*aI1YI|*>UBi6Hn2!8Ml5i#Sqmi)?M{{W9Lt#>7L&%@MN z4nHAyE1QBg+hO%Hm5GQr*`!QlC|xr?*yv}{!>u;2_%_9Qsu>1Anu((@N9q;~`s4Oc zWAaR^lFQGvnOmtdfZAdF`BUR z36VHoqDnbH?IJsVJpn3HV5w1XTO?!ZrPo6pZB>_F8scFHL?%qsa03iKfZU1EAL=>< zl~qbdA!8HwxLRhm*0yHQ{zMIf3=)6fsAk7n2jg(yaT6Qu3~_jZ(hN(nR`M-M)%sA0!)p7MsGWj%w+Ko$y#dcS27CgoPk4HNQg`mWR{WOD`zN(;rNVg zyp@Z?SEWYY7dndTn@U^Cg>g#M*d2)6)3B%kl9mid2OAt>EA+%fk+d5*n%KN*DP%F1 zZCg`=?~0*2)};UevJ$m{9IRv(AaB@U;(dDt@*YmrN_B!AW{w>^>)K!OhRcNbM`@;ndR(>ncJWxWnZ{s>j^5=Dl({IRyID?*^7Xb1exH~I3`&JCmXEf#5P#2 zI)@!ubgE=d%TbvI60EZP=23OnNHHTP63lr*0$IieW=x5!g818@vKYpjB-E`jj$%C- zI@fWS=zP(tqAlE*_rsSmMIc_Nh?!sOefpZ|qa?d^arkh0Ez)a()YW2BY@jwGcyKA0 zI9Nv$nJM*-{{Rp@0V*-JD~2Mn@YV6ePn|tOCH5pBtId>+YAN0c&SMk;*<5~y zjJ$?_&SQ)~1lY%3aWf5GELOUTj8(8e`Yl1r58O?Az`$8BYbXhsFP*>Rs+(6oK*o)f zcpk)(t3dqEV99>w%5hJpavgTBaz}G`0XD* z@BqkhWMOx3FQJ~ShF7$cML4k10GSp+dq|`Yft14nVrP!g{yh+;Y5N0im8*4%kz7qQ zuxm13WoF(YMlR(I-aTSqU+4yB{d5L)xAK-Q(;HIk)OxKzQ+n8VxgW=CHa3lv22ry< zeq3V_@zbhB_kN4CsZO8DT!!Cmd_Ax(HVDRL19a3t-cY4Xm&C&3gnS0w02Vo|5OLkZ zok?YYwUtFw*r-jl1y~5@VJ=QM05fFIuZa%P%aq9$i!wOMWr#XyyIqqDt@ou0tGUO^Y4gxOuXyzL=23d*JylOh3{@FriJ2LAwz z4*Wo31; zS+kD(KBOf1F---W@CB4DQ#0%524yopF}F@@4%1N1; zCi>yi$%}l=f+-08xQN^*uHyb=DA*je?1om! z9pYwL+(tf6BaLMR*j8$ePuXb2!8( zi+R~g0f3o3_LwRE0L!9+d@+-L-bHv_qcz4h-*Pl7@wK%LlUog`Qub@5Vp7($dDos` zODs{H@S^jPK8PbjOX_CoArA^7q69^$LS%8dPi{g&Z^VRAwo@Xt3 z*V%t1JV5%8=^U0n8aRB8t!Ta33_e`Kz3g+K2b5SuL=(~S!3GZTAD+=0PhAzxAMGU4 z_3jco>%5(e@^YWi2fW@Rc!ghC=|3ntY1}{@jFd*!IQZYic+fBcQL9)!rBgI%_> zsWk0Q_R`H{GZ`C7h$|ReO^QH=zCdGi!)%POBjR}?OZO2yc{kSGkn#sJuJ0=bofoh4 zfU@AHSmbjBa{MW5WDCmOlO`c55L^D)akDoVo&Gk+{^IIQU8=Qyt?wsub-t|D`rjsV zV>O-1wq1Jct!1*wr7eOGhBSjVDo+!RV*k36CZ9x zYbZ84$Fp?AXlKT*-F+FpsH@gm1H{tu8^qrGVyoA@SiHtg^A6yH;%i)HChMGxrDZZC ziVR4Dnaqqt?civ@)Bd-Tow@I}iKVQ5s!3z??M~_DYoQucbdXo)Qtl$LLWOIF zlrX9#GPXZ*Y?l}q_G!A^E17NCDsuiAWBNRrUTJk`tfrsjUj9ILD*ph{$Glo=CFAdU zG=-lawZ>d^4|6*cjHo4|aP*i2Xo_YDn-$ow0Rc8P4EFXwEEogU%RF=QqsJdTyFcDu z(|Ez$oip_I^M_gEM&4nI!c+cQAM2Pbnwi8#;LLmA9@+N^!$06=a4WD%`c!JJ;rPke zp3QcDM15BLnC@lOPkMFcQz36XYfjhub{*YAe$!HDtrF=4Kp>UMVnQNhId!RzsppCQ zKlr)lPQL8FjCbqdG>%Sm?WU}*71e0lS462kf^9NMp1)YC&cs`+ta1GS^)ptiV4SDf zA~`q0$0p*>x?Rc89z0k2WBnlWzC!se+$}kgWlrLEov%5ejIv_|X1#o!!X;O*e#qD= z{wacj8QjWeQ+>|*PklnWL8okL9RC1~%*^R(aU}86+4?zKHJ33wpw^>XSbI$JC>e?0 z_dhWk5&FXYLA#IidedGteLs8`?S2!qx@zW@n@QKs#RGoQ65l~8fDn=kAj4U?jcCu} z^-uo*%LKlV{{URysFtYncgIf@`{}Ohc{$syeU>ac?Pal*)0x1O*ESoKkfxO_%U1y+ zh76bX6mr@JZ=YQ2+Jy5`+Hu<+e+T!;Yo(#Z(fIROUYRjl#Qy*`yp8a~xLJKk*v(1* z08PHrlUq`0{QViZLnKO`EBm^zP}JE_E(RR~G9kcVwvD54I#=tb>AW&+$shW3u-D0Po3$vWb-{x7`Y(a55=x3Eywn%=Oh@U2hz*SkE;(5T76PQ}Vsh z?lzsY>)1R+VFR&gE%k-QrE$SZWEk=|h=P$RpP8Pw1@z!S)V0>Y-ti6%5=IYDvx>jx82A*7@MIVee8;2pDUh|U}ZLuij5@QoPO!Z)W zXTG`FuKeV49t{0AbxqAN+4|0YGgfy`5ORiR-z|c594iN7Qe$~p*cpjzZZo)yZ>m1T zc=?U(eiKaQ>td>v^t7v12VCb$*qM_CFD@h5xEo$uFKIY2iTIAJR4u8~jw$eu4CdtW z#2z_#{{W}^OQ*3J8o4{ob)z*!Qmh|rWCUE+<25m+KGn8jS1?6C`iP#hd5229ia8sq z1OQVwOA63bWrwsxfzk|I6p)J?u`}GDca8R)y1TU9JXQ-WhJ9@}Y*9`7MSMnRRb+yG z8yoSHuN;mznQq<;fSKb15oP6W@JUa#$gcr8UN5^{zPB1@Mq z%l$`VQoBOCc%qyh3eD1MY`Fg2h_h8AB)QzdO7#)JL7v4DQOke#9a}f-Q9`PLGTp3m zh=RX5szyCbhDibaqEK9jN^GCX_9Bp(FUB@$k%rP`EQI31trAJidrx!{YpnPg&!hhU z@*IDk2qK<4jKoIqJspb%)2&I^fU}UbkNd0D-+`ut*-Qz5`@A|@tiW;V~*Vydqha;UaL zFEUT{%M4c@)z7J$gH#Z<3t)y1-9H<_Op}ktQODTD)om(N$ZRn+>~RO$M#RE%IPL3! zbcr6}v`Cys`s$iaeABSJStAnnp>Tpipqh2LM&8Pzx!@`vkvN~2J~1DUKpT#2e6q0U zj71t$&K}^aVd=CnUO>63O0}P2$&nC$oNpyFzWqY_$+I+Q<4*QN8j6c{D!($82*}Jf zYy<%?mjlEDkxYz(f>)5H4b{jBL>`SZJ7l@#kQgJPx$pHfZaSNDf z%Q%$Ch{RWq!O_cDtb@w0GK4B^RvWFX>cS4>C95R9fGW`1YcKl9Ss@=j7{Td$Bf zB(lwV{MAg{!&6fftBsdH6p4tme-0`b+-4?cU>H<%TAVq*8;yMyE=t8FnG@`|oC}4t zAbs=g3EmeBjiBd$gPqd2DZnccZy=>=O7>T1s9K=ivCsKXylH!8RA4OuDCZu*N~UA+ zj+rrJ_kFW2>H1gZ!N7g7#fI`AZ1E{3h{bt?tcpNnOK6?vXxrqP7U~#NB(KnIpiAlG93T6uC*Sc(d5ibl0U z?(!I15Fs=a*ivh<6huD6i=pu`1W8m8NXbCVPbuCa2{F`JGb?!GxA!S8yN}^(2iTi^ zw#@!N5o=6V5ry~Wu3xJx*D1z2jC9c7fRizZ+epl_{d0+4j`s#Cme z2S5Fh&^K?_!d1i_T-G~IUwQ%oE_f}*md9H6pOix zx+=YP1`m-WSjc3Il_tP(Os-`@L_;zA+J1VGIn-Dh*08oRD?1x4Sp}Tc3ycX9D)Ppl z0?l{{^}$4OnGzWP03LvOi`1I;0aj6ojXyTMokzQM7*d z=Usf%S;+$L(Yso$R~yql(PM zj&$OkD(;bQ>5ysyHY8#f%i0Dz@|ffJ%*yID6hi6y{DI*n;pE1>G(BUHAeoYhX%{6x z@4o*4zn+N@$mEvHc|QGGWm&b=bMA=S__8EyjL400GM{fFU`*^&^VL={HFG&+j!LdL z-0Ax&mj32pPJx4%Dy{G}jGJn|rhmDT(U3`srK2cgv`>TEL+n{X-$2n zhzY7D4RQ>f#HB|c_|HImw|T<$U%!5vF*3ll54k+qW$ICg?#YNS5-AqIkj%uKmnr4( za^%A8T6tQRlo*S*g48u&mM$6uK?WYj4DJ&H6Ff&^{e0~`F2)Njg)-80oMzAzT(^z5 zpL4)h0>|1XD3J(vklW@bpa`m}xh#kAcd_;@IA0H;NUJg|<@rpE!oBF?y7MtSihrskN@6)lOwVv> z{mu;~PO1*UMANRudn%lAG@Qc%RRSPNA(;_@D39Fqw3#r-R}|#<02R7eR;*}+V=qz1 zrXpPfEms&OGoSSw%yE&KF~N|>uP_%Mda)@FMndg&n4EEtkpMuMSD*5j^+@l>iBG}D zKrb9^x71B*)1*o($x^u#Di%JSx+5?HR%9$eEpSAFQviR=TM_!`n|aK2l65>!-C4)F zz#X>{*$Y_~H=3cs3uqXC&dFP5XNddeCOxOQHRj8$T^h9lu1fKtbwbj?H7dnvmO!~d zvp+v<>-1oy5*xx_1d;s;XY3u8h+1!;!Lu zEAA$zy|0g1HHMWXv#|*aBWR8!ZQpI?dTm)1^0(b*P7<<|YN{g5!@f2~W7+U?=@JGu zOPov${6^m&JIefv>g4FPwvyavos+gob+=c5um>W)vi2aC?3sv}gPswv?GZc7fDJ2H z%wgk^{6)MaD{wY#RjJK3L`W3RU73LyLkcV-^}LLWBY&Cd=Uemt0DE<<)EIipaM-MV z+RQq)q)IkwSp&L(UvAilf{t=UGaDB3U2Lha>4VX6((~hVY|CrccgGVkWo2z)#B)EG z5X_LwZSlO0)?|%oUQV?@%GDyJLP(5Q5O6>cQYj^ZrhgJ9m)u7p|RDA9bwUEqmj;OGAhT{V!jB2P2nvbwF6Kc(Sme&vm%^Q562+U{KBkkLX zM8L;NSC6k-9dh`!83+TbalXWuijFHt%oR|EAF#NDeY*-oKovY=@z^~WMT_lfDr=V)c7)o5;1Xjr#kKFxPgFJTEu5yf~F0701?6gFl*5BcicsYZ)v z4m!f#c~#X4)QtrNE8Xm2#LQTg9864%ltg}{cGzQ}4WiKdoK^D3Co3$qwP)HNZJQD^ zGD~w}83`uI?5s5STE!lWWKQETx8y&N?Z!R^BcKIvsN!*Ny5~}`YCp5NRaGuP7_WA+B*n%n zXsRH$>AQ5thy%+CJaJ_Oqdd$Loo*v`0p|E6DC|; z5@jrwO}cL82iYrhrroO_bt^Jw5%x^Xkuzx`9fo8F{f|}qPTpd+MYQYW9l9K*S+5H; zsG?*}yF>Ff48tIXXY(0|o#HwIEQ2Q=%u_OFT3L~@Su-zK5K}VP;mU%ETLFAvrVM#= zmGAx|ut3LE%h#^T8N$Z8UUcXa4VQocGQ)W}vnq=P&1Jbq02Z^3(nq;w+xV0^z*5tC zW`w!l$dW{9%#%oDhz*f4Wh)BuNsqu{0(ReisJWA`L3ukvtu;oO$H6S%onb`&5>Q^# zW8jw0@nXig#Hqh^9}yul&j+q2mQH1u|pKP8bq0KM@1f%}!wzSB(lSt&p#6 zY`8fpOqj)0h7rh+tO=5EN5qN?Zej5e0zCw!h2$MP9Yw_jOIyiucGs~nl4LM&Bn2fB zL{k!Tzs%3Zz%P_!@zrI3$i)^se(stkf|pSiCyc~^zQoKe8@^27KRIk|yu|cF*F~p| z94>E5Jgr&uuEQN-!Yvl!atdPCGsZp8M6;c_6#oG0uZUDy$mFX#5;st5MB29$1)NpD zC1fioB6l+q9f~F*SHJE$`IE`I^`thIPcNq|%Zb94Dekvyf?%4v3vxGDm*M_Dhs1xl zo`9y!+LrF*u`y{4mrH9TtXEQ`y(cj(dgPa3t1^RFuZb=paWV5H*TAPl(h3=1ZnjNT z;X(3AE-)o7T830gDV@Dc+`kW>jy-%lhDA>PNYRW8n*wZA7r4~_0CAqsD>>qDL(7!R zM;U_{-gcOU;rt#Um9sW4FCAXFGQHLirinevmQ0k{X#+{T*&D!&jEIE6Oz#i}S?bQ* zQO(qYO=HJ}po%qaBkcxnttJ+U;YZwRShSoxIdJy*J#I zzwYQ|G?_(zv_vE&CTxZroNp#AToeTUq>ns?{7%tX%lWP&Bbt64E+XX_l@FbezOSk!HIIPZ||}GIe3m;sPFG#Jb|;4&>myz%5~S< zjc=%67o{;b(`(yP6;{Zz{@TrlEJgMmuoA4QBjsfi+}~8sr*C+^t$obUo=JG+s`Q4K z@{dJn-~Rwk`;pkaTbmjeFu4@I!)_Kf%o{5d8Cm5Hu28osP;)$tqpMTKUod=U^S=V# z-U!g8+@q>7o6(hEgEGNr%3xZl2`G|O&*EHX^*v=a0DFPsMk@h@M{YD1m;N=lgLY+`hMyv|bYJ53J5175PMu!cZJ1i6evNfB-O>FmT@zqpY+#Hq-g)@@`O1 z3kPfMTCKzSyq_G`=z;L~1PRBCKqk1XC-5p9p+q_Uk< z6inAdDMBZ>i@nT`$%Q>=qs<)+<0hKcI!FHi>7&bCdFCa(P>UH2ZJgA&mQcwjGwx9f zB-)gTJ+R4`TLg$Wu6fS!1G5h&ezN{IeJ*>stGqS(eE4(P{Zp#6PDMD~ajtbUzRWIP z5|4TziAg%cVj(-WS;i!`+i~7feM<<^*{F3K{J7RCTE z#Rz(@q(s|ZOk-s-WT1j)^&`|RPO+^+E#gD6(j2TZS@tSNFjXSLHRppuLX@LOtG(n+lcQ~nV*P!58AUp0+GuM82yWd}< zw}`#Ps2@wOr~d$dyR+rSqpr*zCQliVE5a;-f`?@C*BLZX{h!+8K$!$_l9-5y(1jk$ z_Y*7LyPi3A^8o(g_f1-!-j>DFsm&?9W-JnA%=y`A7zraO`1qOq%=PVi>7n%B?Pt^X zNB0A{TJKn5H7>lhg8OY-tgJ-R$6~80Il83=$n3i6Ic$@6f^3w*ZvZ__QPAx!Qmqfd z`Qs^b>_*D!;*xZnvlF;G1LOT`H!XQ(q+&z)xLFH&G-l4B<8W6GJhhRMyuDAEEP*y;D*y6>d=rO zn8p_vf@JOO-GebBw)Rifm+Moh{PD|bZw!1X&Dhd@6k;w#9Z{(@~OK~HEBSeP$B?74b03qaY z6C3T-f|WXS(uFAD5z}r@a|ZGEu{e(3cK-kj?1Wc^R<5?+VI~$e*8~wNO`>!}NfQ=4 zg>q0JUzXDm8J&{5POFn`x`A~HN*IR4xq4wsIRa|q{6rRGw)=d+f5i1pDx~49SimH4 zI9irW>Z0K=))=BG;~t~MebGaK!+b#Pd% zgOJB#2P=>qy^FQdHzGs9slKIYtCx_V!M#qi zGDel%WTqe;03i}0q9BQ{B_T1#{{VdpT4>{Pw35u`MQ?hUCPYA#+Er$Py|xwXBa(j+ zV3bG6PyEEsKuLcyV&AmqC2X2&WJ?)QBs3#!;6EU0rVogTn)V_fnV9&A>y=mc_7TdX zg;475Y}hTUsm3dxWIDkCGyF^N7~vbv-!fegRS7K9tglu70L2bISzK?JP_0osBiO`= zz%lO`l9-vDx0&1Le!1$x-_2swXNSwyU8Jvm04|kG43&hbWYYIULWT=?kI23^l9>Pt zmulpRAJ4H@8(|El+lu=njmNPmJ>Y=%G2<(US$u9YKkurtRhM$kMKXs<1nXY`u~Y2j zOBKq077?5roXcRsCIE(GarvF)HXa`30kNM1U1IB#?6Tz4NvG5@bzVZXilj$}5)qSv zlH9hKh#KW!cdFxVH|&_pb4nbz8o5K7<~+?pJc(<9SwzV|F^ZDo$|ht3aqboc+BnOo zv4kZGYOsb{%x4wCXMhIF zF*IsW)5_$F1y;+wax3Kt2W;^5@L>tZv2g{+Oa3FE0sH#dhpF}S##29eMO6f+RGG1Q zw(2&GH!fkW^?zA189Yp8V`<|(MU(rIbmEnSvKGo0WX9$_c43VbEluJf{jh8_nf_(- z1Tp@)WC^)J)iQZJ1@Nwqv{hE!B6U?Yi{eCXlY)9$MsWu-xR4zDZ`3ne4N|sg0gkPZ zzSW~6Qp2)&geyu{HoC~ME)aGZL=eJKSmI>aIVOxQMqpwJL}E6b z=(B$5*umv;)iM|x)t>bfL>WclUf~DpnVo>SZxQ;9{{UO>(vcv>WW9%hZk**PtBt!{ zR!pe@F)9k{nf!J*GJt{DWTd0!XP_Qq>DbFtMVd{~*(7m@_t=(GVU))y=8>|I5{W4i z;yX!1{O`Wp=nS!9hbMe>7B@>XFYO|6GccHGnNK1njKbm=L_}q@PsvR0Gc&h30c*dL zG*>s%C*OQUs#Rtom6;H5Fw%;|wUBQHJfdO>K&E4T=3=;L7`-Qr9gH{Z;AV&wTN*Tj6v|>5HK?l0Wf@`CT0g{0cA|p3`*(( z2M~j&X*H`>fQxo4TG~V0O@aY71W(T>nVt6DcG@Y5Ox4jjk*UPi^t<)!m(JUT>G4Dni%kBJ57UY1|GrO3RNHD zJPLkx-~IG-FwgmQI<(@k5mkecg>$$DhTTpK!~VobBv@hqB+{89iIAVe z;wNqQ>5efaQi~4_sBy4nwk4OcbXPUtLO@C21S$_?mobIN6pzVso_j#{8Df(U_{?5o zCw|QkSrs&MV`d5j)ydHig$ODN4rAn?zvHN~7GkTfULQzc4e-4 z1Vqr0;6cEp$Pyy>DO7Lzj)BNxn;6S^jDmFGWbHN0yxVqA61D*>gkKP$frW^`2#jwM zJfeRtfNaY=qHKCGLWCw+T{m&8I`me_=CX2>uqyIGGLe~{At|4T-gjH4>tj;7I9z*h zwwjw?Z3zmH$t$2T!xIgOWXa|-16l#zUS$CM6NXL^cwMIQc2+yV*Nbbo1^gueB>1DGH%s zUX`(q7&G_n^DKc}&foAe(f2GxCBEO;QcYX)F0uCyR1M0(0AW_M_7@XeG842%A>F^1 zHu9~7OJxCC|+X_5Th3@ z5o}yV0!JLJj1&+-7?d1N@>|B=jCI0JdmjOF9-Q$A!3E4XqNt~H{zDo{WDpuR5JWM&3uoNd1?z$)`{7pYbECX3w0khLI|I~II>D4*)uzQM99B+b-Iu#TCI?iU3I0 ziQZ*7@sY}qD#pw2SMC9FAm z(3vt~XWr;AXv;|b+^pig^kr2IH7ZG22ABBrumuHKf(CrJ z#_$b~nS$G|m8!5xs^W%H>MK{PWBBScv=#(J9|`v#Qi z0-%h0Yy+WFMr~MP*UTV*1b7o9!Ut~0CF}|=)5Sq#K)MHzVOUPkP^U0? ziwNOB0uwVlb|{bc&=pbCudav`($iRH7p-v2J-}Nm$;_CkRr#=xU)ds4B?r7nmhv+) z^l<M1hXslW!#5LJ!hfxnon!4R3^RfKxXckBHWU%W?Jy%B`1G&tE99(Mr(V_x zmR$PQk#eSc?d~grclE6!1R}VNr{v(Ir1y{1%ot?*(Tuf_t(CcrM9UIQY&yD|1qH;V zMLV3yZ^XVLOPB1XdIBmHt>dzI)2(L=?7T&VSBr^SJyQ!AXAfyf!7!wTLSyCxerNR) zmAq}rPR(1hsBh%H(tXuyb6LQf0TL#gaWcq{Z~p-6?GXSQe2-MVv)+%q%jw)zX93t{ zsJ07Jl3v0&_gG>70DSOT!~$Y?L6*}Tr>Nd%hGL?nRB5WMtPeg3HX7%T=k^Fd7;_>B z5_A~M$V5oT2$=x&U&jtl7mvo-vt2+{+rpe*3nOkqOcWzrCx3h^n;6sOJijlEx(2Fo zkjl9erpp$IzPlu!Z?!KEn-e6d7751N5RAmkOiax3>6;NQCehY9 z;B_Em8(=0QVHpCIM)R@%0K~^YQASOR#JbAyT8Il8VM^Lzm7~+SErM1VGd`k)`~+>e zODAv2cL6pyJcb2kn()pdCdP zt2ZI#XJ(5^MY?Wlzky3|xX>XMOhL{{XIlR|k%% zjiqkoe4Equ!H{V2Q(ELjgsIVFp+wFDDiMw5Sk5iwxb4)L44xrYF7v|HE4D7IVM(y3 zQnR{ZXZj3ARw5pqghPmr2#NTZf{@b_!{zQ|ve>6aMzf10833C#38JH8BDy16?o(EH_O}@JUKleH1~OJNB?#sP9@sJ7B4cfaCP4U#$qa@X z_FEBOCy_${<|#1jnR}Q3V5ICawTQEvkp3kuWPJWzb>6Db!>MsaiyW4e#oMGMRWG?j z60}(o7*T);1ap7`4T>juk@=mXBeBwl;g0b`ar6mQmqOIk^)9tJ{-_4RUJi)@gWhH) z3zFh?{9<}4`sTw*aSx+xLQ0(jxnAYVFG@~e-fm#R+#@@+OD~0)nG8gn%z>@`;`sfP z(^}q+cLifLr8SK=GcAK{9J1-&#KzmgmvL=@Ognk_ncIG2G1kKTT>8uR3$`!D_UFxv zGBb2iwW_AQqf)$$K=~OQwRLhCksX2_jklPY+kNJKx0x(Q+}@~mF?mcSsIgwaZ!#?0=1iA7q;@};At>AR z))@Bp2jmCStICek_uEG4%s#4C11PHVW^8e*kj7e%O`6w8_6o+?WJ26V0y3iBc8;|H z+uc*-SA@CeWIGv=WnBq3Q0uyK_^k1{0yT_5wd>w%3t&cK$Pl&-CMPf?Gd`7k7W3n= z9&JtsL29a49XH=3;}0F0(79t@-CK?a2HNGye(7Zg$|R5EON__I&pOFUE;8)QWv)}f z^UV*VuYkT|ci&j~0i=AayY&3-_HxwaHTICzn7WxfY-9-p=2)p`?h{&I)B@vTp5-%W zDUMQ6)@}GX*q;x+mHn}H7s5?jK2iBQ-Mpyj>fOT6D~2B@kgr|utNoRR7h4jaQ&@7I ze%4qBCm#@ieOKx8;0SBEXY5`XMU?o zrER4x)h9N+9yb2~l3upGa;d6Pd5LLw3E)3$d=2d$W550T%xN6|0FfEG*0pB4?iP6j zjD8V}{^wP!v!80v63Ll8_i+@#Z?|4zey`tI-s1g9vUv{_{6NWSJZFW~vIScyomje*S4O`Adx6I&K0I|XTp=0ImL`Nr7$+78Cx^opul3~h#0N414z4Pg*3fRCnm0WFO- zEpzkowE#?Q@zt80I&g}OHH3(%RBiHFor>}APWIOqj=oszg@qRX0LNwj0FG^H*%e98 z6a0k8f&^j*hZ&JvjQ%klWwtJ&FwrmLnWGjH$i!);&1Adscs@BN^1Awq-m~e{3f(B*=M5JOipPO4HI1~OeAsEW` zbk;y>(XEnLGOFw%Q6gV(xL__e+l&tmJ4AoaTjaq_$7HO#Bv$g;uH^*{o7N7pq?<(G zfJu+769psgmYjUdn3?|LqOvo2pLsR^0FS#Z;&yDE1#x`EFwN5rH4(=sg%Q`A5P_2QtsLQS<1R^QoUs> z2~0y4Vh&uACU_i3@4rAaH`#3BF`1#Oa@@!Z7K^@uYd|1(QOOkWpTuTjVmU0QZ=K~G z^f;*6%i%DTH5G$!jhQU8P*jMJsg{OfV|fqonBy{BCU>4)9deyk>RO4#h47{(X|C1P zSr`#O^H~hX^+v)wNA4qN{{T_b3#}S9Os(X`<|XiT>8%E0YD{e}_ZUGOl!*S zQv%sgRS9d5(Sd|5RbXN!07ZsE(v|P)C>~KW(bW<+*^Qi9GC3L+**00S?O0uK4d4Om zF<24{enlK+WVe}__}VdMO2Ahva#Nj!NErp1<6OmH*@LhRw>(E__kz!sH^IA98W ze+iH&V-99Mcb67ef;*F2Ct|h7RW-tHRWubuGGo&`@haq8`$OUU-XAn)X z0lw*luXd3`eMSaDvcv#p2YD%$mmR1UPWxA3u-MhxNMkCL^Psa2hrH#Gs0mpP`*4$) z{{YT@AZUn0s{7S#*+<22LTl5jWSGe+%!w7uZ7wf}9&&Iq!e?*X%$7p!Ow}`e3{{P3 zUd(b;3dm%Dz>G>7xa49`F6Zom+Dmxbahd1@Ft1i6IYYMClF((ltg&(RZ9dy476$34Ng*jOWmXTZaTCgSk=vB=`JRNqB!f3> z6$k$SW_DA3_~DmB21Z~k8bo47Cujyt7W2rr{rsOnu=UmoD#5-^(aD%C+%uWe;qSpdX< zut`(w1N4k6;%DMiaWNZ2&+a;nG%TK10Yd62kQ4N9JfL%^fDWB*T@ltCoz*2qb1pZ`RSi@z**7B)pbQ{{YA) zt~$6jOr}{?td^Ispo%%FNMn=~K+ODY{{X(Z&;wSYdCaNKA0>A&Nh0Y3c}dN7G9W+i z51gu0JCuMn3PMI_Xx=)K{n>=yiB&v?SNaON3X<6eQYsFD}mg|x$#sK5QgMa zD^9fpWJ0pfJ98;blWF4sZ1k`~3U~;rCxpwk*k_E$&&K=oDGhu~R|@uR4kfBtkk`k! zp^Y8IY`3%ks8_~BRUbYg?OMg^TupNjBd2bf7WJ=>x<+hsHSA>7{y!5kxZXY^sGfIf+q~R0YMEQ|MsBHo z{K5N30ESFBh`vA0IE-=Ic#rqhIC}U+<#H0dMqAxt<~_EKl|UNR(IxrHfs!JGjGo)7 zVt0w?2`@gvV!oL%$63q}rSol*DXm@5zkpP%gbA?*Q8V!oCSU$j)O7QVRK*apicUrx zE;Q0rc0KkNyprt7h?xTdKv4d1Gs}+OhVw=@*@dxerv5u6V#QUWgJ^|#gA(2u!IDg5 zw`daPMH|Ua$L?lajl5%NW+zc(aW(5>6c%jKvtCtIYl4CGGA3mXEr?D>)>ATD?>qbe zk+X$^{v$T(ISS0N?5~Vk1P#`py|611iE|Dl;$vcs{{a4b^vv43wewE5l8p97eRr+^ ztOgR`J|JvC2I?s113MqE<|miLM@%SQ#9pu#DvR4mwvNIXTXTzIppDrO&OV?_Z7~8I zb}z4KSOA26`Ax(${T%#XG~vCopu7%{vN7RC7d04TyLf@ zEq%ZOf&sSFx`m=(`pkq5VX-g=^S|H(!P+8caqSga3Q$?c;%&tzj5@=x<|Aq9nFET- z`SqwszXBbj_c7Bh8GM#Sm~>gLnkrG;wBcyd$K%?;g_5A!=_gLo(=m^OD<3<~{T*I@ z!prF<CT-X4S^scf_)U|DvZlaQny>k(?M8^F923^a>Qu`c%+UCr(T&lT|IiS+I~r?WtD3P*V+`WLgvaY%(CDiAWb2nV6rRikf3)?J5aEZY*t- zwyrhqV;qtudfW+xf;p1~e1?8jFjK$h&=p&%H|V;qJyr7c?xF2**Q@BGV$bzNy3K<5 zh#y=CjK?j4Hu#w6i%Y=!loOw={LP%cQN36^n(pS%Ov z`~0Wp=cb2WHCs+rH{mjPx7S)s=){-~5>5ss3^kDnvPO5>3M284kB$1RHrbJ6*It~= zzc^@$54q?<;t66rN&HMEMCLdW{$u*afBsWrMGmaIPCEvNi(Z&wT$8Q*YXVwu!7qRJ z{{UgQwx5lPKljiJt7I%!%w4wCuPdm9dv6t`XLhQ~h#_hhN3b?zoWcGiMq9@F?sh$N zsztr(FYY$`qQ3e{kG(Y$Kkb^xKV4D{qwtC6v^7VY zjB-W_4Ua*$X^A0@GCwh}&-#v-Ry1ZZ81-bg$v)2Bb#djB*hmjs7EIttT}$Q(m5KwR|&`Cpgt(lr?f8?Lw*; z%*VJ55iB`jOs$ON@yZHhYK=RVf`cwwwRN*$DXn*ni#a;Y4n;Ozn1zW*BnwBDlPTb>8&;Wxnr)U33m!tJwE!Yu2)-Wd#D6iu#tTF zPjZ?08Hn5Cq;xVYJXL)`S!vPuB&3*{(=t(y_Ob>_$E*T!8iL!jl?s&FC+Cpykhc9OlmCqQ6`H(Bhpv5+( z`m83&*|J`xE-TbY!A~T^NpUKjrUYgtAfRLZXQgAZuT zB9XgYhDmU$ObMr0WW?qoAXx>!BZ!~ZKuA+|fmyWpuB;+o2x11@8>@38D)lb41uPGA z54K%1BmJ;5ABR#qA)98NJk(=z!|6d;O4nkoxPt(Xw@Gj?oq|cbPT%4SpY`$bz8TE2 znszCKN^2w9#VBh&nKfY_hRJ~f5^4fid(Zy>XZw=qn-OaLkfK$vSf?_>EHfbJU89yj zuy?3_k3&{44G--ZiH-viun#~=%2>OhZvGO^d3frq3Yi+1>(%T{arcoRn8}$XK(J)x zF+YrOExu!<`DMgKWPsc$Kj}mZ0Gnaba}r7sDBYg}v5@lP&NtiRsVJuIWb5Q<)^s_RRscTh{60u#0B7-ti3yn{#fi64g?q85kydOr-NC;f*=*od9?&MV zm@Ekrkxb7X25}Mj7T^n$$3kum8#J;3n}s5%S9NBBX$Z*?Otw=a%6&URptwK^_K%*F z)O_UbEjYVbJf+ESmFJB`xk*dLBu>oCM6{qoge&F*U}hpYPggxGCN(BsYlFj~Dq%20 z$wq^6qERe;Wws@1ou)z~;9_=&>WFn)$AwlyAgqH%N~qSRD{{_#auEY1Bx(h~#KA=J zjpz08& z6uVYeVat0JS{ej~!xvTUjxn@CoA4WKLmTcpLm_4-48gXFgJ^11Z{5kNRk4sLW-GJ& zn#lF0VCVgrNBW+P9DVvXvK7@z4=W@d(WZ+wlq_^f5L!^2DRHx4OtzVwqkZ;`fJ%eJ z1>{7vcZQL$>MGswV3*GxEMx$R*E}O}2;x#Z{LfDET7+_VtS`K%1NJDc;#yT!!&J9Q z)`NlNz-6Q(Gy0gGx%Vlri$AqZ+VZO)0X6cda*$!nSq({#seuzPLJWd2lHYx#dacD~ z*1kT&c%#m8W zWUb^-tIDu#AO*u3WU9{>DNC6}NRcol$;A66PGDjRIKcE6ItR0VQ(vlQjcUbdT`}ZN zobN`MtI4>;Yt1GZ*Wwf^l}7ht*5EEEDBpRQiQj#vZmizr`E}?20G%3Yk8b>u@>@Hp zJ2`VAyuIBCr|_%CW1h$;^@WL2&G%~V@hMx|E8Sx}B1e~5a5`U2YZ z&9K3P^|HeNAPs&b3K7rr- zk-TrlCS&sGFm$eh?d}6W1$b)lb!}RaQxf4-auG=v_5&w#Qw&a!gp6(=1ra}#$6e)B zPhiR1Vy3EipqqxqNkq7zp6MjGmU5DkCCP+vE)zd9%c*MRa?^#iIOJEytimfY)kT~S ztB9^ZA|_ynM8k+d2t=wT1}EliOSfrPhcxSC%?f3PzR^-W+|h-?T_!NXh8ozoAc=^b zqIUeIXE_5x%*{IjD6fLXFzGde7Hl=4>>z~*z*jjUVF^zNWX~BH+irnlMHfse~@0>5SRF0M=~?Pll6Bu&LW&Hn(f!DOiB9A-I0PSN(&ojAv1>ix=a^%#i8p@JW76j-&a z;0co}7=buAfiWVTprogiL{WaUWGF~Rp~%|9RAH4D*&3lJc!-M)#IgwdP7H;7b}muB zOb)Hf0(9`#R`cU3%7LX~=^{j!v4vc}rMpKch@bHx{{Y`WL3-nyabG)}c0%W`+{KUp zt{77?2Lz_U7#9Bk@9~+5`2F-AIh63%8<(9|PL?SRQk2CFX*UxX11K0=OoHH!XJVcA zBH#DZmkC9NB`dLzrp%ILSxw_DY%QORF^~}|0f~r_<;r9C@iEjDQIp6G7w4(g%ao~B zOzVGA<|AVmkyhpF68z-3#F0$?KO4vp<7njH6~e{Z7qF5r4FJeJ28ZySj>gmI^u&x5 z@ECInW(cH2A_vTJ5W>`9>DJ^?Ddg5#*_fBi$qNZAi6#Nh0Q41O$SNxWdWV1qph=R5qxz?9q(px}Kk*R&EU6h_ z#9}@5(UxQ>DYS`nk)3%VSydJK%ktU`_uu|LJ~|f71Ep6VbVjuxMl+5zRI$>#E-B(W zL%5F_kmDwQvXY(VdSODnq+d$~4ii;y%CU>J_U8%-l}mj_xRY*cZwG_q8k{7yg6q7kZ_hUFzwvps82Y{{{?Z^mbge1EnHQ9*$R#V-hsf0%lkBfN}DKjtT*o);=(omQgaExR##^Lqg^G0 z!5o*aA%a{R6R=LjBmV#+JzQ-=-;q`$6^N&HiPslH$xB%-21*pziTt>>K4xe0-byFp zBcK@3UZTb$?eyBQS7=P~Hnnb7H|-G4K89>#2L%vk`Ig^59D3(KTw+esqV5kO?1*s- z5_WFz6M>J#MPG3>#Bqp{{I}jeQ5|!jEY@RRc@i$s)mw;*MyhnvZSPGw>)6AJ$;&tr zY>yrxCOb3om@T1w+_SH_8JC6puPFxE$k(|h=2+xVLH6!h%2W*Y1PM&Hh(zzkL#ph} zl&>3d%T-NoTXL4{otR=wV1h@|r4&5LqPYQri4Y+&kCQFS^x3gxY^$1nKB>9N234p3 z0C{n<3))SD9D>NeNJ|+7#6~73a-M*#&b4l`@n&^0DpMo?ty-~5?&XYB6q^hp2soL9 z8sul3Z9fqm1zRC*pj-_)87zyTW}8ud(6tGOh4CvYQA?7|xsLE$nKL9?@}16m=+^~U zxSH`++`Yt1P1VKp14o@{Uf^@0x`kv&5;`58e(K~-^@cDa!1)Tb$chY< z3tS&5n4iLCN7d?&)NKF@X;(M5h)q?l)ZP@6QVok2!BTQbCJRDqq)Zqw$Kqlq{(7ls zwPAHxbc)SiTO7J+x$G1Kz?3C1S_@*{AiuD=O#c2h>O8FDfa>7=g&5_R+&*b2PzGsi z&lj#y%2>cLjx#g=06+OpR9�K~p)tGQFE0a77rZW(b2%siLIDzzvdFa4u0iLLy=| zo?QSIMjM^Tx+3;^$=O0e^^?e=L|_bvT1l7^1;mtzL=4QxOw7*vM0e3Al%mUVjL&5n z!);8Z_DGa019=gd2xiginF9X+d(1@qbVV$>te7UPjSr{jQWe+r9Ybr_aKZx$%82y{ zv8r@>$~T|$o#5lHHTCP=w8Bw=PpLjXcgyUsQ8g99oT53e1b5`zsla za?HyZHBEJOBF{Zy#)d}Os$iEYbK2aqlJfmPB%DfHL(NONS=Cp#c z2$#10OieKaAdqy(Fs4#M@&5n_gNWOV^x7}vF1seYyK@#Z0I{(YocV-T6Brov)}9dE z{lzj9GY7zCciZ7*rqRXHsc$kk>{UvZYpJPXKF}5I5#q8jVKt>c+&;zrUm!C(M07Ik ztf(#3881WuwKCcbN~uk9U?RHBqaKE>Ca;K%{{Rs#Uq1jCGl;(2@+hkrjI*d*1;5v7vd!Y08l(*Y2TJ6t8Xge^P0mqkNc%mr%sI}2)|B2eo5*5r)xuYEL=g0{W7Z_qfudq3+H<^5`9S`@KXWw6s;x{8Ce}dl z&3#3oh{#t=22Fd<t@oaQRS`ywFt2ANYNF6J$?XL;YEYg}6sksFtmnsYD`6ydCzYlDe5ij@nMh=GsDe&nV%o;yU#`^s9J z@yN**R>+XTN}o3!1k7!~!c3IEm@VLT_}k;5Lba=PGL-DjJ}fBW)H27l?5vcW$#4dj ztQQhuQlXd3O8(nFXMSA}9_P9WeIMD?@VCA@qb$;1ec=tr(lU8E&Q ztP96IRihv_X|veYFh_?ut0EBwALRrQ5gh(Lcj(iDx-UH7R(Grh&@=89!&5fe2za>t zT(<&%h>fOyT}5b|)z`Us)v^|*y@4Eh#E&nLWUq{gxRtmrI0+QY{$CM0?HvFOM5?lW z?BAMR7NP>fxZ{f&ggAHsJ`J-XL$|JYjBN!3QSwvKqiu}0jKX89IBv~?3UzAQTj_CF zKp9vT#@iCfQM`UXj6{B?pzl;FcQSbDGkV?77gVYjtD&D{aNb2;0lXlQ#hc7Tah@^% z0ORo{O;pXc9{k2~Fhqt`dTQTE#k7*hNLZMHl^YCHOE5T*;$IQI@&MJenbEU+6H6as z9FvzNc*Qj=Nd!c&Sz-oL5fTB$A~}9jAE}O{ZR%(D7OL6IH8$&vCc+97_qJe3zitq* z=L!)8gv`do2e#c&7}{$pk9LyCX0BEzuvVfvV_k?j;D}88T~(ap5viFmh5`{{XI~wQ}xWEfptQOu~k`Xk+S({t#rbi1pa#2mnw_n9M}P z@#FaX)swcQrlm`{CJ7GppYoG4;8PHUBwEN|pCJ82NXYN;ymcmKa!OtG<%Gs7)-E-` z87!_p*YF850EU+m5{VMtA|^^=c7PRy$djdInM?NEc7-r=PT@(hak%}l%Lrg#gm+o~ zJ0AZ4`E_vQ^I1zzO_$zodnDsq@->>ewPuOUgp(lSki?iw#Kc5QM&q>azd;S__M+2r z8JqA;iD4;up;^>HMDwR2o^mk@^|RJLkL%;(s6-K&TtKfWoXJ^49TKpX$^~(>1JuVr zEh(5#kpQk_nFdl*CA0umKE6%tzipb5${Bn<)9=$^34M4oiG>?VN+qlqAtV0)F$o`? zraFSU!G~>FstjJ92TwD{S5xb%C9oR_#6^Y>`i4E@JAR@+$EFre#k`$`<#F?xE&*g= zwWSM+ygfy0p2Nuff*>=t`wVSAu9u~Zvu$q~SKU%5t`}kd0BkkbD~?eB?bgWWFa^AR zU#b0c1X&DqIKno~>~<=xAh#`fWa_MFV%6_IUehr$!((|IGihWV^E3MCkd28^SF?u6 zWUVm6huctM9eIHgD>xevNNlQP%VCizl37R2)6%EYqxTq#&b3G}R*8`guEAxcoIsHz zfTMz-oi2@oVVHsV>4l`^9bU>WWb-w~!;raH5i}+Yq=b2dafX2>meNrJxX;G@0UhM! zb9XG#rH0g%=J7>^Rw@Z(Ve82Wxs4|omgWQ-&iuLajlLtJ;~seG%33|D{zE3giDT z%*XrarK+1+%%A@N<=2^5KFPz3y%QUX&PpeddnKEUmeCtd-#q{r(YtB(7<6gnZ&^Mm z3t&fcC`(%5rC}THpr2%roJ?{xlhSTxJc7o?I5i>I&3o$|$jZNBiD=_QARFzW}m)q?pC+k74bBPV$ zi}f)dKOHAtI|vQ0l33fws?@@d?yNPj592I@z5T>tJ6IEyZ7_Q;efEu>RkbzhIx_e3 z6^hGMjH_)HQC)KrGTnwE9Ja(lAVM+{we7e`5k&rf65}gWaTwEGnNq-cL>$`| zv|3`-;Q|u(5xJJYfM(CI+md^41i^(cD}$0aYaxdu z5+13Yq81azH{NaoVsAQa{{S+DlP-WPoBgj$%YqA<`#%Fl{ z08`P&X3*AIjV$(OAPAF%*}E=^1`-<*gMHSRjf2-8B?GkY5fRW8K{x{)k+DkFa{5zP zDY5hkks^QCspr4spT(0dZv0A5Xy1L~S<E#v~a(bYz&`GsUV+^JY zmQqVu?X=7k!Hkykw(&C(VQEvioMYCnXj(;^LerOW-XP^uJdff}=jH{2{@w&-?a;t<)4csbtrCKXKG;F;SDpl2E~`5MW~! z_K#GFexg5LzLF}YCm~+x9eY_yRlq7a4WDSeVGl7C!9>8!j1+A@JriQ0>`499BGg0#E~^1zI21_; z!GnmG#5Nd+35nZjo&I)*U&<=xLkAYIwcLhSSt7JE>tZj{o19YTOx6;a#of51i;G7-G&aS^x7#O?FEu&_-UmhYo8lc9()V-)J_ z6t_yOE$3-MQ*6k$s%$9>cE@qLlYJgXOx7x1O_?8M+uGhi7Dv1%A=dz zH9eLwwG#;RF-$UBR>FdjcKe{rM*j{HUwh{wMj3@DpUgL^#~B8{y0kJb|_es z@5`VBJbt00aTq%&TIMXR^=$E4%CbaAnJp$9Ea7{^{{TqA9F)w=&q8DGq^FH}r-&=d z+t9{H?xC44aKw?96Oxkoo%flIz9XV(9qe-7TOXdui4qNUbP`u_-o$T8RR5lsTn=_Ol)&8_{T*zCktLz8II4}%;syEw}paDMuEVOu*zIf z6EPbIgm1SQ+J1VMDw_+dluKJymDbACm0M$LJCKx+Pv8*(&si*_V4!Dz`I+gP3gJ;E z->A}~MI|u6ldMMp9EKKA>_Cj04{+KDzGh=-jlfB5RIMu>IRS23*Ss57+=bS!$xsIn zgW}PaN4WNw;}bG_M)NZ=jtv&r+sVZ_trN9z*6b;j`EVfN>mSA77p@jX&O zUW2Kf_Z!&e(q|;TDxKh#$-);f0=XEIFTe&4Cwbpvj-azs5(&rTTsVcS5T>YYl&YPz zl*th}a#Jgga#1nHWTYhid2|GeWgGxSY>q!s)rU!0K-PgU^^s5eX7dxu3O0|Ai2nfJ zT?BZFYCTrERz#1}7@I9+V@#BkNDu&T^CcfKGw~lgZ4u6Zw{CHu=h=Q)xeM0L zD}C(IvF&q{&0dff0CC;|CzM3Q!AH#Pv`Kcg)LkXBPg-RNO4$?ZBe24dCb7iSK$H}a zK>kO({KWqHsGX9bkc^8lcd~CKDnt+&GC+OXY@rC4jwW2U-~CK<0i%#zjK)(c+{P0(oV0Y>yLji-tm|ad z&hln$ID@`(QcDT&{GqhKv*PDY}!*KMO78KtJVQ_Q0hWhz{I@T;sV0<%$W}clLWa$vSMTL-=;YfDrCnXy3x6p!WVX!4D{aSE7-_~?5xle2daR57UupKtM(TU4IfOXP57 zm=G^xAa?dK^E~EeHl95ILSW*hEN)*c`ZUyp*pNguO2;A~CR+}O7CqDcFjKt7+i%j< z+qs#fy{Of*jUm2kH&A^@LGy_8S1~R9tz2$w{{V(eO#IJGswR=*ad_-;2111yZJQ+t zc_0L5{{Z4NsFjuI(C*lY!vL2l?M zE#S9^+9p6@65Doa*}scx5ozRb7~39`mPo+DIV>fLXaIx*pren@+f2^p(ptwltaLJ^ z>pyDsjbF;!mj*tUDTX2hD}@+AflT|P&zCM!)Gn=6tykJ+DBQ=|thzF_AG(*dMzQ2_ z#T0JO*Qm;74iy08sBIXEp0<@;RH87Te9S z?Y=T8xYfWI38(~PehVa%jtF)S-^}&)-bVddb23&@kEv+Fqe$z5O58-Oib4=m96;u0 zns}26OMmf+>I=0hQd-w@8hGcDE+DIYyN%TOlmx=$%4IUeaGBbEMB*p@Isyq7WbUSm zGZ`#Wf;4at^SpZbpUHWMHj0j7(GjQ#@Dp z$m118e<3H&#O<{Hx-A1@u2GZ&8x{C- zuPt2eRDj5SD;xCMN~z3(KG=dpc*~?oa2stLB4_-%0avbqAT43%D^YS^bjQ-Y0>4(` z3~(%V_JEY}+y4M9x9PJmc9O?XMSPTA3qNsgtl9fxt1}1dGvP4V1C@am)3(fknEZO> zsI`>TUwJlBIY?ZnE4V!eg{}o6PI_f#5h3e=7zzBKM|k+_<@p*pIY8xU)yZ55xNo?W zM6CHl5nO)}WRrk54^Z+6ke**VKp$(bH+>)(8N&uL!|9t-d;yivxgh2M(UB>iVYFdv zo#G-t)W<_r1Y7|c+1SUf%TO4_MK-l!E13oip-wm{6c+5y|AMRcXrsL4N4 zOXQBhT!)XnLVSfxFhm@-IoE+V2q$THYo{$j%{5vin7v>zZa;-;@{l>|#N5|7XF`JJXZn${h+ zjaPD1DAcQ$v-a?D;&s7S zO>Hgq0``vrCdh`-2Q%;`$KoTS#?64oR=nxR!iKRuHmW92MGTSkwQD0TJYY?5Q87D- zZMV+#);j91l5K3^T4S6}OtH;^7!A3uOMXUd7Q{k=V|h^T{)6ZkWIF? z8lZq;$jkAWXjzB}9v}fQ6B|U#%zo#um8;dpTz$i{OCg9=#FVUKl%tp!5gN)QPQgbA zD43Yz3!nGUj;Dr7)GTws)pa-Z9`(=6a6YP&gZQNH_3&+mWS&rPda%FpsyeC21GB6635(3+tvjU2MZYCFcCYavwE}8fgnhZ=vGk@* zVoyt$W>O*^!YJF-F){{R!b{`!V$Vygwp^vfBPwQ|Z=bunVPxhIeIlr~9#uo-Or zwlDRz+jT|DOvQ0^#!$SI32N)YmJwOp!b$b48N$6H&U=p-mcYjQ#17TD^{gF;P}|Gn z=GazSR4LkdoCpN2un}z5u%nkKfrW>}Z4)32G~*tytr-hA+Q~4djGtessR$Iuv6i5A zE!L&!2UzK1C+$h-y7}m71O1Wwsq{jnsMq{pzE@!6|$`d zGGqc3-3iX}wic(6xsk>+1(0r5M=)A?=x039f0YvWgD1-6ozEmEsNR-~aQ zI2nkEK@5x#mku-g{{Si9Xg{hy#%A12gdgG5Uz;nwIhJxmmU-*(`uR?e1SSy)0~ikZtzC&PR-G z9>^#e-eYfxnRvXFy17iR-C20tTGXrcc$?E+uNY~x)&dNGAr*{I%*2x?{{SiI0N05& z+h4R-ji&}tbycgBxOXTNivIvVfr)}C*ncl%$IjhbD@vGzV6WEAXDy9LDW_CiR&nDf z+H9s-#7@f?Nr|755ebN&^$xN*W(GRy?UgE71xT{WQH^igRcLS}SUVH_k_r+(#%5=k zbsW^MdCkUD3c83Y%B-&+KH7i_DUu6Fe2)BvCMSMSLR`OJxdNlZ#gS;XzB$xsKHd4O zIJXMuvJQEnhXO#=u#N;Gca_a{Z4n!EEV9)_)EhZ~tTQVDHBTfEk*+xa2nhg8^ND8L z%x%2PZLu~mnEwE<9D#*f&8SUKC7jx%w4!7lFZcWq$sZ$#<+Dq9{HLZSnicHP%6}t_ ziwsh#4VfTQE61Z|g6xaovs`C@h|EkxhyK0*wD9QkRIN^h3iokh9M$ap#8a*SJUzq= z2N**ovM0Rr<-&d!5!DybU2{hlbd5YsBf<35T2R?JI6Cn%bGPNZ9{j#`{{Y9PwW~{4 zi41VH?5k896spueP?|*GNt;Xo@BUwuO#cAA{{USRQT3(t6pI%!w&1FmFe@$VONdP7 zH*`!aM2=*JK0j0b`T+~^)fHjtYELk`1lRFv{&mQ~^pgDgDXUwDp8Ni%bW`r~cJVkCY#0OPDEL#Hh)rIemi zW*XuPNhvb*m!Nz^?oBED z4C8N^-bIsQW;Tcdfwvl=ae6bD{HZtX>sqY#O-aW7Tb#*A2_Ez7E| zIs%M^tGB=j?zrlP{{Ur*?H^jJ0?|Ca@rE%4GdwmCiTnj$KM@c^)f1S>I&EV^9M=-m zF zf}hmJ(H$wsqZf9rqJ0MBsWFXH9eO_9fWnY6CbAc~F`*$b8_wgjPsaQ71;=1)ttI@m zJ5x+V(`PS~AQ(beQbu7UM#CcbEw}#wf3AUP#!751q+|1fihjzJxU1f2j(l#s1&eGz zdgexUowl8)qO*C7SKQrOFXAi0E)BJXr_6hoCCAwk=q-q2a)2G6r)Zz?=!d**BqvkqZm&KX0k!37(hkDA~O?EwJBqtCmfC+*9f2jWeQxW=(jI&|6 zaZ_!EXC@K&0|{|4%x7^j4k8l2)I>~7@)Di?W2w|x6QWICS(LA&B1OLOm7s=xRl*~f z6pr7B{yTC10N+3dZM5Z$taq5V+9pHmzFIMS1ym&E2hFfAR5M}9=kxJ?V3#pe4M@v3k=brP!*)9CP z_x}K{k>sj#%gMb(%%zEJBVmSOy5sjn&0Pj5jMGSLRm|YswcZU^Q z)KZ|cWdpQ8%Zv>tBO81~2}FOX{{T=`#w#I^Mlm=|LzHYxqDo%0OhV!acIETxnIeeg zGdsa_ZN3?cBzjpf@%YzI7BRmZx0slYQ9JLyKo?x{RfpO&Yo;KHh6~9HFDN$-W$iDXQvt_}Pw0R5 z)fLUS$Py97Wxu)4HPU*;12YBbn@6`Tpf~{pd~C7ngEb;?lV}a^3&imY3V?PgWAP+H zP#oHEw!l*{AHDu(sZ279MZ0xrAg%)0O+z--O{x!Br5K==X5=9)y#wLHz#DA{2(APfU)(CBCfBF*2gb;K`9b(MP Xh{Ssd+t0FRX#At&<8SrXIs^aN+iI5( literal 0 HcmV?d00001 diff --git a/docs/samd/pinout.rst b/docs/samd/pinout.rst new file mode 100644 index 0000000000..7e8d7ad901 --- /dev/null +++ b/docs/samd/pinout.rst @@ -0,0 +1,850 @@ +.. _samd_pinout: + +Pinout for the SAMD machine modules +=================================== + +The assignment of device functions to pins is very flexible. The same function may be used +at different pins. The representation of the assignment choices are given by a table, +which is a subset of the MCU's Pin MUX table and is specific to each board, as the +available pin set varies. The structure of the table is the same for each board, but +the set of rows is different. + +.. _samd21_pinout_table: + +Adafruit ItsyBitsy M0 Express pin assignment table +-------------------------------------------------- + +=== ==== ============ ==== ==== ====== ====== ====== ====== +Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC +=== ==== ============ ==== ==== ====== ====== ====== ====== + 0 PA11 D0 11 19 0/3 2/3 1/1 0/3 + 1 PA10 D1 10 18 0/2 2/2 1/0 0/2 + 2 PA14 D2 14 - 2/2 4/2 3/0 0/4 + 3 PA09 D3 9 17 0/1 2/1 0/1 1/3 + 4 PA08 D4 - 16 0/0 2/0 0/0 1/2 + 5 PA15 D5 15 - 2/3 4/3 3/1 0/5 + 7 PA21 D7 5 - 5/3 3/3 7/1 0/7 + 9 PA07 D9 7 7 - 0/3 1/1 - + 10 PA18 D10 2 - 1/2 3/2 3/0 0/2 + 11 PA16 D11 0 - 1/0 3/0 2/0 0/6 + 12 PA19 D12 3 - 1/3 3/3 3/1 0/3 + 13 PA17 D13 1 - 1/1 3/1 2/1 0/7 + 14 PA02 A0 2 0 - - - - + 15 PB08 A1 8 2 - 4/0 4/0 - + 16 PB09 A2 9 3 - 4/1 4/1 - + 17 PA04 A3 4 4 - 0/0 0/0 - + 18 PA05 A4 5 5 - 0/1 0/1 - + 19 PB02 A5 2 - - 5/0 6/0 - + 20 PA22 SDA 6 - 3/0 5/0 4/0 0/4 + 21 PA23 SCL 7 - 3/1 5/1 4/1 0/5 + 22 PB10 MOSI 10 - - 4/2 5/0 0/4 + 23 PA12 MISO 12 - 2/0 4/0 2/0 0/6 + 24 PB11 SCK 11 - - 4/3 5/1 0/5 + 25 PA00 DOTSTAR_CLK 0 - - 1/0 2/0 - + 26 PA01 DOTSTAR_DATA 1 - - 1/1 2/1 - + 27 PB22 FLASH_MOSI 6 - - 5/2 7/0 - + 28 PB03 FLASH_MISO 3 - - 5/1 6/1 - + 29 PB23 FLASH_SCK 7 - - 5/3 7/1 - +=== ==== ============ ==== ==== ====== ====== ====== ====== + + +Description of the columns: + +- *Pin* - The number that is expected at ``machine.Pin(n)``, if the pin is given + as a number. This is NOT the GPIO number, but the board pin number, as + given in the board specific definition file. +- *GPIO* - The GPIO number. +- *Pin Name* - The name of a Pin which is expected argument to ``machine.Pin("name")``. +- *IRQ* - The IRQ number assigned to that GPIO, used internally by ``Pin.irq()``. When + using ``Pin.irq()``, different pins must use different IRQs +- *ADC* - The ADC channel assigned to the pin. When using ADC, different pins must + not use the same ADC channel. +- *Serial* - Two columns with optional Serial signal assignments. Both may be used. + The cell content is device #/pad #. The pad # is the respective internal + signal of that serial device. Details below. +- *TCC/TC* - Two columns with assignments of the TCC modules for PWM. + The cell content is device #/output #. For PWM, devices 0, 1, and 2 + are used. The TC device pair 3/4 is used for ``ticks_us()``. + +SAMD21 UART assignments +``````````````````````` +The UART devices and signals must be chosen according to the following rules: + +- The TX signal must be at a Pin with pad numbers 2 or 0, like Pin 1 with serial + device 0 or 2. +- The RX pin may be assigned to one of the other pads. + +Examples for Adafruit ItsyBitsy M0 Express: + +- uart 0 at pins 0/1 This is the default UART at the RX/TX labelled pins +- uart 1 at pins 12/10 +- uart 2 at pins 0/1 +- uart 3 at pins 11/13 +- uart 4 at pins 2/5 +- uart 5 at pins SCL/SDA + +or other combinations. + +SAMD21 I2C assignments +`````````````````````` +The I2C devices and signals must be chosen according to the following rules: + +- The SDA signal must be at a Pin with pad numbers 0. +- The SCL signal must be at a Pin with pad numbers 1. + +Examples for Adafruit ItsyBitsy M0 Express: + +- I2C 0 at Pin A3/A4 +- I2C 1 at pins 11/13 +- I2C 2 at the pins 4/3 +- I2C 3 at the pins SDA/SCL This is the default I2C device at the SDA/SCl labelled pin +- I2C 4 at the pins A1/A2 +- I2C 5 at the pins SDA/SCL, + +or other combinations. + +SAMD21 SPI assignments +`````````````````````` +The I2C devices and signals must be chosen according to the following rules: + +- The following pad number pairs are suitable for MOSI/SCK: 0/1, 2/3, 3/1, and 0/3. +- The MISO signal must be at a Pin with a different pad number than MOSI or SCK. + +Examples for Adafruit ItsyBitsy M0 Express: + +- SPI 0 at pins 0/4/1 +- SPI 1 at pins 11/12/13 +- SPI 2 at pins 0/4/1 +- SPI 3 at pins 11/12/13 +- SPI 4 at Pin MOSI/MISO/SCK This is the default SPI device at the MOSI/MISO/SCK labelled pins. + +or other combinations. + + +SAMD21 PWM assignments +`````````````````````` + +The TCC/TC device numbers 0, 1 and 2 can be used for PWM. Device 0 has four +channels, device 1 and 2 have two channels. So in total 3 different PWM +frequencies can be used, and 8 different duty cycle values. + +The DAC output for the Adafruit ItsyBitsy M0 Express board is available at the pin A0. + +.. _samd51_pinout_table: + +Adafruit ItsyBitsy M4 Express pin assignment table +-------------------------------------------------- + +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== +Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== + 2 PA02 A0 2 0 - - - - - - + 5 PA05 A1 5 5 - - 0/1 0/1 - - + 40 PB08 A2 8 2 0 - 4/0 4/0 - - + 41 PB09 A3 9 3 1 - 4/1 4/1 - - + 4 PA04 A4 4 4 - - 0/0 0/0 - - + 6 PA06 A5 6 6 - - 0/2 1/0 - - + 16 PA16 D0 0 - - 1/0 3/1 2/0 1/0 0/4 + 17 PA17 D1 1 - - 1/1 3/0 2/1 1/1 0/5 + 7 PA07 D2 7 7 - - 0/3 1/1 - - + 54 PB22 D3 22 - - 1/2 5/2 7/0 - - + 14 PA14 D4 14 - - 2/2 4/2 3/0 2/0 1/2 + 15 PA15 D5 15 - - 2/3 4/3 3/1 2/1 1/3 + 18 PA18 D7 2 - - 1/2 3/2 3/0 1/2 0/6 + 19 PA19 D9 3 - - 1/3 3/3 3/1 1/3 0/7 + 20 PA20 D10 4 - - 5/2 3/2 7/0 1/4 0/0 + 21 PA21 D11 5 - - 5/3 3/3 7/1 1/5 0/1 + 23 PA23 D12 7 - - 3/1 5/0 4/1 1/7 0/3 + 22 PA22 D13 6 - - 3/0 5/1 4/0 1/6 0/2 + 34 PB02 DOTSTAR_CLK 2 14 - - 5/0 6/0 2/2 - + 35 PB03 DOTSTAR_DATA 9 15 - - 5/1 6/1 - - + 43 PB11 FLASH_CS 12 - - - 4/3 5/1 0/5 1/1 + 11 PA11 FLASH_HOLD 11 11 - 0/3 2/3 1/1 0/3 1/7 + 9 PA09 FLASH_MISO 9 9 3 0/1 2/0 0/1 0/1 1/5 + 8 PA08 FLASH_MOSI - 8 2 0/0 2/1 0/0 0/0 1/4 + 42 PB10 FLASH_SCK 10 - - - 4/2 5/0 0/4 1/0 + 10 PA10 FLASH_WP 10 10 - 0/2 2/2 1/0 0/2 1/6 + 55 PB23 MISO 7 - - 1/3 5/3 7/1 - - + 0 PA00 MOSI 0 - - - 1/0 2/0 - - + 1 PA01 SCK 1 - - - 1/1 2/1 - - + 13 PA13 SCL 13 - - 2/1 4/0 2/1 0/7 1/3 + 12 PA12 SDA 12 - - 2/0 4/1 2/0 0/6 1/2 + 30 PA30 SWCLK 14 - - 7/2 1/2 6/0 2/0 - + 31 PA31 SWDIO 15 - - 7/3 1/3 6/1 2/1 - + 24 PA24 USB_DM 8 - - 3/2 5/2 5/0 2/2 - + 25 PA25 USB_DP 9 - - 3/3 5/3 5/1 - - + 3 PA03 - 3 10 - - - - - - + 27 PA27 - 11 - - - - - - - +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== + + +Description of the columns: + +- *Pin* - The number that is expected at ``machine.Pin(n)``, if the pin is given + as a number. This is NOT the GPIO number, but the board pin number, as + given in the board specific definition file. +- *GPIO* - The GPIO number. +- *Pin Name* The name of a Pin which is expected argument to ``machine.Pin("name")``. +- *IRQ* - The IRQ number assigned to that GPIO, used internally by ``Pin.irq()``. When + using ``Pin.irq()``, different pins must use different IRQs +- *ADC* - The ADC0/1 channel assigned to the pin. When using ADC, different pins must + not use the same ADC device and channel. +- *Serial* - Two columns with optional Serial signal assignments. Both may be used. + The cell content is device #/pad #. The pad # is the respective internal + signal of that serial device. Details below. +- *TC* - These device are currently not assigned to Pin. the TC device pair 0/1 + is used for ``ticks_us()``. +- *PWM* - Two columns with assignments of the TCC modules for PWM + The cell content is device #/output #. Details below. + +SAMD51 UART assignments +``````````````````````` +The UART devices and signals must be chosen according to the following rules: + +- The TX signal must be at a Pin with pad numbers 0, like Pin 1 with serial + device 3. +- The RX pin may be assigned to one of the other pads. + +Examples for Adafruit ItsyBitsy 4 Express: + +- uart 0 at pins A4/A1 +- uart 1 at pins 1/0 This is the default UART at the RX/TX labelled pins +- uart 2 at pins SCL/SDA This is the default I2C device at the SDA/SCl labelled pin +- uart 3 at pins 0/1 +- uart 4 at pins SDA/SCL +- uart 5 at pins D12/D13 + +or other combinations. + +SAMD51 I2C assignments +`````````````````````` +The I2C devices and signals must be chosen according to the following rules: + +- The SDA signal must be at a Pin with pad numbers 0. +- The SCL signal must be at a Pin with pad numbers 1. + +Examples for Adafruit ItsyBitsy M0 Express: + +- I2C 0 at pins A3/A4 +- I2C 1 at pins 0/1 +- I2C 2 at the pins SDA/SCL +- I2C 3 at the pins 1/0 +- I2C 4 at the pins A2/A3 +- I2C 5 at the pins 12/13 + +or other combinations. + +SAMD51 SPI assignments +`````````````````````` +The SPI devices and signals must be chosen according to the following rules: + +- The following pad number pairs are suitable for MOSI/SCK: 0/1 and 3/1. +- The MISO signal must be at a Pin with a different pad number than MOSI or SCK. + +Examples for Adafruit ItsyBitsy M0 Express: + +- SPI 1 at Pin MOSI/MISO/SCK This is the default SPI device at the MOSI/MISO/SCK labelled pins. +- SPI 3 at pins 13/11/12 +- SPI 5 at pins 12/3/13 + +or other combinations. + + +SAMD51 PWM assignments +`````````````````````` + +The TCC/PWM device numbers 0 through 4 can be used for PWM. Device 0 has six +channels, device 1 has four channels, device 2 has three channels and devices +3 and 4 have two channels. So in total up to 5 different PWM frequencies +can be used, and up to 17 different duty cycle values. Note that these numbers +do not apply to every board. + +The DAC outputs for the Adafruit ItsyBitsy M4 Express board are available at the pins A0 and A1. + +Adafruit Feather M4 Express pin assignment table +------------------------------------------------ + +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== +Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== + 2 PA02 A0 2 0 - - - - - - + 5 PA05 A1 5 5 - - 0/1 0/1 - - + 40 PB08 A2 8 2 0 - 4/0 4/0 - - + 41 PB09 A3 9 3 1 - 4/1 4/1 - - + 4 PA04 A4 4 4 - - 0/0 0/0 - - + 38 PB06 A5 6 - 8 - - - - - + 49 PB17 D0 1 - - 5/1 - 6/1 3/1 0/5 + 48 PB16 D1 0 - - 5/0 - 6/0 3/0 0/4 + 14 PA14 D4 14 - - 2/2 4/2 3/0 2/0 1/2 + 16 PA16 D5 0 - - 1/0 3/1 2/0 1/0 0/4 + 18 PA18 D6 2 - - 1/2 3/2 3/0 1/2 0/6 + 19 PA19 D9 3 - - 1/3 3/3 3/1 1/3 0/7 + 3 PA03 AREF 3 10 - - - - - - + 20 PA20 D10 4 - - 5/2 3/2 7/0 1/4 0/0 + 21 PA21 D11 5 - - 5/3 3/3 7/1 1/5 0/1 + 22 PA22 D12 6 - - 3/0 5/1 4/0 1/6 0/2 + 23 PA23 D13 7 - - 3/1 5/0 4/1 1/7 0/3 + 43 PB11 FLASH_CS 12 - - - 4/3 5/1 0/5 1/1 + 11 PA11 FLASH_HOLD 11 11 - 0/3 2/3 1/1 0/3 1/7 + 9 PA09 FLASH_MISO 9 9 3 0/1 2/0 0/1 0/1 1/5 + 8 PA08 FLASH_MOSI - 8 2 0/0 2/1 0/0 0/0 1/4 + 42 PB10 FLASH_SCK 10 - - - 4/2 5/0 0/4 1/0 + 10 PA10 FLASH_WP 10 10 - 0/2 2/2 1/0 0/2 1/6 + 54 PB22 MISO 22 - - 1/2 5/2 7/0 - - + 55 PB23 MOSI 7 - - 1/3 5/3 7/1 - - + 35 PB03 NEOPIXEL 9 15 - - 5/1 6/1 - - + 17 PA17 SCK 1 - - 1/1 3/0 2/1 1/1 0/5 + 13 PA13 SCL 13 - - 2/1 4/0 2/1 0/7 1/3 + 12 PA12 SDA 12 - - 2/0 4/1 2/0 0/6 1/2 + 30 PA30 SWCLK 14 - - 7/2 1/2 6/0 2/0 - + 31 PA31 SWDIO 15 - - 7/3 1/3 6/1 2/1 - + 24 PA24 USB_DM 8 - - 3/2 5/2 5/0 2/2 - + 25 PA25 USB_DP 9 - - 3/3 5/3 5/1 - - + 33 PB01 VDIV 1 13 - - 5/3 7/1 - - + 0 PA00 - 0 - - - 1/0 2/0 - - + 1 PA01 - 1 - - - 1/1 2/1 - - + 6 PA06 - 6 6 - - 0/2 1/0 - - + 7 PA07 - 7 7 - - 0/3 1/1 - - + 15 PA15 - 15 - - 2/3 4/3 3/1 2/1 1/3 + 27 PA27 - 11 - - - - - - - + 32 PB00 - 9 12 - - 5/2 7/0 - - + 34 PB02 - 2 14 - - 5/0 6/0 2/2 - + 36 PB04 - 4 - 6 - - - - - + 37 PB05 - 5 - 7 - - - - - + 39 PB07 - 7 - 9 - - - - - + 44 PB12 - 12 - - 4/0 - 4/0 3/0 0/0 + 45 PB13 - 13 - - 4/1 - 4/1 3/1 0/1 + 46 PB14 - 14 - - 4/2 - 5/0 4/0 0/2 + 47 PB15 - 15 - - 4/3 - 5/1 4/1 0/3 + 62 PB30 - 14 - - 7/0 5/1 0/0 4/0 0/6 + 63 PB31 - 15 - - 7/1 5/0 0/1 4/1 0/7 +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== + +For the definition of the table columns see the explanation at the table for +Adafruit ItsyBitsy M4 Express :ref:`samd51_pinout_table`. + +The default devices at the board are: + +- UART 5 at pins 0/1, labelled RX/TX +- I2C 2 at pins 21/20, labelled SDA/SCL +- SPI 1 at pins 22/23/24, labelled MOSI, MISO and SCK +- DAC output on pins 14 and 15, labelled A0 and A1 + +SEEED XIAO pin assignment table +------------------------------- + +=== ==== ============ ==== ==== ====== ====== ====== ====== +Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC +=== ==== ============ ==== ==== ====== ====== ====== ====== + 2 PA02 A0_D0 2 0 - - - - + 4 PA04 A1_D1 4 4 - 0/0 0/0 - + 10 PA10 A2_D2 10 18 0/2 2/2 1/0 0/2 + 11 PA11 A3_D3 11 19 0/3 2/3 1/1 0/3 + 8 PA08 A4_D4 - 16 0/0 2/0 0/0 1/2 + 9 PA09 A5_D5 9 17 0/1 2/1 0/1 1/3 + 40 PB08 A6_D6 8 2 - 4/0 4/0 - + 41 PB09 A7_D7 9 3 - 4/1 4/1 - + 7 PA07 A8_D8 7 7 - 0/3 1/1 - + 5 PA05 A9_D9 5 5 - 0/1 0/1 - + 6 PA06 A10_D10 6 6 - 0/2 1/0 - + 18 PA18 RX_LED 2 - 1/2 3/2 3/0 0/2 + 30 PA30 SWCLK 10 - - 1/2 1/0 - + 31 PA31 SWDIO 11 - - 1/3 1/1 - + 19 PA19 TX_LED 3 - 1/3 3/3 3/1 0/3 + 24 PA24 USB_DM 12 - 3/2 5/2 5/0 1/2 + 25 PA25 USB_DP 13 - 3/3 5/3 5/1 1/3 + 17 PA17 USER_LED 1 - 1/1 3/1 2/1 0/7 + 0 PA00 - 0 - - 1/0 2/0 - + 1 PA01 - 1 - - 1/1 2/1 - + 3 PA03 - 3 1 - - - - + 12 PA12 - 12 - 2/0 4/0 2/0 0/6 + 13 PA13 - 13 - 2/1 4/1 2/0 0/7 + 14 PA14 - 14 - 2/2 4/2 3/0 0/4 + 15 PA15 - 15 - 2/3 4/3 3/1 0/5 + 16 PA16 - 0 - 1/0 3/0 2/0 0/6 + 20 PA20 - 4 - 5/2 3/2 7/0 0/4 + 21 PA21 - 5 - 5/3 3/3 7/1 0/7 + 22 PA22 - 6 - 3/0 5/0 4/0 0/4 + 23 PA23 - 7 - 3/1 5/1 4/1 0/5 + 27 PA27 - 15 - - - - - + 28 PA28 - 8 - - - - - + 34 PB02 - 2 10 - 5/0 6/0 - + 35 PB03 - 3 11 - 5/1 6/1 - + 42 PB10 - 10 - - 4/2 5/0 0/4 + 43 PB11 - 11 - - 4/3 5/1 0/5 + 54 PB22 - 6 - - 5/2 7/0 - + 55 PB23 - 7 - - 5/3 7/1 - +=== ==== ============ ==== ==== ====== ====== ====== ====== + +For the definition of the table columns see the explanation at the table for +Adafruit ItsyBitsy M0 Express :ref:`samd21_pinout_table`. + +The default devices at the board are: + +- UART 4 at pins 7/6, labelled A6_D6/A7_D7 +- I2C 2 at pins 4/5, labelled A4_D4/A5_D5 +- SPI 0 at pins 10/9/8, labelled A10_D10, A9_D9 and A8_D8 +- DAC output on pin 0, labelled A0_D0 + +Adafruit Feather M0 Express pin assignment table +------------------------------------------------ + +=== ==== ============ ==== ==== ====== ====== ====== ====== +Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC +=== ==== ============ ==== ==== ====== ====== ====== ====== + 2 PA02 A0 2 0 - - - - + 40 PB08 A1 8 2 - 4/0 4/0 - + 41 PB09 A2 9 3 - 4/1 4/1 - + 4 PA04 A3 4 4 - 0/0 0/0 - + 5 PA05 A4 5 5 - 0/1 0/1 - + 34 PB02 A5 2 10 - 5/0 6/0 - + 11 PA11 D0 11 19 0/3 2/3 1/1 0/3 + 10 PA10 D1 10 18 0/2 2/2 1/0 0/2 + 14 PA14 D2 14 - 2/2 4/2 3/0 0/4 + 9 PA09 D3 9 17 0/1 2/1 0/1 1/3 + 8 PA08 D4 - 16 0/0 2/0 0/0 1/2 + 15 PA15 D5 15 - 2/3 4/3 3/1 0/5 + 20 PA20 D6 4 - 5/2 3/2 7/0 0/4 + 21 PA21 D7 5 - 5/3 3/3 7/1 0/7 + 7 PA07 D9 7 7 - 0/3 1/1 - + 55 PB23 RX 7 - - 5/3 7/1 - + 54 PB22 TX 6 - - 5/2 7/0 - + 18 PA18 D10 2 - 1/2 3/2 3/0 0/2 + 16 PA16 D11 0 - 1/0 3/0 2/0 0/6 + 19 PA19 D12 3 - 1/3 3/3 3/1 0/3 + 17 PA17 D13 1 - 1/1 3/1 2/1 0/7 + 13 PA13 FLASH_CS 13 - 2/1 4/1 2/0 0/7 + 35 PB03 LED_RX 3 11 - 5/1 6/1 - + 27 PA27 LED_TX 15 - - - - - + 12 PA12 MISO 12 - 2/0 4/0 2/0 0/6 + 42 PB10 MOSI 10 - - 4/2 5/0 0/4 + 6 PA06 NEOPIXEL 6 6 - 0/2 1/0 - + 43 PB11 SCK 11 - - 4/3 5/1 0/5 + 23 PA23 SCL 7 - 3/1 5/1 4/1 0/5 + 22 PA22 SDA 6 - 3/0 5/0 4/0 0/4 + 30 PA30 SWCLK 10 - - 1/2 1/0 - + 31 PA31 SWDIO 11 - - 1/3 1/1 - + 24 PA24 USB_DM 12 - 3/2 5/2 5/0 1/2 + 25 PA25 USB_DP 13 - 3/3 5/3 5/1 1/3 + 0 PA00 - 0 - - 1/0 2/0 - + 1 PA01 - 1 - - 1/1 2/1 - + 3 PA03 - 3 1 - - - - + 28 PA28 - 8 - - - - - +=== ==== ============ ==== ==== ====== ====== ====== ====== + +For the definition of the table columns see the explanation at the table for +Adafruit ItsyBitsy M0 Express :ref:`samd21_pinout_table`. + +The default devices at the board are: + +- UART 5 at pins 21/20, labelled RX/TX +- I2C 3 at pins 22/23, labelled SDA/SCL +- SPI 4 at pins 24/25/26, labelled MOSI, MISO and SCK +- DAC output on pin 14, labelled A0 + +Adafruit Trinket M0 pin assignment table +------------------------------------------------ + +=== ==== ============ ==== ==== ====== ====== ====== ====== +Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC +=== ==== ============ ==== ==== ====== ====== ====== ====== + 8 PA08 D0 - 16 0/0 2/0 0/0 1/2 + 2 PA02 D1 2 0 - - - - + 9 PA09 D2 9 17 0/1 2/1 0/1 1/3 + 7 PA07 D3 7 7 - 0/3 1/1 - + 6 PA06 D4 6 6 - 0/2 1/0 - + 1 PA01 DOTSTAR_CLK 1 - - 1/1 2/1 - + 0 PA00 DOTSTAR_DATA 0 - - 1/0 2/0 - + 10 PA10 LED 10 18 0/2 2/2 1/0 0/2 + 30 PA30 SWCLK 10 - - 1/2 1/0 - + 31 PA31 SWDIO 11 - - 1/3 1/1 - + 24 PA24 USB_DM 12 - 3/2 5/2 5/0 1/2 + 25 PA25 USB_DP 13 - 3/3 5/3 5/1 1/3 + 3 PA03 - 3 1 - - - - + 4 PA04 - 4 4 - 0/0 0/0 - + 5 PA05 - 5 5 - 0/1 0/1 - + 11 PA11 - 11 19 0/3 2/3 1/1 0/3 + 14 PA14 - 14 - 2/2 4/2 3/0 0/4 + 15 PA15 - 15 - 2/3 4/3 3/1 0/5 + 16 PA16 - 0 - 1/0 3/0 2/0 0/6 + 17 PA17 - 1 - 1/1 3/1 2/1 0/7 + 18 PA18 - 2 - 1/2 3/2 3/0 0/2 + 19 PA19 - 3 - 1/3 3/3 3/1 0/3 + 22 PA22 - 6 - 3/0 5/0 4/0 0/4 + 23 PA23 - 7 - 3/1 5/1 4/1 0/5 + 27 PA27 - 15 - - - - - + 28 PA28 - 8 - - - - - +=== ==== ============ ==== ==== ====== ====== ====== ====== + +For the definition of the table columns see the explanation at the table for +Adafruit ItsyBitsy M0 Express :ref:`samd21_pinout_table`. + +The default devices at the board are: + +- UART 0 at pins 3/4, labelled D3/D4 +- I2C 2 at pins 0/2, labelled D0/D2 +- SPI 0 at pins 4/2/3, labelled D4, D2 and D0 +- DAC output on pin 1, labelled D1 + +SAMD21 Xplained PRO pin assignment table +---------------------------------------- + +=== ==== ============ ==== ==== ====== ====== ====== ====== +Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC +=== ==== ============ ==== ==== ====== ====== ====== ====== + 32 PB00 EXT1_PIN3 0 8 - 5/2 7/0 - + 33 PB01 EXT1_PIN4 1 9 - 5/3 7/1 - + 38 PB06 EXT1_PIN5 6 14 - - - - + 39 PB07 EXT1_PIN6 7 15 - - - - + 34 PB02 EXT1_PIN7 2 10 - 5/0 6/0 - + 35 PB03 EXT1_PIN8 3 11 - 5/1 6/1 - + 36 PB04 EXT1_PIN9 4 12 - - - - + 37 PB05 EXT1_PIN10 5 13 - - - - + 8 PA08 EXT1_PIN11 - 16 0/0 2/0 0/0 1/2 + 9 PA09 EXT1_PIN12 9 17 0/1 2/1 0/1 1/3 + 41 PB09 EXT1_PIN13 9 3 - 4/1 4/1 - + 40 PB08 EXT1_PIN14 8 2 - 4/0 4/0 - + 5 PA05 EXT1_PIN15 5 5 - 0/1 0/1 - + 6 PA06 EXT1_PIN16 6 6 - 0/2 1/0 - + 4 PA04 EXT1_PIN17 4 4 - 0/0 0/0 - + 7 PA07 EXT1_PIN18 7 7 - 0/3 1/1 - + 10 PA10 EXT2_PIN3 10 18 0/2 2/2 1/0 0/2 + 11 PA11 EXT2_PIN4 11 19 0/3 2/3 1/1 0/3 + 20 PA20 EXT2_PIN5 4 - 5/2 3/2 7/0 0/4 + 21 PA21 EXT2_PIN6 5 - 5/3 3/3 7/1 0/7 + 44 PB12 EXT2_PIN7 12 - 4/0 - 4/0 0/6 + 45 PB13 EXT2_PIN8 13 - 4/1 - 4/1 0/7 + 46 PB14 EXT2_PIN9 14 - 4/2 - 5/0 - + 47 PB15 EXT2_PIN10 15 - 4/3 - 5/1 - + 43 PB11 EXT2_PIN13 11 - - 4/3 5/1 0/5 + 42 PB10 EXT2_PIN14 10 - - 4/2 5/0 0/4 + 17 PA17 EXT2_PIN15 1 - 1/1 3/1 2/1 0/7 + 18 PA18 EXT2_PIN16 2 - 1/2 3/2 3/0 0/2 + 16 PA16 EXT2_PIN17 0 - 1/0 3/0 2/0 0/6 + 19 PA19 EXT2_PIN18 3 - 1/3 3/3 3/1 0/3 + 2 PA02 EXT3_PIN3 2 0 - - - - + 3 PA03 EXT3_PIN4 3 1 - - - - + 15 PA15 EXT3_PIN6 15 - 2/3 4/3 3/1 0/5 + 12 PA12 EXT3_PIN7 12 - 2/0 4/0 2/0 0/6 + 13 PA13 EXT3_PIN8 13 - 2/1 4/1 2/0 0/7 + 28 PA28 EXT3_PIN9 8 - - - - - + 27 PA27 EXT3_PIN10 15 - - - - - + 49 PB17 EXT3_PIN15 1 - 5/1 - 6/1 0/5 + 54 PB22 EXT3_PIN16 6 - - 5/2 7/0 - + 48 PB16 EXT3_PIN17 9 - 5/0 - 6/0 0/4 + 55 PB23 EXT3_PIN18 7 - - 5/3 7/1 - + 62 PB30 LED 14 - - 5/0 0/0 1/2 + 30 PA30 SWCLK 10 - - 1/2 1/0 - + 31 PA31 SWDIO 11 - - 1/3 1/1 - + 24 PA24 USB_DM 12 - 3/2 5/2 5/0 1/2 + 25 PA25 USB_DP 13 - 3/3 5/3 5/1 1/3 + 0 PA00 - 0 - - 1/0 2/0 - + 1 PA01 - 1 - - 1/1 2/1 - + 14 PA14 - 14 - 2/2 4/2 3/0 0/4 + 22 PA22 - 6 - 3/0 5/0 4/0 0/4 + 23 PA23 - 7 - 3/1 5/1 4/1 0/5 + 63 PB31 - 15 - - 5/1 0/1 1/3 +=== ==== ============ ==== ==== ====== ====== ====== ====== + +For the definition of the table columns see the explanation at the table for +Adafruit ItsyBitsy M0 Express :ref:`samd21_pinout_table`. + +There are no pins labelled for default devices on this board. DAC output +is on pin 32, labelled EXT3_PIN3 + +Minisam M4 pin assignment table +------------------------------- + +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== +Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== + 16 PA16 D0 0 - - 1/0 3/1 2/0 1/0 0/4 + 17 PA17 D1 1 - - 1/1 3/0 2/1 1/1 0/5 + 19 PA19 D3 3 - - 1/3 3/3 3/1 1/3 0/7 + 20 PA20 D4 4 - - 5/2 3/2 7/0 1/4 0/0 + 21 PA21 D5 5 - - 5/3 3/3 7/1 1/5 0/1 + 2 PA02 A0_D9 2 0 - - - - - - + 40 PB08 A1_D10 8 2 0 - 4/0 4/0 - - + 41 PB09 A2_D11 9 3 1 - 4/1 4/1 - - + 4 PA04 A3_D12 4 4 - - 0/0 0/0 - - + 5 PA05 A4_D13 5 5 - - 0/1 0/1 - - + 6 PA06 A5 6 6 - - 0/2 1/0 - - + 7 PA07 A6_D2 7 7 - - 0/3 1/1 - - + 3 PA03 AREF 3 10 - - - - - - + 0 PA00 BUTTON 0 - - - 1/0 2/0 - - + 34 PB02 DOTSTAR_CLK 2 14 - - 5/0 6/0 2/2 - + 35 PB03 DOTSTAR_DATA 9 15 - - 5/1 6/1 - - + 15 PA15 LED 15 - - 2/3 4/3 3/1 2/1 1/3 + 55 PB23 MISO 7 - - 1/3 5/3 7/1 - - + 54 PB22 MOSI 22 - - 1/2 5/2 7/0 - - + 1 PA01 SCK 1 - - - 1/1 2/1 - - + 13 PA13 SCL 13 - - 2/1 4/0 2/1 0/7 1/3 + 12 PA12 SDA 12 - - 2/0 4/1 2/0 0/6 1/2 + 30 PA30 SWCLK 14 - - 7/2 1/2 6/0 2/0 - + 31 PA31 SWDIO 15 - - 7/3 1/3 6/1 2/1 - + 24 PA24 USB_DM 8 - - 3/2 5/2 5/0 2/2 - + 25 PA25 USB_DP 9 - - 3/3 5/3 5/1 - - + 8 PA08 - - 8 2 0/0 2/1 0/0 0/0 1/4 + 9 PA09 - 9 9 3 0/1 2/0 0/1 0/1 1/5 + 10 PA10 - 10 10 - 0/2 2/2 1/0 0/2 1/6 + 11 PA11 - 11 11 - 0/3 2/3 1/1 0/3 1/7 + 14 PA14 - 14 - - 2/2 4/2 3/0 2/0 1/2 + 18 PA18 - 2 - - 1/2 3/2 3/0 1/2 0/6 + 22 PA22 - 6 - - 3/0 5/1 4/0 1/6 0/2 + 23 PA23 - 7 - - 3/1 5/0 4/1 1/7 0/3 + 27 PA27 - 11 - - - - - - - + 42 PB10 - 10 - - - 4/2 5/0 0/4 1/0 + 43 PB11 - 12 - - - 4/3 5/1 0/5 1/1 +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== + +For the definition of the table columns see the explanation at the table for +Adafruit ItsyBitsy M4 Express :ref:`samd51_pinout_table`. + +The default devices at the board are: + +- UART 1 at pins 6/7, labelled D0/D1 +- I2C 2 at pins 14/15, labelled SDA/SCL +- SPI 1 at pins 16/17/18, labelled MOSI, MISO and SCK +- DAC output on pins 0 and 4, labelled A0_D9 and A4_D13 + +Seeed WIO Terminal pin assignment table +--------------------------------------- + +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== +Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== + 33 PB01 CS 1 13 - - 5/3 7/1 - - + 59 PB27 RX 13 - - 2/1 4/0 - 1/3 - + 58 PB26 TX 12 - - 2/0 4/1 - 1/2 - + 79 PC15 3V3_ENABLE 15 - - 7/3 6/3 - 0/5 1/1 + 78 PC14 5V_ENABLE 14 - - 7/2 6/2 - 0/4 1/0 + 40 PB08 A0_D0 8 2 0 - 4/0 4/0 - - + 41 PB09 A1_D1 9 3 1 - 4/1 4/1 - - + 7 PA07 A2_D2 7 7 - - 0/3 1/1 - - + 36 PB04 A3_D3 4 - 6 - - - - - + 37 PB05 A4_D4 5 - 7 - - - - - + 38 PB06 A5_D5 6 - 8 - - - - - + 4 PA04 A6_D6 4 4 - - 0/0 0/0 - - + 39 PB07 A7_D7 7 - 9 - - - - - + 6 PA06 A8_D8 6 6 - - 0/2 1/0 - - + 90 PC26 BUTTON_1 10 - - - - - - - + 91 PC27 BUTTON_2 11 - - 1/0 - - - - + 92 PC28 BUTTON_3 12 - - 1/1 - - - - +107 PD11 BUZZER 6 - - 7/3 6/3 - 0/4 - + 47 PB15 GPCLK0 15 - - 4/3 - 5/1 4/1 0/3 + 44 PB12 GPCLK1 12 - - 4/0 - 4/0 3/0 0/0 + 45 PB13 GPCLK2 13 - - 4/1 - 4/1 3/1 0/1 + 48 PB16 I2C_BCLK 0 - - 5/0 - 6/0 3/0 0/4 + 20 PA20 I2S_LRCLK 4 - - 5/2 3/2 7/0 1/4 0/0 + 21 PA21 I2S_SDIN 5 - - 5/3 3/3 7/1 1/5 0/1 + 22 PA22 I2S_SDOUT 6 - - 3/0 5/1 4/0 1/6 0/2 + 50 PB18 LCD_MISO 2 - - 5/2 7/2 - 1/0 - + 51 PB19 LCD_MOSI 3 - - 5/3 7/3 - 1/1 - + 52 PB20 LCD_SCK 4 - - 3/0 7/1 - 1/2 - + 53 PB21 LCD_CS 5 - - 3/1 7/0 - 1/3 - + 70 PC06 LCD_D/C 6 - - 6/2 - - - - + 71 PC07 LCD_RESET 9 - - 6/3 - - - - + 74 PC10 LCD_XL 10 - - 6/2 7/2 - 0/0 1/4 + 76 PC12 LCD_XR 12 - - 7/0 6/1 - 0/2 1/6 + 77 PC13 LCD_YD 13 - - 7/1 6/0 - 0/3 1/7 + 75 PC11 LCD_YU 11 - - 6/3 7/3 - 0/1 1/5 + 15 PA15 LED_BLUE 15 - - 2/3 4/3 3/1 2/1 1/3 + 69 PC05 LED_LCD 5 - - 6/1 - - - - + 94 PC30 MIC 14 - 12 - - - - - + 32 PB00 MISO 9 12 - - 5/2 7/0 - - + 34 PB02 MOSI 2 14 - - 5/0 6/0 2/2 - + 35 PB03 SCK 9 15 - - 5/1 6/1 - - + 12 PA12 SCL0 12 - - 2/0 4/1 2/0 0/6 1/2 + 13 PA13 SDA0 13 - - 2/1 4/0 2/1 0/7 1/3 + 16 PA16 SCL1 0 - - 1/0 3/1 2/0 1/0 0/4 + 17 PA17 SDA1 1 - - 1/1 3/0 2/1 1/1 0/5 +117 PD21 SD_DET 11 - - 1/3 3/3 - 1/1 - + 83 PC19 SD_CS 3 - - 6/3 0/3 - 0/3 - + 82 PC18 SD_MISO 2 - - 6/2 0/2 - 0/2 - + 80 PC16 SD_MOSI 0 - - 6/0 0/1 - 0/0 - + 81 PC17 SD_SCK 1 - - 6/1 0/0 - 0/1 - + 30 PA30 SWCLK 14 - - 7/2 1/2 6/0 2/0 - + 31 PA31 SWDIO 15 - - 7/3 1/3 6/1 2/1 - +108 PD12 SWITCH_B 7 - - - - - 0/5 - +116 PD20 SWITCH_U 10 - - 1/2 3/2 - 1/0 - +104 PD08 SWITCH_X 3 - - 7/0 6/1 - 0/1 - +105 PD09 SWITCH_Y 4 - - 7/1 6/0 - 0/2 - +106 PD10 SWITCH_Z 5 - - 7/2 6/2 - 0/3 - + 24 PA24 USB_DM 8 - - 3/2 5/2 5/0 2/2 - + 25 PA25 USB_DP 9 - - 3/3 5/3 5/1 - - + 0 PA00 - 0 - - - 1/0 2/0 - - + 1 PA01 - 1 - - - 1/1 2/1 - - + 2 PA02 - 2 0 - - - - - - + 3 PA03 - 3 10 - - - - - - + 5 PA05 - 5 5 - - 0/1 0/1 - - + 8 PA08 - - 8 2 0/0 2/1 0/0 0/0 1/4 + 9 PA09 - 9 9 3 0/1 2/0 0/1 0/1 1/5 + 10 PA10 - 10 10 - 0/2 2/2 1/0 0/2 1/6 + 11 PA11 - 11 11 - 0/3 2/3 1/1 0/3 1/7 + 14 PA14 - 14 - - 2/2 4/2 3/0 2/0 1/2 + 18 PA18 - 2 - - 1/2 3/2 3/0 1/2 0/6 + 19 PA19 - 3 - - 1/3 3/3 3/1 1/3 0/7 + 23 PA23 - 7 - - 3/1 5/0 4/1 1/7 0/3 + 27 PA27 - 11 - - - - - - - + 42 PB10 - 10 - - - 4/2 5/0 0/4 1/0 + 43 PB11 - 12 - - - 4/3 5/1 0/5 1/1 + 46 PB14 - 14 - - 4/2 - 5/0 4/0 0/2 + 49 PB17 - 1 - - 5/1 - 6/1 3/1 0/5 + 54 PB22 - 22 - - 1/2 5/2 7/0 - - + 55 PB23 - 7 - - 1/3 5/3 7/1 - - + 56 PB24 - 8 - - 0/0 2/1 - - - + 57 PB25 - 9 - - 0/1 2/0 - - - + 60 PB28 - 14 - - 2/2 4/2 - 1/4 - + 61 PB29 - 15 - - 2/3 4/3 - 1/5 - + 62 PB30 - 14 - - 7/0 5/1 0/0 4/0 0/6 + 63 PB31 - 15 - - 7/1 5/0 0/1 4/1 0/7 + 64 PC00 - 0 - 10 - - - - - + 65 PC01 - 1 - 11 - - - - - + 66 PC02 - 2 - 4 - - - - - + 67 PC03 - 3 - 5 - - - - - + 68 PC04 - 4 - - 6/0 - - 0/0 - + 84 PC20 - 4 - - - - - 0/4 - + 85 PC21 - 5 - - - - - 0/5 - + 86 PC22 - 6 - - 1/0 3/1 - 0/5 - + 87 PC23 - 7 - - 1/1 3/0 - 0/7 - + 88 PC24 - 8 - - 0/2 2/2 - - - + 89 PC25 - 9 - - 0/3 2/3 - - - + 95 PC31 - 15 - 13 - - - - - + 96 PD00 - 0 - 14 - - - - - + 97 PD01 - 1 - 15 - - - - - +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== + +For the definition of the table columns see the explanation at the table for +Adafruit ItsyBitsy M4 Express :ref:`samd51_pinout_table`. + +There seems to be no default pin assignment for this board. + +Sparkfun SAMD51 Thing Plus pin assignment table +------------------------------------------------ + +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== +Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== + 2 PA02 A0 2 0 - - - - - - + 40 PB08 A1 8 2 0 - 4/0 4/0 - - + 41 PB09 A2 9 3 1 - 4/1 4/1 - - + 4 PA04 A3 4 4 - - 0/0 0/0 - - + 5 PA05 A4 5 5 - - 0/1 0/1 - - + 34 PB02 A5 2 14 - - 5/0 6/0 2/2 - + 13 PA13 D0 13 - - 2/1 4/0 2/1 0/7 1/3 + 12 PA12 D1 12 - - 2/0 4/1 2/0 0/6 1/2 + 6 PA06 D4 6 6 - - 0/2 1/0 - - + 15 PA15 D5 15 - - 2/3 4/3 3/1 2/1 1/3 + 20 PA20 D6 4 - - 5/2 3/2 7/0 1/4 0/0 + 21 PA21 D7 5 - - 5/3 3/3 7/1 1/5 0/1 + 7 PA07 D9 7 7 - - 0/3 1/1 - - + 18 PA18 D10 2 - - 1/2 3/2 3/0 1/2 0/6 + 16 PA16 D11 0 - - 1/0 3/1 2/0 1/0 0/4 + 19 PA19 D12 3 - - 1/3 3/3 3/1 1/3 0/7 + 17 PA17 D13 1 - - 1/1 3/0 2/1 1/1 0/5 + 10 PA10 FLASH_CS 10 10 - 0/2 2/2 1/0 0/2 1/6 + 11 PA11 FLASH_MISO 11 11 - 0/3 2/3 1/1 0/3 1/7 + 8 PA08 FLASH_MOSI - 8 2 0/0 2/1 0/0 0/0 1/4 + 9 PA09 FLASH_SCK 9 9 3 0/1 2/0 0/1 0/1 1/5 + 43 PB11 MISO 12 - - - 4/3 5/1 0/5 1/1 + 44 PB12 MOSI 12 - - 4/0 - 4/0 3/0 0/0 + 55 PB23 RXD 7 - - 1/3 5/3 7/1 - - + 35 PB03 RXLED 9 15 - - 5/1 6/1 - - + 45 PB13 SCK 13 - - 4/1 - 4/1 3/1 0/1 + 23 PA23 SCL 7 - - 3/1 5/0 4/1 1/7 0/3 + 22 PA22 SDA 6 - - 3/0 5/1 4/0 1/6 0/2 + 30 PA30 SWCLK 14 - - 7/2 1/2 6/0 2/0 - + 31 PA31 SWDIO 15 - - 7/3 1/3 6/1 2/1 - + 54 PB22 TXD 22 - - 1/2 5/2 7/0 - - + 27 PA27 TXLED 11 - - - - - - - + 24 PA24 USB_DM 8 - - 3/2 5/2 5/0 2/2 - + 25 PA25 USB_DP 9 - - 3/3 5/3 5/1 - - + 0 PA00 - 0 - - - 1/0 2/0 - - + 1 PA01 - 1 - - - 1/1 2/1 - - + 3 PA03 - 3 10 - - - - - - + 14 PA14 - 14 - - 2/2 4/2 3/0 2/0 1/2 + 32 PB00 - 9 12 - - 5/2 7/0 - - + 33 PB01 - 1 13 - - 5/3 7/1 - - + 36 PB04 - 4 - 6 - - - - - + 37 PB05 - 5 - 7 - - - - - + 38 PB06 - 6 - 8 - - - - - + 39 PB07 - 7 - 9 - - - - - + 42 PB10 - 10 - - - 4/2 5/0 0/4 1/0 + 46 PB14 - 14 - - 4/2 - 5/0 4/0 0/2 + 47 PB15 - 15 - - 4/3 - 5/1 4/1 0/3 + 48 PB16 - 0 - - 5/0 - 6/0 3/0 0/4 + 49 PB17 - 1 - - 5/1 - 6/1 3/1 0/5 + 62 PB30 - 14 - - 7/0 5/1 0/0 4/0 0/6 + 63 PB31 - 15 - - 7/1 5/0 0/1 4/1 0/7 +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== + +For the definition of the table columns see the explanation at the table for +Adafruit ItsyBitsy M4 Express :ref:`samd51_pinout_table`. + +The default devices at the board are: + +- UART 1 at pins 2/3, labelled RXD/TXD +- I2C 5 at pins 20/21, labelled SDA/SCL +- SPI 4 at pins 22/23/24, labelled MOSI, MISO and SCK +- DAC output on pins 14 and 18, labelled A0 and A4 + +Scripts for creating the pin assignment tables +---------------------------------------------- + +The tables shown above were created with small a Python script running on the target board:: + + from samd import pininfo + from machine import Pin + import os + + def print_entry(e, txt): + print(txt, end=": ") + if e == 255: + print(" - ", end="") + else: + print("%d/%d" % (e >> 4, e & 0x0f), end="") + + def print_pininfo(pin, info): + print("%3d" % pin, end=" ") + print("P%c%02d" % ("ABCD"[pin // 32], pin % 32), end="") + print(" %12s" % info[0], end="") + print(" IRQ:%2s" % (info[1] if info[1] != 255 else "-"), end="") + print(" ADC0:%2s" % (info[2] if info[2] != 255 else "-"), end="") + if len(info) == 7: + print_entry(info[3], " Serial1") + print_entry(info[4], " Serial2") + print_entry(info[5], " PWM1" if (info[5] >> 4) < 3 else " TC") + print_entry(info[6], " PWM2") + else: + print(" ADC1:%2s" % (info[3] if info[3] != 255 else "-"), end="") + print_entry(info[4], " Serial1") + print_entry(info[5], " Serial2") + print_entry(info[6], " TC") + print_entry(info[7], " PWM1") + print_entry(info[8], " PWM2") + print() + + def tblkey(i): + name = i[1][0] + if name != "-": + if len(name) < 3: + return " " + name + else: + return name + else: + return "zzzzzzz%03d" % i[0] + + def table(num = 127): + pintbl = [] + for i in range(num): + try: + pintbl.append((i, pininfo(i))) + except: + pass + # print("not defined") + + pintbl.sort(key=tblkey) + for item in pintbl: + print_pininfo(item[0], item[1]) + + table() diff --git a/docs/samd/quickref.rst b/docs/samd/quickref.rst new file mode 100644 index 0000000000..5e8298d1b3 --- /dev/null +++ b/docs/samd/quickref.rst @@ -0,0 +1,469 @@ +.. _samd_quickref: + +Quick reference for the SAMD21/SAMD51 family +============================================ + +.. image:: img/itsybitsy_m4_express.jpg + :alt: Adafruit ItsyBitsy M4 Express board + :width: 640px + +The Adafruit ItsyBitsy M4 Express board. + +Below is a quick reference for SAMD21/SAMD51-based boards. If it is your first time +working with this board it may be useful to get an overview of the microcontroller: + +.. toctree:: + :maxdepth: 1 + + general.rst + tutorial/intro.rst + pinout.rst + + +Installing MicroPython +---------------------- + +See the corresponding section of tutorial: :ref:`samd_intro`. It also includes +a troubleshooting subsection. + +General board control +--------------------- + +The MicroPython REPL is on the USB port, configured in VCP mode. +Tab-completion is useful to find out what methods an object has. +Paste mode (Ctrl-E) is useful to paste a large slab of Python code into +the REPL. + +The :mod:`machine` module:: + + import machine + + machine.freq() # get the current frequency of the CPU + machine.freq(96_000_000) # set the CPU frequency to 96 MHz + +The range accepted by the function call is 1_000_000 to 200_000_000 (1 MHz to 200 MHz) +for SAMD51 and 1_000_000 to 48_000_000 (1 MHz to 48 MHz) for SAMD21. The safe +range for SAMD51 according to the data sheet is 96 MHz to 120 MHz. +At frequencies below 8 MHz USB will be disabled. Changing the frequency below 48 MHz +impacts the baud rates of UART, I2C and SPI. These have to be set again after +changing the CPU frequency. The ms and µs timers are not affected by the frequency +change. + + +Delay and timing +---------------- + +Use the :mod:`time Quick reference for the Renesas RA
general information for Renesas RA based boards, snippets of useful code, and a tutorial

+ From c138e10fbb60981ca9e9b7459e7b9ae0c2528c94 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 27 Oct 2022 12:57:10 +1100 Subject: [PATCH 0591/1041] py/makeversionhdr: Fall back to py/mpconfig.h instead of docs/conf.py. Commit 64af916c111b61bce82c00f356a6b1cb81946d87 removed the version string from docs/conf.py. py/mpconfig.h is a better place to get the version from, so use that (when there is no git repository). Signed-off-by: Damien George --- py/makeversionhdr.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/py/makeversionhdr.py b/py/makeversionhdr.py index 54b7fa9ab7..d1b41e63b0 100644 --- a/py/makeversionhdr.py +++ b/py/makeversionhdr.py @@ -62,21 +62,27 @@ def get_version_info_from_git(): return git_tag, git_hash -def get_version_info_from_docs_conf(): - with open(os.path.join(os.path.dirname(sys.argv[0]), "..", "docs", "conf.py")) as f: +def get_version_info_from_mpconfig(): + with open(os.path.join(os.path.dirname(sys.argv[0]), "..", "py", "mpconfig.h")) as f: for line in f: - if line.startswith("version = release = '"): - ver = line.strip().split(" = ")[2].strip("'") - git_tag = "v" + ver + if line.startswith("#define MICROPY_VERSION_MAJOR "): + ver_major = int(line.strip().split()[2]) + elif line.startswith("#define MICROPY_VERSION_MINOR "): + ver_minor = int(line.strip().split()[2]) + elif line.startswith("#define MICROPY_VERSION_MICRO "): + ver_micro = int(line.strip().split()[2]) + git_tag = "v%d.%d" % (ver_major, ver_minor) + if ver_micro != 0: + git_tag += ".%d" % (ver_micro,) return git_tag, "" return None def make_version_header(filename): - # Get version info using git, with fallback to docs/conf.py + # Get version info using git, with fallback to py/mpconfig.h info = get_version_info_from_git() if info is None: - info = get_version_info_from_docs_conf() + info = get_version_info_from_mpconfig() git_tag, git_hash = info From e20bb98392c988a410ba04d01d3f573e6c15803d Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 15 Oct 2022 21:37:51 +0200 Subject: [PATCH 0592/1041] mimxrt/machine_pin: Add the Pin.toggle() method. For consistency with other ports, even if this method is undocumented at the moment. --- ports/mimxrt/machine_pin.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ports/mimxrt/machine_pin.c b/ports/mimxrt/machine_pin.c index 836bd8524b..bb2c820100 100644 --- a/ports/mimxrt/machine_pin.c +++ b/ports/mimxrt/machine_pin.c @@ -285,6 +285,14 @@ STATIC mp_obj_t machine_pin_on(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_on_obj, machine_pin_on); +// pin.toggle() +STATIC mp_obj_t machine_pin_toggle(mp_obj_t self_in) { + machine_pin_obj_t *self = self_in; + mp_hal_pin_toggle(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_toggle_obj, machine_pin_toggle); + // pin.value([value]) STATIC mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) { return machine_pin_obj_call(args[0], (n_args - 1), 0, args + 1); @@ -366,6 +374,7 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_pin_on_obj) }, { MP_ROM_QSTR(MP_QSTR_low), MP_ROM_PTR(&machine_pin_off_obj) }, { MP_ROM_QSTR(MP_QSTR_high), MP_ROM_PTR(&machine_pin_on_obj) }, + { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&machine_pin_toggle_obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) }, { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) }, { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_pin_irq_obj) }, From 9d2e179fa565d8af96fb6ce3643e00f999c9210a Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 22 Oct 2022 21:28:42 +0200 Subject: [PATCH 0593/1041] mimxrt: Fix CPU freeze when calling __WFE() in MICROPY_EVENT_POLL_HOOK. This issue affected i.MX RT 1052, 1062 and 1064. It seems to be addressed by Errata ERR006223, which also mentions i.MX RT101x and 102x, but these devices worked well even without the change. As a side effect, the current consumption at an idle REPL drops significantly with this fix. Fixes issue #7235. --- ports/mimxrt/boards/MIMXRT1052_clock_config.c | 1 + ports/mimxrt/boards/MIMXRT1062_clock_config.c | 1 + ports/mimxrt/boards/MIMXRT1064_clock_config.c | 1 + ports/mimxrt/mpconfigport.h | 1 + 4 files changed, 4 insertions(+) diff --git a/ports/mimxrt/boards/MIMXRT1052_clock_config.c b/ports/mimxrt/boards/MIMXRT1052_clock_config.c index 9349281297..fa7450d487 100644 --- a/ports/mimxrt/boards/MIMXRT1052_clock_config.c +++ b/ports/mimxrt/boards/MIMXRT1052_clock_config.c @@ -465,4 +465,5 @@ void BOARD_BootClockRUN(void) { IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_MASK; /* Set SystemCoreClock variable. */ SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK; + CLOCK_SetMode(kCLOCK_ModeRun); } diff --git a/ports/mimxrt/boards/MIMXRT1062_clock_config.c b/ports/mimxrt/boards/MIMXRT1062_clock_config.c index 05474167bd..589ffb0b58 100644 --- a/ports/mimxrt/boards/MIMXRT1062_clock_config.c +++ b/ports/mimxrt/boards/MIMXRT1062_clock_config.c @@ -487,4 +487,5 @@ void BOARD_BootClockRUN(void) { IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_MASK; /* Set SystemCoreClock variable. */ SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK; + CLOCK_SetMode(kCLOCK_ModeRun); } diff --git a/ports/mimxrt/boards/MIMXRT1064_clock_config.c b/ports/mimxrt/boards/MIMXRT1064_clock_config.c index 5e49a2fff8..56dd75d7fb 100644 --- a/ports/mimxrt/boards/MIMXRT1064_clock_config.c +++ b/ports/mimxrt/boards/MIMXRT1064_clock_config.c @@ -487,4 +487,5 @@ void BOARD_BootClockRUN(void) { IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_MASK; /* Set SystemCoreClock variable. */ SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK; + CLOCK_SetMode(kCLOCK_ModeRun); } diff --git a/ports/mimxrt/mpconfigport.h b/ports/mimxrt/mpconfigport.h index 8642d53ecc..3f87800e30 100644 --- a/ports/mimxrt/mpconfigport.h +++ b/ports/mimxrt/mpconfigport.h @@ -241,6 +241,7 @@ extern const struct _mp_obj_type_t network_lan_type; do { \ extern void mp_handle_pending(bool); \ mp_handle_pending(true); \ + __WFE(); \ } while (0); #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1)) From 65fa7fd8bbaf570be3f4654bcc597a46c70e4b75 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 15 Oct 2022 11:40:22 +0200 Subject: [PATCH 0594/1041] mimxrt/machine_timer: Use soft-timer implementation for machine.Timer. This releases the hardware timers for other tasks, which need a higher resolution and faster response. And it is less port-specific code. --- docs/mimxrt/quickref.rst | 9 +-- ports/mimxrt/Makefile | 1 + ports/mimxrt/board_init.c | 3 - ports/mimxrt/machine_timer.c | 152 +++++++++-------------------------- ports/mimxrt/main.c | 2 + ports/mimxrt/mphalport.h | 4 + ports/mimxrt/systick.c | 7 ++ 7 files changed, 55 insertions(+), 123 deletions(-) diff --git a/docs/mimxrt/quickref.rst b/docs/mimxrt/quickref.rst index c75fe60c8d..06f91f7f50 100644 --- a/docs/mimxrt/quickref.rst +++ b/docs/mimxrt/quickref.rst @@ -56,21 +56,18 @@ Use the :mod:`time