From f24cfd1a69df9ef1a8233c5bd57c56f701762b49 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Mon, 12 Dec 2022 14:16:59 +0100 Subject: [PATCH 01/59] extmod/axtls-include: Add back needed header files for building axTLS. MicroPython overrides the axTLS port configuration file, but fails to include (needed for htonl) and (needed for gettimeofday). This results in build failures with compilers which do not support implicit function declarations (which were removed from C in 1999). This commit adds back the needed headers that were removed in this commit: https://github.com/micropython/axtls/commit/bd0801730969a290572c72b8c65e53f160ed2680 Signed-off-by: Damien George --- extmod/axtls-include/axtls_os_port.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/extmod/axtls-include/axtls_os_port.h b/extmod/axtls-include/axtls_os_port.h index ef2683acfc..057642f974 100644 --- a/extmod/axtls-include/axtls_os_port.h +++ b/extmod/axtls-include/axtls_os_port.h @@ -26,7 +26,11 @@ #ifndef AXTLS_OS_PORT_H #define AXTLS_OS_PORT_H +#ifndef __ets__ +#include +#endif #include +#include #include "py/stream.h" #include "lib/crypto-algorithms/sha256.h" From b5823604a005de9232b482ce8f820735e8f69106 Mon Sep 17 00:00:00 2001 From: Paul Grayson Date: Wed, 23 Nov 2022 12:01:37 -0800 Subject: [PATCH 02/59] rp2/machine_pwm: Use more accurate formulas for freq and duty_u16. This changes the freq() and duty_u16() functions to use more simpler, more accurate formulas, in particular increasing the frequency accuracy from a few percent to a fraction of a percent in many cases. Signed-off-by: Paul Grayson --- ports/rp2/machine_pwm.c | 50 +++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/ports/rp2/machine_pwm.c b/ports/rp2/machine_pwm.c index 41dc3ab476..1b70746a73 100644 --- a/ports/rp2/machine_pwm.c +++ b/ports/rp2/machine_pwm.c @@ -113,30 +113,31 @@ STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) { // Maximum "top" is set at 65534 to be able to achieve 100% duty with 65535. #define TOP_MAX 65534 uint32_t source_hz = clock_get_hz(clk_sys); - uint32_t div16_top = 16 * source_hz / freq; - uint32_t top = 1; - for (;;) { - // Try a few small prime factors to get close to the desired frequency. - if (div16_top >= 16 * 5 && div16_top % 5 == 0 && top * 5 <= TOP_MAX) { - div16_top /= 5; - top *= 5; - } else if (div16_top >= 16 * 3 && div16_top % 3 == 0 && top * 3 <= TOP_MAX) { - div16_top /= 3; - top *= 3; - } else if (div16_top >= 16 * 2 && top * 2 <= TOP_MAX) { - div16_top /= 2; - top *= 2; - } else { - break; - } + uint32_t div16; + + if ((source_hz + freq / 2) / freq < TOP_MAX) { + // If possible (based on the formula for TOP below), use a DIV of 1. + // This also prevents overflow in the DIV calculation. + div16 = 16; + } else { + // Otherwise, choose the smallest possible DIV for maximum + // duty cycle resolution. + // Constraint: 16*F/(div16*freq) < TOP_MAX + // So: div16 = ceil(16*F/(TOP_MAX*freq)) + + div16 = (16 * source_hz + TOP_MAX * freq - 1) / (TOP_MAX * freq); } - if (div16_top < 16) { + + // Set TOP as accurately as possible using rounding. + uint32_t top = (16 * source_hz + div16 * freq / 2) / (div16 * freq) - 1; + + if (div16 < 16) { mp_raise_ValueError(MP_ERROR_TEXT("freq too large")); - } else if (div16_top >= 256 * 16) { + } else if (div16 >= 256 * 16) { mp_raise_ValueError(MP_ERROR_TEXT("freq too small")); } - pwm_hw->slice[self->slice].div = div16_top; - pwm_hw->slice[self->slice].top = top - 1; + pwm_hw->slice[self->slice].div = div16; + pwm_hw->slice[self->slice].top = top; if (self->duty_type == DUTY_U16) { mp_machine_pwm_duty_set_u16(self, self->duty); } else if (self->duty_type == DUTY_NS) { @@ -148,12 +149,17 @@ STATIC mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self) { uint32_t top = pwm_hw->slice[self->slice].top; uint32_t cc = pwm_hw->slice[self->slice].cc; cc = (cc >> (self->channel ? PWM_CH0_CC_B_LSB : PWM_CH0_CC_A_LSB)) & 0xffff; - return MP_OBJ_NEW_SMALL_INT(cc * 65535 / (top + 1)); + + // Use rounding (instead of flooring) here to give as accurate an + // estimate as possible. + return MP_OBJ_NEW_SMALL_INT((cc * 65535 + (top + 1) / 2) / (top + 1)); } STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16) { uint32_t top = pwm_hw->slice[self->slice].top; - uint32_t cc = duty_u16 * (top + 1) / 65535; + + // Use rounding here to set it as accurately as possible. + uint32_t cc = (duty_u16 * (top + 1) + 65535 / 2) / 65535; pwm_set_chan_level(self->slice, self->channel, cc); pwm_set_enabled(self->slice, true); self->duty = duty_u16; From f0f5c6568de8a194f4f77c19f4e2087b87d1ab7e Mon Sep 17 00:00:00 2001 From: Paul Grayson Date: Wed, 14 Dec 2022 19:19:21 -0800 Subject: [PATCH 03/59] rp2/machine_pwm: Fix overflows with freq > 268 MHz. There were several places where 32-bit integer could overflow with frequencies of 2^28 Hz or above (~268 MHz). This fixes those overflows and also introduces rounding for more accurate duty_ns computations. Signed-off-by: Paul Grayson --- ports/rp2/machine_pwm.c | 49 +++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/ports/rp2/machine_pwm.c b/ports/rp2/machine_pwm.c index 1b70746a73..0c840eca94 100644 --- a/ports/rp2/machine_pwm.c +++ b/ports/rp2/machine_pwm.c @@ -100,11 +100,33 @@ STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self) { pwm_set_enabled(self->slice, false); } -STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) { +// Returns: floor((16*F + offset) / div16) +// Avoids overflow in the numerator that would occur if +// 16*F + offset > 2**32 +// F + offset/16 > 2**28 = 268435456 (approximately, due to flooring) +uint32_t get_slice_hz(uint32_t offset, uint32_t div16) { uint32_t source_hz = clock_get_hz(clk_sys); + if (source_hz + offset / 16 > 268000000) { + return (16 * (uint64_t)source_hz + offset) / div16; + } else { + return (16 * source_hz + offset) / div16; + } +} + +// Returns 16*F / denom, rounded. +uint32_t get_slice_hz_round(uint32_t div16) { + return get_slice_hz(div16 / 2, div16); +} + +// Returns ceil(16*F / denom). +uint32_t get_slice_hz_ceil(uint32_t div16) { + return get_slice_hz(div16 - 1, div16); +} + +STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) { uint32_t div16 = pwm_hw->slice[self->slice].div; uint32_t top = pwm_hw->slice[self->slice].top; - uint32_t pwm_freq = 16 * source_hz / div16 / (top + 1); + uint32_t pwm_freq = get_slice_hz_round(div16 * (top + 1)); return MP_OBJ_NEW_SMALL_INT(pwm_freq); } @@ -114,22 +136,27 @@ STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) { #define TOP_MAX 65534 uint32_t source_hz = clock_get_hz(clk_sys); uint32_t div16; + uint32_t top; if ((source_hz + freq / 2) / freq < TOP_MAX) { // If possible (based on the formula for TOP below), use a DIV of 1. // This also prevents overflow in the DIV calculation. div16 = 16; + + // Same as get_slice_hz_round() below but canceling the 16s + // to avoid overflow for high freq. + top = (source_hz + freq / 2) / freq - 1; } else { // Otherwise, choose the smallest possible DIV for maximum // duty cycle resolution. // Constraint: 16*F/(div16*freq) < TOP_MAX - // So: div16 = ceil(16*F/(TOP_MAX*freq)) + // So: + div16 = get_slice_hz_ceil(TOP_MAX * freq); - div16 = (16 * source_hz + TOP_MAX * freq - 1) / (TOP_MAX * freq); + // Set TOP as accurately as possible using rounding. + top = get_slice_hz_round(div16 * freq) - 1; } - // Set TOP as accurately as possible using rounding. - uint32_t top = (16 * source_hz + div16 * freq / 2) / (div16 * freq) - 1; if (div16 < 16) { mp_raise_ValueError(MP_ERROR_TEXT("freq too large")); @@ -167,17 +194,15 @@ STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u } STATIC mp_obj_t mp_machine_pwm_duty_get_ns(machine_pwm_obj_t *self) { - uint32_t source_hz = clock_get_hz(clk_sys); - uint32_t slice_hz = 16 * source_hz / pwm_hw->slice[self->slice].div; + uint32_t slice_hz = get_slice_hz_round(pwm_hw->slice[self->slice].div); uint32_t cc = pwm_hw->slice[self->slice].cc; cc = (cc >> (self->channel ? PWM_CH0_CC_B_LSB : PWM_CH0_CC_A_LSB)) & 0xffff; - return MP_OBJ_NEW_SMALL_INT((uint64_t)cc * 1000000000ULL / slice_hz); + return MP_OBJ_NEW_SMALL_INT(((uint64_t)cc * 1000000000ULL + slice_hz / 2) / slice_hz); } STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns) { - uint32_t source_hz = clock_get_hz(clk_sys); - uint32_t slice_hz = 16 * source_hz / pwm_hw->slice[self->slice].div; - uint32_t cc = (uint64_t)duty_ns * slice_hz / 1000000000ULL; + uint32_t slice_hz = get_slice_hz_round(pwm_hw->slice[self->slice].div); + uint32_t cc = ((uint64_t)duty_ns * slice_hz + 500000000ULL) / 1000000000ULL; if (cc > 65535) { mp_raise_ValueError(MP_ERROR_TEXT("duty larger than period")); } From b208cf23e290c169bf346137c30bc2a0176a223d Mon Sep 17 00:00:00 2001 From: Paul Grayson Date: Sat, 24 Dec 2022 09:55:12 -0800 Subject: [PATCH 04/59] rp2/mphalport: Change order of pin operations to prevent glitches. When switching from a special function like SPI to an input or output, there was a brief period after the function was disabled but before the pin's I/O state was configured, in which the state would be poorly defined. This fixes the problem by switching off the special function after fully configuring the I/O state. Fixes #10226. Signed-off-by: Paul Grayson --- ports/rp2/mphalport.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ports/rp2/mphalport.h b/ports/rp2/mphalport.h index 73a503f5a9..2cb9121fa2 100644 --- a/ports/rp2/mphalport.h +++ b/ports/rp2/mphalport.h @@ -91,22 +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_function(pin, GPIO_FUNC_SIO); gpio_set_dir(pin, GPIO_IN); machine_pin_open_drain_mask &= ~(1 << pin); + gpio_set_function(pin, GPIO_FUNC_SIO); } static inline void mp_hal_pin_output(mp_hal_pin_obj_t pin) { - gpio_set_function(pin, GPIO_FUNC_SIO); gpio_set_dir(pin, GPIO_OUT); machine_pin_open_drain_mask &= ~(1 << pin); + gpio_set_function(pin, GPIO_FUNC_SIO); } static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) { - gpio_set_function(pin, GPIO_FUNC_SIO); gpio_set_dir(pin, GPIO_IN); gpio_put(pin, 0); machine_pin_open_drain_mask |= 1 << pin; + gpio_set_function(pin, GPIO_FUNC_SIO); } static inline void mp_hal_pin_config(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, uint32_t alt) { From 5890a17ae049aad39f97744cadf5844c06a5a4c0 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 6 Jan 2023 11:36:18 +0100 Subject: [PATCH 05/59] rp2/rp2_flash: Call MICROPY_EVENT_POLL_HOOK_FAST after reading flash. To allow the USB to work in cases where there is a lot of filesystem access, in particular on boot. For example, registering of the USB CDC interface may fail if: - the board file system is lfs2 (default), and - sys.path contains entries for the local file system (default), and - files are imported by boot.py or main.py from frozen bytecode of the file system (common) and the file system contains many files, like 100. In that case the board is very busy with scanning LFS, and registering the USB interface seems to time out. This commit fixes this by allowing the USB to make progress during filesystem reads. Also switch existing MICROPY_EVENT_POLL_HOOK uses in this file to MICROPY_EVENT_POLL_HOOK_FAST now that the latter macro exists. --- ports/rp2/rp2_flash.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ports/rp2/rp2_flash.c b/ports/rp2/rp2_flash.c index 0a94b6cc90..26ec41949e 100644 --- a/ports/rp2/rp2_flash.c +++ b/ports/rp2/rp2_flash.c @@ -120,6 +120,11 @@ STATIC mp_obj_t rp2_flash_readblocks(size_t n_args, const mp_obj_t *args) { offset += mp_obj_get_int(args[3]); } memcpy(bufinfo.buf, (void *)(XIP_BASE + self->flash_base + offset), bufinfo.len); + // MICROPY_EVENT_POLL_HOOK_FAST is called here to avoid a fail in registering + // USB at boot time, if the board is busy loading files or scanning the file + // system. MICROPY_EVENT_POLL_HOOK_FAST calls tud_task(). As the alternative + // tud_task() should be called in the USB IRQ. See discussion in PR #10423. + MICROPY_EVENT_POLL_HOOK_FAST; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rp2_flash_readblocks_obj, 3, 4, rp2_flash_readblocks); @@ -134,7 +139,7 @@ STATIC mp_obj_t rp2_flash_writeblocks(size_t n_args, const mp_obj_t *args) { mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); flash_range_erase(self->flash_base + offset, bufinfo.len); MICROPY_END_ATOMIC_SECTION(atomic_state); - MICROPY_EVENT_POLL_HOOK + MICROPY_EVENT_POLL_HOOK_FAST; // TODO check return value } else { offset += mp_obj_get_int(args[3]); @@ -143,7 +148,7 @@ STATIC mp_obj_t rp2_flash_writeblocks(size_t n_args, const mp_obj_t *args) { mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); flash_range_program(self->flash_base + offset, bufinfo.buf, bufinfo.len); MICROPY_END_ATOMIC_SECTION(atomic_state); - MICROPY_EVENT_POLL_HOOK + MICROPY_EVENT_POLL_HOOK_FAST; // TODO check return value return mp_const_none; } From 209a6bb6b7b39882e0efdf25eab29931fb2de859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stig=20Bj=C3=B8rlykke?= Date: Thu, 15 Dec 2022 18:32:10 +0100 Subject: [PATCH 06/59] docs/rp2: Make LED have exactly 50% duty cycle in PIO 1Hz example. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ensures the same number of cycles are used for LED on and LED off in the PIO 1Hz example. It's also possible to swap the first set() and the irq() to avoid using an extra instruction, but this tutorial is a good example of how to calculate the cycles. Signed-off-by: Stig Bjørlykke --- docs/rp2/tutorial/pio.rst | 7 +++++-- examples/rp2/pio_1hz.py | 5 +++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/rp2/tutorial/pio.rst b/docs/rp2/tutorial/pio.rst index 9981aed832..4e519650ee 100644 --- a/docs/rp2/tutorial/pio.rst +++ b/docs/rp2/tutorial/pio.rst @@ -76,9 +76,10 @@ and state machines. Below is the code for reference. nop() [29] jmp(x_dec, "delay_high") - # Cycles: 1 + 7 + 32 * (30 + 1) = 1000 + # Cycles: 1 + 1 + 6 + 32 * (30 + 1) = 1000 + nop() set(pins, 0) - set(x, 31) [6] + set(x, 31) [5] label("delay_low") nop() [29] jmp(x_dec, "delay_low") @@ -113,6 +114,8 @@ the following: X starts with the value 31 this jump will happen 31 times, so the ``nop() [29]`` runs 32 times in total (note there is also one instruction cycle taken by the ``jmp`` for each of these 32 loops). +- The single ``nop()`` correlates with the cycle used for IRQ raise, and ensures + the same number of cycles are used for LED on and LED off. - ``set(pins, 0)`` will turn the LED off by setting pin 25 low. - Another 32 loops of ``nop() [29]`` and ``jmp(...)`` will execute. - Because ``wrap_target()`` and ``wrap()`` are not specified, their default will diff --git a/examples/rp2/pio_1hz.py b/examples/rp2/pio_1hz.py index c18aa22fc0..4b6fe95bbd 100644 --- a/examples/rp2/pio_1hz.py +++ b/examples/rp2/pio_1hz.py @@ -16,9 +16,10 @@ def blink_1hz(): nop() [29] jmp(x_dec, "delay_high") - # Cycles: 1 + 7 + 32 * (30 + 1) = 1000 + # Cycles: 1 + 1 + 6 + 32 * (30 + 1) = 1000 + nop() set(pins, 0) - set(x, 31) [6] + set(x, 31) [5] label("delay_low") nop() [29] jmp(x_dec, "delay_low") From a322ebafc0427f03e1423cf7642b1e6ded5a90a8 Mon Sep 17 00:00:00 2001 From: Paul Warren Date: Wed, 11 Jan 2023 14:08:08 +0000 Subject: [PATCH 07/59] docs/library/rp2.StateMachine: Expand put() documentation. Document that put() can also accept arrays/bytearrays as values. Fixes issue #10465. Signed-off-by: Paul Warren --- docs/library/rp2.StateMachine.rst | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/library/rp2.StateMachine.rst b/docs/library/rp2.StateMachine.rst index 7e38ba8b1a..d39194e6ff 100644 --- a/docs/library/rp2.StateMachine.rst +++ b/docs/library/rp2.StateMachine.rst @@ -99,13 +99,17 @@ Methods .. method:: StateMachine.put(value, shift=0) - Push a word onto the state machine's TX FIFO. + Push words onto the state machine's TX FIFO. - If the FIFO is full, it blocks until there is space (i.e. the state machine - pulls a word). + *value* can be an integer, an array of type ``B``, ``H`` or ``I``, or a + `bytearray`. - The value is first shifted left by *shift* bits, i.e. the state machine - receives ``value << shift``. + This method will block until all words have been written to the FIFO. If + the FIFO is, or becomes, full, the method will block until the state machine + pulls enough words to complete the write. + + Each word is first shifted left by *shift* bits, i.e. the state machine + receives ``word << shift``. .. method:: StateMachine.rx_fifo() From edc92d18db3e80c95ee565075fbe81f5b79d7df1 Mon Sep 17 00:00:00 2001 From: Philip Peitsch Date: Tue, 9 Jun 2020 12:34:58 +1000 Subject: [PATCH 08/59] py/map: Clear value when re-using slot with ordered dictionaries. To adhere to the contract of mp_map_lookup, namely: MP_MAP_LOOKUP_ADD_IF_NOT_FOUND behaviour: - returns slot, with key non-null and value=MP_OBJ_NULL if it was added --- py/map.c | 1 + 1 file changed, 1 insertion(+) diff --git a/py/map.c b/py/map.c index 7a6f2233e6..c18df5a9f3 100644 --- a/py/map.c +++ b/py/map.c @@ -221,6 +221,7 @@ mp_map_elem_t *MICROPY_WRAP_MP_MAP_LOOKUP(mp_map_lookup)(mp_map_t * map, mp_obj_ } mp_map_elem_t *elem = map->table + map->used++; elem->key = index; + elem->value = MP_OBJ_NULL; if (!mp_obj_is_qstr(index)) { map->all_keys_are_qstrs = 0; } From fa57ee971bcdffeeadf84dc608bd25dcb6af464f Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 15 Aug 2022 08:35:23 +1000 Subject: [PATCH 09/59] stm32/boards: Consolidate linker snippets to reduce duplication. This commit uses the REGION_ALIAS GNU linker command to simplify the linker snippets and consolidate the duplication. Signed-off-by: Damien George --- .../boards/ARDUINO_PORTENTA_H7/stm32h747.ld | 11 +++----- ports/stm32/boards/PYBD_SF2/f722_qspi.ld | 22 ++++----------- ports/stm32/boards/PYBD_SF6/f767.ld | 11 +++----- ports/stm32/boards/STM32F769DISC/f769_qspi.ld | 24 ++++------------ ports/stm32/boards/common_basic.ld | 26 +++-------------- ports/stm32/boards/common_bl.ld | 28 ++++--------------- ports/stm32/boards/common_blifs.ld | 28 ++++--------------- .../boards/common_extratext_data_in_flash.ld | 4 +-- .../common_extratext_data_in_flash_app.ld | 22 --------------- .../common_extratext_data_in_flash_text.ld | 22 --------------- ports/stm32/boards/common_ifs.ld | 18 +++--------- ports/stm32/boards/common_isr.ld | 9 ++++++ ports/stm32/boards/common_text.ld | 14 ++++++++++ 13 files changed, 61 insertions(+), 178 deletions(-) delete mode 100644 ports/stm32/boards/common_extratext_data_in_flash_app.ld delete mode 100644 ports/stm32/boards/common_extratext_data_in_flash_text.ld create mode 100644 ports/stm32/boards/common_isr.ld create mode 100644 ports/stm32/boards/common_text.ld diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/stm32h747.ld b/ports/stm32/boards/ARDUINO_PORTENTA_H7/stm32h747.ld index 650756a19f..7a973289cb 100644 --- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/stm32h747.ld +++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/stm32h747.ld @@ -44,15 +44,12 @@ _micropy_hw_internal_flash_storage_ram_cache_end = ORIGIN(DTCM) + LENGTH(DTCM); _micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); _micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); +REGION_ALIAS("FLASH_COMMON", FLASH_TEXT); + /* define output sections */ SECTIONS { - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) - . = ALIGN(4); - } >FLASH_TEXT + INCLUDE common_isr.ld .text : { @@ -65,6 +62,6 @@ SECTIONS _etext = .; } >FLASH_TEXT - INCLUDE common_extratext_data_in_flash_text.ld + INCLUDE common_extratext_data_in_flash.ld INCLUDE common_bss_heap_stack.ld } diff --git a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld index c9199b341b..85145b22a3 100644 --- a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld +++ b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld @@ -42,6 +42,8 @@ _heap_end = _sstack; ENTRY(Reset_Handler) +REGION_ALIAS("FLASH_COMMON", FLASH_APP); + /* Define output sections */ SECTIONS { @@ -56,22 +58,8 @@ SECTIONS . = ALIGN(4); } >FLASH_EXT - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) - . = ALIGN(4); - } >FLASH_APP - - .text : - { - . = ALIGN(4); - *(.text*) - *(.rodata*) - . = ALIGN(4); - _etext = .; - } >FLASH_APP - - INCLUDE common_extratext_data_in_flash_app.ld + INCLUDE common_isr.ld + INCLUDE common_text.ld + INCLUDE common_extratext_data_in_flash.ld INCLUDE common_bss_heap_stack.ld } diff --git a/ports/stm32/boards/PYBD_SF6/f767.ld b/ports/stm32/boards/PYBD_SF6/f767.ld index 5866f0b5cc..cbe74696e8 100644 --- a/ports/stm32/boards/PYBD_SF6/f767.ld +++ b/ports/stm32/boards/PYBD_SF6/f767.ld @@ -41,15 +41,12 @@ _heap_end = _sstack; ENTRY(Reset_Handler) +REGION_ALIAS("FLASH_COMMON", FLASH_APP); + /* Define output sections */ SECTIONS { - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) - . = ALIGN(4); - } >FLASH_APP + INCLUDE common_isr.ld .text : { @@ -62,6 +59,6 @@ SECTIONS _etext = .; } >FLASH_APP - INCLUDE common_extratext_data_in_flash_app.ld + INCLUDE common_extratext_data_in_flash.ld INCLUDE common_bss_heap_stack.ld } diff --git a/ports/stm32/boards/STM32F769DISC/f769_qspi.ld b/ports/stm32/boards/STM32F769DISC/f769_qspi.ld index b6957a3213..b6515b0666 100644 --- a/ports/stm32/boards/STM32F769DISC/f769_qspi.ld +++ b/ports/stm32/boards/STM32F769DISC/f769_qspi.ld @@ -40,6 +40,8 @@ _heap_end = _sstack; ENTRY(Reset_Handler) +REGION_ALIAS("FLASH_COMMON", FLASH_APP); + SECTIONS { /* Define the code that goes in QSPI flash */ @@ -50,24 +52,8 @@ SECTIONS . = ALIGN(4); } >FLASH_QSPI - /* The startup code goes first into main flash */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) - . = ALIGN(4); - } >FLASH_APP - - /* The program code and other data goes into flash */ - .text : - { - . = ALIGN(4); - *(.text*) - *(.rodata*) - . = ALIGN(4); - _etext = .; - } >FLASH_APP - - INCLUDE common_extratext_data_in_flash_app.ld + INCLUDE common_isr.ld + INCLUDE common_text.ld + INCLUDE common_extratext_data_in_flash.ld INCLUDE common_bss_heap_stack.ld } diff --git a/ports/stm32/boards/common_basic.ld b/ports/stm32/boards/common_basic.ld index dbda1b8b68..9916a4c254 100644 --- a/ports/stm32/boards/common_basic.ld +++ b/ports/stm32/boards/common_basic.ld @@ -12,31 +12,13 @@ ENTRY(Reset_Handler) +REGION_ALIAS("FLASH_COMMON", FLASH); + /* define output sections */ SECTIONS { - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text*) /* .text* sections (code) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - /* *(.glue_7) */ /* glue arm to thumb code */ - /* *(.glue_7t) */ /* glue thumb to arm code */ - - . = ALIGN(4); - _etext = .; /* define a global symbol at end of code */ - } >FLASH - + INCLUDE common_isr.ld + INCLUDE common_text.ld INCLUDE common_extratext_data_in_flash.ld INCLUDE common_bss_heap_stack.ld } diff --git a/ports/stm32/boards/common_bl.ld b/ports/stm32/boards/common_bl.ld index 21d809a3d2..b17fe98743 100644 --- a/ports/stm32/boards/common_bl.ld +++ b/ports/stm32/boards/common_bl.ld @@ -12,31 +12,13 @@ ENTRY(Reset_Handler) +REGION_ALIAS("FLASH_COMMON", FLASH_APP); + /* define output sections */ SECTIONS { - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - - . = ALIGN(4); - } >FLASH_APP - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text*) /* .text* sections (code) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - /* *(.glue_7) */ /* glue arm to thumb code */ - /* *(.glue_7t) */ /* glue thumb to arm code */ - - . = ALIGN(4); - _etext = .; /* define a global symbol at end of code */ - } >FLASH_APP - - INCLUDE common_extratext_data_in_flash_app.ld + INCLUDE common_isr.ld + INCLUDE common_text.ld + INCLUDE common_extratext_data_in_flash.ld INCLUDE common_bss_heap_stack.ld } diff --git a/ports/stm32/boards/common_blifs.ld b/ports/stm32/boards/common_blifs.ld index 5517a2d09c..51969e1f90 100644 --- a/ports/stm32/boards/common_blifs.ld +++ b/ports/stm32/boards/common_blifs.ld @@ -12,31 +12,13 @@ ENTRY(Reset_Handler) +REGION_ALIAS("FLASH_COMMON", FLASH_TEXT); + /* define output sections */ SECTIONS { - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - - . = ALIGN(4); - } >FLASH_TEXT - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text*) /* .text* sections (code) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - /* *(.glue_7) */ /* glue arm to thumb code */ - /* *(.glue_7t) */ /* glue thumb to arm code */ - - . = ALIGN(4); - _etext = .; /* define a global symbol at end of code */ - } >FLASH_TEXT - - INCLUDE common_extratext_data_in_flash_text.ld + INCLUDE common_isr.ld + INCLUDE common_text.ld + INCLUDE common_extratext_data_in_flash.ld INCLUDE common_bss_heap_stack.ld } diff --git a/ports/stm32/boards/common_extratext_data_in_flash.ld b/ports/stm32/boards/common_extratext_data_in_flash.ld index eb9b86f49d..db4306641b 100644 --- a/ports/stm32/boards/common_extratext_data_in_flash.ld +++ b/ports/stm32/boards/common_extratext_data_in_flash.ld @@ -6,7 +6,7 @@ __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; -} >FLASH +} >FLASH_COMMON /* Used by the start-up code to initialise data */ _sidata = LOADADDR(.data); @@ -19,4 +19,4 @@ _sidata = LOADADDR(.data); *(.data*) . = ALIGN(4); _edata = .; -} >RAM AT> FLASH +} >RAM AT> FLASH_COMMON diff --git a/ports/stm32/boards/common_extratext_data_in_flash_app.ld b/ports/stm32/boards/common_extratext_data_in_flash_app.ld deleted file mode 100644 index aba6bf57c8..0000000000 --- a/ports/stm32/boards/common_extratext_data_in_flash_app.ld +++ /dev/null @@ -1,22 +0,0 @@ -/* This linker script fragment is intended to be included in SECTIONS. */ - -/* For C++ exception handling */ -.ARM : -{ - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; -} >FLASH_APP - -/* Used by the start-up code to initialise data */ -_sidata = LOADADDR(.data); - -/* Initialised data section, start-up code will copy it from flash to RAM */ -.data : -{ - . = ALIGN(4); - _sdata = .; - *(.data*) - . = ALIGN(4); - _edata = .; -} >RAM AT> FLASH_APP diff --git a/ports/stm32/boards/common_extratext_data_in_flash_text.ld b/ports/stm32/boards/common_extratext_data_in_flash_text.ld deleted file mode 100644 index 5a29e47307..0000000000 --- a/ports/stm32/boards/common_extratext_data_in_flash_text.ld +++ /dev/null @@ -1,22 +0,0 @@ -/* This linker script fragment is intended to be included in SECTIONS. */ - -/* For C++ exception handling */ -.ARM : -{ - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; -} >FLASH_TEXT - -/* Used by the start-up code to initialise data */ -_sidata = LOADADDR(.data); - -/* Initialised data section, start-up code will copy it from flash to RAM */ -.data : -{ - . = ALIGN(4); - _sdata = .; - *(.data*) - . = ALIGN(4); - _edata = .; -} >RAM AT> FLASH_TEXT diff --git a/ports/stm32/boards/common_ifs.ld b/ports/stm32/boards/common_ifs.ld index 733ca12f67..1876e41561 100644 --- a/ports/stm32/boards/common_ifs.ld +++ b/ports/stm32/boards/common_ifs.ld @@ -13,6 +13,8 @@ ENTRY(Reset_Handler) +REGION_ALIAS("FLASH_COMMON", FLASH_TEXT); + /* define output sections */ SECTIONS { @@ -41,19 +43,7 @@ SECTIONS . = ALIGN(4); } >FLASH_ISR - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text*) /* .text* sections (code) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - /* *(.glue_7) */ /* glue arm to thumb code */ - /* *(.glue_7t) */ /* glue thumb to arm code */ - - . = ALIGN(4); - _etext = .; /* define a global symbol at end of code */ - } >FLASH_TEXT - - INCLUDE common_extratext_data_in_flash_text.ld + INCLUDE common_text.ld + INCLUDE common_extratext_data_in_flash.ld INCLUDE common_bss_heap_stack.ld } diff --git a/ports/stm32/boards/common_isr.ld b/ports/stm32/boards/common_isr.ld new file mode 100644 index 0000000000..0f9b8bcaad --- /dev/null +++ b/ports/stm32/boards/common_isr.ld @@ -0,0 +1,9 @@ +/* This linker script fragment is intended to be included in SECTIONS. */ + +/* The startup code goes first into FLASH */ +.isr_vector : +{ + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); +} >FLASH_COMMON diff --git a/ports/stm32/boards/common_text.ld b/ports/stm32/boards/common_text.ld new file mode 100644 index 0000000000..16eea43bae --- /dev/null +++ b/ports/stm32/boards/common_text.ld @@ -0,0 +1,14 @@ +/* This linker script fragment is intended to be included in SECTIONS. */ + +/* The program code and other data goes into FLASH */ +.text : +{ + . = ALIGN(4); + *(.text*) /* .text* sections (code) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ +/* *(.glue_7) */ /* glue arm to thumb code */ +/* *(.glue_7t) */ /* glue thumb to arm code */ + + . = ALIGN(4); + _etext = .; /* define a global symbol at end of code */ +} >FLASH_COMMON From 77002a92bfcef58e01f20428df25793d43231b15 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 22 Dec 2022 21:35:28 +1100 Subject: [PATCH 10/59] tools/pyboard.py: Fix Python 2 compatibility. In Python 2, serial.read()[0] a string, not int. Use struct.unpack to do this instead. Signed-off-by: Jim Mussared --- tools/pyboard.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/pyboard.py b/tools/pyboard.py index 55c00fbca1..73250a7c28 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -67,10 +67,11 @@ Or: """ +import ast +import os +import struct import sys import time -import os -import ast try: stdout = sys.stdout.buffer @@ -379,7 +380,7 @@ class Pyboard: def raw_paste_write(self, command_bytes): # Read initial header, with window size. data = self.serial.read(2) - window_size = data[0] | data[1] << 8 + window_size = struct.unpack(" Date: Wed, 21 Dec 2022 11:43:35 +1100 Subject: [PATCH 11/59] tools/pyboard.py: Add parse kwarg to eval. This is useful when using pyboard.py as a library rather than at the command line. pyb.eval("1+1") --> b"2" pyb.eval("{'a': '\x00'}") --> b"{'a': '\\x00'}" Now you can also do pyb.eval("1+1", parse=True) --> 2 pyb.eval("{'a': '\x00'}", parse=True) --> {'a': '\x00'} This work was funded through GitHub Sponsors. 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 73250a7c28..b45cc19196 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -457,10 +457,15 @@ class Pyboard: self.exec_raw_no_follow(command) return self.follow(timeout, data_consumer) - def eval(self, expression): - ret = self.exec_("print({})".format(expression)) - ret = ret.strip() - return ret + def eval(self, expression, parse=False): + if parse: + ret = self.exec_("print(repr({}))".format(expression)) + ret = ret.strip() + return ast.literal_eval(ret.decode()) + else: + ret = self.exec_("print({})".format(expression)) + ret = ret.strip() + return ret def exec_(self, command, data_consumer=None): ret, ret_err = self.exec_raw(command, data_consumer=data_consumer) From aa64280666d40208ade0183503fe683fbb32c2ab Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 21 Dec 2022 11:36:18 +1100 Subject: [PATCH 12/59] tools/pyboard.py: Add fs_{listdir,readfile,writefile,stat}. These are for working with the filesystem when using pyboard.py as a library, rather than at the command line. - fs_listdir returns a list of tuples, in the same format as os.ilistdir(). - fs_readfile returns the contents of a file as a bytes object. - fs_writefile allows writing a bytes object to a file. - fs_stat returns an os.statresult. All raise FileNotFoundError (or OSError(ENOENT) on Python 2) if the file is not found (or PyboardError on other errors). Updated fs_cp and fs_get to use fs_stat to compute file size. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared --- tools/pyboard.py | 69 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/tools/pyboard.py b/tools/pyboard.py index b45cc19196..d1abd2b781 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -73,6 +73,8 @@ import struct import sys import time +from collections import namedtuple + try: stdout = sys.stdout.buffer except AttributeError: @@ -87,7 +89,15 @@ def stdout_write_bytes(b): class PyboardError(Exception): - pass + def convert(self, info): + if len(self.args) >= 3: + if b"OSError" in self.args[2] and b"ENOENT" in self.args[2]: + return OSError(errno.ENOENT, info) + + return self + + +listdir_result = namedtuple("dir_result", ["name", "st_mode", "st_ino", "st_size"]) class TelnetToSerial: @@ -467,6 +477,7 @@ class Pyboard: ret = ret.strip() return ret + # In Python3, call as pyboard.exec(), see the setattr call below. def exec_(self, command, data_consumer=None): ret, ret_err = self.exec_raw(command, data_consumer=data_consumer) if ret_err: @@ -497,6 +508,34 @@ class Pyboard: ) self.exec_(cmd, data_consumer=stdout_write_bytes) + def fs_listdir(self, src=""): + buf = bytearray() + + def repr_consumer(b): + buf.extend(b.replace(b"\x04", b"")) + + cmd = "import uos\nfor f in uos.ilistdir(%s):\n" " print(repr(f), end=',')" % ( + ("'%s'" % src) if src else "" + ) + try: + buf.extend(b"[") + self.exec_(cmd, data_consumer=repr_consumer) + buf.extend(b"]") + except PyboardError as e: + raise e.convert(src) + + return [ + listdir_result(*f) if len(f) == 4 else listdir_result(*(f + (0,))) + for f in ast.literal_eval(buf.decode()) + ] + + def fs_stat(self, src): + try: + self.exec_("import uos") + return os.stat_result(self.eval("uos.stat(%s)" % (("'%s'" % src)), parse=True)) + except PyboardError as e: + raise e.convert(src) + def fs_cat(self, src, chunk_size=256): cmd = ( "with open('%s') as f:\n while 1:\n" @@ -504,9 +543,33 @@ class Pyboard: ) self.exec_(cmd, data_consumer=stdout_write_bytes) + def fs_readfile(self, src, chunk_size=256): + buf = bytearray() + + def repr_consumer(b): + buf.extend(b.replace(b"\x04", b"")) + + cmd = ( + "with open('%s', 'rb') as f:\n while 1:\n" + " b=f.read(%u)\n if not b:break\n print(b,end='')" % (src, chunk_size) + ) + try: + self.exec_(cmd, data_consumer=repr_consumer) + except PyboardError as e: + raise e.convert(src) + return ast.literal_eval(buf.decode()) + + def fs_writefile(self, dest, data, chunk_size=256): + self.exec_("f=open('%s','wb')\nw=f.write" % dest) + while data: + chunk = data[:chunk_size] + self.exec_("w(" + repr(chunk) + ")") + data = data[len(chunk) :] + self.exec_("f.close()") + 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)) + src_size = self.fs_stat(src).st_size written = 0 self.exec_("fr=open('%s','rb')\nr=fr.read\nfw=open('%s','wb')\nw=fw.write" % (src, dest)) while True: @@ -520,7 +583,7 @@ class Pyboard: 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)) + src_size = self.fs_stat(src).st_size written = 0 self.exec_("f=open('%s','rb')\nr=f.read" % src) with open(dest, "wb") as f: From d263438a6e365d3199494498a9b734cda29dde52 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 27 Dec 2022 13:56:58 +0100 Subject: [PATCH 13/59] tools/pyboard.py: Set DTR on Windows to avoid ESPxx hard reset. Fixes issue #9659. Signed-off-by: Jos Verlinde --- tools/pyboard.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/pyboard.py b/tools/pyboard.py index d1abd2b781..d0e67d1f31 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -286,7 +286,15 @@ class Pyboard: delayed = False for attempt in range(wait + 1): try: - self.serial = serial.Serial(device, **serial_kwargs) + if os.name == "nt": + # Windows does not set DTR or RTS by default + self.serial = serial.Serial(**serial_kwargs) + self.serial.dtr = True + self.serial.rts = False + self.serial.port = device + self.serial.open() + else: + self.serial = serial.Serial(device, **serial_kwargs) break except (OSError, IOError): # Py2 and Py3 have different errors if wait == 0: From f4811b0b42f10aa12fc2f94c0459344d84c89eb8 Mon Sep 17 00:00:00 2001 From: Dorukyum <53639936+Dorukyum@users.noreply.github.com> Date: Sun, 25 Dec 2022 19:49:15 +0300 Subject: [PATCH 14/59] docs/library/socket: Use correct sockaddr variable name. Signed-off-by: Dorukyum --- docs/library/socket.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/library/socket.rst b/docs/library/socket.rst index 1d1c23abd1..944e7e631a 100644 --- a/docs/library/socket.rst +++ b/docs/library/socket.rst @@ -29,7 +29,7 @@ returned by `getaddrinfo` function, which must be used to resolve textual addres # You must use getaddrinfo() even for numeric addresses sockaddr = socket.getaddrinfo('127.0.0.1', 80)[0][-1] # Now you can use that address - sock.connect(addr) + sock.connect(sockaddr) Using `getaddrinfo` is the most efficient (both in terms of memory and processing power) and portable way to work with addresses. From 66e0cfc3b96b60e8be7e69e004ded525cedc3391 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Tue, 25 Oct 2022 18:43:38 +0200 Subject: [PATCH 15/59] rp2/machine_pin: Refactor the machine.Pin class for external GPIO. Handle externally controlled GPIO pins more generically, by removing all CYW43-specific code from `machine_pin.c`, and adding hooks to initialise, configure, read and write external pins. This allows any driver for an on-board module which controls GPIO pins (such as CYW43 or NINA), to provide its own implementation of those hooks and work seamlessly with `machine_pin.c`. --- ports/rp2/CMakeLists.txt | 4 + ports/rp2/boards/PICO_W/mpconfigboard.h | 6 +- ports/rp2/machine_pin.c | 338 ++++++++---------------- ports/rp2/machine_pin.h | 55 ++++ ports/rp2/machine_pin_cyw43.c | 93 +++++++ 5 files changed, 273 insertions(+), 223 deletions(-) create mode 100644 ports/rp2/machine_pin.h create mode 100644 ports/rp2/machine_pin_cyw43.c diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 15264bf8ad..1bedc58101 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -261,6 +261,10 @@ if (MICROPY_PY_NETWORK_CYW43) ${MICROPY_DIR}/extmod/network_cyw43.c ) + list(APPEND MICROPY_SOURCE_PORT + machine_pin_cyw43.c + ) + target_link_libraries(${MICROPY_TARGET} cyw43_driver_picow cmsis_core diff --git a/ports/rp2/boards/PICO_W/mpconfigboard.h b/ports/rp2/boards/PICO_W/mpconfigboard.h index 43a9fbafa7..b3653aaeb0 100644 --- a/ports/rp2/boards/PICO_W/mpconfigboard.h +++ b/ports/rp2/boards/PICO_W/mpconfigboard.h @@ -17,9 +17,11 @@ // 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 +#define MICROPY_HW_PIN_EXT_PREFIX "WL_GPIO" +#define MICROPY_HW_PIN_EXT_COUNT CYW43_WL_GPIO_COUNT + #ifdef CYW43_WL_GPIO_LED_PIN -#define MICROPY_HW_PIN_CYW43_LED_PIN_NUM CYW43_WL_GPIO_LED_PIN +#define MICROPY_HW_PIN_EXT_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) diff --git a/ports/rp2/machine_pin.c b/ports/rp2/machine_pin.c index 9abcf064e7..4bce0353f1 100644 --- a/ports/rp2/machine_pin.c +++ b/ports/rp2/machine_pin.c @@ -31,6 +31,7 @@ #include "py/mphal.h" #include "shared/runtime/mpirq.h" #include "modmachine.h" +#include "machine_pin.h" #include "extmod/virtpin.h" #include "hardware/irq.h" @@ -38,11 +39,6 @@ #include "hardware/structs/iobank0.h" #include "hardware/structs/padsbank0.h" -#define GPIO_MODE_IN (0) -#define GPIO_MODE_OUT (1) -#define GPIO_MODE_OPEN_DRAIN (2) -#define GPIO_MODE_ALT (3) - // These can be or'd together. #define GPIO_PULL_UP (1) #define GPIO_PULL_DOWN (2) @@ -62,16 +58,6 @@ #define MICROPY_HW_PIN_RESERVED(i) (0) #endif -typedef struct _machine_pin_obj_t { - mp_obj_base_t base; - 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 { mp_irq_obj_t base; uint32_t flags; @@ -113,23 +99,21 @@ 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) +#if defined(MICROPY_HW_PIN_EXT_LED_PIN_NUM) || defined(PICO_DEFAULT_LED_PIN) #define MICROPY_HW_PIN_ENABLE_LED_PIN 1 #endif #endif +#if MICROPY_HW_PIN_EXT_COUNT +extern machine_pin_obj_t ext_pin_obj[MICROPY_HW_PIN_EXT_COUNT]; +#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]; +#ifdef MICROPY_HW_PIN_EXT_LED_PIN_NUM +STATIC machine_pin_obj_t *led_pin_obj = &ext_pin_obj[MICROPY_HW_PIN_EXT_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) @@ -142,29 +126,12 @@ STATIC const machine_pin_obj_t *led_pin_obj = &machine_pin_obj[PICO_DEFAULT_LED_ // 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; +#if MICROPY_HW_PIN_EXT_COUNT +STATIC inline bool is_ext_pin(__unused const machine_pin_obj_t *self) { + return self->is_ext; } #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; -} +#define is_ext_pin(x) false #endif STATIC void gpio_irq(void) { @@ -191,12 +158,8 @@ void machine_pin_init(void) { memset(MP_STATE_PORT(machine_pin_irq_obj), 0, sizeof(MP_STATE_PORT(machine_pin_irq_obj))); 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; - } + #if MICROPY_HW_PIN_EXT_COUNT + machine_pin_ext_init(); #endif } @@ -214,7 +177,7 @@ 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 (!is_cyw43_pin(self)) { + if (!is_ext_pin(self)) { if (funcsel == GPIO_FUNC_SIO) { if (GPIO_IS_OPEN_DRAIN(self->id)) { mode_qst = MP_QSTR_OPEN_DRAIN; @@ -243,9 +206,9 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin mp_printf(print, ", alt=%u", funcsel); } } else { - #if MICROPY_HW_PIN_CYW43_COUNT + #if MICROPY_HW_PIN_EXT_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); + mp_printf(print, "Pin(%s%u, mode=%q", MICROPY_HW_PIN_EXT_PREFIX, self->id, mode_qst); #endif } mp_printf(print, ")"); @@ -261,97 +224,59 @@ static const mp_arg_t allowed_args[] = { {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) { // 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 (is_ext_pin(self) && args[ARG_pull].u_obj != mp_const_none) { + mp_raise_ValueError("Pulls are not supported for external pins."); + } + + if (is_ext_pin(self) && args[ARG_alt].u_int != GPIO_FUNC_SIO) { + mp_raise_ValueError("Alternate functions are not supported for external pins."); + } + + int value = -1; if (args[ARG_value].u_obj != mp_const_none) { - gpio_put(self->id, mp_obj_is_true(args[ARG_value].u_obj)); + value = mp_obj_is_true(args[ARG_value].u_obj); + // set initial value (do this before configuring mode/pull) + if (!is_ext_pin(self)) { + gpio_put(self->id, value); + } } // 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) { + if (is_ext_pin(self)) { + #if MICROPY_HW_PIN_EXT_COUNT + // The regular Pins are const, but the external pins are mutable. + machine_pin_obj_t *mutable_self = (machine_pin_obj_t *)self; + machine_pin_ext_config(mutable_self, mode, value); + #endif + } else if (mode == MACHINE_PIN_MODE_IN) { mp_hal_pin_input(self->id); - } else if (mode == GPIO_MODE_OUT) { + } else if (mode == MACHINE_PIN_MODE_OUT) { mp_hal_pin_output(self->id); - } else if (mode == GPIO_MODE_OPEN_DRAIN) { + } else if (mode == MACHINE_PIN_MODE_OPEN_DRAIN) { mp_hal_pin_open_drain(self->id); } else { - // Alternate function. + // Configure alternate function. gpio_set_function(self->id, args[ARG_alt].u_int); machine_pin_open_drain_mask &= ~(1 << self->id); } } - // configure pull (unconditionally because None means no-pull) - uint32_t pull = 0; - if (args[ARG_pull].u_obj != mp_const_none) { - pull = mp_obj_get_int(args[ARG_pull].u_obj); + if (!is_ext_pin(self)) { + // Configure pull (unconditionally because None means no-pull). + uint32_t pull = 0; + if (args[ARG_pull].u_obj != mp_const_none) { + pull = mp_obj_get_int(args[ARG_pull].u_obj); + } + gpio_set_pulls(self->id, pull & GPIO_PULL_UP, pull & GPIO_PULL_DOWN); } - gpio_set_pulls(self->id, pull & GPIO_PULL_UP, pull & GPIO_PULL_DOWN); return mp_const_none; } @@ -359,7 +284,6 @@ 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); - const machine_pin_obj_t *self = NULL; if (mp_obj_is_str(args[0])) { const char *name = mp_obj_str_get_str(args[0]); @@ -368,12 +292,12 @@ mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, 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]; + #if MICROPY_HW_PIN_EXT_COUNT + static_assert(MICROPY_HW_PIN_EXT_COUNT < 10, ""); // makes parsing name easy! + if (!self && !strncmp(name, MICROPY_HW_PIN_EXT_PREFIX, strlen(MICROPY_HW_PIN_EXT_PREFIX)) && strlen(name) == strlen(MICROPY_HW_PIN_EXT_PREFIX) + 1) { + int num = name[strlen(MICROPY_HW_PIN_EXT_PREFIX)] - '0'; + if (num < MICROPY_HW_PIN_EXT_COUNT) { + self = &ext_pin_obj[num]; } } #endif @@ -389,27 +313,14 @@ mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, } 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); - // 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); + machine_pin_obj_init_helper(self, n_args - 1, args + 1, &kw_args); } return MP_OBJ_FROM_PTR(self); - #endif } // fast method for getting/setting pin value @@ -418,39 +329,33 @@ 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 - if (!is_cyw43_pin(self)) { + if (is_ext_pin(self)) { + #if MICROPY_HW_PIN_EXT_COUNT + return MP_OBJ_NEW_SMALL_INT(machine_pin_ext_get(self)); + #endif + } else { 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 (!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; + if (is_ext_pin(self)) { + #if MICROPY_HW_PIN_EXT_COUNT + machine_pin_ext_set(self, value); + #endif + } else 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 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) { - 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 + return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); } MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init); @@ -463,36 +368,32 @@ 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 (!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 (is_ext_pin(self)) { + #if MICROPY_HW_PIN_EXT_COUNT + machine_pin_ext_set(self, 0); + #endif + } else if (GPIO_IS_OPEN_DRAIN(self->id)) { + gpio_set_dir(self->id, GPIO_OUT); + } else { + gpio_clr_mask(1u << self->id); } - #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 (!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 (is_ext_pin(self)) { + #if MICROPY_HW_PIN_EXT_COUNT + machine_pin_ext_set(self, 1); + #endif + } else if (GPIO_IS_OPEN_DRAIN(self->id)) { + gpio_set_dir(self->id, GPIO_IN); + } else { + gpio_set_mask(1u << self->id); } - #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); @@ -500,22 +401,20 @@ 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 (!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); - } + if (is_ext_pin(self)) { + #if MICROPY_HW_PIN_EXT_COUNT + machine_pin_ext_set(self, self->last_output_value ^ 1); + #endif + } else if (GPIO_IS_OPEN_DRAIN(self->id)) { + if (GPIO_IS_OUT(self->id)) { + gpio_set_dir(self->id, GPIO_IN); } else { - gpio_xor_mask(1u << self->id); + gpio_set_dir(self->id, GPIO_OUT); } - return mp_const_none; + } else { + gpio_xor_mask(1u << self->id); } - #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); @@ -563,7 +462,7 @@ 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)) { + if (is_ext_pin(self)) { mp_raise_ValueError(MP_ERROR_TEXT("expecting a regular GPIO Pin")); } @@ -595,10 +494,10 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { { 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_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_OPEN_DRAIN) }, - { MP_ROM_QSTR(MP_QSTR_ALT), MP_ROM_INT(GPIO_MODE_ALT) }, + { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(MACHINE_PIN_MODE_IN) }, + { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(MACHINE_PIN_MODE_OUT) }, + { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(MACHINE_PIN_MODE_OPEN_DRAIN) }, + { MP_ROM_QSTR(MP_QSTR_ALT), MP_ROM_INT(MACHINE_PIN_MODE_ALT) }, { 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_IRQ_RISING), MP_ROM_INT(GPIO_IRQ_EDGE_RISE) }, @@ -610,31 +509,28 @@ 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 get_cyw43_value(self); + if (is_ext_pin(self)) { + #if MICROPY_HW_PIN_EXT_COUNT + return machine_pin_ext_get(self); + #endif + } else { + return gpio_get(self->id); + } } case MP_PIN_WRITE: { - update_cyw43_value(self, arg); + if (is_ext_pin(self)) { + #if MICROPY_HW_PIN_EXT_COUNT + machine_pin_ext_set(self, arg); + #endif + } else { + gpio_put(self->id, arg); + } return 0; } } return -1; - #endif } STATIC const mp_pin_p_t pin_pin_p = { @@ -683,7 +579,7 @@ 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)) { + if (is_ext_pin(pin)) { mp_raise_ValueError(MP_ERROR_TEXT("expecting a regular GPIO Pin")); } return pin->id; diff --git a/ports/rp2/machine_pin.h b/ports/rp2/machine_pin.h new file mode 100644 index 0000000000..83a81007c8 --- /dev/null +++ b/ports/rp2/machine_pin.h @@ -0,0 +1,55 @@ +/* + * 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. + */ +#ifndef MICROPY_INCLUDED_RP2_MACHINE_PIN_H +#define MICROPY_INCLUDED_RP2_MACHINE_PIN_H + +#include +#include "py/obj.h" +#include "py/mphal.h" + +enum { + MACHINE_PIN_MODE_IN = 0, + MACHINE_PIN_MODE_OUT = 1, + MACHINE_PIN_MODE_OPEN_DRAIN = 2, + MACHINE_PIN_MODE_ALT = 3 +}; + +typedef struct _machine_pin_obj_t { + mp_obj_base_t base; + uint8_t id : 5; + #if MICROPY_HW_PIN_EXT_COUNT + uint8_t is_ext : 1; + uint8_t is_output : 1; + uint8_t last_output_value : 1; + #endif +} machine_pin_obj_t; + +void machine_pin_ext_init(void); +void machine_pin_ext_set(machine_pin_obj_t *self, bool value); +bool machine_pin_ext_get(machine_pin_obj_t *self); +void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value); + +#endif // MICROPY_INCLUDED_RP2_MACHINE_PIN_H diff --git a/ports/rp2/machine_pin_cyw43.c b/ports/rp2/machine_pin_cyw43.c new file mode 100644 index 0000000000..a41a2f3caa --- /dev/null +++ b/ports/rp2/machine_pin_cyw43.c @@ -0,0 +1,93 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016-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 + +#include "py/runtime.h" +#include "py/mphal.h" + +#if defined(MICROPY_PY_NETWORK_CYW43) && defined(MICROPY_HW_PIN_EXT_COUNT) + +#include "modmachine.h" +#include "machine_pin.h" +#include "lib/cyw43-driver/src/cyw43.h" + +machine_pin_obj_t ext_pin_obj[MICROPY_HW_PIN_EXT_COUNT]; + +void machine_pin_ext_init(void) { + for (uint i = 0; i < count_of(ext_pin_obj); i++) { + ext_pin_obj[i].id = i; + ext_pin_obj[i].base.type = &machine_pin_type; + ext_pin_obj[i].is_ext = true; + } +} + +void machine_pin_ext_set(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; +} + +bool machine_pin_ext_get(machine_pin_obj_t *self) { + bool value = false; + cyw43_gpio_get(&cyw43_state, self->id, &value); + return value; +} + +void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value) { + if (mode == MACHINE_PIN_MODE_IN) { + if (self->is_output) { + // TODO need to disable output + } + self->is_output = false; + } else if (mode == MACHINE_PIN_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 + machine_pin_ext_set(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) { + machine_pin_ext_set(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; + } + } +} + +#endif // defined(MICROPY_PY_NETWORK_CYW43) && defined(MICROPY_HW_PIN_EXT_COUNT) From c214c9e6481749d90a7c487e24afddef061c0d8d Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Tue, 25 Oct 2022 20:45:00 +0200 Subject: [PATCH 16/59] rp2/machine_pin: Add support for named pins and alternate functions. This commit adds support for generating named pin mappings for all pins including CPU, board-defined, LED and externally controlled pins. CPU pins are mapped to `pin_GPIO`, externally-controlled pins are mapped to `pin_EXT_GPIO`, and defined conditionally (up to 10 pins, and can be expanded in the future), and they are non-const to allow `machine-pin.c` to write the pin object fields. Both CPU and externally controlled pins are generated even if there's no board CSV file; if one exists it will just be added to board pins. --- ports/rp2/CMakeLists.txt | 44 +++- ports/rp2/boards/make-pins.py | 428 ++++++++++++++++++++++++++++++++++ ports/rp2/boards/rp2_af.csv | 31 +++ ports/rp2/boards/rp2_prefix.c | 36 +++ ports/rp2/machine_pin.c | 185 ++++++++------- ports/rp2/machine_pin.h | 27 +++ ports/rp2/machine_pin_cyw43.c | 7 - 7 files changed, 660 insertions(+), 98 deletions(-) create mode 100755 ports/rp2/boards/make-pins.py create mode 100644 ports/rp2/boards/rp2_af.csv create mode 100644 ports/rp2/boards/rp2_prefix.c diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 1bedc58101..88971a5c90 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -131,6 +131,7 @@ set(MICROPY_SOURCE_PORT usbd.c msc_disk.c mbedtls/mbedtls_port.c + ${CMAKE_BINARY_DIR}/pins_${MICROPY_BOARD}.c ) set(MICROPY_SOURCE_QSTR @@ -153,6 +154,7 @@ set(MICROPY_SOURCE_QSTR ${PROJECT_SOURCE_DIR}/modutime.c ${PROJECT_SOURCE_DIR}/rp2_flash.c ${PROJECT_SOURCE_DIR}/rp2_pio.c + ${CMAKE_BINARY_DIR}/pins_${MICROPY_BOARD}.c ) set(PICO_SDK_COMPONENTS @@ -257,14 +259,14 @@ if (MICROPY_PY_NETWORK_CYW43) ) endif() - list(APPEND MICROPY_SOURCE_EXTMOD - ${MICROPY_DIR}/extmod/network_cyw43.c - ) - list(APPEND MICROPY_SOURCE_PORT machine_pin_cyw43.c ) + list(APPEND MICROPY_SOURCE_EXTMOD + ${MICROPY_DIR}/extmod/network_cyw43.c + ) + target_link_libraries(${MICROPY_TARGET} cyw43_driver_picow cmsis_core @@ -439,3 +441,37 @@ endforeach() # Include the main MicroPython cmake rules. include(${MICROPY_DIR}/py/mkrules.cmake) + +set(MICROPY_BOARDS_DIR "${MICROPY_PORT_DIR}/boards") +set(GEN_PINS_AF_CSV "${MICROPY_BOARDS_DIR}/rp2_af.csv") +set(GEN_PINS_PREFIX "${MICROPY_BOARDS_DIR}/rp2_prefix.c") +set(GEN_PINS_MKPINS "${MICROPY_BOARDS_DIR}/make-pins.py") +set(GEN_PINS_SRC "${CMAKE_BINARY_DIR}/pins_${MICROPY_BOARD}.c") +set(GEN_PINS_HDR "${MICROPY_GENHDR_DIR}/pins.h") +set(GEN_PINS_QSTR "${CMAKE_BINARY_DIR}/pins_qstr.h") +set(GEN_PINS_AF_CONST "${MICROPY_GENHDR_DIR}/pins_af_const.h") +set(GEN_PINS_AF_PY "${CMAKE_BINARY_DIR}/pins_af.py") + +if(EXISTS "${MICROPY_BOARDS_DIR}/${MICROPY_BOARD}/pins.csv") + set(GEN_PINS_BOARD_CSV "${MICROPY_BOARDS_DIR}/${MICROPY_BOARD}/pins.csv") + set(GEN_PINS_CSV_ARG --board "${GEN_PINS_BOARD_CSV}") +endif() + +target_sources(${MICROPY_TARGET} PRIVATE + ${GEN_PINS_HDR} +) + +# Generate pins +add_custom_command( + OUTPUT ${GEN_PINS_HDR} ${GEN_PINS_SRC} ${GEN_PINS_QSTR} + COMMAND ${Python3_EXECUTABLE} ${GEN_PINS_MKPINS} ${GEN_PINS_CSV_ARG} --af ${GEN_PINS_AF_CSV} --prefix ${GEN_PINS_PREFIX} + --hdr ${GEN_PINS_HDR} --qstr ${GEN_PINS_QSTR} --af-const ${GEN_PINS_AF_CONST} --af-py ${GEN_PINS_AF_PY} > ${GEN_PINS_SRC} + DEPENDS + ${GEN_PINS_AF_CSV} + ${GEN_PINS_BOARD_CSV} + ${GEN_PINS_MKPINS} + ${GEN_PINS_PREFIX} + ${MICROPY_MPVERSION} + VERBATIM + COMMAND_EXPAND_LISTS +) diff --git a/ports/rp2/boards/make-pins.py b/ports/rp2/boards/make-pins.py new file mode 100755 index 0000000000..55e7ebe01f --- /dev/null +++ b/ports/rp2/boards/make-pins.py @@ -0,0 +1,428 @@ +#!/usr/bin/env python +"""Creates the pin file for the RP2.""" + +from __future__ import print_function + +import argparse +import sys +import csv +import re + +SUPPORTED_FN = { + "SPI": ["TX", "RX", "SCK", "CS"], + "UART": ["TX", "RX", "CTS", "RTS"], + "I2C": ["SCL", "SDA"], + "PWM": ["A", "B"], + "SIO": [""], + "PIO0": [""], + "PIO1": [""], + "GPCK": ["GPIN0", "GPOUT0", "GPIN1", "GPOUT1", "GPOUT2", "GPOUT3"], + "USB": ["OVCUR_DET", "VBUS_DET", "VBUS_EN"], +} + + +def parse_pin(name_str): + """Parses a string and returns a pin number.""" + if len(name_str) < 2: + raise ValueError("Expecting pin name to be at least 2 charcters.") + if not name_str.startswith("GPIO") and not name_str.startswith("EXT_GPIO"): + raise ValueError("Expecting pin name to start with EXT_/GPIO") + return int(re.findall(r"\d+$", name_str)[0]) + + +def split_name_num(name_num): + num = None + for num_idx in range(len(name_num) - 1, -1, -1): + if not name_num[num_idx].isdigit(): + name = name_num[0 : num_idx + 1] + num_str = name_num[num_idx + 1 :] + if len(num_str) > 0: + num = int(num_str) + break + if name == "PIO": + name += str(num) + return name, num + + +class AlternateFunction(object): + """Holds the information associated with a pins alternate function.""" + + def __init__(self, idx, af_str): + self.idx = idx + self.af_str = af_str + + self.func = "" + self.fn_num = None + self.pin_type = "" + self.supported = False + + af_words = af_str.split("_", 1) + self.func, self.fn_num = split_name_num(af_words[0]) + if len(af_words) > 1: + self.pin_type = af_words[1] + if self.func in SUPPORTED_FN: + pin_types = SUPPORTED_FN[self.func] + if self.pin_type in pin_types: + self.supported = True + + def is_supported(self): + return self.supported + + def ptr(self): + """Returns the numbered function (i.e. USART6) for this AF.""" + if self.fn_num is None: + return self.func + return "{:s}{:d}".format(self.func, self.fn_num) + + def mux_name(self): + return "AF{:d}_{:s}".format(self.idx, self.ptr()) + + def print(self): + """Prints the C representation of this AF.""" + if self.supported: + print(" AF", end="") + else: + print(" //", end="") + fn_num = self.fn_num + if fn_num is None: + fn_num = 0 + print("({:d}, {:4s}, {:d}), // {:s}".format(self.idx, self.func, fn_num, self.af_str)) + + def qstr_list(self): + return [self.mux_name()] + + +class Pin(object): + """Holds the information associated with a pin.""" + + def __init__(self, pin, is_ext=False): + self.pin = pin + self.alt_fn = [] + self.alt_fn_count = 0 + self.is_board = False + self.is_ext = is_ext + + def cpu_pin_name(self): + return "{:s}GPIO{:d}".format("EXT_" if self.is_ext else "", self.pin) + + def is_board_pin(self): + return self.is_board + + def set_is_board_pin(self): + self.is_board = True + + def parse_af(self, af_idx, af_strs_in): + if len(af_strs_in) == 0: + return + # If there is a slash, then the slash separates 2 aliases for the + # same alternate function. + af_strs = af_strs_in.split("/") + for af_str in af_strs: + alt_fn = AlternateFunction(af_idx, af_str) + self.alt_fn.append(alt_fn) + if alt_fn.is_supported(): + self.alt_fn_count += 1 + + def alt_fn_name(self, null_if_0=False): + if null_if_0 and self.alt_fn_count == 0: + return "NULL" + return "pin_{:s}_af".format(self.cpu_pin_name()) + + def print(self): + if self.is_ext: + print("#if (MICROPY_HW_PIN_EXT_COUNT > {:d})".format(self.pin)) + + if self.alt_fn_count == 0: + print("// ", end="") + print("const machine_pin_af_obj_t {:s}[] = {{".format(self.alt_fn_name())) + for alt_fn in self.alt_fn: + alt_fn.print() + if self.alt_fn_count == 0: + print("// ", end="") + print("};") + print("") + print( + "{:s}machine_pin_obj_t pin_{:s} = PIN({:d}, {:s}, {:d}, {:d}, {:s});".format( + "" if self.is_ext else "const ", + self.cpu_pin_name(), + self.pin, + self.cpu_pin_name(), + self.is_ext, + self.alt_fn_count, + self.alt_fn_name(null_if_0=True), + ) + ) + if self.is_ext: + print("#endif") + print("") + + def print_header(self, hdr_file): + n = self.cpu_pin_name() + hdr_file.write( + "extern{:s}machine_pin_obj_t pin_{:s};\n".format(" " if self.is_ext else " const ", n) + ) + if self.alt_fn_count > 0: + hdr_file.write("extern const machine_pin_af_obj_t pin_{:s}_af[];\n".format(n)) + + def qstr_list(self): + result = [] + for alt_fn in self.alt_fn: + if alt_fn.is_supported(): + result += alt_fn.qstr_list() + return result + + +class NamedPin(object): + def __init__(self, name, pin): + self._name = name + self._pin = pin + + def pin(self): + return self._pin + + def name(self): + return self._name + + +class Pins(object): + def __init__(self): + self.cpu_pins = [] # list of NamedPin objects + self.board_pins = [] # list of NamedPin objects + self.ext_pins = [] # list of NamedPin objects + for i in range(0, 10): + self.ext_pins.append(NamedPin("EXT_GPIO{:d}".format(i), Pin(i, True))) + + def find_pin(self, pin_name): + for pin in self.cpu_pins: + if pin.name() == pin_name: + return pin.pin() + + for pin in self.ext_pins: + if pin.name() == pin_name: + return pin.pin() + + def parse_af_file(self, filename, pinname_col, af_col): + with open(filename, "r") as csvfile: + rows = csv.reader(csvfile) + for row in rows: + try: + pin_num = parse_pin(row[pinname_col]) + except Exception as e: + # import traceback; traceback.print_exc() + continue + pin = Pin(pin_num) + for af_idx in range(af_col, len(row)): + if af_idx >= af_col: + pin.parse_af(af_idx, row[af_idx]) + self.cpu_pins.append(NamedPin(pin.cpu_pin_name(), pin)) + + def parse_board_file(self, filename): + with open(filename, "r") as csvfile: + rows = csv.reader(csvfile) + for row in rows: + if len(row) == 0 or row[0].startswith("#"): + # Skip empty lines, and lines starting with "#" + continue + if len(row) != 2: + raise ValueError("Expecting two entries in a row") + + cpu_pin_name = row[1] + try: + pin_num = parse_pin(cpu_pin_name) + except: + # import traceback; traceback.print_exc() + continue + pin = self.find_pin(cpu_pin_name) + if pin: + pin.set_is_board_pin() + if row[0]: # Only add board pins that have a name + self.board_pins.append(NamedPin(row[0], pin)) + + def print_table(self, label, named_pins): + print("") + print("const machine_pin_obj_t *machine_pin_{:s}_pins[] = {{".format(label)) + for pin in named_pins: + if not pin.pin().is_ext: + print(" &pin_{},".format(pin.name())) + print("};") + print("") + + def print_named(self, label, named_pins): + print("") + print( + "STATIC const mp_rom_map_elem_t pin_{:s}_pins_locals_dict_table[] = {{".format(label) + ) + for named_pin in named_pins: + pin = named_pin.pin() + if pin.is_ext: + print(" #if (MICROPY_HW_PIN_EXT_COUNT > {:d})".format(pin.pin)) + print( + " {{ MP_ROM_QSTR(MP_QSTR_{:s}), MP_ROM_PTR(&pin_{:s}) }},".format( + named_pin.name(), pin.cpu_pin_name() + ) + ) + if pin.is_ext: + print(" #endif") + + print("};") + print( + "MP_DEFINE_CONST_DICT(pin_{:s}_pins_locals_dict, pin_{:s}_pins_locals_dict_table);".format( + label, label + ) + ) + print("") + + def print(self): + for pin in self.cpu_pins: + pin.pin().print() + + for pin in self.ext_pins: + if pin.pin().is_ext: + pin.pin().print() + + self.print_table("cpu", self.cpu_pins) + self.print_named("cpu", self.cpu_pins + self.ext_pins) + self.print_named("board", self.board_pins) + + def print_header(self, hdr_filename, obj_decls): + with open(hdr_filename, "wt") as hdr_file: + if obj_decls: + for named_pin in self.cpu_pins: + pin = named_pin.pin() + pin.print_header(hdr_file) + for named_pin in self.board_pins: + pin = named_pin.pin() + if pin.is_ext: + pin.print_header(hdr_file) + # provide #define's mapping board to cpu name + for named_pin in self.board_pins: + if named_pin.pin().is_board_pin(): + hdr_file.write( + "#define pin_{:s} pin_{:s}\n".format( + named_pin.name(), named_pin.pin().cpu_pin_name() + ) + ) + + def print_qstr(self, qstr_filename): + with open(qstr_filename, "wt") as qstr_file: + qstr_set = set([]) + for named_pin in self.cpu_pins: + pin = named_pin.pin() + if pin.is_board_pin(): + qstr_set |= set(pin.qstr_list()) + qstr_set |= set([named_pin.name()]) + for named_pin in self.board_pins: + qstr_set |= set([named_pin.name()]) + for qstr in sorted(qstr_set): + print("Q({})".format(qstr), file=qstr_file) + + def print_af_hdr(self, af_const_filename): + with open(af_const_filename, "wt") as af_const_file: + af_hdr_set = set([]) + mux_name_width = 0 + for named_pin in self.cpu_pins: + pin = named_pin.pin() + if pin.is_board_pin(): + for af in pin.alt_fn: + if af.is_supported(): + mux_name = af.mux_name() + af_hdr_set |= set([mux_name]) + if len(mux_name) > mux_name_width: + mux_name_width = len(mux_name) + for mux_name in sorted(af_hdr_set): + key = "MP_OBJ_NEW_QSTR(MP_QSTR_{}),".format(mux_name) + val = "MP_OBJ_NEW_SMALL_INT(GPIO_{})".format(mux_name) + print(" { %-*s %s }," % (mux_name_width + 26, key, val), file=af_const_file) + + def print_af_py(self, af_py_filename): + with open(af_py_filename, "wt") as af_py_file: + print("PINS_AF = (", file=af_py_file) + for named_pin in self.board_pins: + print(" ('%s', " % named_pin.name(), end="", file=af_py_file) + for af in named_pin.pin().alt_fn: + if af.is_supported(): + print("(%d, '%s'), " % (af.idx, af.af_str), end="", file=af_py_file) + print("),", file=af_py_file) + print(")", file=af_py_file) + + +def main(): + parser = argparse.ArgumentParser( + prog="make-pins.py", + usage="%(prog)s [options] [command]", + description="Generate board specific pin file", + ) + parser.add_argument( + "-a", + "--af", + dest="af_filename", + help="Specifies the alternate function file for the chip", + default="rp2_af.csv", + ) + parser.add_argument( + "--af-const", + dest="af_const_filename", + help="Specifies header file for alternate function constants.", + default="build/pins_af_const.h", + ) + parser.add_argument( + "--af-py", + dest="af_py_filename", + help="Specifies the filename for the python alternate function mappings.", + default="build/pins_af.py", + ) + parser.add_argument( + "-b", + "--board", + dest="board_filename", + help="Specifies the board file", + ) + parser.add_argument( + "-p", + "--prefix", + dest="prefix_filename", + help="Specifies beginning portion of generated pins file", + default="rp2_prefix.c", + ) + parser.add_argument( + "-q", + "--qstr", + dest="qstr_filename", + help="Specifies name of generated qstr header file", + default="build/pins_qstr.h", + ) + parser.add_argument( + "-r", + "--hdr", + dest="hdr_filename", + help="Specifies name of generated pin header file", + default="build/pins.h", + ) + args = parser.parse_args(sys.argv[1:]) + + pins = Pins() + + print("// This file was automatically generated by make-pins.py") + print("//") + if args.af_filename: + print("// --af {:s}".format(args.af_filename)) + pins.parse_af_file(args.af_filename, 0, 1) + + if args.board_filename: + print("// --board {:s}".format(args.board_filename)) + pins.parse_board_file(args.board_filename) + + if args.prefix_filename: + print("// --prefix {:s}".format(args.prefix_filename)) + print("") + with open(args.prefix_filename, "r") as prefix_file: + print(prefix_file.read()) + pins.print() + pins.print_header(args.hdr_filename, True) + pins.print_qstr(args.qstr_filename) + pins.print_af_hdr(args.af_const_filename) + pins.print_af_py(args.af_py_filename) + + +if __name__ == "__main__": + main() diff --git a/ports/rp2/boards/rp2_af.csv b/ports/rp2/boards/rp2_af.csv new file mode 100644 index 0000000000..454f7ed2d1 --- /dev/null +++ b/ports/rp2/boards/rp2_af.csv @@ -0,0 +1,31 @@ +Pin,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9 +GPIO0,SPI0_RX,UART0_TX,I2C0_SDA,PWM0_A,SIO,PIO0,PIO1,,USB_OVCUR_DET +GPIO1,SPI0_CS,UART0_RX,I2C0_SCL,PWM0_B,SIO,PIO0,PIO1,,USB_VBUS_DET +GPIO2,SPI0_SCK,UART0_CTS,I2C1_SDA,PWM1_A,SIO,PIO0,PIO1,,USB_VBUS_EN +GPIO3,SPI0_TX,UART0_RTS,I2C1_SCL,PWM1_B,SIO,PIO0,PIO1,,USB_OVCUR_DET +GPIO4,SPI0_RX,UART1_TX,I2C0_SDA,PWM2_A,SIO,PIO0,PIO1,,USB_VBUS_DET +GPIO5,SPI0_CS,UART1_RX,I2C0_SCL,PWM2_B,SIO,PIO0,PIO1,,USB_VBUS_EN +GPIO6,SPI0_SCK,UART1_CTS,I2C1_SDA,PWM3_A,SIO,PIO0,PIO1,,USB_OVCUR_DET +GPIO7,SPI0_TX,UART1_RTS,I2C1_SCL,PWM3_B,SIO,PIO0,PIO1,,USB_VBUS_DET +GPIO8,SPI1_RX,UART1_TX,I2C0_SDA,PWM4_A,SIO,PIO0,PIO1,,USB_VBUS_EN +GPIO9,SPI1_CS,UART1_RX,I2C0_SCL,PWM4_B,SIO,PIO0,PIO1,,USB_OVCUR_DET +GPIO10,SPI1_SCK,UART1_CTS,I2C1_SDA,PWM5_A,SIO,PIO0,PIO1,,USB_VBUS_DET +GPIO11,SPI1_TX,UART1_RTS,I2C1_SCL,PWM5_B,SIO,PIO0,PIO1,,USB_VBUS_EN +GPIO12,SPI1_RX,UART0_TX,I2C0_SDA,PWM6_A,SIO,PIO0,PIO1,,USB_OVCUR_DET +GPIO13,SPI1_CS,UART0_RX,I2C0_SCL,PWM6_B,SIO,PIO0,PIO1,,USB_VBUS_DET +GPIO14,SPI1_SCK,UART0_CTS,I2C1_SDA,PWM7_A,SIO,PIO0,PIO1,,USB_VBUS_EN +GPIO15,SPI1_TX,UART0_RTS,I2C1_SCL,PWM7_B,SIO,PIO0,PIO1,,USB_OVCUR_DET +GPIO16,SPI0_RX,UART0_TX,I2C0_SDA,PWM0_A,SIO,PIO0,PIO1,,USB_VBUS_DET +GPIO17,SPI0_CS,UART0_RX,I2C0_SCL,PWM0_B,SIO,PIO0,PIO1,,USB_VBUS_EN +GPIO18,SPI0_SCK,UART0_CTS,I2C1_SDA,PWM1_A,SIO,PIO0,PIO1,,USB_OVCUR_DET +GPIO19,SPI0_TX,UART0_RTS,I2C1_SCL,PWM1_B,SIO,PIO0,PIO1,,USB_VBUS_DET +GPIO20,SPI0_RX,UART1_TX,I2C0_SDA,PWM2_A,SIO,PIO0,PIO1,GPCK_GPIN0,USB_VBUS_EN +GPIO21,SPI0_CS,UART1_RX,I2C0_SCL,PWM2_B,SIO,PIO0,PIO1,GPCK_GPOUT0,USB_OVCUR_DET +GPIO22,SPI0_SCK,UART1_CTS,I2C1_SDA,PWM3_A,SIO,PIO0,PIO1,GPCK_GPIN1,USB_VBUS_DET +GPIO23,SPI0_TX,UART1_RTS,I2C1_SCL,PWM3_B,SIO,PIO0,PIO1,GPCK_GPOUT1,USB_VBUS_EN +GPIO24,SPI1_RX,UART1_TX,I2C0_SDA,PWM4_A,SIO,PIO0,PIO1,GPCK_GPOUT2,USB_OVCUR_DET +GPIO25,SPI1_CS,UART1_RX,I2C0_SCL,PWM4_B,SIO,PIO0,PIO1,GPCK_GPOUT3,USB_VBUS_DET +GPIO26,SPI1_SCK,UART1_CTS,I2C1_SDA,PWM5_A,SIO,PIO0,PIO1,,USB_VBUS_EN +GPIO27,SPI1_TX,UART1_RTS,I2C1_SCL,PWM5_B,SIO,PIO0,PIO1,,USB_OVCUR_DET +GPIO28,SPI1_RX,UART0_TX,I2C0_SDA,PWM6_A,SIO,PIO0,PIO1,,USB_VBUS_DET +GPIO29,SPI1_CS,UART0_RX,I2C0_SCL,PWM6_B,SIO,PIO0,PIO1,,USB_VBUS_EN diff --git a/ports/rp2/boards/rp2_prefix.c b/ports/rp2/boards/rp2_prefix.c new file mode 100644 index 0000000000..50f2852a8a --- /dev/null +++ b/ports/rp2/boards/rp2_prefix.c @@ -0,0 +1,36 @@ +#include +#include "py/obj.h" +#include "py/mphal.h" +#include "machine_pin.h" + +#define AF(af_idx, af_fn, af_unit) \ + { \ + .base = { &machine_pin_af_type }, \ + .name = MP_QSTR_##af_fn, \ + .idx = (af_idx), \ + .fn = GPIO_FUNC_##af_fn, \ + .unit = (af_unit), \ + } + +#if MICROPY_HW_PIN_EXT_COUNT +#define PIN(_id, _name, _is_ext, _af_num, _af_list) \ + { \ + .base = { &machine_pin_type }, \ + .name = MP_QSTR_##_name, \ + .id = (uint8_t)(_id), \ + .is_ext = (_is_ext), \ + .is_output = false, \ + .last_output_value = 0, \ + .af_num = (_af_num), \ + .af = (_af_list), \ + } +#else +#define PIN(_id, _name, _is_ext, _af_num, _af_list) \ + { \ + .base = { &machine_pin_type }, \ + .name = MP_QSTR_##_name, \ + .id = (uint8_t)(_id), \ + .af_num = (_af_num), \ + .af = (_af_list), \ + } +#endif diff --git a/ports/rp2/machine_pin.c b/ports/rp2/machine_pin.c index 4bce0353f1..3de2eaaed8 100644 --- a/ports/rp2/machine_pin.c +++ b/ports/rp2/machine_pin.c @@ -58,6 +58,26 @@ #define MICROPY_HW_PIN_RESERVED(i) (0) #endif +MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_af_type, + MP_QSTR_PinAF, + MP_TYPE_FLAG_NONE + ); + +MP_DEFINE_CONST_OBJ_TYPE( + pin_cpu_pins_obj_type, + MP_QSTR_cpu, + MP_TYPE_FLAG_NONE, + locals_dict, &pin_cpu_pins_locals_dict + ); + +MP_DEFINE_CONST_OBJ_TYPE( + pin_board_pins_obj_type, + MP_QSTR_board, + MP_TYPE_FLAG_NONE, + locals_dict, &pin_board_pins_locals_dict + ); + typedef struct _machine_pin_irq_obj_t { mp_irq_obj_t base; uint32_t flags; @@ -65,63 +85,7 @@ typedef struct _machine_pin_irq_obj_t { } machine_pin_irq_obj_t; STATIC const mp_irq_methods_t machine_pin_irq_methods; - -STATIC const machine_pin_obj_t machine_pin_obj[NUM_BANK0_GPIOS] = { - {{&machine_pin_type}, 0}, - {{&machine_pin_type}, 1}, - {{&machine_pin_type}, 2}, - {{&machine_pin_type}, 3}, - {{&machine_pin_type}, 4}, - {{&machine_pin_type}, 5}, - {{&machine_pin_type}, 6}, - {{&machine_pin_type}, 7}, - {{&machine_pin_type}, 8}, - {{&machine_pin_type}, 9}, - {{&machine_pin_type}, 10}, - {{&machine_pin_type}, 11}, - {{&machine_pin_type}, 12}, - {{&machine_pin_type}, 13}, - {{&machine_pin_type}, 14}, - {{&machine_pin_type}, 15}, - {{&machine_pin_type}, 16}, - {{&machine_pin_type}, 17}, - {{&machine_pin_type}, 18}, - {{&machine_pin_type}, 19}, - {{&machine_pin_type}, 20}, - {{&machine_pin_type}, 21}, - {{&machine_pin_type}, 22}, - {{&machine_pin_type}, 23}, - {{&machine_pin_type}, 24}, - {{&machine_pin_type}, 25}, - {{&machine_pin_type}, 26}, - {{&machine_pin_type}, 27}, - {{&machine_pin_type}, 28}, - {{&machine_pin_type}, 29}, -}; - -#define LED_PIN_NAME "LED" - -#ifndef MICROPY_HW_PIN_ENABLE_LED_PIN -#if defined(MICROPY_HW_PIN_EXT_LED_PIN_NUM) || defined(PICO_DEFAULT_LED_PIN) -#define MICROPY_HW_PIN_ENABLE_LED_PIN 1 -#endif -#endif - -#if MICROPY_HW_PIN_EXT_COUNT -extern machine_pin_obj_t ext_pin_obj[MICROPY_HW_PIN_EXT_COUNT]; -#endif - -#ifdef MICROPY_HW_PIN_ENABLE_LED_PIN -#ifdef MICROPY_HW_PIN_EXT_LED_PIN_NUM -STATIC machine_pin_obj_t *led_pin_obj = &ext_pin_obj[MICROPY_HW_PIN_EXT_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 +extern const machine_pin_obj_t *machine_pin_cpu_pins[NUM_BANK0_GPIOS]; // Mask with "1" indicating that the corresponding pin is in simulated open-drain mode. uint32_t machine_pin_open_drain_mask; @@ -173,6 +137,35 @@ void machine_pin_deinit(void) { irq_remove_handler(IO_IRQ_BANK0, gpio_irq); } +const machine_pin_obj_t *machine_pin_find_named(const mp_obj_dict_t *named_pins, mp_obj_t name) { + const mp_map_t *named_map = &named_pins->map; + mp_map_elem_t *named_elem = mp_map_lookup((mp_map_t *)named_map, name, MP_MAP_LOOKUP); + if (named_elem != NULL && named_elem->value != NULL) { + return MP_OBJ_TO_PTR(named_elem->value); + } + return NULL; +} + +const machine_pin_af_obj_t *machine_pin_find_alt(const machine_pin_obj_t *pin, uint8_t fn) { + const machine_pin_af_obj_t *af = pin->af; + for (mp_uint_t i = 0; i < pin->af_num; i++, af++) { + if (af->fn == fn) { + return af; + } + } + return NULL; +} + +const machine_pin_af_obj_t *machine_pin_find_alt_by_index(const machine_pin_obj_t *pin, mp_uint_t af_idx) { + const machine_pin_af_obj_t *af = pin->af; + for (mp_uint_t i = 0; i < pin->af_num; i++, af++) { + if (af->idx == af_idx) { + return af; + } + } + return NULL; +} + 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; uint funcsel = GPIO_GET_FUNCSEL(self->id); @@ -189,7 +182,7 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin } else { mode_qst = MP_QSTR_ALT; } - mp_printf(print, "Pin(%u, mode=%q", self->id, mode_qst); + mp_printf(print, "Pin(%q, mode=%q", self->name, mode_qst); bool pull_up = false; if (GPIO_IS_PULL_UP(self->id)) { mp_printf(print, ", pull=%q", MP_QSTR_PULL_UP); @@ -203,12 +196,17 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin } } if (funcsel != GPIO_FUNC_SIO) { - mp_printf(print, ", alt=%u", funcsel); + const machine_pin_af_obj_t *af = machine_pin_find_alt_by_index(self, funcsel); + if (af == NULL) { + mp_printf(print, ", alt=%u", funcsel); + } else { + mp_printf(print, ", alt=%q", af->name); + } } } else { #if MICROPY_HW_PIN_EXT_COUNT - mode_qst = self->is_output ? MP_QSTR_OUT : MP_QSTR_IN; - mp_printf(print, "Pin(%s%u, mode=%q", MICROPY_HW_PIN_EXT_PREFIX, self->id, mode_qst); + mode_qst = (self->is_output) ? MP_QSTR_OUT : MP_QSTR_IN; + mp_printf(print, "Pin(%q, mode=%q", self->name, mode_qst); #endif } mp_printf(print, ")"); @@ -231,11 +229,11 @@ 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); if (is_ext_pin(self) && args[ARG_pull].u_obj != mp_const_none) { - mp_raise_ValueError("Pulls are not supported for external pins."); + mp_raise_ValueError("pulls are not supported for external pins"); } if (is_ext_pin(self) && args[ARG_alt].u_int != GPIO_FUNC_SIO) { - mp_raise_ValueError("Alternate functions are not supported for external pins."); + mp_raise_ValueError("alternate functions are not supported for external pins"); } int value = -1; @@ -264,7 +262,11 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_ mp_hal_pin_open_drain(self->id); } else { // Configure alternate function. - gpio_set_function(self->id, args[ARG_alt].u_int); + mp_uint_t af = args[ARG_alt].u_int; + if (machine_pin_find_alt(self, af) == NULL) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid pin af: %d"), af); + } + gpio_set_function(self->id, af); machine_pin_open_drain_mask &= ~(1 << self->id); } } @@ -283,35 +285,29 @@ 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 = 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_EXT_COUNT - static_assert(MICROPY_HW_PIN_EXT_COUNT < 10, ""); // makes parsing name easy! - if (!self && !strncmp(name, MICROPY_HW_PIN_EXT_PREFIX, strlen(MICROPY_HW_PIN_EXT_PREFIX)) && strlen(name) == strlen(MICROPY_HW_PIN_EXT_PREFIX) + 1) { - int num = name[strlen(MICROPY_HW_PIN_EXT_PREFIX)] - '0'; - if (num < MICROPY_HW_PIN_EXT_COUNT) { - self = &ext_pin_obj[num]; - } - } - #endif + // Try to find the pin in the board pins first. + self = machine_pin_find_named(&pin_board_pins_locals_dict, args[0]); if (!self) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Unknown named pin \"%s\""), name); + // If not found, try to find the pin in the cpu pins which include + // CPU and and externally controlled pins (if any). + self = machine_pin_find_named(&pin_cpu_pins_locals_dict, args[0]); + } + if (!self) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("unknown named pin \"%s\""), name); + } + } else if (mp_obj_is_int(args[0])) { + // 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_cpu_pins)) { + self = machine_pin_cpu_pins[wanted_pin]; } } 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]; + mp_raise_ValueError("invalid pin"); } if (n_args > 1 || n_kw > 0) { @@ -427,7 +423,7 @@ STATIC machine_pin_irq_obj_t *machine_pin_get_irq(mp_hal_pin_obj_t pin) { 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(&machine_pin_obj[pin]); + irq->base.parent = MP_OBJ_FROM_PTR(&machine_pin_cpu_pins[pin]); irq->base.handler = mp_const_none; irq->base.ishard = false; MP_STATE_PORT(machine_pin_irq_obj[pin]) = irq; @@ -493,6 +489,10 @@ 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_irq), MP_ROM_PTR(&machine_pin_irq_obj) }, + // class attributes + { MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&pin_board_pins_obj_type) }, + { 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(MACHINE_PIN_MODE_IN) }, { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(MACHINE_PIN_MODE_OUT) }, @@ -502,6 +502,17 @@ 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_IRQ_RISING), MP_ROM_INT(GPIO_IRQ_EDGE_RISE) }, { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_IRQ_EDGE_FALL) }, + + // Pins alternate functions + { MP_ROM_QSTR(MP_QSTR_ALT_SPI), MP_ROM_INT(GPIO_FUNC_SPI) }, + { MP_ROM_QSTR(MP_QSTR_ALT_UART), MP_ROM_INT(GPIO_FUNC_UART) }, + { MP_ROM_QSTR(MP_QSTR_ALT_I2C), MP_ROM_INT(GPIO_FUNC_I2C) }, + { MP_ROM_QSTR(MP_QSTR_ALT_PWM), MP_ROM_INT(GPIO_FUNC_PWM) }, + { MP_ROM_QSTR(MP_QSTR_ALT_SIO), MP_ROM_INT(GPIO_FUNC_SIO) }, + { MP_ROM_QSTR(MP_QSTR_ALT_PIO0), MP_ROM_INT(GPIO_FUNC_PIO0) }, + { MP_ROM_QSTR(MP_QSTR_ALT_PIO1), MP_ROM_INT(GPIO_FUNC_PIO1) }, + { MP_ROM_QSTR(MP_QSTR_ALT_GPCK), MP_ROM_INT(GPIO_FUNC_GPCK) }, + { MP_ROM_QSTR(MP_QSTR_ALT_USB), MP_ROM_INT(GPIO_FUNC_USB) }, }; STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table); diff --git a/ports/rp2/machine_pin.h b/ports/rp2/machine_pin.h index 83a81007c8..c10dc4f9e8 100644 --- a/ports/rp2/machine_pin.h +++ b/ports/rp2/machine_pin.h @@ -37,19 +37,46 @@ enum { MACHINE_PIN_MODE_ALT = 3 }; +typedef struct _machine_pin_af_obj_t { + mp_obj_base_t base; + qstr name; + uint8_t idx : 4; + uint8_t fn : 4; + uint8_t unit : 8; +} machine_pin_af_obj_t; + typedef struct _machine_pin_obj_t { mp_obj_base_t base; + qstr name; uint8_t id : 5; #if MICROPY_HW_PIN_EXT_COUNT uint8_t is_ext : 1; uint8_t is_output : 1; uint8_t last_output_value : 1; #endif + uint8_t af_num : 4; + const machine_pin_af_obj_t *af; } machine_pin_obj_t; +extern const mp_obj_type_t machine_pin_type; +extern const mp_obj_type_t machine_pin_af_type; + +// Include all of the individual pin objects +#include "genhdr/pins.h" + +extern const mp_obj_type_t pin_cpu_pins_obj_type; +extern const mp_obj_dict_t pin_cpu_pins_locals_dict; + +extern const mp_obj_type_t pin_board_pins_obj_type; +extern const mp_obj_dict_t pin_board_pins_locals_dict; + void machine_pin_ext_init(void); void machine_pin_ext_set(machine_pin_obj_t *self, bool value); bool machine_pin_ext_get(machine_pin_obj_t *self); void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value); +const machine_pin_obj_t *machine_pin_find_named(const mp_obj_dict_t *named_pins, mp_obj_t name); +const machine_pin_af_obj_t *machine_pin_find_alt(const machine_pin_obj_t *pin, uint8_t fn); +const machine_pin_af_obj_t *machine_pin_find_alt_by_index(const machine_pin_obj_t *pin, mp_uint_t af_idx); + #endif // MICROPY_INCLUDED_RP2_MACHINE_PIN_H diff --git a/ports/rp2/machine_pin_cyw43.c b/ports/rp2/machine_pin_cyw43.c index a41a2f3caa..c09561461f 100644 --- a/ports/rp2/machine_pin_cyw43.c +++ b/ports/rp2/machine_pin_cyw43.c @@ -36,14 +36,7 @@ #include "machine_pin.h" #include "lib/cyw43-driver/src/cyw43.h" -machine_pin_obj_t ext_pin_obj[MICROPY_HW_PIN_EXT_COUNT]; - void machine_pin_ext_init(void) { - for (uint i = 0; i < count_of(ext_pin_obj); i++) { - ext_pin_obj[i].id = i; - ext_pin_obj[i].base.type = &machine_pin_type; - ext_pin_obj[i].is_ext = true; - } } void machine_pin_ext_set(machine_pin_obj_t *self, bool value) { From 7d01f3817015ecfaaa15fbc28a84f4bb3f875098 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Tue, 25 Oct 2022 22:35:30 +0200 Subject: [PATCH 17/59] drivers/ninaw10: Implement machine.Pin external pin controls. --- drivers/ninaw10/machine_pin_nina.c | 92 +++++++++++++++++++ ports/rp2/CMakeLists.txt | 1 + .../mpconfigboard.h | 3 + 3 files changed, 96 insertions(+) create mode 100644 drivers/ninaw10/machine_pin_nina.c diff --git a/drivers/ninaw10/machine_pin_nina.c b/drivers/ninaw10/machine_pin_nina.c new file mode 100644 index 0000000000..23c547b81f --- /dev/null +++ b/drivers/ninaw10/machine_pin_nina.c @@ -0,0 +1,92 @@ +/* + * 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 +#include + +#include "py/runtime.h" +#include "py/mphal.h" + +#if defined(MICROPY_PY_NETWORK_NINAW10) && defined(MICROPY_HW_PIN_EXT_COUNT) + +#include "modmachine.h" +#include "machine_pin.h" +#include "nina_wifi_drv.h" + +#define NINA_GPIO_INPUT (0x00) +#define NINA_GPIO_OUTPUT (0x01) +#define NINA_GPIO_INPUT_PULLUP (0x02) + +#define NINA_GPIO_MODE (0x50) +#define NINA_GPIO_READ (0x53) +#define NINA_GPIO_WRITE (0x51) + +static uint8_t pin_map[MICROPY_HW_PIN_EXT_COUNT] = { + 27, // LEDR + 25, // LEDG + 26, // LEDB + 36, // A6 + 35, // A7 +}; + +void machine_pin_ext_init(void) { + nina_init(); +} + +void machine_pin_ext_set(machine_pin_obj_t *self, bool value) { + if (self->id >= 0 && self->id < MICROPY_HW_PIN_EXT_COUNT) { + uint8_t buf[] = {pin_map[self->id], value}; + nina_ioctl(NINA_GPIO_WRITE, sizeof(buf), buf, 0); + } +} + +bool machine_pin_ext_get(machine_pin_obj_t *self) { + bool value = false; + if (self->id >= 0 && self->id < MICROPY_HW_PIN_EXT_COUNT) { + uint8_t buf[] = {pin_map[self->id]}; + nina_ioctl(NINA_GPIO_READ, sizeof(buf), buf, 0); + } + return value; +} + +void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value) { + if (mode == MACHINE_PIN_MODE_IN) { + mode = NINA_GPIO_INPUT; + self->is_output = false; + } else if (mode == MACHINE_PIN_MODE_OUT) { + mode = NINA_GPIO_OUTPUT; + self->is_output = true; + machine_pin_ext_set(self, value); + } else { + mp_raise_ValueError("only Pin.OUT and Pin.IN are supported for this pin"); + } + if (self->id >= 0 && self->id < MICROPY_HW_PIN_EXT_COUNT) { + uint8_t buf[] = {pin_map[self->id], mode}; + nina_ioctl(NINA_GPIO_MODE, sizeof(buf), buf, 0); + } +} + +#endif // defined(MICROPY_PY_NETWORK_NINAW10) && defined(MICROPY_HW_PIN_EXT_COUNT) diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 88971a5c90..485476355e 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -287,6 +287,7 @@ if (MICROPY_PY_NETWORK_NINAW10) ${MICROPY_DIR}/drivers/ninaw10/nina_bt_hci.c ${MICROPY_DIR}/drivers/ninaw10/nina_wifi_drv.c ${MICROPY_DIR}/drivers/ninaw10/nina_wifi_bsp.c + ${MICROPY_DIR}/drivers/ninaw10/machine_pin_nina.c ) list(APPEND MICROPY_SOURCE_EXTMOD diff --git a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h index 1818b56a68..6498cbf560 100644 --- a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h +++ b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h @@ -13,6 +13,9 @@ // Disable internal error numbers. #define MICROPY_USE_INTERNAL_ERRNO (0) +// Enable externally controlled pins. +#define MICROPY_HW_PIN_EXT_COUNT (5) + // Enable USB Mass Storage with FatFS filesystem. #define MICROPY_HW_USB_MSC (1) #define MICROPY_HW_USB_VID (0x2341) From d02f089058b9623ea976fbeead9b8acbf4d44bc6 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Tue, 25 Oct 2022 22:42:56 +0200 Subject: [PATCH 18/59] rp2/boards: Add pin CSV files to board definitions. Pin defines are: - For Pico define board pins and the default LED pin (WL_GPIO25). - For Pico-W define board pins, external pins and the default LED pin (WL_GPIO0). - For the Nano-RP2040, define board pins, external pins and the default LED pin (GPIO25) - For all other boards, the pins.csv defines the LED pin (if any) for backwards compatibility with code that assumes there's always an LED pin. --- .../boards/ADAFRUIT_FEATHER_RP2040/pins.csv | 1 + .../boards/ADAFRUIT_ITSYBITSY_RP2040/pins.csv | 1 + .../ARDUINO_NANO_RP2040_CONNECT/pins.csv | 26 ++++++++++++++++ .../GARATRONIC_PYBSTICK26_RP2040/pins.csv | 1 + ports/rp2/boards/PICO/pins.csv | 28 +++++++++++++++++ ports/rp2/boards/PICO_W/mpconfigboard.h | 5 ---- ports/rp2/boards/PICO_W/pins.csv | 30 +++++++++++++++++++ .../boards/PIMORONI_PICOLIPO_16MB/pins.csv | 1 + .../rp2/boards/PIMORONI_PICOLIPO_4MB/pins.csv | 1 + ports/rp2/boards/PIMORONI_TINY2040/pins.csv | 1 + ports/rp2/boards/SPARKFUN_THINGPLUS/pins.csv | 1 + ports/rp2/boards/W5100S_EVB_PICO/pins.csv | 1 + ports/rp2/boards/W5500_EVB_PICO/pins.csv | 1 + ports/rp2/boards/WEACTSTUDIO/pins.csv | 1 + 14 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/pins.csv create mode 100644 ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/pins.csv create mode 100644 ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/pins.csv create mode 100644 ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/pins.csv create mode 100644 ports/rp2/boards/PICO/pins.csv create mode 100644 ports/rp2/boards/PICO_W/pins.csv create mode 100644 ports/rp2/boards/PIMORONI_PICOLIPO_16MB/pins.csv create mode 100644 ports/rp2/boards/PIMORONI_PICOLIPO_4MB/pins.csv create mode 100644 ports/rp2/boards/PIMORONI_TINY2040/pins.csv create mode 100644 ports/rp2/boards/SPARKFUN_THINGPLUS/pins.csv create mode 100644 ports/rp2/boards/W5100S_EVB_PICO/pins.csv create mode 100644 ports/rp2/boards/W5500_EVB_PICO/pins.csv create mode 100644 ports/rp2/boards/WEACTSTUDIO/pins.csv diff --git a/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/pins.csv b/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/pins.csv new file mode 100644 index 0000000000..ee6fd99fee --- /dev/null +++ b/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/pins.csv @@ -0,0 +1 @@ +LED,GPIO13 diff --git a/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/pins.csv b/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/pins.csv new file mode 100644 index 0000000000..1b7e7c3c73 --- /dev/null +++ b/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/pins.csv @@ -0,0 +1 @@ +LED,GPIO11 diff --git a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/pins.csv b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/pins.csv new file mode 100644 index 0000000000..b398c8ec94 --- /dev/null +++ b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/pins.csv @@ -0,0 +1,26 @@ +TX,GPIO0 +RX,GPIO1 +D2,GPIO25 +D3,GPIO15 +D4,GPIO16 +D5,GPIO17 +D6,GPIO18 +D7,GPIO19 +D8,GPIO20 +D9,GPIO21 +D10,GPIO5 +D11,GPIO7 +D12,GPIO4 +D13,GPIO6 +LED,GPIO6 +A0,GPIO26 +A1,GPIO27 +A2,GPIO28 +A3,GPIO29 +A4,GPIO12 +A5,GPIO13 +LEDR,EXT_GPIO0 +LEDG,EXT_GPIO1 +LEDB,EXT_GPIO2 +A6,EXT_GPIO3 +A7,EXT_GPIO4 diff --git a/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/pins.csv b/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/pins.csv new file mode 100644 index 0000000000..6b3bedc0e1 --- /dev/null +++ b/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/pins.csv @@ -0,0 +1 @@ +LED,GPIO23 diff --git a/ports/rp2/boards/PICO/pins.csv b/ports/rp2/boards/PICO/pins.csv new file mode 100644 index 0000000000..16e3340264 --- /dev/null +++ b/ports/rp2/boards/PICO/pins.csv @@ -0,0 +1,28 @@ +GP0,GPIO0 +GP1,GPIO1 +GP2,GPIO2 +GP3,GPIO3 +GP4,GPIO4 +GP5,GPIO5 +GP6,GPIO6 +GP7,GPIO7 +GP8,GPIO8 +GP9,GPIO9 +GP10,GPIO10 +GP11,GPIO11 +GP12,GPIO12 +GP13,GPIO13 +GP14,GPIO14 +GP15,GPIO15 +GP16,GPIO16 +GP17,GPIO17 +GP18,GPIO18 +GP19,GPIO19 +GP20,GPIO20 +GP21,GPIO21 +GP22,GPIO22 +GP25,GPIO25 +GP26,GPIO26 +GP27,GPIO27 +GP28,GPIO28 +LED,GPIO25 diff --git a/ports/rp2/boards/PICO_W/mpconfigboard.h b/ports/rp2/boards/PICO_W/mpconfigboard.h index b3653aaeb0..227e7e3ff4 100644 --- a/ports/rp2/boards/PICO_W/mpconfigboard.h +++ b/ports/rp2/boards/PICO_W/mpconfigboard.h @@ -17,11 +17,6 @@ // Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose // #define MODUSSL_MBEDTLS_DEBUG_LEVEL 1 -#define MICROPY_HW_PIN_EXT_PREFIX "WL_GPIO" #define MICROPY_HW_PIN_EXT_COUNT CYW43_WL_GPIO_COUNT -#ifdef CYW43_WL_GPIO_LED_PIN -#define MICROPY_HW_PIN_EXT_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) diff --git a/ports/rp2/boards/PICO_W/pins.csv b/ports/rp2/boards/PICO_W/pins.csv new file mode 100644 index 0000000000..8debb6326e --- /dev/null +++ b/ports/rp2/boards/PICO_W/pins.csv @@ -0,0 +1,30 @@ +GP0,GPIO0 +GP1,GPIO1 +GP2,GPIO2 +GP3,GPIO3 +GP4,GPIO4 +GP5,GPIO5 +GP6,GPIO6 +GP7,GPIO7 +GP8,GPIO8 +GP9,GPIO9 +GP10,GPIO10 +GP11,GPIO11 +GP12,GPIO12 +GP13,GPIO13 +GP14,GPIO14 +GP15,GPIO15 +GP16,GPIO16 +GP17,GPIO17 +GP18,GPIO18 +GP19,GPIO19 +GP20,GPIO20 +GP21,GPIO21 +GP22,GPIO22 +GP26,GPIO26 +GP27,GPIO27 +GP28,GPIO28 +WL_GPIO0,EXT_GPIO0 +WL_GPIO1,EXT_GPIO1 +WL_GPIO2,EXT_GPIO2 +LED,EXT_GPIO0 diff --git a/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/pins.csv b/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/pins.csv new file mode 100644 index 0000000000..e75354485d --- /dev/null +++ b/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/pins.csv @@ -0,0 +1 @@ +LED,GPIO25 diff --git a/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/pins.csv b/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/pins.csv new file mode 100644 index 0000000000..e75354485d --- /dev/null +++ b/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/pins.csv @@ -0,0 +1 @@ +LED,GPIO25 diff --git a/ports/rp2/boards/PIMORONI_TINY2040/pins.csv b/ports/rp2/boards/PIMORONI_TINY2040/pins.csv new file mode 100644 index 0000000000..e4add1b0be --- /dev/null +++ b/ports/rp2/boards/PIMORONI_TINY2040/pins.csv @@ -0,0 +1 @@ +LED,GPIO19 diff --git a/ports/rp2/boards/SPARKFUN_THINGPLUS/pins.csv b/ports/rp2/boards/SPARKFUN_THINGPLUS/pins.csv new file mode 100644 index 0000000000..e75354485d --- /dev/null +++ b/ports/rp2/boards/SPARKFUN_THINGPLUS/pins.csv @@ -0,0 +1 @@ +LED,GPIO25 diff --git a/ports/rp2/boards/W5100S_EVB_PICO/pins.csv b/ports/rp2/boards/W5100S_EVB_PICO/pins.csv new file mode 100644 index 0000000000..e75354485d --- /dev/null +++ b/ports/rp2/boards/W5100S_EVB_PICO/pins.csv @@ -0,0 +1 @@ +LED,GPIO25 diff --git a/ports/rp2/boards/W5500_EVB_PICO/pins.csv b/ports/rp2/boards/W5500_EVB_PICO/pins.csv new file mode 100644 index 0000000000..e75354485d --- /dev/null +++ b/ports/rp2/boards/W5500_EVB_PICO/pins.csv @@ -0,0 +1 @@ +LED,GPIO25 diff --git a/ports/rp2/boards/WEACTSTUDIO/pins.csv b/ports/rp2/boards/WEACTSTUDIO/pins.csv new file mode 100644 index 0000000000..e75354485d --- /dev/null +++ b/ports/rp2/boards/WEACTSTUDIO/pins.csv @@ -0,0 +1 @@ +LED,GPIO25 From 4eefe78e8ed409641f30ad6c0edca8ca07a8e934 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 13 Jan 2023 11:07:47 -0600 Subject: [PATCH 19/59] github/workflows/code_size: Print code size change. The intention of using `tee` is to both print the code size change in the CI logs and save them to a file. Using redirection to a file caused it to not print the changes. Signed-off-by: David Lechner --- .github/workflows/code_size.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code_size.yml b/.github/workflows/code_size.yml index de75bfe08f..5d955703b6 100644 --- a/.github/workflows/code_size.yml +++ b/.github/workflows/code_size.yml @@ -28,7 +28,7 @@ jobs: - name: Build run: source tools/ci.sh && ci_code_size_build - name: Compute code size difference - run: tools/metrics.py diff ~/size0 ~/size1 | tee > diff + run: tools/metrics.py diff ~/size0 ~/size1 | tee diff - name: Save PR number if: github.event_name == 'pull_request' env: From e78e0b7418477af78284478c3e678db7bf2298cd Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 12 Jan 2023 10:39:27 +0100 Subject: [PATCH 20/59] py/gc: Increase the address length in gc_dump_alloc_table(). Showing 8 digits instead of 5, supporting devices with more than 1 MByte of RAM (which is common these days). The masking was never needed, and the related commented-out line can go. --- py/gc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/py/gc.c b/py/gc.c index 22cfdae998..f11c34aefe 100644 --- a/py/gc.c +++ b/py/gc.c @@ -1058,8 +1058,7 @@ void gc_dump_alloc_table(void) { } // 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)); + mp_printf(&mp_plat_print, "\n%08x: ", (uint)(bl * BYTES_PER_BLOCK)); } int c = ' '; switch (ATB_GET_KIND(area, bl)) { From 1583c1f6701a2545f0de042e886ee9afc26dfb74 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 12 Jan 2023 22:02:26 +0100 Subject: [PATCH 21/59] mimxrt: Set MICROPY_GC_STACK_ENTRY_TYPE to uint32_t for large RAM. It was uint16_t. The change sets it to uint32_t for devices with SDRAM. Fixes issue #10366. --- ports/mimxrt/mpconfigport.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/mimxrt/mpconfigport.h b/ports/mimxrt/mpconfigport.h index 911fd41b46..224714b071 100644 --- a/ports/mimxrt/mpconfigport.h +++ b/ports/mimxrt/mpconfigport.h @@ -37,7 +37,11 @@ uint32_t trng_random_u32(void); #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_FULL_FEATURES) // Memory allocation policies +#if MICROPY_HW_SDRAM_AVAIL +#define MICROPY_GC_STACK_ENTRY_TYPE uint32_t +#else #define MICROPY_GC_STACK_ENTRY_TYPE uint16_t +#endif #define MICROPY_ALLOC_PARSE_CHUNK_INIT (32) #define MICROPY_ALLOC_PATH_MAX (256) From bd86ce5f8213398a196019ad517df42e27fc173d Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 17 Jan 2023 17:32:53 +1100 Subject: [PATCH 22/59] lib/re1.5: Reduce code size when checking for named class char. Signed-off-by: Damien George --- lib/re1.5/compilecode.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/re1.5/compilecode.c b/lib/re1.5/compilecode.c index add4f6ac20..d4fc2a2895 100644 --- a/lib/re1.5/compilecode.c +++ b/lib/re1.5/compilecode.c @@ -4,6 +4,9 @@ #include "re1.5.h" +// Matches: DSWdsw +#define MATCH_NAMED_CLASS_CHAR(c) (((c) | 0x20) == 'd' || ((c) | 0x24) == 'w') + #define INSERT_CODE(at, num, pc) \ ((code ? memmove(code + at + num, code + at, pc - at) : 0), pc += num) #define REL(at, to) (to - at - 2) @@ -31,7 +34,7 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode) case '\\': re++; if (!*re) return NULL; // Trailing backslash - if ((*re | 0x20) == 'd' || (*re | 0x20) == 's' || (*re | 0x20) == 'w') { + if (MATCH_NAMED_CLASS_CHAR(*re)) { term = PC; EMIT(PC++, NamedClass); EMIT(PC++, *re); From 64193c7de9f53e01dca447a4a902398fe85b9c06 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 22 Oct 2021 22:23:47 +1100 Subject: [PATCH 23/59] lib/re1.5: Add support for named classes in class sets. Total code size change of this and previous commit: bare-arm: +0 +0.000% minimal x86: +0 +0.000% unix x64: +32 +0.004% standard stm32: +24 +0.006% PYBV10 cc3200: +16 +0.009% esp8266: +20 +0.003% GENERIC esp32: +44 +0.003% GENERIC[incl +8(data)] mimxrt: +32 +0.009% TEENSY40 renesas-ra: +24 +0.004% RA6M2_EK nrf: +0 +0.000% pca10040 rp2: +24 +0.005% PICO samd: +32 +0.012% ADAFRUIT_ITSYBITSY_M4_EXPRESS Addresses issue #7920. Signed-off-by: Damien George --- lib/re1.5/charclass.c | 10 +++++++++- lib/re1.5/compilecode.c | 13 ++++++++++--- lib/re1.5/re1.5.h | 1 + 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/re1.5/charclass.c b/lib/re1.5/charclass.c index 7f6388c93d..2553b40530 100644 --- a/lib/re1.5/charclass.c +++ b/lib/re1.5/charclass.c @@ -6,7 +6,15 @@ int _re1_5_classmatch(const char *pc, const char *sp) int is_positive = (pc[-1] == Class); int cnt = *pc++; while (cnt--) { - if (*sp >= *pc && *sp <= pc[1]) return is_positive; + if (*pc == RE15_CLASS_NAMED_CLASS_INDICATOR) { + if (_re1_5_namedclassmatch(pc + 1, sp)) { + return is_positive; + } + } else { + if (*sp >= *pc && *sp <= pc[1]) { + return is_positive; + } + } pc += 2; } return !is_positive; diff --git a/lib/re1.5/compilecode.c b/lib/re1.5/compilecode.c index d4fc2a2895..513a155970 100644 --- a/lib/re1.5/compilecode.c +++ b/lib/re1.5/compilecode.c @@ -66,14 +66,21 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode) PC++; // Skip # of pair byte prog->len++; for (cnt = 0; *re != ']'; re++, cnt++) { - if (*re == '\\') { + char c = *re; + if (c == '\\') { ++re; + c = *re; + if (MATCH_NAMED_CLASS_CHAR(c)) { + c = RE15_CLASS_NAMED_CLASS_INDICATOR; + goto emit_char_pair; + } } - if (!*re) return NULL; - EMIT(PC++, *re); + if (!c) return NULL; if (re[1] == '-' && re[2] != ']') { re += 2; } + emit_char_pair: + EMIT(PC++, c); EMIT(PC++, *re); } EMIT_CHECKED(term + 1, cnt); diff --git a/lib/re1.5/re1.5.h b/lib/re1.5/re1.5.h index 81f43ed7f5..b1ec01cbc5 100644 --- a/lib/re1.5/re1.5.h +++ b/lib/re1.5/re1.5.h @@ -138,6 +138,7 @@ struct Subject { #define NON_ANCHORED_PREFIX 5 #define HANDLE_ANCHORED(bytecode, is_anchored) ((is_anchored) ? (bytecode) + NON_ANCHORED_PREFIX : (bytecode)) +#define RE15_CLASS_NAMED_CLASS_INDICATOR 0 int re1_5_backtrack(ByteProg*, Subject*, const char**, int, int); int re1_5_pikevm(ByteProg*, Subject*, const char**, int, int); From fc745d85febd3f8d407f38a5002ae39fba39cd07 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 18 Jan 2023 09:13:35 +1100 Subject: [PATCH 24/59] tests/extmod/ure_namedclass: Add tests for named classes in class sets. Signed-off-by: Damien George --- tests/extmod/ure_namedclass.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/extmod/ure_namedclass.py b/tests/extmod/ure_namedclass.py index 00d58ad98a..4afc09dc0a 100644 --- a/tests/extmod/ure_namedclass.py +++ b/tests/extmod/ure_namedclass.py @@ -15,7 +15,7 @@ def print_groups(match): try: i = 0 while True: - print(m.group(i)) + print(match.group(i)) i += 1 except IndexError: pass @@ -32,3 +32,8 @@ print_groups(m) m = re.match(r"(([0-9]*)([a-z]*)\d*)", "1234hello567") print_groups(m) + +# named class within a class set +print_groups(re.match("([^\s]+)\s*([^\s]+)", "1 23")) +print_groups(re.match("([\s\d]+)([\W]+)", "1 2-+=")) +print_groups(re.match("([\W]+)([^\W]+)([^\S]+)([^\D]+)", " a_1 23")) From efb4bd35551ef1de393c088ce6d75ced7e810b64 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 24 Dec 2022 09:37:02 +0100 Subject: [PATCH 25/59] esp32/network_lan: Add support for LAN8710 PHY. LAN8710 uses the same drivers as LAN8720, so this commit just adds the names. Alternatively, both could be summarised under LAN87xx, like the esp-idf does. --- ports/esp32/modnetwork.c | 1 + ports/esp32/modnetwork.h | 2 +- ports/esp32/network_lan.c | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ports/esp32/modnetwork.c b/ports/esp32/modnetwork.c index 7429274c15..cc066f361f 100644 --- a/ports/esp32/modnetwork.c +++ b/ports/esp32/modnetwork.c @@ -261,6 +261,7 @@ STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { #endif #if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 1) && (CONFIG_IDF_TARGET_ESP32) + { MP_ROM_QSTR(MP_QSTR_PHY_LAN8710), MP_ROM_INT(PHY_LAN8710) }, { MP_ROM_QSTR(MP_QSTR_PHY_LAN8720), MP_ROM_INT(PHY_LAN8720) }, { MP_ROM_QSTR(MP_QSTR_PHY_IP101), MP_ROM_INT(PHY_IP101) }, { MP_ROM_QSTR(MP_QSTR_PHY_RTL8201), MP_ROM_INT(PHY_RTL8201) }, diff --git a/ports/esp32/modnetwork.h b/ports/esp32/modnetwork.h index 7bcfa0e6fc..5d1c3aaf7c 100644 --- a/ports/esp32/modnetwork.h +++ b/ports/esp32/modnetwork.h @@ -28,7 +28,7 @@ #include "esp_event.h" -enum { PHY_LAN8720, PHY_IP101, PHY_RTL8201, PHY_DP83848, PHY_KSZ8041 }; +enum { PHY_LAN8710, PHY_LAN8720, PHY_IP101, PHY_RTL8201, PHY_DP83848, PHY_KSZ8041 }; enum { ETH_INITIALIZED, ETH_STARTED, ETH_STOPPED, ETH_CONNECTED, ETH_DISCONNECTED, ETH_GOT_IP }; // Cases similar to ESP8266 user_interface.h diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c index c57d7815d7..3cd1efc043 100644 --- a/ports/esp32/network_lan.c +++ b/ports/esp32/network_lan.c @@ -125,7 +125,8 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar } self->phy_addr = args[ARG_phy_addr].u_int; - if (args[ARG_phy_type].u_int != PHY_LAN8720 && + if (args[ARG_phy_type].u_int != PHY_LAN8710 && + args[ARG_phy_type].u_int != PHY_LAN8720 && args[ARG_phy_type].u_int != PHY_IP101 && args[ARG_phy_type].u_int != PHY_RTL8201 && #if ESP_IDF_VERSION_MINOR >= 3 // KSZ8041 is new in ESP-IDF v4.3 @@ -146,6 +147,7 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar self->phy = NULL; switch (args[ARG_phy_type].u_int) { + case PHY_LAN8710: case PHY_LAN8720: self->phy = esp_eth_phy_new_lan8720(&phy_config); break; From 4b52003fb822c04651009b109ba403a23965cb0d Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 24 Dec 2022 16:52:55 +0100 Subject: [PATCH 26/59] esp32/network_lan: Support configuration of ETH ref_clk pin. Both the direction and the Pin used for ref_clk can now be configured. It Requires at least idf v4.4. The new keyword arguments to the constructor are: - ref_clk_mode=mode: with mode being Pin.IN or Pin.OUT. If it is not set, then the default configuration is used, which may be configured by kconfig settings. - ref_clk=pin_obj: which defines the Pin used for ref_clk. This is either Pin(0), Pin(16) or Pin(17). No check is done for the pin number. If it is the wrong one, it simply will not work. Besides that, no harm. --- ports/esp32/network_lan.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c index 3cd1efc043..471e31d627 100644 --- a/ports/esp32/network_lan.c +++ b/ports/esp32/network_lan.c @@ -97,7 +97,8 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar return MP_OBJ_FROM_PTR(&lan_obj); } - enum { ARG_id, ARG_mdc, ARG_mdio, ARG_power, ARG_phy_addr, ARG_phy_type }; + enum { ARG_id, ARG_mdc, ARG_mdio, ARG_power, ARG_phy_addr, ARG_phy_type, + ARG_ref_clk_mode, ARG_ref_clk }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_mdc, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -105,6 +106,11 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar { MP_QSTR_power, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_phy_type, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, + // Dynamic ref_clk configuration available at v4.4 + #if ESP_IDF_VERSION_MINOR >= 4 + { MP_QSTR_ref_clk_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_ref_clk, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + #endif }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -139,6 +145,17 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); mac_config.smi_mdc_gpio_num = self->mdc_pin; mac_config.smi_mdio_gpio_num = self->mdio_pin; + // Dynamic ref_clk configuration available at v4.4 + #if ESP_IDF_VERSION_MINOR >= 4 + if (args[ARG_ref_clk_mode].u_int != -1) { + // Map the GPIO_MODE constants to EMAC_CLK constants. + mac_config.clock_config.rmii.clock_mode = + args[ARG_ref_clk_mode].u_int == GPIO_MODE_INPUT ? EMAC_CLK_EXT_IN : EMAC_CLK_OUT; + } + if (args[ARG_ref_clk].u_obj != mp_const_none) { + mac_config.clock_config.rmii.clock_gpio = machine_pin_get_id(args[ARG_ref_clk].u_obj); + } + #endif esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); From 30bac47b1256154b8fd10508404068daeda19e71 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 25 Dec 2022 11:27:24 +0100 Subject: [PATCH 27/59] docs/esp32/quickref: Add docs for the LAN interface constructor. Incorporating PR #7356. --- docs/esp32/quickref.rst | 64 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 03ca97c7a7..f74926c374 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -68,6 +68,9 @@ by reading the temperature sensor immediately after waking up from sleep. Networking ---------- +WLAN +^^^^ + The :mod:`network` module:: import network @@ -110,6 +113,67 @@ calling ``wlan.config(reconnects=n)``, where n are the number of desired reconne attempts (0 means it won't retry, -1 will restore the default behaviour of trying to reconnect forever). +LAN +^^^ + +To use the wired interfaces one has to specify the pins and mode :: + + import network + + lan = network.LAN(mdc=PIN_MDC, ...) # Set the pin and mode configuration + lan.active(True) # activate the interface + lan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses + + +The keyword arguments for the constructor defining the PHY type and interface are: + +- mdc=pin-object # set the mdc and mdio pins. +- mdio=pin-object +- power=pin-object # set the pin which switches the power of the PHY device. +- phy_type= # Select the PHY device type. Supported devices are PHY_LAN8710, + PHY_LAN8720, PH_IP101, PHY_RTL8201, PHY_DP83848 and PHY_KSZ8041 +- phy_addr=number # The address number of the PHY device. +- ref_clk_mode=mode # Defines, whether the ref_clk at the ESP32 is an input + or output. Suitable values are Pin.IN and Pin.OUT. +- ref_clk=pin-object # defines the Pin used for ref_clk. + +The options ref_clk_mode and ref_clk require at least esp-idf version 4.4. For +earlier esp-idf versions, these parameters must be defined by kconfig board options. + +These are working configurations for LAN interfaces of popular boards:: + + # Olimex ESP32-GATEWAY: power controlled by Pin(5) + # Olimex ESP32 PoE and ESP32-PoE ISO: power controlled by Pin(12) + + lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), power=machine.Pin(5), + phy_type=network.PHY_LAN8720, phy_addr=0) + + # or with dynamic ref_clk pin configuration + + lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), power=machine.Pin(5), + phy_type=network.PHY_LAN8720, phy_addr=0, + ref_clk=machine.Pin(17), ref_clk_mode=machine.Pin.OUT) + + # Wireless-Tag's WT32-ETH01 + + lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), + phy_type=network.PHY_LAN8720, phy_addr=1, power=None) + + # Espressif ESP32-Ethernet-Kit_A_V1.2 + + lan = network.LAN(id=0, mdc=Pin(23), mdio=Pin(18), power=Pin(5), + phy_type=network.PHY_IP101, phy_addr=1) + +A suitable definition of the PHY interface in a sdkconfig.board file is:: + + CONFIG_ETH_PHY_INTERFACE_RMII=y + CONFIG_ETH_RMII_CLK_OUTPUT=y + CONFIG_ETH_RMII_CLK_OUT_GPIO=17 + CONFIG_LWIP_LOCAL_HOSTNAME="ESP32_POE" + +The value assigned to CONFIG_ETH_RMII_CLK_OUT_GPIO may vary depending on the +board's wiring. + Delay and timing ---------------- From e982c1d8de27145579b8ece24af81d8c7d07a99d Mon Sep 17 00:00:00 2001 From: Damien Tournoud Date: Thu, 12 Jan 2023 21:04:07 -0800 Subject: [PATCH 28/59] esp32/network_lan: Add support for SPI-based ethernet chips. Add support for various SPI-based ethernet chips (W5500, KSZ8851SNL, DM9051) to the ESP32 port. This leverages the existing support in ESP-IDF for these chips -- which configures these chips in "MAC raw" mode -- and the existing support for network.LAN in the ESP32 port. In particular, this doesn't leverage the wiznet5k support that is used on the rp2 and stm32 ports (because that's for native use of lwIP). Tested on the POE Featherwing (with the SJIRQ solder jumper bridged) and a ESP32-S3 feather. A note about the interrupt pin: The W5500 implementation within ESP-IDF relies on hardware interrupt, and requires the interrupt pin from the W5500 to be wired to a GPIO. This is not the case by default on the Adafruit Ethernet FeatherWing, which makes it not directly compatible with this implementation. --- ports/esp32/machine_hw_spi.c | 8 +++ ports/esp32/modnetwork.c | 14 +++- ports/esp32/modnetwork.h | 3 +- ports/esp32/mpconfigport.h | 18 +++++ ports/esp32/mphalport.h | 4 ++ ports/esp32/network_lan.c | 128 ++++++++++++++++++++++++++++++----- 6 files changed, 155 insertions(+), 20 deletions(-) diff --git a/ports/esp32/machine_hw_spi.c b/ports/esp32/machine_hw_spi.c index 35ecc397b3..36f8d3f069 100644 --- a/ports/esp32/machine_hw_spi.c +++ b/ports/esp32/machine_hw_spi.c @@ -533,6 +533,14 @@ mp_obj_t machine_hw_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_ return MP_OBJ_FROM_PTR(self); } +spi_host_device_t machine_hw_spi_get_host(mp_obj_t in) { + if (mp_obj_get_type(in) != &machine_spi_type) { + mp_raise_ValueError(MP_ERROR_TEXT("expecting a SPI object")); + } + machine_hw_spi_obj_t *self = (machine_hw_spi_obj_t *)in; + return self->host; +} + STATIC const mp_machine_spi_p_t machine_hw_spi_p = { .init = machine_hw_spi_init, .deinit = machine_hw_spi_deinit, diff --git a/ports/esp32/modnetwork.c b/ports/esp32/modnetwork.c index cc066f361f..3ebba2ade9 100644 --- a/ports/esp32/modnetwork.c +++ b/ports/esp32/modnetwork.c @@ -229,7 +229,7 @@ STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&get_wlan_obj) }, #endif - #if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 1) && (CONFIG_IDF_TARGET_ESP32) + #if MICROPY_PY_NETWORK_LAN { MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&get_lan_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_PPP), MP_ROM_PTR(&ppp_make_new_obj) }, @@ -260,7 +260,7 @@ STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_AUTH_MAX), MP_ROM_INT(WIFI_AUTH_MAX) }, #endif - #if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 1) && (CONFIG_IDF_TARGET_ESP32) + #if MICROPY_PY_NETWORK_LAN { MP_ROM_QSTR(MP_QSTR_PHY_LAN8710), MP_ROM_INT(PHY_LAN8710) }, { MP_ROM_QSTR(MP_QSTR_PHY_LAN8720), MP_ROM_INT(PHY_LAN8720) }, { MP_ROM_QSTR(MP_QSTR_PHY_IP101), MP_ROM_INT(PHY_IP101) }, @@ -271,6 +271,16 @@ STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_PHY_KSZ8041), MP_ROM_INT(PHY_KSZ8041) }, #endif + #if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL + { MP_ROM_QSTR(MP_QSTR_PHY_KSZ8851SNL), MP_ROM_INT(PHY_KSZ8851SNL) }, + #endif + #if CONFIG_ETH_SPI_ETHERNET_DM9051 + { MP_ROM_QSTR(MP_QSTR_PHY_DM9051), MP_ROM_INT(PHY_DM9051) }, + #endif + #if CONFIG_ETH_SPI_ETHERNET_W5500 + { MP_ROM_QSTR(MP_QSTR_PHY_W5500), MP_ROM_INT(PHY_W5500) }, + #endif + { MP_ROM_QSTR(MP_QSTR_ETH_INITIALIZED), MP_ROM_INT(ETH_INITIALIZED)}, { MP_ROM_QSTR(MP_QSTR_ETH_STARTED), MP_ROM_INT(ETH_STARTED)}, { MP_ROM_QSTR(MP_QSTR_ETH_STOPPED), MP_ROM_INT(ETH_STOPPED)}, diff --git a/ports/esp32/modnetwork.h b/ports/esp32/modnetwork.h index 5d1c3aaf7c..49bbd9c496 100644 --- a/ports/esp32/modnetwork.h +++ b/ports/esp32/modnetwork.h @@ -28,7 +28,8 @@ #include "esp_event.h" -enum { PHY_LAN8710, PHY_LAN8720, PHY_IP101, PHY_RTL8201, PHY_DP83848, PHY_KSZ8041 }; +enum { PHY_LAN8710, PHY_LAN8720, PHY_IP101, PHY_RTL8201, PHY_DP83848, PHY_KSZ8041, PHY_KSZ8851SNL = 100, PHY_DM9051, PHY_W5500 }; +#define IS_SPI_PHY(NUM) (NUM >= 100) enum { ETH_INITIALIZED, ETH_STARTED, ETH_STOPPED, ETH_CONNECTED, ETH_DISCONNECTED, ETH_GOT_IP }; // Cases similar to ESP8266 user_interface.h diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index d8822980b7..38468cf9cf 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -217,3 +217,21 @@ typedef long mp_off_t; #endif void boardctrl_startup(void); + +#ifndef MICROPY_PY_NETWORK_LAN +#if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 1) && (CONFIG_IDF_TARGET_ESP32 || (CONFIG_ETH_USE_SPI_ETHERNET && (CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL || CONFIG_ETH_SPI_ETHERNET_DM9051 || CONFIG_ETH_SPI_ETHERNET_W5500))) +#define MICROPY_PY_NETWORK_LAN (1) +#else +#define MICROPY_PY_NETWORK_LAN (0) +#endif +#endif + +#if MICROPY_PY_NETWORK_LAN && CONFIG_ETH_USE_SPI_ETHERNET +#ifndef MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 +#define MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ (12) +#else +#define MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ (36) +#endif +#endif +#endif diff --git a/ports/esp32/mphalport.h b/ports/esp32/mphalport.h index c838bd2284..7f14b6e188 100644 --- a/ports/esp32/mphalport.h +++ b/ports/esp32/mphalport.h @@ -35,6 +35,8 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "driver/spi_master.h" + #define MICROPY_PLATFORM_VERSION "IDF" IDF_VER // The core that the MicroPython task(s) are pinned to. @@ -111,4 +113,6 @@ static inline void mp_hal_pin_write(mp_hal_pin_obj_t pin, int v) { gpio_set_level(pin, v); } +spi_host_device_t machine_hw_spi_get_host(mp_obj_t in); + #endif // INCLUDED_MPHALPORT_H diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c index 471e31d627..f63c7ef8eb 100644 --- a/ports/esp32/network_lan.c +++ b/ports/esp32/network_lan.c @@ -33,13 +33,16 @@ #include "esp_idf_version.h" // LAN only for ESP32 (not ESP32S2) and only for ESP-IDF v4.1 and higher -#if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 1) && (CONFIG_IDF_TARGET_ESP32) +#if MICROPY_PY_NETWORK_LAN #include "esp_eth.h" #include "esp_eth_mac.h" #include "esp_event.h" #include "esp_log.h" #include "esp_netif.h" +#if CONFIG_ETH_USE_SPI_ETHERNET +#include "driver/spi_master.h" +#endif #include "modnetwork.h" @@ -48,9 +51,11 @@ typedef struct _lan_if_obj_t { int if_id; // MUST BE FIRST to match wlan_if_obj_t bool initialized; bool active; - uint8_t mdc_pin; - uint8_t mdio_pin; + int8_t mdc_pin; + int8_t mdio_pin; int8_t phy_power_pin; + int8_t phy_cs_pin; + int8_t phy_int_pin; uint8_t phy_addr; uint8_t phy_type; esp_eth_phy_t *phy; @@ -98,19 +103,22 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar } enum { ARG_id, ARG_mdc, ARG_mdio, ARG_power, ARG_phy_addr, ARG_phy_type, - ARG_ref_clk_mode, ARG_ref_clk }; + ARG_ref_clk_mode, ARG_ref_clk, ARG_spi, ARG_cs, ARG_int }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_mdc, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_mdio, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_mdc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_mdio, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_power, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_phy_type, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, - // Dynamic ref_clk configuration available at v4.4 #if ESP_IDF_VERSION_MINOR >= 4 + // Dynamic ref_clk configuration available at v4.4 { MP_QSTR_ref_clk_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_ref_clk, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, #endif + { MP_QSTR_spi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_int, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -122,9 +130,13 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar } } - self->mdc_pin = machine_pin_get_id(args[ARG_mdc].u_obj); - self->mdio_pin = machine_pin_get_id(args[ARG_mdio].u_obj); - self->phy_power_pin = args[ARG_power].u_obj == mp_const_none ? -1 : machine_pin_get_id(args[ARG_power].u_obj); + #define GET_PIN(XXX) args[XXX].u_obj == mp_const_none ? -1 : machine_pin_get_id(args[XXX].u_obj); + + self->mdc_pin = GET_PIN(ARG_mdc); + self->mdio_pin = GET_PIN(ARG_mdio); + self->phy_power_pin = GET_PIN(ARG_power); + self->phy_cs_pin = GET_PIN(ARG_cs); + self->phy_int_pin = GET_PIN(ARG_int); if (args[ARG_phy_addr].u_int < 0x00 || args[ARG_phy_addr].u_int > 0x1f) { mp_raise_ValueError(MP_ERROR_TEXT("invalid phy address")); @@ -138,13 +150,24 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar #if ESP_IDF_VERSION_MINOR >= 3 // KSZ8041 is new in ESP-IDF v4.3 args[ARG_phy_type].u_int != PHY_KSZ8041 && #endif + #if CONFIG_ETH_USE_SPI_ETHERNET + #if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL + args[ARG_phy_type].u_int != PHY_KSZ8851SNL && + #endif + #if CONFIG_ETH_SPI_ETHERNET_DM9051 + args[ARG_phy_type].u_int != PHY_DM9051 && + #endif + #if CONFIG_ETH_SPI_ETHERNET_W5500 + args[ARG_phy_type].u_int != PHY_W5500 && + #endif + #endif args[ARG_phy_type].u_int != PHY_DP83848) { mp_raise_ValueError(MP_ERROR_TEXT("invalid phy type")); } eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); - mac_config.smi_mdc_gpio_num = self->mdc_pin; - mac_config.smi_mdio_gpio_num = self->mdio_pin; + esp_eth_mac_t *mac = NULL; + // Dynamic ref_clk configuration available at v4.4 #if ESP_IDF_VERSION_MINOR >= 4 if (args[ARG_ref_clk_mode].u_int != -1) { @@ -156,14 +179,46 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar mac_config.clock_config.rmii.clock_gpio = machine_pin_get_id(args[ARG_ref_clk].u_obj); } #endif - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); phy_config.phy_addr = self->phy_addr; phy_config.reset_gpio_num = self->phy_power_pin; self->phy = NULL; + #if CONFIG_ETH_USE_SPI_ETHERNET + spi_device_handle_t spi_handle = NULL; + if (IS_SPI_PHY(args[ARG_phy_type].u_int)) { + spi_device_interface_config_t devcfg = { + .mode = 0, + .clock_speed_hz = MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ * 1000 * 1000, + .queue_size = 20, + .spics_io_num = self->phy_cs_pin, + }; + switch (args[ARG_phy_type].u_int) { + #if CONFIG_ETH_SPI_ETHERNET_DM9051 + case PHY_DM9051: { + devcfg.command_bits = 1; + devcfg.address_bits = 7; + break; + } + #endif + #if CONFIG_ETH_SPI_ETHERNET_W5500 + case PHY_W5500: { + devcfg.command_bits = 16; + devcfg.address_bits = 8; + break; + } + #endif + } + spi_host_device_t host = machine_hw_spi_get_host(args[ARG_spi].u_obj); + if (spi_bus_add_device(host, &devcfg, &spi_handle) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("spi_bus_add_device failed")); + } + } + #endif + switch (args[ARG_phy_type].u_int) { + #if CONFIG_IDF_TARGET_ESP32 case PHY_LAN8710: case PHY_LAN8720: self->phy = esp_eth_phy_new_lan8720(&phy_config); @@ -177,15 +232,54 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar case PHY_DP83848: self->phy = esp_eth_phy_new_dp83848(&phy_config); break; + #if ESP_IDF_VERSION_MINOR >= 3 // KSZ8041 is new in ESP-IDF v4.3 case PHY_KSZ8041: - #if ESP_IDF_VERSION_MINOR >= 3 // KSZ8041 is new in ESP-IDF v4.3 self->phy = esp_eth_phy_new_ksz8041(&phy_config); break; - #endif - default: - mp_raise_ValueError(MP_ERROR_TEXT("unknown phy")); + #endif + #endif + #if CONFIG_ETH_USE_SPI_ETHERNET + #if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL + case PHY_KSZ8851SNL: { + eth_ksz8851snl_config_t chip_config = ETH_KSZ8851SNL_DEFAULT_CONFIG(spi_handle); + chip_config.int_gpio_num = self->phy_int_pin; + mac = esp_eth_mac_new_ksz8851snl(&chip_config, &mac_config); + self->phy = esp_eth_phy_new_ksz8851snl(&phy_config); + break; + } + #endif + #if CONFIG_ETH_SPI_ETHERNET_DM9051 + case PHY_DM9051: { + eth_dm9051_config_t chip_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle); + chip_config.int_gpio_num = self->phy_int_pin; + mac = esp_eth_mac_new_dm9051(&chip_config, &mac_config); + self->phy = esp_eth_phy_new_dm9051(&phy_config); + break; + } + #endif + #if CONFIG_ETH_SPI_ETHERNET_W5500 + case PHY_W5500: { + eth_w5500_config_t chip_config = ETH_W5500_DEFAULT_CONFIG(spi_handle); + chip_config.int_gpio_num = self->phy_int_pin; + mac = esp_eth_mac_new_w5500(&chip_config, &mac_config); + self->phy = esp_eth_phy_new_w5500(&phy_config); + break; + } + #endif + #endif } + #if CONFIG_IDF_TARGET_ESP32 + if (!IS_SPI_PHY(args[ARG_phy_type].u_int)) { + if (self->mdc_pin == -1 || self->mdio_pin == -1) { + mp_raise_ValueError(MP_ERROR_TEXT("mdc and mdio must be specified")); + } + mac_config.smi_mdc_gpio_num = self->mdc_pin; + mac_config.smi_mdio_gpio_num = self->mdio_pin; + mac = esp_eth_mac_new_esp32(&mac_config); + } + #endif + if (esp_netif_init() != ESP_OK) { mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("esp_netif_init failed")); } From c7301b8d03d4681247c892d260696b0bfa4139d9 Mon Sep 17 00:00:00 2001 From: Damien Tournoud Date: Thu, 12 Jan 2023 21:04:07 -0800 Subject: [PATCH 29/59] esp32/network_lan: Fix setting MAC address of ethernet devices. `esp_eth_ioctl(ETH_CMD_S_MAC_ADDR)` sets the MAC address of the hardware device, but we also need to notify the upper layers of the change so that e.g. DHCP work properly. --- ports/esp32/network_lan.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c index f63c7ef8eb..13d0bbd16f 100644 --- a/ports/esp32/network_lan.c +++ b/ports/esp32/network_lan.c @@ -374,7 +374,12 @@ STATIC mp_obj_t lan_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs if (bufinfo.len != 6) { mp_raise_ValueError(MP_ERROR_TEXT("invalid buffer length")); } - esp_eth_ioctl(self->eth_handle, ETH_CMD_S_MAC_ADDR, bufinfo.buf); + if ( + (esp_eth_ioctl(self->eth_handle, ETH_CMD_S_MAC_ADDR, bufinfo.buf) != ESP_OK) || + (esp_netif_set_mac(self->eth_netif, bufinfo.buf) != ESP_OK) + ) { + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("failed setting MAC address")); + } break; } default: From 67097d8c2b3887f7b177564c230d0bf34d23bb43 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 18 Jan 2023 13:47:10 +1100 Subject: [PATCH 30/59] esp32/network_lan: Fix compilation on IDF lower than v4.4. Signed-off-by: Damien George --- ports/esp32/network_lan.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c index 13d0bbd16f..d482f95064 100644 --- a/ports/esp32/network_lan.c +++ b/ports/esp32/network_lan.c @@ -103,7 +103,7 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar } enum { ARG_id, ARG_mdc, ARG_mdio, ARG_power, ARG_phy_addr, ARG_phy_type, - ARG_ref_clk_mode, ARG_ref_clk, ARG_spi, ARG_cs, ARG_int }; + ARG_spi, ARG_cs, ARG_int, ARG_ref_clk_mode, ARG_ref_clk }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_mdc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, @@ -111,14 +111,14 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar { MP_QSTR_power, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_phy_type, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_spi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_int, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, #if ESP_IDF_VERSION_MINOR >= 4 // Dynamic ref_clk configuration available at v4.4 { MP_QSTR_ref_clk_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_ref_clk, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, #endif - { MP_QSTR_spi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_int, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; From fb0dd86b39950f78de0b360a436b99fccc80c9a9 Mon Sep 17 00:00:00 2001 From: Maripo GODA Date: Fri, 13 Jan 2023 15:24:15 +0900 Subject: [PATCH 31/59] esp32/machine_sdcard: Change dma_channel to SPI_DMA_CH_AUTO for ESP32S3. Specifying DMA channel 2 causes an "invalid dma channel" error. In ESP-IDF, the only available channel for ESP32S3 is SPI_DMA_CH_AUTO=3. --- ports/esp32/machine_sdcard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/machine_sdcard.c b/ports/esp32/machine_sdcard.c index 801a26f378..5b495f8494 100644 --- a/ports/esp32/machine_sdcard.c +++ b/ports/esp32/machine_sdcard.c @@ -211,7 +211,7 @@ STATIC mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args .gpio_cs = GPIO_NUM_34, .gpio_cd = SDSPI_SLOT_NO_CD, .gpio_wp = SDSPI_SLOT_NO_WP, - .dma_channel = 2 + .dma_channel = SPI_DMA_CH_AUTO }, SDSPI_SLOT_CONFIG_DEFAULT() }; From e30e543a7559f1235637a54ef2b0b4feb196c44d Mon Sep 17 00:00:00 2001 From: Antonello Margottini Date: Wed, 4 Jan 2023 11:36:54 +0100 Subject: [PATCH 32/59] esp8266/modnetwork: Add ability to set tx power for WLAN interface. --- ports/esp8266/modnetwork.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ports/esp8266/modnetwork.c b/ports/esp8266/modnetwork.c index ec62528a08..29bdd3a1b7 100644 --- a/ports/esp8266/modnetwork.c +++ b/ports/esp8266/modnetwork.c @@ -410,6 +410,11 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs wifi_set_phy_mode(mp_obj_get_int(kwargs->table[i].value)); break; } + case MP_QSTR_txpower: { + int8_t power = mp_obj_get_float(kwargs->table[i].value) * 4; + system_phy_set_max_tpw(power); + break; + } default: goto unknown; } From 4eb7063608c93418f4c4b24df6c029e6314256a0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 19 Jan 2023 14:59:18 +1100 Subject: [PATCH 33/59] esp8266/README: Remove notice about port being "experimental". It has been around for a long time and the API is mature enough. Signed-off-by: Damien George --- ports/esp8266/README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ports/esp8266/README.md b/ports/esp8266/README.md index b54d8958d7..1e0cae2139 100644 --- a/ports/esp8266/README.md +++ b/ports/esp8266/README.md @@ -1,10 +1,9 @@ MicroPython port to ESP8266 =========================== -This is an experimental port of MicroPython for the WiFi modules based -on Espressif ESP8266 chip. - -WARNING: The port is experimental and many APIs are subject to change. +This is a port of MicroPython to the Espressif ESP8266 WiFi microcontroller. +MicroPython runs on this chip without any underlying operating system, using +the ESP8266 NONOS SDK. Supported features include: - REPL (Python prompt) over UART0. From 720f2cfba9532879625d5418b04ae21424cb3639 Mon Sep 17 00:00:00 2001 From: Juan Francisco Cantero Hurtado Date: Sun, 1 Jan 2023 00:29:35 +0100 Subject: [PATCH 34/59] unix/Makefile: Disable building the shared library of libffi. MicroPython doesn't need the shared library and disabling it in the configure could ease the build of a static version of MicroPython. --- ports/unix/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/unix/Makefile b/ports/unix/Makefile index cd18a6ed1e..8e9094b40c 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -294,7 +294,7 @@ $(TOP)/lib/libffi/configure: $(TOP)/lib/libffi/autogen.sh # docs and depending on makeinfo $(BUILD)/lib/libffi/include/ffi.h: $(TOP)/lib/libffi/configure mkdir -p $(BUILD)/lib/libffi; cd $(BUILD)/lib/libffi; \ - $(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"; \ + $(abspath $(TOP))/lib/libffi/configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out --disable-shared --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 PREFIX = /usr/local From 7f6345a9734f5772b2b579d2ac915cdeb1fcbed1 Mon Sep 17 00:00:00 2001 From: LiaoJingyi_winY7kp <924765359@qq.com> Date: Sun, 23 Oct 2022 20:47:14 +0300 Subject: [PATCH 35/59] docs/library/machine.Timer: Add freq argument to machine.Timer. Based on and tested on the rp2 port. Signed-off-by: Liao Jingyi Signed-off-by: Damien George --- docs/library/machine.Timer.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/library/machine.Timer.rst b/docs/library/machine.Timer.rst index 424a49bcba..48c023a11c 100644 --- a/docs/library/machine.Timer.rst +++ b/docs/library/machine.Timer.rst @@ -38,13 +38,16 @@ Constructors Methods ------- -.. method:: Timer.init(*, mode=Timer.PERIODIC, period=-1, callback=None) +.. method:: Timer.init(*, mode=Timer.PERIODIC, freq=-1, period=-1, callback=None) Initialise the timer. Example:: def mycallback(t): pass + # periodic at 1kHz + tim.init(mode=Timer.PERIODIC, freq=1000, callback=mycallback) + # periodic with 100ms period tim.init(period=100, callback=mycallback) @@ -60,6 +63,11 @@ Methods - ``Timer.PERIODIC`` - The timer runs periodically at the configured frequency of the channel. + - ``freq`` - The timer frequency, in units of Hz. The upper bound of + the frequency is dependent on the port. When both the ``freq`` and + ``period`` arguments are given, ``freq`` has a higher priority and + ``period`` is ignored. + - ``period`` - The timer period, in milliseconds. - ``callback`` - The callable to call upon expiration of the timer period. From 23ef29706e3be7515d07161234208b889cebae15 Mon Sep 17 00:00:00 2001 From: Chris Overgaauw <14801878+chrisovergaauw@users.noreply.github.com> Date: Mon, 19 Dec 2022 11:18:19 +0100 Subject: [PATCH 36/59] docs/reference/constrained: Add missing heap-dump symbols to mem_info(). --- docs/reference/constrained.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/reference/constrained.rst b/docs/reference/constrained.rst index 8b64fd98fc..2bcf9f7fb7 100644 --- a/docs/reference/constrained.rst +++ b/docs/reference/constrained.rst @@ -392,6 +392,8 @@ Symbol Meaning F float B byte code M module + S string or bytes + A bytearray ====== ================= Each letter represents a single block of memory, a block being 16 bytes. So each From 5c10727b68cd22d3f280acf00ea6c3ac062bec8a Mon Sep 17 00:00:00 2001 From: enriquezgarc Date: Tue, 30 Aug 2022 17:06:25 +0200 Subject: [PATCH 37/59] docs/zephyr/quickref: Fix zsensor module usage examples. Signed-off-by: enriquezgarc --- docs/zephyr/quickref.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/zephyr/quickref.rst b/docs/zephyr/quickref.rst index 783621316c..329a9c41c0 100644 --- a/docs/zephyr/quickref.rst +++ b/docs/zephyr/quickref.rst @@ -151,7 +151,7 @@ Use the :ref:`zsensor.Sensor ` class to access sensor data:: accel.measure() # obtain a measurement reading from the accelerometer # each of these prints the value taken by measure() - accel.float(zsensor.ACCEL_X) # print measurement value for accelerometer X-axis sensor channel as float - accel.millis(zsensor.ACCEL_Y) # print measurement value for accelerometer Y-axis sensor channel in millionths - accel.micro(zsensor.ACCEL_Z) # print measurement value for accelerometer Z-axis sensor channel in thousandths - accel.int(zsensor.ACCEL_X) # print measurement integer value only for accelerometer X-axis sensor channel + accel.get_float(zsensor.ACCEL_X) # print measurement value for accelerometer X-axis sensor channel as float + accel.get_millis(zsensor.ACCEL_Y) # print measurement value for accelerometer Y-axis sensor channel in millionths + accel.get_micro(zsensor.ACCEL_Z) # print measurement value for accelerometer Z-axis sensor channel in thousandths + accel.get_int(zsensor.ACCEL_X) # print measurement integer value only for accelerometer X-axis sensor channel From 36347817ec7715f74c76a44eb92533821502f4d5 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Nov 2022 09:05:29 +1100 Subject: [PATCH 38/59] CODECONVENTIONS: Explain uncrustify dependency for pre-commit setup. pre-commit manages its own dependencies otherwise (including Black), but this one is a C/C++ binary so needs to be installed independently. Signed-off-by: Angus Gratton --- CODECONVENTIONS.md | 55 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/CODECONVENTIONS.md b/CODECONVENTIONS.md index 53b202ea37..0bd7a7327a 100644 --- a/CODECONVENTIONS.md +++ b/CODECONVENTIONS.md @@ -65,16 +65,52 @@ 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. +uncrustify +========== + +Only [uncrustify](https://github.com/uncrustify/uncrustify) v0.71 or v0.72 can +be used for MicroPython. Different uncrustify versions produce slightly +different formatting, and the configuration file formats are often +incompatible. v0.73 or newer *will not work*. + +Depending on your operating system version, it may be possible to install a pre-compiled +uncrustify version: + +Ubuntu, Debian +-------------- + +Ubuntu versions 21.10 or 22.04LTS, and Debian versions bullseye or bookworm all +include v0.72 so can be installed directly: + +``` +$ apt install uncrustify +``` + +Arch Linux +---------- + +The current Arch uncrustify version is too new. There is an [old Arch package +for v0.72](https://archive.archlinux.org/packages/u/uncrustify/) that can be +installed from the Arch Linux archive ([more +information](https://wiki.archlinux.org/title/Downgrading_packages#Arch_Linux_Archive)). Use +the [IgnorePkg feature](https://wiki.archlinux.org/title/Pacman#Skip_package_from_being_upgraded) +to prevent it re-updating. + +Brew +---- + +This command may work, please raise a new Issue if it doesn't: + +``` +brew install https://github.com/Homebrew/homebrew-core/raw/2b07d8192623365078a8b855a164ebcdf81494a6/Formula/uncrustify.rb +``` Automatic Pre-Commit Hooks ========================== To have code formatting and commit message conventions automatically checked, -a configuration file is provided for the [pre-commit] -(https://pre-commit.com/) tool. +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 @@ -82,13 +118,17 @@ virtual environment. Other sources, such as Brew are also available, see [the docs](https://pre-commit.com/index.html#install) for details. ``` -$ apt install pre-commit # Ubuntu +$ apt install pre-commit # Ubuntu, Debian $ pacman -Sy python-precommit # Arch Linux $ brew install pre-commit # Brew $ pip install pre-commit # PyPI ``` -Then inside the MicroPython repository, register the git hooks for pre-commit +Next, install [uncrustify (see above)](#uncrustify). Other dependencies are managed by +pre-commit automatically, but uncrustify needs to be installed and available on +the PATH. + +Then, inside the MicroPython repository, register the git hooks for pre-commit by running: ``` @@ -115,7 +155,6 @@ Tips: * To ignore the pre-commit message format check temporarily, start the commit message subject line with "WIP" (for "Work In Progress"). - Python code conventions ======================= From 3b5cafc7163724a50b3d077baf83c4d8c7b6de4a Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Wed, 12 Oct 2022 20:54:15 +0200 Subject: [PATCH 39/59] stm32/Makefile: Leave DFU mode after download when using dfu-util. Not all DFU bootloaders exit after download, this modifier is required for some boards to reset, otherwise they sit idle in DFU mode. --- ports/stm32/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 418562f7cb..19643cac56 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -546,7 +546,7 @@ define RUN_DFU $(ECHO) "Writing $(1) to the board" $(if $(filter $(USE_PYDFU),1),\ $(Q)$(PYTHON) $(PYDFU) --vid $(BOOTLOADER_DFU_USB_VID) --pid $(BOOTLOADER_DFU_USB_PID) -u $(1), - $(Q)$(DFU_UTIL) -a 0 -d $(BOOTLOADER_DFU_USB_VID):$(BOOTLOADER_DFU_USB_PID) -D $(1)) + $(Q)$(DFU_UTIL) -a 0 -d $(BOOTLOADER_DFU_USB_VID):$(BOOTLOADER_DFU_USB_PID) -D $(1) -s :leave) endef define RUN_STLINK From 32a858e254b3c6f53dc4969f62b830fbb51cf8ee Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 25 Dec 2022 14:34:33 +0100 Subject: [PATCH 40/59] esp32/boards: Add board definition for Olimex ESP32 PoE boards. The major setting is about the PHY interface configuration. The configuration matches the Olimex ESP32 Gateway as well. Tested with esp-idf v4.2.4 and Olimex ESP32 POE boards. --- .../esp32/boards/OLIMEX_ESP32_POE/board.json | 24 +++++++++++++++++++ ports/esp32/boards/OLIMEX_ESP32_POE/board.md | 4 ++++ .../OLIMEX_ESP32_POE/mpconfigboard.cmake | 5 ++++ .../boards/OLIMEX_ESP32_POE/mpconfigboard.h | 2 ++ .../boards/OLIMEX_ESP32_POE/sdkconfig.board | 4 ++++ 5 files changed, 39 insertions(+) create mode 100644 ports/esp32/boards/OLIMEX_ESP32_POE/board.json create mode 100644 ports/esp32/boards/OLIMEX_ESP32_POE/board.md create mode 100644 ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.cmake create mode 100644 ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h create mode 100644 ports/esp32/boards/OLIMEX_ESP32_POE/sdkconfig.board diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/board.json b/ports/esp32/boards/OLIMEX_ESP32_POE/board.json new file mode 100644 index 0000000000..f3b1402bb1 --- /dev/null +++ b/ports/esp32/boards/OLIMEX_ESP32_POE/board.json @@ -0,0 +1,24 @@ +{ + "deploy": [ + "../deploy.md" + ], + "docs": "", + "features": [ + "BLE", + "WiFi", + "MicroSD", + "Battery Charging", + "Ethernet", + "PoE", + "Breadboard friendly" + ], + "id": "esp32", + "images": [ + "ESP32-POE-ISO-1.jpg" + ], + "mcu": "esp32", + "product": "ESP32", + "thumbnail": "", + "url": "https://www.olimex.com/", + "vendor": "Olimex" +} diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/board.md b/ports/esp32/boards/OLIMEX_ESP32_POE/board.md new file mode 100644 index 0000000000..1e2dbb744a --- /dev/null +++ b/ports/esp32/boards/OLIMEX_ESP32_POE/board.md @@ -0,0 +1,4 @@ +The following files are daily firmware for Olimex ESP32 boards with Ethernet. +They match the boards ESP32 ETH-PoE, ESP32 ETH-PoE-ISO and ESP32 Gateway. + +This firmware is compiled using ESP-IDF v4.x. diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.cmake b/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.cmake new file mode 100644 index 0000000000..c460b07d5e --- /dev/null +++ b/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.cmake @@ -0,0 +1,5 @@ +set(SDKCONFIG_DEFAULTS + boards/sdkconfig.base + boards/sdkconfig.ble + boards/OLIMEX_ESP32_POE/sdkconfig.board +) diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h b/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h new file mode 100644 index 0000000000..c8458e35fa --- /dev/null +++ b/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h @@ -0,0 +1,2 @@ +#define MICROPY_HW_BOARD_NAME "Olimex ESP32 ETH" +#define MICROPY_HW_MCU_NAME "ESP32" diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/sdkconfig.board b/ports/esp32/boards/OLIMEX_ESP32_POE/sdkconfig.board new file mode 100644 index 0000000000..15ffbf3a67 --- /dev/null +++ b/ports/esp32/boards/OLIMEX_ESP32_POE/sdkconfig.board @@ -0,0 +1,4 @@ +CONFIG_ETH_PHY_INTERFACE_RMII=y +CONFIG_ETH_RMII_CLK_OUTPUT=y +CONFIG_ETH_RMII_CLK_OUT_GPIO=17 +CONFIG_LWIP_LOCAL_HOSTNAME="ESP32_POE" From 54e85fe212b15390b60246846e5f2087d566aeda Mon Sep 17 00:00:00 2001 From: Clayton Cronk Date: Mon, 21 Feb 2022 09:13:42 -0600 Subject: [PATCH 41/59] esp32/boards/GENERIC_UNICORE: Add board definition for unicore chips. Tested to work on an ESP32-MINI-1, which is a single core ESP32-U4DWH. Signed-off-by: Clayton Cronk --- ports/esp32/boards/GENERIC_UNICORE/board.json | 19 +++++++++++++++++++ ports/esp32/boards/GENERIC_UNICORE/board.md | 1 + .../GENERIC_UNICORE/mpconfigboard.cmake | 5 +++++ .../boards/GENERIC_UNICORE/mpconfigboard.h | 2 ++ .../boards/GENERIC_UNICORE/sdkconfig.board | 1 + ports/esp32/mphalport.h | 4 +++- 6 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 ports/esp32/boards/GENERIC_UNICORE/board.json create mode 100644 ports/esp32/boards/GENERIC_UNICORE/board.md create mode 100644 ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.cmake create mode 100644 ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h create mode 100644 ports/esp32/boards/GENERIC_UNICORE/sdkconfig.board diff --git a/ports/esp32/boards/GENERIC_UNICORE/board.json b/ports/esp32/boards/GENERIC_UNICORE/board.json new file mode 100644 index 0000000000..8fed71a018 --- /dev/null +++ b/ports/esp32/boards/GENERIC_UNICORE/board.json @@ -0,0 +1,19 @@ +{ + "deploy": [ + "../deploy.md" + ], + "docs": "", + "features": [ + "BLE", + "WiFi" + ], + "id": "esp32-unicore", + "images": [ + "generic_unicore.jpg" + ], + "mcu": "esp32", + "product": "ESP32 Unicore", + "thumbnail": "", + "url": "https://www.espressif.com/en/products/modules", + "vendor": "Espressif" +} diff --git a/ports/esp32/boards/GENERIC_UNICORE/board.md b/ports/esp32/boards/GENERIC_UNICORE/board.md new file mode 100644 index 0000000000..b41c167498 --- /dev/null +++ b/ports/esp32/boards/GENERIC_UNICORE/board.md @@ -0,0 +1 @@ +The following files are daily firmware for single-core ESP32-based boards without external SPIRAM. diff --git a/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.cmake b/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.cmake new file mode 100644 index 0000000000..2f34688c8c --- /dev/null +++ b/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.cmake @@ -0,0 +1,5 @@ +set(SDKCONFIG_DEFAULTS + boards/sdkconfig.base + boards/sdkconfig.ble + boards/GENERIC_UNICORE/sdkconfig.board +) diff --git a/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h b/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h new file mode 100644 index 0000000000..5d0624b9c3 --- /dev/null +++ b/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h @@ -0,0 +1,2 @@ +#define MICROPY_HW_BOARD_NAME "ESP32 Unicore module" +#define MICROPY_HW_MCU_NAME "ESP32-UNICORE" diff --git a/ports/esp32/boards/GENERIC_UNICORE/sdkconfig.board b/ports/esp32/boards/GENERIC_UNICORE/sdkconfig.board new file mode 100644 index 0000000000..f0b0b5e03d --- /dev/null +++ b/ports/esp32/boards/GENERIC_UNICORE/sdkconfig.board @@ -0,0 +1 @@ +CONFIG_FREERTOS_UNICORE=y diff --git a/ports/esp32/mphalport.h b/ports/esp32/mphalport.h index 7f14b6e188..672fa306f5 100644 --- a/ports/esp32/mphalport.h +++ b/ports/esp32/mphalport.h @@ -44,7 +44,9 @@ // and avoid the Wifi/BLE timing problems on the same core. // Best effort here to remain backwards compatible in rare version edge cases... // See https://github.com/micropython/micropython/issues/5489 for history -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) +#if CONFIG_FREERTOS_UNICORE +#define MP_TASK_COREID (0) +#elif ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) #define MP_TASK_COREID (1) #else #define MP_TASK_COREID (0) From 30db33d1e024c9c16140ed8f44283728b1428fac Mon Sep 17 00:00:00 2001 From: ma-lalonde Date: Mon, 30 May 2022 01:16:51 -0400 Subject: [PATCH 42/59] esp32/network_lan: Add support for Ethernet PHY KSZ8081. This is available since ESP-IDF v4.4. Signed-off-by: Damien George --- ports/esp32/modnetwork.c | 4 ++++ ports/esp32/modnetwork.h | 2 +- ports/esp32/network_lan.c | 8 ++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ports/esp32/modnetwork.c b/ports/esp32/modnetwork.c index 3ebba2ade9..3f56fcfae2 100644 --- a/ports/esp32/modnetwork.c +++ b/ports/esp32/modnetwork.c @@ -270,6 +270,10 @@ STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { // PHY_KSZ8041 is new in ESP-IDF v4.3 { MP_ROM_QSTR(MP_QSTR_PHY_KSZ8041), MP_ROM_INT(PHY_KSZ8041) }, #endif + #if ESP_IDF_VERSION_MINOR >= 4 + // PHY_KSZ8081 is new in ESP-IDF v4.4 + { MP_ROM_QSTR(MP_QSTR_PHY_KSZ8081), MP_ROM_INT(PHY_KSZ8081) }, + #endif #if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL { MP_ROM_QSTR(MP_QSTR_PHY_KSZ8851SNL), MP_ROM_INT(PHY_KSZ8851SNL) }, diff --git a/ports/esp32/modnetwork.h b/ports/esp32/modnetwork.h index 49bbd9c496..d90679fa8a 100644 --- a/ports/esp32/modnetwork.h +++ b/ports/esp32/modnetwork.h @@ -28,7 +28,7 @@ #include "esp_event.h" -enum { PHY_LAN8710, PHY_LAN8720, PHY_IP101, PHY_RTL8201, PHY_DP83848, PHY_KSZ8041, PHY_KSZ8851SNL = 100, PHY_DM9051, PHY_W5500 }; +enum { PHY_LAN8710, PHY_LAN8720, PHY_IP101, PHY_RTL8201, PHY_DP83848, PHY_KSZ8041, PHY_KSZ8081, PHY_KSZ8851SNL = 100, PHY_DM9051, PHY_W5500 }; #define IS_SPI_PHY(NUM) (NUM >= 100) enum { ETH_INITIALIZED, ETH_STARTED, ETH_STOPPED, ETH_CONNECTED, ETH_DISCONNECTED, ETH_GOT_IP }; diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c index d482f95064..d4d630e345 100644 --- a/ports/esp32/network_lan.c +++ b/ports/esp32/network_lan.c @@ -150,6 +150,9 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar #if ESP_IDF_VERSION_MINOR >= 3 // KSZ8041 is new in ESP-IDF v4.3 args[ARG_phy_type].u_int != PHY_KSZ8041 && #endif + #if ESP_IDF_VERSION_MINOR >= 4 // KSZ8081 is new in ESP-IDF v4.4 + args[ARG_phy_type].u_int != PHY_KSZ8081 && + #endif #if CONFIG_ETH_USE_SPI_ETHERNET #if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL args[ARG_phy_type].u_int != PHY_KSZ8851SNL && @@ -237,6 +240,11 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar self->phy = esp_eth_phy_new_ksz8041(&phy_config); break; #endif + #if ESP_IDF_VERSION_MINOR >= 4 // KSZ8081 is new in ESP-IDF v4.4 + case PHY_KSZ8081: + self->phy = esp_eth_phy_new_ksz8081(&phy_config); + break; + #endif #endif #if CONFIG_ETH_USE_SPI_ETHERNET #if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL From d6bc34a13aa734d8b32e5768c021377ac4815029 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 19 Jan 2023 12:42:09 +0100 Subject: [PATCH 43/59] esp32: Add a small delay before leaving wlan.active(). The delay is 1 ms. It avoids the crashes reported by the issues #8289, #8792 and #9236 with esp-idf versions >= 4.2, but does not solve an underlying problem in the esp-idf. --- ports/esp32/network_wlan.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ports/esp32/network_wlan.c b/ports/esp32/network_wlan.c index f0b458e6dd..e4b34b2204 100644 --- a/ports/esp32/network_wlan.c +++ b/ports/esp32/network_wlan.c @@ -35,6 +35,7 @@ #include "py/objlist.h" #include "py/runtime.h" +#include "py/mphal.h" #include "modnetwork.h" #include "esp_wifi.h" @@ -210,6 +211,12 @@ STATIC mp_obj_t network_wlan_active(size_t n_args, const mp_obj_t *args) { wifi_started = true; } } + // This delay is a band-aid patch for issues #8289, #8792 and #9236, + // allowing the esp data structures to settle. It looks like some + // kind of race condition, which is not yet found. But at least + // this small delay seems not hurt much, since wlan.active() is + // usually not called in a time critical part of the code. + mp_hal_delay_ms(1); } return (mode & bit) ? mp_const_true : mp_const_false; From 5c4153ea379550bf595bf0bfa0e3711afea17aa0 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Sun, 7 Aug 2022 16:24:37 +1000 Subject: [PATCH 44/59] py/objarray: Raise error on out-of-bound memoryview slice start. 32-bit platforms only support a slice offset start of 24 bit max due to the limited size of the mp_obj_array_t.free member. Similarly on 64-bit platforms the limit is 56 bits. This commit adds an OverflowError if the user attempts to slice a memoryview beyond this limit. Signed-off-by: Damien George --- py/objarray.c | 4 ++++ py/objarray.h | 5 ++++- tests/basics/memoryview_slice_size.py | 27 +++++++++++++++++++++++ tests/basics/memoryview_slice_size.py.exp | 2 ++ 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 tests/basics/memoryview_slice_size.py create mode 100644 tests/basics/memoryview_slice_size.py.exp diff --git a/py/objarray.c b/py/objarray.c index c660705389..0d9411d7c4 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -53,6 +53,7 @@ #if MICROPY_PY_BUILTINS_MEMORYVIEW #define TYPECODE_MASK (0x7f) #define memview_offset free +#define memview_offset_max ((1LL << MP_OBJ_ARRAY_FREE_SIZE_BITS) - 1) #else // make (& TYPECODE_MASK) a null operation if memorview not enabled #define TYPECODE_MASK (~(size_t)0) @@ -522,6 +523,9 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value assert(sz > 0); #if MICROPY_PY_BUILTINS_MEMORYVIEW if (o->base.type == &mp_type_memoryview) { + if (slice.start > memview_offset_max) { + mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("memoryview offset too large")); + } res = m_new_obj(mp_obj_array_t); *res = *o; res->memview_offset += slice.start; diff --git a/py/objarray.h b/py/objarray.h index 48a26c3fb3..4a0e8a983f 100644 --- a/py/objarray.h +++ b/py/objarray.h @@ -32,6 +32,9 @@ // Used only for memoryview types, set in "typecode" to indicate a writable memoryview #define MP_OBJ_ARRAY_TYPECODE_FLAG_RW (0x80) +// Bit size used for mp_obj_array_t.free member. +#define MP_OBJ_ARRAY_FREE_SIZE_BITS (8 * sizeof(size_t) - 8) + // This structure is used for all of bytearray, array.array, memoryview // objects. Note that memoryview has different meaning for some fields, // see comment at the beginning of objarray.c. @@ -44,7 +47,7 @@ typedef struct _mp_obj_array_t { // parent object. (Union is not used to not go into a complication of // union-of-bitfields with different toolchains). See comments in // objarray.c. - size_t free : (8 * sizeof(size_t) - 8); + size_t free : MP_OBJ_ARRAY_FREE_SIZE_BITS; size_t len; // in elements void *items; } mp_obj_array_t; diff --git a/tests/basics/memoryview_slice_size.py b/tests/basics/memoryview_slice_size.py new file mode 100644 index 0000000000..c56514d21f --- /dev/null +++ b/tests/basics/memoryview_slice_size.py @@ -0,0 +1,27 @@ +# test memoryview slicing beyond the limit of what memoryview can internally index + +try: + from sys import maxsize + from uctypes import bytearray_at + + memoryview +except: + print("SKIP") + raise SystemExit + +if maxsize <= 0xFFFF_FFFF: + slice_max = 0xFF_FFFF +else: + slice_max = 0xFF_FFFF_FFFF_FFFF + +buf = bytearray_at(0, slice_max + 2) +mv = memoryview(buf) + +# this should work +print(mv[slice_max : slice_max + 1]) + +# this should overflow the internal index for memoryview slicing +try: + print(mv[slice_max + 1 : slice_max + 2]) +except OverflowError: + print("OverflowError") diff --git a/tests/basics/memoryview_slice_size.py.exp b/tests/basics/memoryview_slice_size.py.exp new file mode 100644 index 0000000000..34baadd35e --- /dev/null +++ b/tests/basics/memoryview_slice_size.py.exp @@ -0,0 +1,2 @@ + +OverflowError From fb8792c095802a9fcc8b38c1d8cbc3f641918433 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 19 Oct 2022 11:30:28 +1100 Subject: [PATCH 45/59] py/lexer: Wrap in parenthesis all f-string arguments passed to format. This is important for literal tuples, e.g. f"{a,b,}, {c}" --> "{}".format((a,b), (c),) which would otherwise result in either a syntax error or the wrong result. Fixes issue #9635. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared --- py/lexer.c | 7 ++++++- tests/basics/string_fstring.py | 5 +++++ tests/basics/string_fstring_debug.py | 4 ++++ tests/basics/string_fstring_debug.py.exp | 3 +++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/py/lexer.c b/py/lexer.c index 39e9662f63..e7d0e81440 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -356,6 +356,9 @@ STATIC void parse_string_literal(mp_lexer_t *lex, bool is_raw, bool is_fstring) vstr_add_byte(&lex->vstr, '{'); next_char(lex); } else { + // wrap each argument in (), e.g. + // f"{a,b,}, {c}" --> "{}".format((a,b), (c),) + vstr_add_byte(&lex->fstring_args, '('); // remember the start of this argument (if we need it for f'{a=}'). size_t i = lex->fstring_args.len; // extract characters inside the { until we reach the @@ -382,7 +385,9 @@ STATIC void parse_string_literal(mp_lexer_t *lex, bool is_raw, bool is_fstring) // remove the trailing '=' lex->fstring_args.len--; } - // comma-separate args + // close the paren-wrapped arg to .format(). + vstr_add_byte(&lex->fstring_args, ')'); + // comma-separate args to .format(). vstr_add_byte(&lex->fstring_args, ','); } vstr_add_byte(&lex->vstr, '{'); diff --git a/tests/basics/string_fstring.py b/tests/basics/string_fstring.py index 7e8a97fd30..8907a5c478 100644 --- a/tests/basics/string_fstring.py +++ b/tests/basics/string_fstring.py @@ -56,3 +56,8 @@ try: except (ValueError, SyntaxError): # MicroPython incorrectly raises ValueError here. print('SyntaxError') + +# Allow literal tuples +print(f"a {1,} b") +print(f"a {x,y,} b") +print(f"a {x,1} b") diff --git a/tests/basics/string_fstring_debug.py b/tests/basics/string_fstring_debug.py index 76a448ca06..95abd4d6d0 100644 --- a/tests/basics/string_fstring_debug.py +++ b/tests/basics/string_fstring_debug.py @@ -21,3 +21,7 @@ print(f"a {x=:08x} b {y} c") print(f'a {f() + g("foo") + h()=} b') print(f'a {f() + g("foo") + h()=:08x} b') + +print(f"a {1,=} b") +print(f"a {x,y,=} b") +print(f"a {x,1=} b") diff --git a/tests/basics/string_fstring_debug.py.exp b/tests/basics/string_fstring_debug.py.exp index 563030f400..f0309e1c98 100644 --- a/tests/basics/string_fstring_debug.py.exp +++ b/tests/basics/string_fstring_debug.py.exp @@ -4,3 +4,6 @@ a x=1 b 2 c a x=00000001 b 2 c a f() + g("foo") + h()=15 b a f() + g("foo") + h()=0000000f b +a 1,=(1,) b +a x,y,=(1, 2) b +a x,1=(1, 1) b From 94ee1b629a18429a92fc0475e7318c6a48dabd2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=9D=83=E4=B8=80=E5=8F=A5=E4=B8=A4=E5=8F=A5?= Date: Sat, 22 Oct 2022 14:05:25 +0800 Subject: [PATCH 46/59] unix/main: Free pathbuf when there's an error opening a file. --- ports/unix/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/unix/main.c b/ports/unix/main.c index 7920db02f2..d6ae1e611b 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -699,6 +699,7 @@ MP_NOINLINE int main_(int argc, char **argv) { char *basedir = realpath(argv[a], pathbuf); if (basedir == NULL) { mp_printf(&mp_stderr_print, "%s: can't open file '%s': [Errno %d] %s\n", argv[0], argv[a], errno, strerror(errno)); + free(pathbuf); // CPython exits with 2 in such case ret = 2; break; From abaa4abd2d5d43eb812301ab7f0fcaa9c93c18c2 Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Thu, 19 Jan 2023 12:09:39 +0100 Subject: [PATCH 47/59] py: Add parenthesis to default impl of MP_OBJ_TO_PTR, MP_OBJ_FROM_PTR. Unless MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D, these macros only work with values and "->"/"." expressions as their sole argument. In other words, the macros are broken with expressions which contain operations of lower precedence than the cast operator. Depending on situation, the old code either results in compiler error: MP_OBJ_TO_PTR(flag ? o1 : o2) expands into "(void *)flag ? o1 : o2", which some compiler configurations will reject (e.g. GCC -Wint-conversion -Wint-to-pointer-cast -Werror) Or in an incorrect address calculation: For ptr declared as "uint8_t *" the MP_OBJ_FROM_PTR(ptr + off) expands into ((mp_obj_t)ptr) + off, resulting in an obviously wrong address. Signed-off-by: Alex Riesen --- py/obj.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/py/obj.h b/py/obj.h index cb9a6cc459..8a0a256708 100644 --- a/py/obj.h +++ b/py/obj.h @@ -313,12 +313,12 @@ typedef union _mp_rom_obj_t { // Cast mp_obj_t to object pointer #ifndef MP_OBJ_TO_PTR -#define MP_OBJ_TO_PTR(o) ((void *)o) +#define MP_OBJ_TO_PTR(o) ((void *)(o)) #endif // Cast object pointer to mp_obj_t #ifndef MP_OBJ_FROM_PTR -#define MP_OBJ_FROM_PTR(p) ((mp_obj_t)p) +#define MP_OBJ_FROM_PTR(p) ((mp_obj_t)(p)) #endif // Macros to create objects that are stored in ROM. From a8a1ad13916aa74fca30ad23061a5552935bf097 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 6 Oct 2022 11:14:13 +1100 Subject: [PATCH 48/59] embed: Add new "embed" port which builds a simple C package. Signed-off-by: Damien George --- ports/embed/README.md | 18 +++++ ports/embed/embed.mk | 65 +++++++++++++++ ports/embed/port/embed_util.c | 106 +++++++++++++++++++++++++ ports/embed/port/micropython_embed.h | 41 ++++++++++ ports/embed/port/mpconfigport_common.h | 38 +++++++++ ports/embed/port/mphalport.c | 33 ++++++++ ports/embed/port/mphalport.h | 2 + 7 files changed, 303 insertions(+) create mode 100644 ports/embed/README.md create mode 100644 ports/embed/embed.mk create mode 100644 ports/embed/port/embed_util.c create mode 100644 ports/embed/port/micropython_embed.h create mode 100644 ports/embed/port/mpconfigport_common.h create mode 100644 ports/embed/port/mphalport.c create mode 100644 ports/embed/port/mphalport.h diff --git a/ports/embed/README.md b/ports/embed/README.md new file mode 100644 index 0000000000..556cfc749d --- /dev/null +++ b/ports/embed/README.md @@ -0,0 +1,18 @@ +MicroPython embed port +====================== + +This is a port of MicroPython that outputs a set of .c and .h files for embedding +into a wider project. This port essentially targets the C language, instead of a +particular hardware architecture or platform. + +To use this port in a project there are three main steps: + +1. Provide configuration for the project via an `mpconfigport.h` file. + +2. Build this embed port against that configuration, using the provided `embed.mk`. + The output is a set of self-contained source files for building MicroPython. + These files can be placed outside this repository. + +3. Build the project. This requires compiling all .c files from the above step. + +See `examples/embedding` for an example. diff --git a/ports/embed/embed.mk b/ports/embed/embed.mk new file mode 100644 index 0000000000..7fb344d704 --- /dev/null +++ b/ports/embed/embed.mk @@ -0,0 +1,65 @@ +# This file is part of the MicroPython project, http://micropython.org/ +# The MIT License (MIT) +# Copyright (c) 2022-2023 Damien P. George +# +# This file is intended to be included by a Makefile in a custom project. + +# Set the build output directory for the generated files. +BUILD = build-embed + +# Include the core environment definitions; this will set $(TOP). +include $(MICROPYTHON_TOP)/py/mkenv.mk + +# Include py core make definitions. +include $(TOP)/py/py.mk + +# Set the location of the MicroPython embed port. +MICROPYTHON_EMBED_PORT = $(MICROPYTHON_TOP)/ports/embed + +# Set default makefile-level MicroPython feature configurations. +MICROPY_ROM_TEXT_COMPRESSION ?= 0 + +# Set CFLAGS for the MicroPython build. +CFLAGS += -I. -I$(TOP) -I$(BUILD) -I$(MICROPYTHON_EMBED_PORT) +CFLAGS += -Wall -Werror -std=c99 + +# Define the required generated header files. +GENHDR_OUTPUT = $(addprefix $(BUILD)/genhdr/, \ + moduledefs.h \ + mpversion.h \ + qstrdefs.generated.h \ + root_pointers.h \ + ) + +# Define the top-level target, the generated output files. +.PHONY: all +all: micropython-embed-package + +clean: clean-micropython-embed-package + +.PHONY: clean-micropython-embed-package +clean-micropython-embed-package: + $(RM) -rf $(PACKAGE_DIR) + +PACKAGE_DIR ?= micropython_embed +PACKAGE_DIR_LIST = $(addprefix $(PACKAGE_DIR)/,py extmod shared/runtime genhdr port) + +.PHONY: micropython-embed-package +micropython-embed-package: $(GENHDR_OUTPUT) + $(ECHO) "Generate micropython_embed output:" + $(Q)$(RM) -rf $(PACKAGE_DIR_LIST) + $(Q)$(MKDIR) -p $(PACKAGE_DIR_LIST) + $(ECHO) "- py" + $(Q)$(CP) $(TOP)/py/*.[ch] $(PACKAGE_DIR)/py + $(ECHO) "- extmod" + $(Q)$(CP) $(TOP)/extmod/moduplatform.h $(PACKAGE_DIR)/extmod + $(ECHO) "- shared" + $(Q)$(CP) $(TOP)/shared/runtime/gchelper.h $(PACKAGE_DIR)/shared/runtime + $(Q)$(CP) $(TOP)/shared/runtime/gchelper_generic.c $(PACKAGE_DIR)/shared/runtime + $(ECHO) "- genhdr" + $(Q)$(CP) $(GENHDR_OUTPUT) $(PACKAGE_DIR)/genhdr + $(ECHO) "- port" + $(Q)$(CP) $(MICROPYTHON_EMBED_PORT)/port/*.[ch] $(PACKAGE_DIR)/port + +# Include remaining core make rules. +include $(TOP)/py/mkrules.mk diff --git a/ports/embed/port/embed_util.c b/ports/embed/port/embed_util.c new file mode 100644 index 0000000000..a3850f3c0f --- /dev/null +++ b/ports/embed/port/embed_util.c @@ -0,0 +1,106 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022-2023 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include "py/compile.h" +#include "py/gc.h" +#include "py/persistentcode.h" +#include "py/runtime.h" +#include "py/stackctrl.h" +#include "shared/runtime/gchelper.h" +#include "port/micropython_embed.h" + +// Initialise the runtime. +void mp_embed_init(void *gc_heap, size_t gc_heap_size) { + mp_stack_ctrl_init(); + gc_init(gc_heap, (uint8_t *)gc_heap + gc_heap_size); + mp_init(); +} + +#if MICROPY_ENABLE_COMPILER +// Compile and execute the given source script (Python text). +void mp_embed_exec_str(const char *src) { + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + // Compile, parse and execute the given string. + mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); + qstr source_name = lex->source_name; + mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT); + mp_obj_t module_fun = mp_compile(&parse_tree, source_name, true); + mp_call_function_0(module_fun); + nlr_pop(); + } else { + // Uncaught exception: print it out. + mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); + } +} +#endif + +#if MICROPY_PERSISTENT_CODE_LOAD +void mp_embed_exec_mpy(const uint8_t *mpy, size_t len) { + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + // Execute the given .mpy data. + mp_module_context_t *ctx = m_new_obj(mp_module_context_t); + ctx->module.globals = mp_globals_get(); + mp_compiled_module_t cm = mp_raw_code_load_mem(mpy, len, ctx); + mp_obj_t f = mp_make_function_from_raw_code(cm.rc, ctx, MP_OBJ_NULL); + mp_call_function_0(f); + nlr_pop(); + } else { + // Uncaught exception: print it out. + mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); + } +} +#endif + +// Deinitialise the runtime. +void mp_embed_deinit(void) { + mp_deinit(); +} + +#if MICROPY_ENABLE_GC +// Run a garbage collection cycle. +void gc_collect(void) { + gc_collect_start(); + gc_helper_collect_regs_and_stack(); + gc_collect_end(); +} +#endif + +// Called if an exception is raised outside all C exception-catching handlers. +void nlr_jump_fail(void *val) { + for (;;) { + } +} + +#ifndef NDEBUG +// Used when debugging is enabled. +void __assert_func(const char *file, int line, const char *func, const char *expr) { + for (;;) { + } +} +#endif diff --git a/ports/embed/port/micropython_embed.h b/ports/embed/port/micropython_embed.h new file mode 100644 index 0000000000..bf55d9b2b4 --- /dev/null +++ b/ports/embed/port/micropython_embed.h @@ -0,0 +1,41 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022-2023 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_MICROPYTHON_EMBED_H +#define MICROPY_INCLUDED_MICROPYTHON_EMBED_H + +#include +#include + +void mp_embed_init(void *gc_heap, size_t gc_heap_size); +void mp_embed_deinit(void); + +// Only available if MICROPY_ENABLE_COMPILER is enabled. +void mp_embed_exec_str(const char *src); + +// Only available if MICROPY_PERSISTENT_CODE_LOAD is enabled. +void mp_embed_exec_mpy(const uint8_t *mpy, size_t len); + +#endif // MICROPY_INCLUDED_MICROPYTHON_EMBED_H diff --git a/ports/embed/port/mpconfigport_common.h b/ports/embed/port/mpconfigport_common.h new file mode 100644 index 0000000000..69216a7582 --- /dev/null +++ b/ports/embed/port/mpconfigport_common.h @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022-2023 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +// Type definitions for the specific machine + +typedef intptr_t mp_int_t; // must be pointer size +typedef uintptr_t mp_uint_t; // must be pointer size +typedef long mp_off_t; + +// Need to provide a declaration/definition of alloca() +#include + +#define MICROPY_MPHALPORT_H "port/mphalport.h" diff --git a/ports/embed/port/mphalport.c b/ports/embed/port/mphalport.c new file mode 100644 index 0000000000..8e76a8e22e --- /dev/null +++ b/ports/embed/port/mphalport.c @@ -0,0 +1,33 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022-2023 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include "py/mphal.h" + +// Send string of given length to stdout, converting \n to \r\n. +void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { + printf("%.*s", (int)len, str); +} diff --git a/ports/embed/port/mphalport.h b/ports/embed/port/mphalport.h new file mode 100644 index 0000000000..49928e154d --- /dev/null +++ b/ports/embed/port/mphalport.h @@ -0,0 +1,2 @@ +// Define so there's no dependency on extmod/virtpin.h +#define mp_hal_pin_obj_t From 4f3780a156e1ba3f6981ab3a90be655a718f88f5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 6 Oct 2022 11:14:58 +1100 Subject: [PATCH 49/59] examples/embedding: Rework example to use ports/embed. Signed-off-by: Damien George --- .github/workflows/examples.yml | 4 +- examples/embedding/Makefile | 29 +++- examples/embedding/Makefile.upylib | 184 ---------------------- examples/embedding/README.md | 66 +++----- examples/embedding/hello-embed.c | 76 --------- examples/embedding/main.c | 44 ++++++ examples/embedding/micropython_embed.mk | 9 ++ examples/embedding/mpconfigport.h | 16 +- examples/embedding/mpconfigport_minimal.h | 122 -------------- 9 files changed, 111 insertions(+), 439 deletions(-) delete mode 100644 examples/embedding/Makefile.upylib delete mode 100644 examples/embedding/hello-embed.c create mode 100644 examples/embedding/main.c create mode 100644 examples/embedding/micropython_embed.mk delete mode 100644 examples/embedding/mpconfigport_minimal.h diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index e4105e8d43..450805a6bd 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -20,6 +20,6 @@ jobs: steps: - uses: actions/checkout@v3 - name: Build - run: make -C examples/embedding + run: make -C examples/embedding -f micropython_embed.mk && make -C examples/embedding - name: Run - run: test "$(./examples/embedding/hello-embed)" = "Hello world of easy embedding!" + run: ./examples/embedding/embed | grep "hello world" diff --git a/examples/embedding/Makefile b/examples/embedding/Makefile index edaa577f57..13bfdf1239 100644 --- a/examples/embedding/Makefile +++ b/examples/embedding/Makefile @@ -1,8 +1,25 @@ -MPTOP = ../.. -CFLAGS += -std=c99 -I. -I$(MPTOP) -DNO_QSTR -LDFLAGS += -L./build +# This file is part of the MicroPython project, http://micropython.org/ +# The MIT License (MIT) +# Copyright (c) 2022-2023 Damien P. George +# +# This is a very simple makefile that demonstrates how to build the embed port. +# All it needs to do is build all *.c files in the micropython_embed directory. +# This makefile would be replaced with your custom build system. -hello-embed: hello-embed.o -lmicropython +EMBED_DIR = micropython_embed +PROG = embed --lmicropython: - $(MAKE) -f $(MPTOP)/examples/embedding/Makefile.upylib MPTOP=$(MPTOP) +CFLAGS += -I. +CFLAGS += -I$(EMBED_DIR) +CFLAGS += -I$(EMBED_DIR)/port +CFLAGS += -Wall -Og + +SRC += main.c +SRC += $(wildcard $(EMBED_DIR)/*/*.c) $(wildcard $(EMBED_DIR)/*/*/*.c) +OBJ += $(SRC:.c=.o) + +$(PROG): $(OBJ) + $(CC) -o $@ $^ + +clean: + /bin/rm -f $(OBJ) $(PROG) diff --git a/examples/embedding/Makefile.upylib b/examples/embedding/Makefile.upylib deleted file mode 100644 index 99ce94b7ad..0000000000 --- a/examples/embedding/Makefile.upylib +++ /dev/null @@ -1,184 +0,0 @@ -MPTOP = ../.. --include mpconfigport.mk -include $(MPTOP)/py/mkenv.mk - -all: lib - -# OS name, for simple autoconfig -UNAME_S := $(shell uname -s) - -# include py core make definitions -include $(MPTOP)/py/py.mk -include $(MPTOP)/extmod/extmod.mk - -INC += -I. -INC += -I.. -INC += -I$(MPTOP) -INC += -I$(MPTOP)/ports/unix -INC += -I$(BUILD) - -# compiler settings -CWARN = -Wall -Werror -CWARN += -Wpointer-arith -Wuninitialized -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 - -# Debugging/Optimization -ifdef DEBUG -CFLAGS += -g -COPT = -O0 -else -COPT = -Os #-DNDEBUG -# _FORTIFY_SOURCE is a feature in gcc/glibc which is intended to provide extra -# security for detecting buffer overflows. Some distros (Ubuntu at the very least) -# have it enabled by default. -# -# gcc already optimizes some printf calls to call puts and/or putchar. When -# _FORTIFY_SOURCE is enabled and compiling with -O1 or greater, then some -# printf calls will also be optimized to call __printf_chk (in glibc). Any -# printfs which get redirected to __printf_chk are then no longer synchronized -# with printfs that go through mp_printf. -# -# In MicroPython, we don't want to use the runtime library's printf but rather -# go through mp_printf, so that stdout is properly tied into streams, etc. -# This means that we either need to turn off _FORTIFY_SOURCE or provide our -# own implementation of __printf_chk. We've chosen to turn off _FORTIFY_SOURCE. -# It should also be noted that the use of printf in MicroPython is typically -# quite limited anyways (primarily for debug and some error reporting, etc -# in the unix version). -# -# Information about _FORTIFY_SOURCE seems to be rather scarce. The best I could -# find was this: https://securityblog.redhat.com/2014/03/26/fortify-and-you/ -# Original patchset was introduced by -# https://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html . -# -# Turning off _FORTIFY_SOURCE is only required when compiling with -O1 or greater -CFLAGS += -U _FORTIFY_SOURCE -endif - -# On OSX, 'gcc' is a symlink to clang unless a real gcc is installed. -# The unix port of MicroPython on OSX must be compiled with clang, -# while cross-compile ports require gcc, so we test here for OSX and -# if necessary override the value of 'CC' set in py/mkenv.mk -ifeq ($(UNAME_S),Darwin) -CC = clang -# Use clang syntax for map file -LDFLAGS_ARCH = -Wl,-map,$@.map -else -# Use gcc syntax for map file -LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref -endif -LDFLAGS += $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA) - -ifeq ($(MICROPY_FORCE_32BIT),1) -# Note: you may need to install i386 versions of dependency packages, -# starting with linux-libc-dev:i386 -ifeq ($(MICROPY_PY_FFI),1) -ifeq ($(UNAME_S),Linux) -CFLAGS_MOD += -I/usr/include/i686-linux-gnu -endif -endif -endif - -ifeq ($(MICROPY_USE_READLINE),1) -INC += -I$(MPTOP)/shared/readline -CFLAGS_MOD += -DMICROPY_USE_READLINE=1 -SHARED_SRC_C_EXTRA += readline/readline.c -endif -ifeq ($(MICROPY_USE_READLINE),2) -CFLAGS_MOD += -DMICROPY_USE_READLINE=2 -LDFLAGS_MOD += -lreadline -# the following is needed for BSD -#LDFLAGS_MOD += -ltermcap -endif -ifeq ($(MICROPY_PY_TIME),1) -CFLAGS_MOD += -DMICROPY_PY_TIME=1 -SRC_MOD += modtime.c -endif -ifeq ($(MICROPY_PY_TERMIOS),1) -CFLAGS_MOD += -DMICROPY_PY_TERMIOS=1 -SRC_MOD += modtermios.c -endif -ifeq ($(MICROPY_PY_SOCKET),1) -CFLAGS_MOD += -DMICROPY_PY_SOCKET=1 -SRC_MOD += modsocket.c -endif - -ifeq ($(MICROPY_PY_FFI),1) - -ifeq ($(MICROPY_STANDALONE),1) -LIBFFI_CFLAGS_MOD := -I$(shell ls -1d $(MPTOP)/lib/libffi/build_dir/out/lib/libffi-*/include) - ifeq ($(MICROPY_FORCE_32BIT),1) - LIBFFI_LDFLAGS_MOD = $(MPTOP)/lib/libffi/build_dir/out/lib32/libffi.a - else - LIBFFI_LDFLAGS_MOD = $(MPTOP)/lib/libffi/build_dir/out/lib/libffi.a - endif -else -LIBFFI_CFLAGS_MOD := $(shell pkg-config --cflags libffi) -LIBFFI_LDFLAGS_MOD := $(shell pkg-config --libs libffi) -endif - -ifeq ($(UNAME_S),Linux) -LIBFFI_LDFLAGS_MOD += -ldl -endif - -CFLAGS_MOD += $(LIBFFI_CFLAGS_MOD) -DMICROPY_PY_FFI=1 -LDFLAGS_MOD += $(LIBFFI_LDFLAGS_MOD) -SRC_MOD += modffi.c -endif - -MAIN_C = main.c - -# source files -SRC_C = $(addprefix ports/unix/,\ - $(MAIN_C) \ - gccollect.c \ - unix_mphal.c \ - input.c \ - modmachine.c \ - moduselect.c \ - alloc.c \ - coverage.c \ - fatfs_port.c \ - $(SRC_MOD) \ - ) - -SHARED_SRC_C = $(addprefix shared/,\ - libc/printf.c \ - runtime/gchelper_generic.c \ - timeutils/timeutils.c \ - $(SHARED_SRC_C_EXTRA) \ - ) - -OBJ = $(PY_O) -OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o)) - -# List of sources for qstr extraction -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 += - -include $(MPTOP)/py/mkrules.mk - -# Value of configure's --host= option (required for cross-compilation). -# Deduce it from CROSS_COMPILE by default, but can be overridden. -ifneq ($(CROSS_COMPILE),) -CROSS_COMPILE_HOST = --host=$(patsubst %-,%,$(CROSS_COMPILE)) -else -CROSS_COMPILE_HOST = -endif - -deplibs: libffi - -# install-exec-recursive & install-data-am targets are used to avoid building -# docs and depending on makeinfo -libffi: - cd $(MPTOP)/lib/libffi; git clean -d -x -f - cd $(MPTOP)/lib/libffi; ./autogen.sh - 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 diff --git a/examples/embedding/README.md b/examples/embedding/README.md index 0dfc52e1dc..e3683acdc2 100644 --- a/examples/embedding/README.md +++ b/examples/embedding/README.md @@ -1,67 +1,37 @@ Example of embedding MicroPython in a standalone C application ============================================================== -This directory contains a (very simple!) example of how to embed a MicroPython -in an existing C application. - -A C application is represented by the file `hello-embed.c`. It executes a simple -Python statement which prints to the standard output. +This directory contains a simple example of how to embed MicroPython in an +existing C application. +A C application is represented here by the file `main.c`. It executes two +simple Python scripts which print things to the standard output. Building the example -------------------- -Building the example is as simple as running: +First build the embed port using: - make + $ make -f micropython_embed.mk -It's worth to trace what's happening behind the scenes though: +This will generate the `micropython_embed` directory which is a self-contained +copy of MicroPython suitable for embedding. The .c files in this directory need +to be compiled into your project, in whatever way your project can do that. The +example here uses make and a provided `Makefile`. -1. As a first step, a MicroPython library is built. This is handled by a -separate makefile, `Makefile.upylib`. It is more or less complex, but the -good news is that you won't need to change anything in it, just use it -as is, the main `Makefile` shows how. What may require editing though is -a MicroPython configuration file. MicroPython is highly configurable, so -you would need to build a library suiting your application well, while -not bloating its size. Check the options in the file `mpconfigport.h`. -Included is a copy of the "minimal" Unix port, which should be a good start -for minimal embedding. For the list of all available options, see -`py/mpconfig.h`. +To build the example project, based on `main.c`, use: -2. Once the MicroPython library is built, your application is compiled -and linked it. The main Makefile is very simple and shows that the changes -you would need to do to your application's `Makefile` (or other build -configuration) are also simple: + $ make -a) You would need to use C99 standard (you're using this 15+ years old -standard already, not a 25+ years old one, right?). - -b) You need to provide a path to MicroPython's top-level dir, for includes. - -c) You need to include `-DNO_QSTR` compile-time flag. - -d) Otherwise, just link with the MicroPython library produced in step 1. +That will create an exacutable called `embed` which you can run: + $ ./embed Out of tree build ----------------- This example is set up to work out of the box, being part of the MicroPython -tree. Your application of course will be outside of its tree, but the -only thing you need to do is to pass `MPTOP` variable pointing to -MicroPython directory to both Makefiles (in this example, the main Makefile -automatically passes it to `Makefile.upylib`; in your own Makefile, don't forget -to use a suitable value). - -A practical way to embed MicroPython in your application is to include it -as a git submodule. Suppose you included it as `libs/micropython`. Then in -your main Makefile you would have something like: - -~~~ -MPTOP = libs/micropython - -my_app: $(MY_OBJS) -lmicropython - --lmicropython: - $(MAKE) -f $(MPTOP)/examples/embedding/Makefile.upylib MPTOP=$(MPTOP) -~~~ +tree. Your application will be outside of this tree, but the only thing you +need to do for that is to change `MICROPYTHON_TOP` (found in `micropython_embed.mk`) +to point to the location of the MicroPython repository. The MicroPython +repository may, for example, be a git submodule in your project. diff --git a/examples/embedding/hello-embed.c b/examples/embedding/hello-embed.c deleted file mode 100644 index 0b778986b3..0000000000 --- a/examples/embedding/hello-embed.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Paul Sokolovsky - * - * 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/builtin.h" -#include "py/compile.h" -#include "py/runtime.h" -#include "py/gc.h" -#include "py/stackctrl.h" - -static char heap[16384]; - -mp_obj_t execute_from_str(const char *str) { - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - qstr src_name = 1/*MP_QSTR_*/; - mp_lexer_t *lex = mp_lexer_new_from_str_len(src_name, str, strlen(str), false); - mp_parse_tree_t pt = mp_parse(lex, MP_PARSE_FILE_INPUT); - mp_obj_t module_fun = mp_compile(&pt, src_name, false); - mp_call_function_0(module_fun); - nlr_pop(); - return 0; - } else { - // uncaught exception - return (mp_obj_t)nlr.ret_val; - } -} - -int main() { - // Initialized stack limit - mp_stack_set_limit(40000 * (sizeof(void *) / 4)); - // Initialize heap - gc_init(heap, heap + sizeof(heap)); - // Initialize interpreter - mp_init(); - - const char str[] = "print('Hello world of easy embedding!')"; - if (execute_from_str(str)) { - printf("Error\n"); - } -} - -uint mp_import_stat(const char *path) { - return MP_IMPORT_STAT_NO_EXIST; -} - -void nlr_jump_fail(void *val) { - printf("FATAL: uncaught NLR %p\n", val); - exit(1); -} diff --git a/examples/embedding/main.c b/examples/embedding/main.c new file mode 100644 index 0000000000..ee673fc93a --- /dev/null +++ b/examples/embedding/main.c @@ -0,0 +1,44 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2022-2023 Damien P. George + */ + +#include "port/micropython_embed.h" + +// This is example 1 script, which will be compiled and executed. +static const char *example_1 = + "print('hello world!', list(x + 1 for x in range(10)), end='eol\\n')"; + +// This is example 2 script, which will be compiled and executed. +static const char *example_2 = + "for i in range(10):\n" + " print('iter {:08}'.format(i))\n" + "\n" + "try:\n" + " 1//0\n" + "except Exception as er:\n" + " print('caught exception', repr(er))\n" + "\n" + "import gc\n" + "print('run GC collect')\n" + "gc.collect()\n" + "\n" + "print('finish')\n" + ; + +// This array is the MicroPython GC heap. +static char heap[8 * 1024]; + +int main() { + // Initialise MicroPython. + mp_embed_init(&heap[0], sizeof(heap)); + + // Run the example scripts (they will be compiled first). + mp_embed_exec_str(example_1); + mp_embed_exec_str(example_2); + + // Deinitialise MicroPython. + mp_embed_deinit(); + + return 0; +} diff --git a/examples/embedding/micropython_embed.mk b/examples/embedding/micropython_embed.mk new file mode 100644 index 0000000000..5db5415927 --- /dev/null +++ b/examples/embedding/micropython_embed.mk @@ -0,0 +1,9 @@ +# This file is part of the MicroPython project, http://micropython.org/ +# The MIT License (MIT) +# Copyright (c) 2022-2023 Damien P. George + +# Set the location of the top of the MicroPython repository. +MICROPYTHON_TOP = ../.. + +# Include the main makefile fragment to build the MicroPython component. +include $(MICROPYTHON_TOP)/ports/embed/embed.mk diff --git a/examples/embedding/mpconfigport.h b/examples/embedding/mpconfigport.h index 89c180b2a8..ed34a5d766 100644 --- a/examples/embedding/mpconfigport.h +++ b/examples/embedding/mpconfigport.h @@ -1 +1,15 @@ -#include "mpconfigport_minimal.h" +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2022-2023 Damien P. George + */ + +// Include common MicroPython embed configuration. +#include + +// Use the minimal starting configuration (disables all optional features). +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_MINIMUM) + +// MicroPython configuration. +#define MICROPY_ENABLE_COMPILER (1) +#define MICROPY_ENABLE_GC (1) +#define MICROPY_PY_GC (1) diff --git a/examples/embedding/mpconfigport_minimal.h b/examples/embedding/mpconfigport_minimal.h deleted file mode 100644 index 02089c1a62..0000000000 --- a/examples/embedding/mpconfigport_minimal.h +++ /dev/null @@ -1,122 +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_ALLOC_PATH_MAX (PATH_MAX) -#define MICROPY_ENABLE_GC (1) -#define MICROPY_ENABLE_FINALISER (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_KBD_EXCEPTION (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_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_CAN_OVERRIDE_BUILTINS (0) -#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0) -#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_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" -#define MICROPY_PY_SYS_MAXSIZE (0) -#define MICROPY_PY_SYS_PATH_DEFAULT ".frozen" -#define MICROPY_PY_SYS_STDFILES (0) -#define MICROPY_PY_CMATH (0) -#define MICROPY_PY_UCTYPES (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 -////////////////////////////////////////// - -#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 - -// 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 From d4a4cde42e80dc2c25c018af200e641b03999e19 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 22 Jan 2023 17:49:10 +0100 Subject: [PATCH 50/59] rp2: Fix crash in a pin.irq handler. When accessing the argument of the irq function. --- ports/rp2/machine_pin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/rp2/machine_pin.c b/ports/rp2/machine_pin.c index 3de2eaaed8..3c7cd86eea 100644 --- a/ports/rp2/machine_pin.c +++ b/ports/rp2/machine_pin.c @@ -423,7 +423,7 @@ STATIC machine_pin_irq_obj_t *machine_pin_get_irq(mp_hal_pin_obj_t pin) { 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(&machine_pin_cpu_pins[pin]); + irq->base.parent = MP_OBJ_FROM_PTR(machine_pin_cpu_pins[pin]); irq->base.handler = mp_const_none; irq->base.ishard = false; MP_STATE_PORT(machine_pin_irq_obj[pin]) = irq; From d387ae3444751a3ba1032bd16243cb2dc741e333 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 23 Jan 2023 12:24:39 +1100 Subject: [PATCH 51/59] py/objint_mpz: Catch and reject @ and @= operating on big integers. This will also catch / and /= when float support is disabled. Fixes issue #10544. Signed-off-by: Damien George --- py/objint_mpz.c | 6 ++++-- tests/basics/int_big_error.py | 10 ++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 2811bcf2aa..e9545149f8 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -296,8 +296,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_pow_inpl(&res->mpz, zlhs, zrhs); break; - default: { - assert(op == MP_BINARY_OP_DIVMOD); + case MP_BINARY_OP_DIVMOD: { if (mpz_is_zero(zrhs)) { goto zero_division_error; } @@ -306,6 +305,9 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i mp_obj_t tuple[2] = {MP_OBJ_FROM_PTR(quo), MP_OBJ_FROM_PTR(res)}; return mp_obj_new_tuple(2, tuple); } + + default: + return MP_OBJ_NULL; // op not supported } return MP_OBJ_FROM_PTR(res); diff --git a/tests/basics/int_big_error.py b/tests/basics/int_big_error.py index 79809aef11..1793cf3253 100644 --- a/tests/basics/int_big_error.py +++ b/tests/basics/int_big_error.py @@ -7,6 +7,16 @@ try: except ValueError: print("ValueError") +try: + i @ 0 +except TypeError: + print("TypeError") + +try: + i @= 0 +except TypeError: + print("TypeError") + try: len(i) except TypeError: From 31139b437a05a9cf05608df11843aba3790184b9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 24 Jan 2023 16:55:23 +1100 Subject: [PATCH 52/59] py/mkrules: Support mpy-tool-flags in cmake frozen code generation. Signed-off-by: Damien George --- py/mkrules.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/mkrules.cmake b/py/mkrules.cmake index b29986585a..38bad80fdb 100644 --- a/py/mkrules.cmake +++ b/py/mkrules.cmake @@ -205,7 +205,7 @@ if(MICROPY_FROZEN_MANIFEST) add_custom_command( OUTPUT ${MICROPY_FROZEN_CONTENT} - 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} + 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} --mpy-tool-flags=${MICROPY_MPY_TOOL_FLAGS} ${MICROPY_FROZEN_MANIFEST} DEPENDS MICROPY_FORCE_BUILD ${MICROPY_QSTRDEFS_GENERATED} ${MICROPY_ROOT_POINTERS} From 1978b838b7b75d2e525771f95f3532cc623419ef Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 24 Jan 2023 16:57:26 +1100 Subject: [PATCH 53/59] shared/runtime: Use mp_printf consistently, instead of printf. Signed-off-by: Damien George --- shared/runtime/mpirq.c | 4 ++-- shared/runtime/pyexec.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/shared/runtime/mpirq.c b/shared/runtime/mpirq.c index f9a85ebbd6..acd727403b 100644 --- a/shared/runtime/mpirq.c +++ b/shared/runtime/mpirq.c @@ -81,8 +81,8 @@ void mp_irq_handler(mp_irq_obj_t *self) { // Uncaught exception; disable the callback so that it doesn't run again self->methods->trigger(self->parent, 0); self->handler = mp_const_none; - printf("Uncaught exception in IRQ callback handler\n"); - mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + mp_printf(MICROPY_ERROR_PRINTER, "Uncaught exception in IRQ callback handler\n"); + mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(nlr.ret_val)); } gc_unlock(); mp_sched_unlock(); diff --git a/shared/runtime/pyexec.c b/shared/runtime/pyexec.c index 2c9f1e80ff..b6e7d8fe68 100644 --- a/shared/runtime/pyexec.c +++ b/shared/runtime/pyexec.c @@ -154,12 +154,12 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input // display debugging info if wanted if ((exec_flags & EXEC_FLAG_ALLOW_DEBUGGING) && repl_display_debugging_info) { mp_uint_t ticks = mp_hal_ticks_ms() - start; // TODO implement a function that does this properly - printf("took " UINT_FMT " ms\n", ticks); + mp_printf(&mp_plat_print, "took " UINT_FMT " ms\n", ticks); // qstr info { size_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes; qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes); - printf("qstr:\n n_pool=%u\n n_qstr=%u\n " + mp_printf(&mp_plat_print, "qstr:\n n_pool=%u\n n_qstr=%u\n " "n_str_data_bytes=%u\n n_total_bytes=%u\n", (unsigned)n_pool, (unsigned)n_qstr, (unsigned)n_str_data_bytes, (unsigned)n_total_bytes); } @@ -713,7 +713,7 @@ int pyexec_frozen_module(const char *name) { #endif default: - printf("could not find module '%s'\n", name); + mp_printf(MICROPY_ERROR_PRINTER, "could not find module '%s'\n", name); return false; } } From 8a0353525f913f464b9b8a6f610661a0e8fb4fd1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 24 Jan 2023 16:58:29 +1100 Subject: [PATCH 54/59] rp2/main: Use mp_printf in nlr_jump_fail. The mp_plat_print output is already being used by the subsequent call to mp_obj_print_exception(). And this eliminates all references to printf for this port (at least in non-debug builds). Signed-off-by: Damien George --- ports/rp2/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/rp2/main.c b/ports/rp2/main.c index fdcdd90d4c..c5b5037491 100644 --- a/ports/rp2/main.c +++ b/ports/rp2/main.c @@ -234,7 +234,7 @@ void gc_collect(void) { } void nlr_jump_fail(void *val) { - printf("FATAL: uncaught exception %p\n", val); + mp_printf(&mp_plat_print, "FATAL: uncaught exception %p\n", val); mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(val)); for (;;) { __breakpoint(); From 67fac4ebc53db6337008ba06df7932faec80f57c Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 24 Jan 2023 17:29:45 +1100 Subject: [PATCH 55/59] rp2/machine_pin: Fix configuring OPEN_DRAIN with initial value. Prior to this commit, Pin(Pin.OPEN_DRAIN, value=0) would not set the initial value of the open-drain pin to low, instead it would be high. Signed-off-by: Damien George --- ports/rp2/machine_pin.c | 11 ++++++----- ports/rp2/mphalport.h | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/ports/rp2/machine_pin.c b/ports/rp2/machine_pin.c index 3c7cd86eea..71eda316da 100644 --- a/ports/rp2/machine_pin.c +++ b/ports/rp2/machine_pin.c @@ -236,13 +236,10 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_ mp_raise_ValueError("alternate functions are not supported for external pins"); } + // get initial value of pin (only valid for OUT and OPEN_DRAIN modes) int value = -1; if (args[ARG_value].u_obj != mp_const_none) { value = mp_obj_is_true(args[ARG_value].u_obj); - // set initial value (do this before configuring mode/pull) - if (!is_ext_pin(self)) { - gpio_put(self->id, value); - } } // configure mode @@ -257,9 +254,13 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_ } else if (mode == MACHINE_PIN_MODE_IN) { mp_hal_pin_input(self->id); } else if (mode == MACHINE_PIN_MODE_OUT) { + if (value != -1) { + // set initial output value before configuring mode + gpio_put(self->id, value); + } mp_hal_pin_output(self->id); } else if (mode == MACHINE_PIN_MODE_OPEN_DRAIN) { - mp_hal_pin_open_drain(self->id); + mp_hal_pin_open_drain_with_value(self->id, value == -1 ? 1 : value); } else { // Configure alternate function. mp_uint_t af = args[ARG_alt].u_int; diff --git a/ports/rp2/mphalport.h b/ports/rp2/mphalport.h index 2cb9121fa2..8b4a5b6093 100644 --- a/ports/rp2/mphalport.h +++ b/ports/rp2/mphalport.h @@ -102,13 +102,22 @@ static inline void mp_hal_pin_output(mp_hal_pin_obj_t pin) { gpio_set_function(pin, GPIO_FUNC_SIO); } -static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) { - gpio_set_dir(pin, GPIO_IN); - gpio_put(pin, 0); +static inline void mp_hal_pin_open_drain_with_value(mp_hal_pin_obj_t pin, int v) { + if (v) { + gpio_set_dir(pin, GPIO_IN); + gpio_put(pin, 0); + } else { + gpio_put(pin, 0); + gpio_set_dir(pin, GPIO_OUT); + } machine_pin_open_drain_mask |= 1 << pin; gpio_set_function(pin, GPIO_FUNC_SIO); } +static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) { + mp_hal_pin_open_drain_with_value(pin, 1); +} + 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); From be420bf9bbf8f8c9d73e2a3694a319c6b4e779ea Mon Sep 17 00:00:00 2001 From: Jay Greco Date: Tue, 20 Dec 2022 06:41:19 +0000 Subject: [PATCH 56/59] rp2/boards/NULLBITS_BIT_C_PRO: Add Bit-C PRO board. --- ports/rp2/boards/NULLBITS_BIT_C_PRO/README.md | 17 ++++ .../rp2/boards/NULLBITS_BIT_C_PRO/board.json | 20 ++++ ports/rp2/boards/NULLBITS_BIT_C_PRO/board.py | 7 ++ .../rp2/boards/NULLBITS_BIT_C_PRO/manifest.py | 2 + .../NULLBITS_BIT_C_PRO/mpconfigboard.cmake | 10 ++ .../boards/NULLBITS_BIT_C_PRO/mpconfigboard.h | 9 ++ .../NULLBITS_BIT_C_PRO/nullbits_bit_c_pro.h | 96 +++++++++++++++++++ ports/rp2/boards/NULLBITS_BIT_C_PRO/pins.csv | 4 + 8 files changed, 165 insertions(+) create mode 100644 ports/rp2/boards/NULLBITS_BIT_C_PRO/README.md create mode 100644 ports/rp2/boards/NULLBITS_BIT_C_PRO/board.json create mode 100644 ports/rp2/boards/NULLBITS_BIT_C_PRO/board.py create mode 100644 ports/rp2/boards/NULLBITS_BIT_C_PRO/manifest.py create mode 100644 ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.cmake create mode 100644 ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.h create mode 100644 ports/rp2/boards/NULLBITS_BIT_C_PRO/nullbits_bit_c_pro.h create mode 100644 ports/rp2/boards/NULLBITS_BIT_C_PRO/pins.csv diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/README.md b/ports/rp2/boards/NULLBITS_BIT_C_PRO/README.md new file mode 100644 index 0000000000..0849108413 --- /dev/null +++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/README.md @@ -0,0 +1,17 @@ +# nullbits Bit-C PRO + +The nullbits Bit-C PRO Board is based on the Raspberry Pi RP2040, and comes in the Arduino Pro Micro footprint. + + +## Board-specific modules + +The `board` module contains definitions for the onboard RGB LED. + +Example: + +```python +>>> import board +>>> board.led_red.on() +>>> board.led_green.on() +>>> board.led_blue.on() +``` diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/board.json b/ports/rp2/boards/NULLBITS_BIT_C_PRO/board.json new file mode 100644 index 0000000000..2aff0580d8 --- /dev/null +++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/board.json @@ -0,0 +1,20 @@ +{ + "deploy": [ + "../deploy.md" + ], + "docs": "", + "features": [ + "Breadboard Friendly", + "RGB LED", + "USB-C", + "SPI Flash" + ], + "images": [ + "nullbits_bit_c_pro.jpg" + ], + "mcu": "rp2040", + "product": "Bit-C PRO", + "thumbnail": "", + "url": "https://nullbits.co/bit-c-pro", + "vendor": "nullbits" +} diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/board.py b/ports/rp2/boards/NULLBITS_BIT_C_PRO/board.py new file mode 100644 index 0000000000..9ee8cc806f --- /dev/null +++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/board.py @@ -0,0 +1,7 @@ +from machine import Pin, Signal + +led_red = Signal("LED_RED", Pin.OUT, invert=True, value=0) +led_green = Signal("LED_GREEN", Pin.OUT, invert=True, value=0) +led_blue = Signal("LED_BLUE", Pin.OUT, invert=True, value=0) + +del Pin diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/manifest.py b/ports/rp2/boards/NULLBITS_BIT_C_PRO/manifest.py new file mode 100644 index 0000000000..3a6af47a16 --- /dev/null +++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/manifest.py @@ -0,0 +1,2 @@ +include("$(PORT_DIR)/boards/manifest.py") +module("board.py") diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.cmake b/ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.cmake new file mode 100644 index 0000000000..050ca347be --- /dev/null +++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.cmake @@ -0,0 +1,10 @@ +# cmake file for nullbits Bit-C PRO + +# The Bit-C PRO is not yet in upstream pico-sdk, so define it here +# See also: https://github.com/raspberrypi/pico-sdk/tree/master/src/boards/include/boards +list(APPEND PICO_BOARD_HEADER_DIRS ${MICROPY_BOARD_DIR}) + +set(PICO_BOARD "nullbits_bit_c_pro") + +# Freeze board.py +set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py) diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.h b/ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.h new file mode 100644 index 0000000000..e28c379fa7 --- /dev/null +++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.h @@ -0,0 +1,9 @@ +// https://nullbits.co/bit-c-pro + +#define MICROPY_HW_BOARD_NAME "nullbits Bit-C PRO" +#define MICROPY_HW_FLASH_STORAGE_BYTES (PICO_FLASH_SIZE_BYTES - (1 * 512 * 1024)) // 512K reserved + +// RGB LED, active low +// Red LED 16 +// Green LED 17 +// Blue LED 18 diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/nullbits_bit_c_pro.h b/ports/rp2/boards/NULLBITS_BIT_C_PRO/nullbits_bit_c_pro.h new file mode 100644 index 0000000000..2e8b03a430 --- /dev/null +++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/nullbits_bit_c_pro.h @@ -0,0 +1,96 @@ +// Board definition for the nullbits Bit-C PRO + +#ifndef _BOARDS_NULLBITS_BIT_C_PRO_H +#define _BOARDS_NULLBITS_BIT_C_PRO_H + +// For board detection +#define NULLBITS_BIT_C_PRO + +// On some samples, the xosc can take longer to stabilize than is usual +#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER +#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 +#endif + +// --- BOARD SPECIFIC --- +#define BIT_C_PRO_LED_R_PIN 16 +#define BIT_C_PRO_LED_G_PIN 17 +#define BIT_C_PRO_LED_B_PIN 18 + +// ------------- 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 --- +// Set the default LED to the Bit-C PRO's B led +#ifndef PICO_DEFAULT_LED_PIN +#define PICO_DEFAULT_LED_PIN BIT_C_PRO_LED_B_PIN +#endif + +#ifndef PICO_DEFAULT_LED_PIN_INVERTED +#define PICO_DEFAULT_LED_PIN_INVERTED 1 +#endif +// no PICO_DEFAULT_WS2812_PIN + +// ------------- I2C -------------// +#ifndef PICO_DEFAULT_I2C +#define PICO_DEFAULT_I2C 0 +#endif + +#ifndef PICO_DEFAULT_I2C_SDA_PIN +#define PICO_DEFAULT_I2C_SDA_PIN 2 +#endif + +#ifndef PICO_DEFAULT_I2C_SCL_PIN +#define PICO_DEFAULT_I2C_SCL_PIN 3 +#endif + +// ------------- SPI -------------// +#ifndef PICO_DEFAULT_SPI +#define PICO_DEFAULT_SPI 0 +#endif + +#ifndef PICO_DEFAULT_SPI_TX_PIN +#define PICO_DEFAULT_SPI_TX_PIN 23 +#endif + +#ifndef PICO_DEFAULT_SPI_RX_PIN +#define PICO_DEFAULT_SPI_RX_PIN 20 +#endif + +#ifndef PICO_DEFAULT_SPI_SCK_PIN +#define PICO_DEFAULT_SPI_SCK_PIN 22 +#endif + +#ifndef PICO_DEFAULT_SPI_CSN_PIN +#define PICO_DEFAULT_SPI_CSN_PIN 21 +#endif + +// ------------- FLASH -------------// + +// Best performance/compatibility with selected flash +#define PICO_BOOT_STAGE2_CHOOSE_W25X10CL 1 + +#ifndef PICO_FLASH_SPI_CLKDIV +#define PICO_FLASH_SPI_CLKDIV 2 +#endif + +// Bit-C PRO has 4MB SPI flash +#ifndef PICO_FLASH_SIZE_BYTES +#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024) +#endif + +// All boards have B1+ RP2040 +#ifndef PICO_RP2040_B0_SUPPORTED +#define PICO_RP2040_B0_SUPPORTED 0 +#endif + +#endif diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/pins.csv b/ports/rp2/boards/NULLBITS_BIT_C_PRO/pins.csv new file mode 100644 index 0000000000..1274effaef --- /dev/null +++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/pins.csv @@ -0,0 +1,4 @@ +LED,GPIO16 +LED_RED,GPIO16 +LED_GREEN,GPIO17 +LED_BLUE,GPIO18 From 0baf6c80d971b8d5c6b1d7b0648c0cb01cedc81d Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 23 Jan 2023 12:09:05 +0100 Subject: [PATCH 57/59] nrf/mpconfigport: Enable seeding of the PRNG by the hardware RNG. A suitable function already existed, so just the declaration was needed. --- ports/nrf/mpconfigport.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 27dbd3b584..629ba5e946 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -277,6 +277,11 @@ typedef int mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size typedef long mp_off_t; +#if MICROPY_HW_ENABLE_RNG +#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (rng_generate_random_word()) +long unsigned int rng_generate_random_word(void); +#endif + #if BOARD_SPECIFIC_MODULES #include "boardmodules.h" #endif // BOARD_SPECIFIC_MODULES From c2ab1b51859109738b01ecbddb0809bf538f18f6 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 24 Jan 2023 13:12:16 +0100 Subject: [PATCH 58/59] esp32/boards/OLIMEX_ESP32_POE: Remove id from and update board.json. --- ports/esp32/boards/OLIMEX_ESP32_POE/board.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/board.json b/ports/esp32/boards/OLIMEX_ESP32_POE/board.json index f3b1402bb1..84b6680d59 100644 --- a/ports/esp32/boards/OLIMEX_ESP32_POE/board.json +++ b/ports/esp32/boards/OLIMEX_ESP32_POE/board.json @@ -12,13 +12,12 @@ "PoE", "Breadboard friendly" ], - "id": "esp32", "images": [ "ESP32-POE-ISO-1.jpg" ], "mcu": "esp32", - "product": "ESP32", + "product": "Olimex ESP32 POE", "thumbnail": "", "url": "https://www.olimex.com/", - "vendor": "Olimex" + "vendor": "OLIMEX" } From 3446d440f661cf3c052c08e5c6879b1e59a478bb Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 23 Jan 2023 14:53:39 -0600 Subject: [PATCH 59/59] shared/runtime/gchelper: Drop cpu directive from ARM asm helpers. This drops the `.cpu` directive from the ARM gchelper_*.s files. Having this directive breaks the linker when targeting older CPUs (e.g. `-mthumb -mthumb-interwork` for `-mcpu=arm7tdmi`). The actual target CPU should be determined by the compiler options. The exact CPU doesn't actually matter, but rather the supported assembly instruction set. So the files are renamed to *_thumb1.s and *thumb2.s to indicate the instruction set support instead of the CPU support. Signed-off-by: David Lechner --- ports/cc3200/application.mk | 2 +- ports/mimxrt/Makefile | 2 +- ports/qemu-arm/Makefile | 6 +++--- ports/renesas-ra/Makefile | 2 +- ports/rp2/CMakeLists.txt | 2 +- ports/samd/mcu/samd21/mpconfigmcu.mk | 2 +- ports/samd/mcu/samd51/mpconfigmcu.mk | 2 +- ports/stm32/Makefile | 6 +++--- ports/teensy/Makefile | 2 +- shared/runtime/gchelper_generic.c | 2 +- shared/runtime/{gchelper_m0.s => gchelper_thumb1.s} | 4 +++- shared/runtime/{gchelper_m3.s => gchelper_thumb2.s} | 3 ++- 12 files changed, 19 insertions(+), 16 deletions(-) rename shared/runtime/{gchelper_m0.s => gchelper_thumb1.s} (94%) rename shared/runtime/{gchelper_m3.s => gchelper_thumb2.s} (96%) diff --git a/ports/cc3200/application.mk b/ports/cc3200/application.mk index 428367d66a..97e113b040 100644 --- a/ports/cc3200/application.mk +++ b/ports/cc3200/application.mk @@ -162,7 +162,7 @@ APP_STM_SRC_C = $(addprefix ports/stm32/,\ OBJ = $(PY_O) $(addprefix $(BUILD)/, $(APP_FATFS_SRC_C:.c=.o) $(APP_RTOS_SRC_C:.c=.o) $(APP_FTP_SRC_C:.c=.o) $(APP_HAL_SRC_C:.c=.o) $(APP_MISC_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(APP_MODS_SRC_C:.c=.o) $(APP_CC3100_SRC_C:.c=.o) $(APP_SL_SRC_C:.c=.o) $(APP_TELNET_SRC_C:.c=.o) $(APP_UTIL_SRC_C:.c=.o) $(APP_UTIL_SRC_S:.s=.o)) OBJ += $(addprefix $(BUILD)/, $(APP_MAIN_SRC_C:.c=.o) $(APP_SHARED_SRC_C:.c=.o) $(APP_LIB_SRC_C:.c=.o) $(APP_STM_SRC_C:.c=.o)) -OBJ += $(BUILD)/shared/runtime/gchelper_m3.o +OBJ += $(BUILD)/shared/runtime/gchelper_thumb2.o OBJ += $(BUILD)/pins.o # List of sources for qstr extraction diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index e08f2ad602..18e91639ef 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -262,7 +262,7 @@ SRC_SS = \ $(MCU_DIR)/gcc/startup_$(MCU_SERIES)$(MCU_CORE).S \ hal/resethandler_MIMXRT10xx.S -SRC_S += shared/runtime/gchelper_m3.s \ +SRC_S += shared/runtime/gchelper_thumb2.s \ # ============================================================================= # QSTR Sources diff --git a/ports/qemu-arm/Makefile b/ports/qemu-arm/Makefile index 7ae7955cf4..40b3062ae4 100644 --- a/ports/qemu-arm/Makefile +++ b/ports/qemu-arm/Makefile @@ -17,7 +17,7 @@ ifeq ($(BOARD),netduino2) CFLAGS += -mthumb -mcpu=cortex-m3 -mfloat-abi=soft CFLAGS += -DQEMU_SOC_STM32 LDSCRIPT = stm32.ld -SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_m3.o +SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_thumb2.o MPY_CROSS_FLAGS += -march=armv7m endif @@ -26,7 +26,7 @@ CFLAGS += -mthumb -mcpu=cortex-m0 -mfloat-abi=soft CFLAGS += -DQEMU_SOC_NRF51 LDSCRIPT = nrf51.ld QEMU_EXTRA = -global nrf51-soc.flash-size=1048576 -global nrf51-soc.sram-size=262144 -SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_m0.o +SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_thumb1.o MPY_CROSS_FLAGS += -march=armv7m endif @@ -34,7 +34,7 @@ ifeq ($(BOARD),mps2-an385) CFLAGS += -mthumb -mcpu=cortex-m3 -mfloat-abi=soft CFLAGS += -DQEMU_SOC_MPS2 LDSCRIPT = mps2.ld -SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_m3.o +SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_thumb2.o MPY_CROSS_FLAGS += -march=armv7m endif diff --git a/ports/renesas-ra/Makefile b/ports/renesas-ra/Makefile index b02379b472..17ec58ae0b 100644 --- a/ports/renesas-ra/Makefile +++ b/ports/renesas-ra/Makefile @@ -335,7 +335,7 @@ SRC_O += \ $(SYSTEM_FILE) SRC_O += \ - shared/runtime/gchelper_m3.o + shared/runtime/gchelper_thumb2.o HAL_SRC_C += $(addprefix $(HAL_DIR)/ra/board/$(BOARD_LOW)/,\ board_init.c \ diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 485476355e..357125e734 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -87,7 +87,7 @@ set(MICROPY_SOURCE_LIB ${MICROPY_DIR}/shared/netutils/netutils.c ${MICROPY_DIR}/shared/netutils/trace.c ${MICROPY_DIR}/shared/readline/readline.c - ${MICROPY_DIR}/shared/runtime/gchelper_m0.s + ${MICROPY_DIR}/shared/runtime/gchelper_thumb1.s ${MICROPY_DIR}/shared/runtime/gchelper_native.c ${MICROPY_DIR}/shared/runtime/interrupt_char.c ${MICROPY_DIR}/shared/runtime/mpirq.c diff --git a/ports/samd/mcu/samd21/mpconfigmcu.mk b/ports/samd/mcu/samd21/mpconfigmcu.mk index 90112759b9..ddd3e8b410 100644 --- a/ports/samd/mcu/samd21/mpconfigmcu.mk +++ b/ports/samd/mcu/samd21/mpconfigmcu.mk @@ -2,7 +2,7 @@ CFLAGS_MCU += -mtune=cortex-m0plus -mcpu=cortex-m0plus -msoft-float MPY_CROSS_MCU_ARCH = armv6m -SRC_S += shared/runtime/gchelper_m0.s +SRC_S += shared/runtime/gchelper_thumb1.s LIBM_SRC_C += $(addprefix lib/libm/,\ acoshf.c \ diff --git a/ports/samd/mcu/samd51/mpconfigmcu.mk b/ports/samd/mcu/samd51/mpconfigmcu.mk index e79dbc3aa6..8596f59821 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.mk +++ b/ports/samd/mcu/samd51/mpconfigmcu.mk @@ -6,7 +6,7 @@ MICROPY_VFS_LFS2 ?= 1 MICROPY_VFS_FAT ?= 1 FROZEN_MANIFEST ?= mcu/$(MCU_SERIES_LOWER)/manifest.py -SRC_S += shared/runtime/gchelper_m3.s +SRC_S += shared/runtime/gchelper_thumb2.s SRC_C += \ fatfs_port.c \ diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 19643cac56..d57e72a6c5 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -362,18 +362,18 @@ 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 + shared/runtime/gchelper_thumb1.o else ifeq ($(MCU_SERIES),l1) CFLAGS += -DUSE_HAL_DRIVER SRC_O += \ resethandler_m3.o \ - shared/runtime/gchelper_m3.o + shared/runtime/gchelper_thumb2.o else SRC_O += \ system_stm32.o \ resethandler.o \ - shared/runtime/gchelper_m3.o + shared/runtime/gchelper_thumb2.o endif endif diff --git a/ports/teensy/Makefile b/ports/teensy/Makefile index 89e5cbce9d..70331c5dc7 100644 --- a/ports/teensy/Makefile +++ b/ports/teensy/Makefile @@ -169,7 +169,7 @@ 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 += $(BUILD)/shared/runtime/gchelper_thumb2.o OBJ += $(GEN_PINS_SRC:.c=.o) all: hex diff --git a/shared/runtime/gchelper_generic.c b/shared/runtime/gchelper_generic.c index dcd35f9c7e..272e37056a 100644 --- a/shared/runtime/gchelper_generic.c +++ b/shared/runtime/gchelper_generic.c @@ -98,7 +98,7 @@ STATIC void gc_helper_get_regs(gc_helper_regs_t arr) { #elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__) -// Fallback implementation, prefer gchelper_m0.s or gchelper_m3.s +// Fallback implementation, prefer gchelper_thumb1.s or gchelper_thumb2.s STATIC void gc_helper_get_regs(gc_helper_regs_t arr) { register long r4 asm ("r4"); diff --git a/shared/runtime/gchelper_m0.s b/shared/runtime/gchelper_thumb1.s similarity index 94% rename from shared/runtime/gchelper_m0.s rename to shared/runtime/gchelper_thumb1.s index db0d9738d1..a316c4fb36 100644 --- a/shared/runtime/gchelper_m0.s +++ b/shared/runtime/gchelper_thumb1.s @@ -25,7 +25,6 @@ */ .syntax unified - .cpu cortex-m0 .thumb .section .text @@ -34,6 +33,9 @@ .global gc_helper_get_regs_and_sp .type gc_helper_get_regs_and_sp, %function +@ This function will compile on processors like Cortex M0 that don't support +@ newer Thumb-2 instructions. + @ uint gc_helper_get_regs_and_sp(r0=uint regs[10]) gc_helper_get_regs_and_sp: @ store registers into given array diff --git a/shared/runtime/gchelper_m3.s b/shared/runtime/gchelper_thumb2.s similarity index 96% rename from shared/runtime/gchelper_m3.s rename to shared/runtime/gchelper_thumb2.s index 5220fa0883..bbc98459ec 100644 --- a/shared/runtime/gchelper_m3.s +++ b/shared/runtime/gchelper_thumb2.s @@ -25,7 +25,6 @@ */ .syntax unified - .cpu cortex-m3 .thumb .section .text @@ -34,6 +33,8 @@ .global gc_helper_get_regs_and_sp .type gc_helper_get_regs_and_sp, %function +@ This function requires Thumb-2 instruction support, e.g. Cortex M3/M4. + @ uint gc_helper_get_regs_and_sp(r0=uint regs[10]) gc_helper_get_regs_and_sp: @ store registers into given array