diff --git a/.github/workflows/ports_unix.yml b/.github/workflows/ports_unix.yml index 1707fdc9fb37..64fd5c902a05 100644 --- a/.github/workflows/ports_unix.yml +++ b/.github/workflows/ports_unix.yml @@ -88,7 +88,7 @@ jobs: (cd ports/unix && gcov -o build-coverage/py ../../py/*.c || true) (cd ports/unix && gcov -o build-coverage/extmod ../../extmod/*.c || true) - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: fail_ci_if_error: true verbose: true diff --git a/docs/library/binascii.rst b/docs/library/binascii.rst index 6c02f019aaa5..c728c5a8a574 100644 --- a/docs/library/binascii.rst +++ b/docs/library/binascii.rst @@ -36,3 +36,9 @@ Functions Encode binary data in base64 format, as in `RFC 3548 `_. Returns the encoded data followed by a newline character if newline is true, as a bytes object. + +.. function:: crc32(data, [value]) + + Compute CRC-32, the 32-bit checksum of *data*, starting with an initial CRC + of *value*. The default initial CRC is zero. The algorithm is consistent + with the ZIP file checksum. diff --git a/docs/library/bluetooth.rst b/docs/library/bluetooth.rst index f8b154dd1144..b09c370abd46 100644 --- a/docs/library/bluetooth.rst +++ b/docs/library/bluetooth.rst @@ -665,7 +665,7 @@ L2CAP connection-oriented-channels Connect to a listening peer on the specified *psm* with local MTU set to *mtu*. - On successful connection, the the ``_IRQ_L2CAP_CONNECT`` event will be + On successful connection, the ``_IRQ_L2CAP_CONNECT`` event will be raised, allowing the client to obtain the CID and the local and remote (peer) MTU. An unsuccessful connection will raise the ``_IRQ_L2CAP_DISCONNECT`` event diff --git a/docs/library/machine.RTC.rst b/docs/library/machine.RTC.rst index ad0b0759efe5..a457189037b5 100644 --- a/docs/library/machine.RTC.rst +++ b/docs/library/machine.RTC.rst @@ -62,10 +62,13 @@ Methods Get the number of milliseconds left before the alarm expires. -.. method:: RTC.cancel(alarm_id=0) +.. method:: RTC.alarm_cancel(alarm_id=0) Cancel a running alarm. + The mimxrt port also exposes this function as ``RTC.cancel(alarm_id=0)``, but this is + scheduled to be removed in MicroPython 2.0. + .. method:: RTC.irq(*, trigger, handler=None, wake=machine.IDLE) Create an irq object triggered by a real time clock alarm. diff --git a/docs/library/machine.TimerWiPy.rst b/docs/library/machine.TimerWiPy.rst index f8c8bb29da7f..54280a5994ad 100644 --- a/docs/library/machine.TimerWiPy.rst +++ b/docs/library/machine.TimerWiPy.rst @@ -71,7 +71,7 @@ Methods Otherwise, a TimerChannel object is initialized and returned. - The operating mode is is the one configured to the Timer object that was used to + The operating mode is the one configured to the Timer object that was used to create the channel. - ``channel`` if the width of the timer is 16-bit, then must be either ``TIMER.A``, ``TIMER.B``. diff --git a/docs/library/pyb.Timer.rst b/docs/library/pyb.Timer.rst index 1749efce2d50..c644e38d7862 100644 --- a/docs/library/pyb.Timer.rst +++ b/docs/library/pyb.Timer.rst @@ -163,7 +163,7 @@ Methods - ``callback`` - as per TimerChannel.callback() - ``pin`` None (the default) or a Pin object. If specified (and not None) - this will cause the alternate function of the the indicated pin + this will cause the alternate function of the indicated pin to be configured for this timer channel. An error will be raised if the pin doesn't support any alternate functions for this timer channel. diff --git a/docs/reference/manifest.rst b/docs/reference/manifest.rst index 1a80b1259e39..dc9d6dd75b2b 100644 --- a/docs/reference/manifest.rst +++ b/docs/reference/manifest.rst @@ -26,7 +26,7 @@ re-flashing the entire firmware. However, it can still be useful to selectively freeze some rarely-changing dependencies (such as third-party libraries). -The way to list the Python files to be be frozen into the firmware is via +The way to list the Python files to be frozen into the firmware is via a "manifest", which is a Python file that will be interpreted by the build process. Typically you would write a manifest file as part of a board definition, but you can also write a stand-alone manifest file and use it with diff --git a/drivers/memory/spiflash.c b/drivers/memory/spiflash.c index e66153636b1f..773334e167ae 100644 --- a/drivers/memory/spiflash.c +++ b/drivers/memory/spiflash.c @@ -44,6 +44,8 @@ #define CMD_RD_DEVID (0x9f) #define CMD_CHIP_ERASE (0xc7) #define CMD_C4READ (0xeb) +#define CMD_RSTEN (0x66) +#define CMD_RESET (0x99) // 32 bit addressing commands #define CMD_WRITE_32 (0x12) @@ -180,6 +182,14 @@ void mp_spiflash_init(mp_spiflash_t *self) { // Ensure SPI flash is out of sleep mode mp_spiflash_deepsleep_internal(self, 0); + // Software reset. + #if MICROPY_HW_SPIFLASH_SOFT_RESET + mp_spiflash_write_cmd(self, CMD_RSTEN); + mp_spiflash_write_cmd(self, CMD_RESET); + mp_spiflash_wait_wip0(self); + mp_hal_delay_ms(1); + #endif + #if defined(CHECK_DEVID) // Validate device id uint32_t devid; diff --git a/extmod/extmod.mk b/extmod/extmod.mk index 514197d6b9a8..f2ae3ad6923f 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -616,6 +616,6 @@ $(BUILD)/$(OPENAMP_DIR)/lib/virtio_mmio/virtio_mmio_drv.o: CFLAGS += -Wno-unused # We need to have generated libmetal before compiling OpenAMP. $(addprefix $(BUILD)/, $(SRC_OPENAMP_C:.c=.o)): $(BUILD)/openamp/metal/config.h -SRC_THIRDPARTY_C += $(SRC_LIBMETAL_C) $(SRC_OPENAMP_C) +SRC_THIRDPARTY_C += $(SRC_OPENAMP_C) $(SRC_LIBMETAL_C:$(BUILD)/%=%) endif # MICROPY_PY_OPENAMP diff --git a/extmod/modplatform.h b/extmod/modplatform.h index b932551c7ccb..a155f071cba1 100644 --- a/extmod/modplatform.h +++ b/extmod/modplatform.h @@ -36,7 +36,11 @@ // See: https://sourceforge.net/p/predef/wiki/Home/ #if defined(__ARM_ARCH) +#if defined(__ARM_ARCH_ISA_A64) +#define MICROPY_PLATFORM_ARCH "aarch64" +#else #define MICROPY_PLATFORM_ARCH "arm" +#endif #elif defined(__x86_64__) || defined(_M_X64) #define MICROPY_PLATFORM_ARCH "x86_64" #elif defined(__i386__) || defined(_M_IX86) @@ -44,12 +48,22 @@ #elif defined(__xtensa__) #define MICROPY_PLATFORM_ARCH "xtensa" #elif defined(__riscv) +#if __riscv_xlen == 64 +#define MICROPY_PLATFORM_ARCH "riscv64" +#else #define MICROPY_PLATFORM_ARCH "riscv" +#endif #else #define MICROPY_PLATFORM_ARCH "" #endif -#if defined(__GNUC__) +#if defined(__clang__) +#define MICROPY_PLATFORM_COMPILER \ + "Clang " \ + MP_STRINGIFY(__clang_major__) "." \ + MP_STRINGIFY(__clang_minor__) "." \ + MP_STRINGIFY(__clang_patchlevel__) +#elif defined(__GNUC__) #define MICROPY_PLATFORM_COMPILER \ "GCC " \ MP_STRINGIFY(__GNUC__) "." \ @@ -86,12 +100,17 @@ #elif defined(_PICOLIBC__) #define MICROPY_PLATFORM_LIBC_LIB "picolibc" #define MICROPY_PLATFORM_LIBC_VER _PICOLIBC_VERSION +#elif defined(__ANDROID__) +#define MICROPY_PLATFORM_LIBC_LIB "bionic" +#define MICROPY_PLATFORM_LIBC_VER MP_STRINGIFY(__ANDROID_API__) #else #define MICROPY_PLATFORM_LIBC_LIB "" #define MICROPY_PLATFORM_LIBC_VER "" #endif -#if defined(__linux) +#if defined(__ANDROID__) +#define MICROPY_PLATFORM_SYSTEM "Android" +#elif defined(__linux) #define MICROPY_PLATFORM_SYSTEM "Linux" #elif defined(__unix__) #define MICROPY_PLATFORM_SYSTEM "Unix" diff --git a/lib/micropython-lib b/lib/micropython-lib index 68e3e07bc7ab..e4cf09527bce 160000 --- a/lib/micropython-lib +++ b/lib/micropython-lib @@ -1 +1 @@ -Subproject commit 68e3e07bc7ab63931cead3854b2a114e9a084248 +Subproject commit e4cf09527bce7569f5db742cf6ae9db68d50c6a9 diff --git a/ports/cc3200/FreeRTOS/Source/tasks.c b/ports/cc3200/FreeRTOS/Source/tasks.c index 6c261a65101d..3d35c667274c 100644 --- a/ports/cc3200/FreeRTOS/Source/tasks.c +++ b/ports/cc3200/FreeRTOS/Source/tasks.c @@ -1671,7 +1671,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE ) { /* Is it in the suspended list because it is in the Suspended - state, or because is is blocked with no timeout? */ + state, or because it is blocked with no timeout? */ if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) { xReturn = pdTRUE; diff --git a/ports/esp32/CMakeLists.txt b/ports/esp32/CMakeLists.txt index d695170fa2b5..c3a675eb2b78 100644 --- a/ports/esp32/CMakeLists.txt +++ b/ports/esp32/CMakeLists.txt @@ -5,10 +5,6 @@ # needs to be duplicated for out-of-tree builds, and can easily get out of date. cmake_minimum_required(VERSION 3.12) -# Retrieve IDF version -include($ENV{IDF_PATH}/tools/cmake/version.cmake) -set(IDF_VERSION "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}.${IDF_VERSION_PATCH}") - # Set the board if it's not already set. if(NOT MICROPY_BOARD) set(MICROPY_BOARD ESP32_GENERIC) @@ -35,12 +31,6 @@ set(SDKCONFIG ${CMAKE_BINARY_DIR}/sdkconfig) # Save the manifest file set from the cmake command line. set(MICROPY_USER_FROZEN_MANIFEST ${MICROPY_FROZEN_MANIFEST}) -# Specific options for IDF v5.2 and later -set(SDKCONFIG_IDF_VERSION_SPECIFIC "") -if (IDF_VERSION VERSION_GREATER_EQUAL "5.2.0") - set(SDKCONFIG_IDF_VERSION_SPECIFIC boards/sdkconfig.idf52) -endif() - # Include board config; this is expected to set (among other options): # - SDKCONFIG_DEFAULTS # - IDF_TARGET diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 4ad3cf0267cd..8888180766b7 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -2,6 +2,8 @@ # # This is a simple, convenience wrapper around idf.py (which uses cmake). +include ../../py/verbose.mk + # Select the board to build for: ifdef BOARD_DIR # Custom board path - remove trailing slash and get the final component of @@ -61,6 +63,10 @@ ifdef MICROPY_PREVIEW_VERSION_2 IDFPY_FLAGS += -D MICROPY_PREVIEW_VERSION_2=1 endif +ifeq ($(BUILD_VERBOSE),1) + IDFPY_FLAGS += --verbose +endif + HELP_BUILD_ERROR ?= "See \033[1;31mhttps://github.com/micropython/micropython/wiki/Build-Troubleshooting\033[0m" define RUN_IDF_PY diff --git a/ports/esp32/README.md b/ports/esp32/README.md index 4eb791389380..a8bada7510f4 100644 --- a/ports/esp32/README.md +++ b/ports/esp32/README.md @@ -28,7 +28,7 @@ manage the ESP32 microcontroller, as well as a way to manage the required build environment and toolchains needed to build the firmware. The ESP-IDF changes quickly and MicroPython only supports certain versions. -Currently MicroPython supports v5.0.4, v5.0.5, v5.1.2, v5.2.0, v5.2.2. +Currently MicroPython supports v5.2, v5.2.2, and v5.3. To install the ESP-IDF the full instructions can be found at the [Espressif Getting Started guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html#installation-step-by-step). diff --git a/ports/esp32/adc.c b/ports/esp32/adc.c index ccf264e5c2ae..83af6dce0b2a 100644 --- a/ports/esp32/adc.c +++ b/ports/esp32/adc.c @@ -33,28 +33,26 @@ #define DEFAULT_VREF 1100 void madcblock_bits_helper(machine_adc_block_obj_t *self, mp_int_t bits) { + if (bits < SOC_ADC_RTC_MIN_BITWIDTH && bits > SOC_ADC_RTC_MAX_BITWIDTH) { + // Invalid value for the current chip, raise exception in the switch below. + bits = -1; + } switch (bits) { - #if CONFIG_IDF_TARGET_ESP32 case 9: - self->width = ADC_WIDTH_BIT_9; + self->width = ADC_BITWIDTH_9; break; case 10: - self->width = ADC_WIDTH_BIT_10; + self->width = ADC_BITWIDTH_10; break; case 11: - self->width = ADC_WIDTH_BIT_11; + self->width = ADC_BITWIDTH_11; break; - #endif - #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 case 12: - self->width = ADC_WIDTH_BIT_12; + self->width = ADC_BITWIDTH_12; break; - #endif - #if CONFIG_IDF_TARGET_ESP32S2 case 13: - self->width = ADC_WIDTH_BIT_13; + self->width = ADC_BITWIDTH_13; break; - #endif default: mp_raise_ValueError(MP_ERROR_TEXT("invalid bits")); } diff --git a/ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.cmake b/ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.cmake index d7db192ca43f..a3888823421d 100644 --- a/ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.cmake +++ b/ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.cmake @@ -6,7 +6,6 @@ set(IDF_TARGET esp32s3) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.usb boards/sdkconfig.ble boards/sdkconfig.240mhz diff --git a/ports/esp32/boards/ESP32_GENERIC/mpconfigboard.cmake b/ports/esp32/boards/ESP32_GENERIC/mpconfigboard.cmake index 9d0077a15e8d..ac60dc863092 100644 --- a/ports/esp32/boards/ESP32_GENERIC/mpconfigboard.cmake +++ b/ports/esp32/boards/ESP32_GENERIC/mpconfigboard.cmake @@ -1,5 +1,4 @@ set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.ble ) diff --git a/ports/esp32/boards/ESP32_GENERIC_C3/mpconfigboard.cmake b/ports/esp32/boards/ESP32_GENERIC_C3/mpconfigboard.cmake index 8c9d7c27a117..429366afac97 100644 --- a/ports/esp32/boards/ESP32_GENERIC_C3/mpconfigboard.cmake +++ b/ports/esp32/boards/ESP32_GENERIC_C3/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32c3) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.ble boards/ESP32_GENERIC_C3/sdkconfig.c3usb ) diff --git a/ports/esp32/boards/ESP32_GENERIC_C6/mpconfigboard.cmake b/ports/esp32/boards/ESP32_GENERIC_C6/mpconfigboard.cmake index 3ab98e9da1af..3060c1cfd978 100644 --- a/ports/esp32/boards/ESP32_GENERIC_C6/mpconfigboard.cmake +++ b/ports/esp32/boards/ESP32_GENERIC_C6/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32c6) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.c6 boards/sdkconfig.ble ) diff --git a/ports/esp32/boards/ESP32_GENERIC_S2/mpconfigboard.cmake b/ports/esp32/boards/ESP32_GENERIC_S2/mpconfigboard.cmake index c9bc60d4cb57..76d185d90d5f 100644 --- a/ports/esp32/boards/ESP32_GENERIC_S2/mpconfigboard.cmake +++ b/ports/esp32/boards/ESP32_GENERIC_S2/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32s2) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.usb boards/sdkconfig.spiram_sx ) diff --git a/ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.cmake b/ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.cmake index 2bfdad21df49..9b0df3b3771e 100644 --- a/ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.cmake +++ b/ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32s3) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.usb boards/sdkconfig.ble boards/sdkconfig.spiram_sx diff --git a/ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.cmake b/ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.cmake index 42c431681ef1..5bbac10e22f1 100644 --- a/ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.cmake +++ b/ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.cmake @@ -1,6 +1,5 @@ set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.ble ) diff --git a/ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.cmake b/ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.cmake index 7767e3b8497f..0ce7f85e5d58 100644 --- a/ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.cmake +++ b/ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32c3) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.ble boards/LOLIN_C3_MINI/sdkconfig.board ) diff --git a/ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.cmake b/ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.cmake index 8be4a69d72e7..dc9abd7478bc 100644 --- a/ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.cmake +++ b/ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32s2) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.spiram_sx boards/sdkconfig.usb ) diff --git a/ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.cmake b/ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.cmake index 8be4a69d72e7..dc9abd7478bc 100644 --- a/ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.cmake +++ b/ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32s2) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.spiram_sx boards/sdkconfig.usb ) diff --git a/ports/esp32/boards/M5STACK_ATOM/mpconfigboard.cmake b/ports/esp32/boards/M5STACK_ATOM/mpconfigboard.cmake index 19b55d165978..f0355e2b0388 100644 --- a/ports/esp32/boards/M5STACK_ATOM/mpconfigboard.cmake +++ b/ports/esp32/boards/M5STACK_ATOM/mpconfigboard.cmake @@ -1,6 +1,5 @@ set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.ble boards/sdkconfig.240mhz boards/M5STACK_ATOM/sdkconfig.board diff --git a/ports/esp32/boards/M5STACK_NANOC6/mpconfigboard.cmake b/ports/esp32/boards/M5STACK_NANOC6/mpconfigboard.cmake index 3ab98e9da1af..3060c1cfd978 100644 --- a/ports/esp32/boards/M5STACK_NANOC6/mpconfigboard.cmake +++ b/ports/esp32/boards/M5STACK_NANOC6/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32c6) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.c6 boards/sdkconfig.ble ) diff --git a/ports/esp32/boards/OLIMEX_ESP32_EVB/mpconfigboard.cmake b/ports/esp32/boards/OLIMEX_ESP32_EVB/mpconfigboard.cmake index d6369d9ef18a..3a6323d126d9 100644 --- a/ports/esp32/boards/OLIMEX_ESP32_EVB/mpconfigboard.cmake +++ b/ports/esp32/boards/OLIMEX_ESP32_EVB/mpconfigboard.cmake @@ -1,6 +1,5 @@ set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.ble boards/OLIMEX_ESP32_EVB/sdkconfig.board ) diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.cmake b/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.cmake index 59d2831b3e0d..c460b07d5efa 100644 --- a/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.cmake +++ b/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.cmake @@ -1,6 +1,5 @@ set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.ble boards/OLIMEX_ESP32_POE/sdkconfig.board ) diff --git a/ports/esp32/boards/SIL_WESP32/mpconfigboard.cmake b/ports/esp32/boards/SIL_WESP32/mpconfigboard.cmake index 9caef1123ccd..a1460397b818 100644 --- a/ports/esp32/boards/SIL_WESP32/mpconfigboard.cmake +++ b/ports/esp32/boards/SIL_WESP32/mpconfigboard.cmake @@ -1,6 +1,5 @@ set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.ble boards/sdkconfig.240mhz boards/SIL_WESP32/sdkconfig.board diff --git a/ports/esp32/boards/UM_FEATHERS2/mpconfigboard.cmake b/ports/esp32/boards/UM_FEATHERS2/mpconfigboard.cmake index e3bcba9f509e..5e570d513bb4 100644 --- a/ports/esp32/boards/UM_FEATHERS2/mpconfigboard.cmake +++ b/ports/esp32/boards/UM_FEATHERS2/mpconfigboard.cmake @@ -1,7 +1,6 @@ set(IDF_TARGET esp32s2) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.spiram_sx boards/sdkconfig.usb boards/UM_FEATHERS2/sdkconfig.board diff --git a/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.cmake b/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.cmake index fc7f246a7ee0..c98ef691769b 100644 --- a/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.cmake +++ b/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.cmake @@ -1,7 +1,6 @@ set(IDF_TARGET esp32s2) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.spiram_sx boards/sdkconfig.usb boards/UM_FEATHERS2NEO/sdkconfig.board diff --git a/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.cmake b/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.cmake index d7fcc3469485..63d1af1da76c 100644 --- a/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.cmake +++ b/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32s3) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.usb boards/sdkconfig.ble boards/sdkconfig.240mhz diff --git a/ports/esp32/boards/UM_FEATHERS3NEO/mpconfigboard.cmake b/ports/esp32/boards/UM_FEATHERS3NEO/mpconfigboard.cmake index 2114b321b2e7..1d2b887d2ce4 100644 --- a/ports/esp32/boards/UM_FEATHERS3NEO/mpconfigboard.cmake +++ b/ports/esp32/boards/UM_FEATHERS3NEO/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32s3) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.usb boards/sdkconfig.ble boards/sdkconfig.240mhz diff --git a/ports/esp32/boards/UM_NANOS3/mpconfigboard.cmake b/ports/esp32/boards/UM_NANOS3/mpconfigboard.cmake index 9030d837289c..6c7f34009e43 100644 --- a/ports/esp32/boards/UM_NANOS3/mpconfigboard.cmake +++ b/ports/esp32/boards/UM_NANOS3/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32s3) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.usb boards/sdkconfig.ble boards/sdkconfig.240mhz diff --git a/ports/esp32/boards/UM_OMGS3/mpconfigboard.cmake b/ports/esp32/boards/UM_OMGS3/mpconfigboard.cmake index a6a42a262e05..aa82111d7588 100644 --- a/ports/esp32/boards/UM_OMGS3/mpconfigboard.cmake +++ b/ports/esp32/boards/UM_OMGS3/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32s3) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.usb boards/sdkconfig.ble boards/sdkconfig.240mhz diff --git a/ports/esp32/boards/UM_PROS3/mpconfigboard.cmake b/ports/esp32/boards/UM_PROS3/mpconfigboard.cmake index 8bd67567ffda..41a96f26e34c 100644 --- a/ports/esp32/boards/UM_PROS3/mpconfigboard.cmake +++ b/ports/esp32/boards/UM_PROS3/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32s3) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.usb boards/sdkconfig.ble boards/sdkconfig.240mhz diff --git a/ports/esp32/boards/UM_RGBTOUCH_MINI/mpconfigboard.cmake b/ports/esp32/boards/UM_RGBTOUCH_MINI/mpconfigboard.cmake index f734411616bd..8b29cb344e77 100644 --- a/ports/esp32/boards/UM_RGBTOUCH_MINI/mpconfigboard.cmake +++ b/ports/esp32/boards/UM_RGBTOUCH_MINI/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32s3) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.usb boards/sdkconfig.ble boards/sdkconfig.240mhz diff --git a/ports/esp32/boards/UM_TINYC6/mpconfigboard.cmake b/ports/esp32/boards/UM_TINYC6/mpconfigboard.cmake index e2df716a16b1..024b1299fa3e 100644 --- a/ports/esp32/boards/UM_TINYC6/mpconfigboard.cmake +++ b/ports/esp32/boards/UM_TINYC6/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32c6) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.c6 boards/sdkconfig.ble boards/UM_TINYC6/sdkconfig.board diff --git a/ports/esp32/boards/UM_TINYPICO/mpconfigboard.cmake b/ports/esp32/boards/UM_TINYPICO/mpconfigboard.cmake index c85fb9d723b0..58b42b55eb7f 100644 --- a/ports/esp32/boards/UM_TINYPICO/mpconfigboard.cmake +++ b/ports/esp32/boards/UM_TINYPICO/mpconfigboard.cmake @@ -1,6 +1,5 @@ set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.ble boards/sdkconfig.240mhz boards/sdkconfig.spiram diff --git a/ports/esp32/boards/UM_TINYS2/mpconfigboard.cmake b/ports/esp32/boards/UM_TINYS2/mpconfigboard.cmake index 1c794baeed6a..70cb4a814ff2 100644 --- a/ports/esp32/boards/UM_TINYS2/mpconfigboard.cmake +++ b/ports/esp32/boards/UM_TINYS2/mpconfigboard.cmake @@ -1,7 +1,6 @@ set(IDF_TARGET esp32s2) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.spiram_sx boards/sdkconfig.usb boards/UM_TINYS2/sdkconfig.board diff --git a/ports/esp32/boards/UM_TINYS3/mpconfigboard.cmake b/ports/esp32/boards/UM_TINYS3/mpconfigboard.cmake index 9030d837289c..6c7f34009e43 100644 --- a/ports/esp32/boards/UM_TINYS3/mpconfigboard.cmake +++ b/ports/esp32/boards/UM_TINYS3/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32s3) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.usb boards/sdkconfig.ble boards/sdkconfig.240mhz diff --git a/ports/esp32/boards/UM_TINYWATCHS3/mpconfigboard.cmake b/ports/esp32/boards/UM_TINYWATCHS3/mpconfigboard.cmake index e788dc965d15..089149c44c54 100644 --- a/ports/esp32/boards/UM_TINYWATCHS3/mpconfigboard.cmake +++ b/ports/esp32/boards/UM_TINYWATCHS3/mpconfigboard.cmake @@ -2,7 +2,6 @@ set(IDF_TARGET esp32s3) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} boards/sdkconfig.usb boards/sdkconfig.ble boards/sdkconfig.240mhz diff --git a/ports/esp32/boards/sdkconfig.base b/ports/esp32/boards/sdkconfig.base index c7179b6125a1..e20835c70c42 100644 --- a/ports/esp32/boards/sdkconfig.base +++ b/ports/esp32/boards/sdkconfig.base @@ -49,7 +49,8 @@ CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n # FreeRTOS CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=2 CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y -CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP=y +CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP=n +CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK=y # UDP CONFIG_LWIP_PPP_SUPPORT=y diff --git a/ports/esp32/boards/sdkconfig.idf52 b/ports/esp32/boards/sdkconfig.idf52 deleted file mode 100644 index 49b7317d4d69..000000000000 --- a/ports/esp32/boards/sdkconfig.idf52 +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP=n -CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK=y diff --git a/ports/esp32/esp32_common.cmake b/ports/esp32/esp32_common.cmake index 9d51a03aa856..b6bfcdacc3cb 100644 --- a/ports/esp32/esp32_common.cmake +++ b/ports/esp32/esp32_common.cmake @@ -78,6 +78,7 @@ if(MICROPY_PY_TINYUSB) ${MICROPY_DIR}/shared/tinyusb/mp_usbd.c ${MICROPY_DIR}/shared/tinyusb/mp_usbd_cdc.c ${MICROPY_DIR}/shared/tinyusb/mp_usbd_descriptor.c + ${MICROPY_DIR}/shared/tinyusb/mp_usbd_runtime.c ) list(APPEND MICROPY_INC_TINYUSB @@ -242,12 +243,19 @@ target_include_directories(${MICROPY_TARGET} PUBLIC target_link_libraries(${MICROPY_TARGET} micropy_extmod_btree) target_link_libraries(${MICROPY_TARGET} usermod) -# Enable the panic handler wrapper -idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=esp_panic_handler" APPEND) - -# Patch LWIP memory pool allocators (see lwip_patch.c) -idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=memp_malloc" APPEND) -idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=memp_free" APPEND) +# Extra linker options +# (when wrap symbols are in standalone files, --undefined ensures +# the linker doesn't skip that file.) +target_link_options(${MICROPY_TARGET} PUBLIC + # Patch LWIP memory pool allocators (see lwip_patch.c) + -Wl,--undefined=memp_malloc + -Wl,--wrap=memp_malloc + -Wl,--wrap=memp_free + + # Enable the panic handler wrapper + -Wl,--undefined=esp_panic_handler + -Wl,--wrap=esp_panic_handler +) # Collect all of the include directories and compile definitions for the IDF components, # including those added by the IDF Component Manager via idf_components.yaml. diff --git a/ports/esp32/machine_adc.c b/ports/esp32/machine_adc.c index dc21b69083c6..be1725c3709a 100644 --- a/ports/esp32/machine_adc.c +++ b/ports/esp32/machine_adc.c @@ -35,7 +35,7 @@ #define ADCBLOCK1 (&madcblock_obj[0]) #define ADCBLOCK2 (&madcblock_obj[1]) -#if CONFIG_IDF_TARGET_ESP32 +#if SOC_ADC_RTC_MIN_BITWIDTH <= 9 && SOC_ADC_RTC_MAX_BITWIDTH >= 11 #define MICROPY_PY_MACHINE_ADC_CLASS_CONSTANTS_WIDTH_9_10_11 \ { MP_ROM_QSTR(MP_QSTR_WIDTH_9BIT), MP_ROM_INT(9) }, \ { MP_ROM_QSTR(MP_QSTR_WIDTH_10BIT), MP_ROM_INT(10) }, \ @@ -44,14 +44,14 @@ #define MICROPY_PY_MACHINE_ADC_CLASS_CONSTANTS_WIDTH_9_10_11 #endif -#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 +#if SOC_ADC_RTC_MIN_BITWIDTH <= 12 && SOC_ADC_RTC_MAX_BITWIDTH >= 12 #define MICROPY_PY_MACHINE_ADC_CLASS_CONSTANTS_WIDTH_12 \ { MP_ROM_QSTR(MP_QSTR_WIDTH_12BIT), MP_ROM_INT(12) }, #else #define MICROPY_PY_MACHINE_ADC_CLASS_CONSTANTS_WIDTH_12 #endif -#if CONFIG_IDF_TARGET_ESP32S2 +#if SOC_ADC_RTC_MIN_BITWIDTH <= 13 && SOC_ADC_RTC_MAX_BITWIDTH >= 13 #define MICROPY_PY_MACHINE_ADC_CLASS_CONSTANTS_WIDTH_13 \ { MP_ROM_QSTR(MP_QSTR_WIDTH_13BIT), MP_ROM_INT(13) }, #else @@ -87,13 +87,21 @@ static const machine_adc_obj_t madc_obj[] = { {{&machine_adc_type}, ADCBLOCK2, ADC_CHANNEL_7, GPIO_NUM_27}, {{&machine_adc_type}, ADCBLOCK2, ADC_CHANNEL_8, GPIO_NUM_25}, {{&machine_adc_type}, ADCBLOCK2, ADC_CHANNEL_9, GPIO_NUM_26}, - #elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 + #elif CONFIG_IDF_TARGET_ESP32C3 {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_0, GPIO_NUM_0}, {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_1, GPIO_NUM_1}, {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_2, GPIO_NUM_2}, {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_3, GPIO_NUM_3}, {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_4, GPIO_NUM_4}, {{&machine_adc_type}, ADCBLOCK2, ADC_CHANNEL_0, GPIO_NUM_5}, + #elif CONFIG_IDF_TARGET_ESP32C6 + {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_0, GPIO_NUM_0}, + {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_1, GPIO_NUM_1}, + {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_2, GPIO_NUM_2}, + {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_3, GPIO_NUM_3}, + {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_4, GPIO_NUM_4}, + {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_5, GPIO_NUM_5}, + {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_6, GPIO_NUM_6}, #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_0, GPIO_NUM_1}, {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_1, GPIO_NUM_2}, diff --git a/ports/esp32/machine_adc_block.c b/ports/esp32/machine_adc_block.c index 78c5b2491b8b..a373603b7e39 100644 --- a/ports/esp32/machine_adc_block.c +++ b/ports/esp32/machine_adc_block.c @@ -32,12 +32,9 @@ #include "driver/adc.h" machine_adc_block_obj_t madcblock_obj[] = { - #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 - {{&machine_adc_block_type}, ADC_UNIT_1, 12, -1, {0}}, - {{&machine_adc_block_type}, ADC_UNIT_2, 12, -1, {0}}, - #elif CONFIG_IDF_TARGET_ESP32S2 - {{&machine_adc_block_type}, ADC_UNIT_1, 13, -1, {0}}, - {{&machine_adc_block_type}, ADC_UNIT_2, 13, -1, {0}}, + {{&machine_adc_block_type}, ADC_UNIT_1, SOC_ADC_RTC_MAX_BITWIDTH, -1, {0}}, + #if SOC_ADC_PERIPH_NUM > 1 + {{&machine_adc_block_type}, ADC_UNIT_2, SOC_ADC_RTC_MAX_BITWIDTH, -1, {0}}, #endif }; diff --git a/ports/esp32/machine_bitstream.c b/ports/esp32/machine_bitstream.c index b4e58c51f4d1..6296ff06708c 100644 --- a/ports/esp32/machine_bitstream.c +++ b/ports/esp32/machine_bitstream.c @@ -42,7 +42,7 @@ // This is a translation of the cycle counter implementation in ports/stm32/machine_bitstream.c. static void IRAM_ATTR machine_bitstream_high_low_bitbang(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const uint8_t *buf, size_t len) { uint32_t pin_mask, gpio_reg_set, gpio_reg_clear; - #if !CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 + #if SOC_GPIO_PIN_COUNT > 32 if (pin >= 32) { pin_mask = 1 << (pin - 32); gpio_reg_set = GPIO_OUT1_W1TS_REG; diff --git a/ports/esp32/machine_dac.c b/ports/esp32/machine_dac.c index 3d1d2df80818..1c5b7c914caf 100644 --- a/ports/esp32/machine_dac.c +++ b/ports/esp32/machine_dac.c @@ -34,21 +34,13 @@ #if MICROPY_PY_MACHINE_DAC #include "driver/gpio.h" -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) #include "driver/dac_oneshot.h" -#else -#include "driver/dac.h" -#define DAC_CHAN_0 DAC_CHANNEL_1 -#define DAC_CHAN_1 DAC_CHANNEL_2 -#endif typedef struct _mdac_obj_t { mp_obj_base_t base; gpio_num_t gpio_id; dac_channel_t dac_id; - #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) dac_oneshot_handle_t dac_oneshot_handle; - #endif } mdac_obj_t; static mdac_obj_t mdac_obj[] = { @@ -77,21 +69,10 @@ static mp_obj_t mdac_make_new(const mp_obj_type_t *type, size_t n_args, size_t n mp_raise_ValueError(MP_ERROR_TEXT("invalid Pin for DAC")); } - #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) dac_oneshot_config_t dac_oneshot_config = {.chan_id = self->dac_id}; check_esp_err(dac_oneshot_new_channel(&dac_oneshot_config, (dac_oneshot_handle_t *)&self->dac_oneshot_handle)); check_esp_err(dac_oneshot_output_voltage(self->dac_oneshot_handle, 0)); return MP_OBJ_FROM_PTR(self); - #else - esp_err_t err = dac_output_enable(self->dac_id); - if (err == ESP_OK) { - err = dac_output_voltage(self->dac_id, 0); - } - if (err == ESP_OK) { - return MP_OBJ_FROM_PTR(self); - } - mp_raise_ValueError(MP_ERROR_TEXT("parameter error")); - #endif } static void mdac_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -106,16 +87,8 @@ static mp_obj_t mdac_write(mp_obj_t self_in, mp_obj_t value_in) { mp_raise_ValueError(MP_ERROR_TEXT("value out of range")); } - #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) check_esp_err(dac_oneshot_output_voltage(self->dac_oneshot_handle, value)); return mp_const_none; - #else - esp_err_t err = dac_output_voltage(self->dac_id, value); - if (err == ESP_OK) { - return mp_const_none; - } - mp_raise_ValueError(MP_ERROR_TEXT("parameter error")); - #endif } MP_DEFINE_CONST_FUN_OBJ_2(mdac_write_obj, mdac_write); diff --git a/ports/esp32/machine_i2c.c b/ports/esp32/machine_i2c.c index e1e1850da57c..732a62f47f19 100644 --- a/ports/esp32/machine_i2c.c +++ b/ports/esp32/machine_i2c.c @@ -49,9 +49,9 @@ #endif #endif -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 +#if SOC_I2C_SUPPORT_XTAL #define I2C_SCLK_FREQ XTAL_CLK_FREQ -#elif CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 +#elif SOC_I2C_SUPPORT_APB #define I2C_SCLK_FREQ APB_CLK_FREQ #else #error "unsupported I2C for ESP32 SoC variant" diff --git a/ports/esp32/machine_pin.c b/ports/esp32/machine_pin.c index 687dfe1938da..74202d6f758c 100644 --- a/ports/esp32/machine_pin.c +++ b/ports/esp32/machine_pin.c @@ -43,7 +43,7 @@ #include "modesp32.h" #include "genhdr/pins.h" -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 +#if SOC_USB_SERIAL_JTAG_SUPPORTED #include "soc/usb_serial_jtag_reg.h" #endif diff --git a/ports/esp32/machine_touchpad.c b/ports/esp32/machine_touchpad.c index 48250280bada..299c489f5a83 100644 --- a/ports/esp32/machine_touchpad.c +++ b/ports/esp32/machine_touchpad.c @@ -31,9 +31,17 @@ #if SOC_TOUCH_SENSOR_SUPPORTED -#if SOC_TOUCH_VERSION_1 // ESP32 only +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 3, 0) +#if SOC_TOUCH_VERSION_1 +#define SOC_TOUCH_SENSOR_VERSION (1) +#elif SOC_TOUCH_VERSION_2 +#define SOC_TOUCH_SENSOR_VERSION (2) +#endif +#endif + +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 only #include "driver/touch_pad.h" -#elif SOC_TOUCH_VERSION_2 // All other SoCs with touch, to date +#elif SOC_TOUCH_SENSOR_VERSION == 2 // All other SoCs with touch, to date #include "driver/touch_sensor.h" #else #error "Unknown touch hardware version" @@ -98,13 +106,13 @@ static mp_obj_t mtp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); initialized = 1; } - #if SOC_TOUCH_VERSION_1 + #if SOC_TOUCH_SENSOR_VERSION == 1 esp_err_t err = touch_pad_config(self->touchpad_id, 0); - #elif SOC_TOUCH_VERSION_2 + #elif SOC_TOUCH_SENSOR_VERSION == 2 esp_err_t err = touch_pad_config(self->touchpad_id); #endif if (err == ESP_OK) { - #if SOC_TOUCH_VERSION_2 + #if SOC_TOUCH_SENSOR_VERSION == 2 touch_pad_fsm_start(); #endif @@ -115,10 +123,10 @@ static mp_obj_t mtp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ static mp_obj_t mtp_config(mp_obj_t self_in, mp_obj_t value_in) { mtp_obj_t *self = self_in; - #if SOC_TOUCH_VERSION_1 + #if SOC_TOUCH_SENSOR_VERSION == 1 uint16_t value = mp_obj_get_int(value_in); esp_err_t err = touch_pad_config(self->touchpad_id, value); - #elif SOC_TOUCH_VERSION_2 + #elif SOC_TOUCH_SENSOR_VERSION == 2 esp_err_t err = touch_pad_config(self->touchpad_id); #endif if (err == ESP_OK) { @@ -130,10 +138,10 @@ MP_DEFINE_CONST_FUN_OBJ_2(mtp_config_obj, mtp_config); static mp_obj_t mtp_read(mp_obj_t self_in) { mtp_obj_t *self = self_in; - #if SOC_TOUCH_VERSION_1 + #if SOC_TOUCH_SENSOR_VERSION == 1 uint16_t value; esp_err_t err = touch_pad_read(self->touchpad_id, &value); - #elif SOC_TOUCH_VERSION_2 + #elif SOC_TOUCH_SENSOR_VERSION == 2 uint32_t value; esp_err_t err = touch_pad_read_raw_data(self->touchpad_id, &value); #endif diff --git a/ports/esp32/machine_uart.c b/ports/esp32/machine_uart.c index cff942f39e72..73089ef46368 100644 --- a/ports/esp32/machine_uart.c +++ b/ports/esp32/machine_uart.c @@ -399,11 +399,7 @@ static void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, } self->flowcontrol = args[ARG_flow].u_int; } - #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) uint8_t uart_fifo_len = UART_HW_FIFO_LEN(self->uart_num); - #else - uint8_t uart_fifo_len = UART_FIFO_LEN; - #endif check_esp_err(uart_set_hw_flow_ctrl(self->uart_num, self->flowcontrol, uart_fifo_len - uart_fifo_len / 4)); } diff --git a/ports/esp32/main.c b/ports/esp32/main.c index 18ef9d735479..4f0c27ee078f 100644 --- a/ports/esp32/main.c +++ b/ports/esp32/main.c @@ -183,6 +183,10 @@ void mp_task(void *pvParameter) { mp_thread_deinit(); #endif + #if MICROPY_HW_ENABLE_USB_RUNTIME_DEVICE + mp_usbd_deinit(); + #endif + gc_sweep_all(); // Free any native code pointers that point to iRAM. diff --git a/ports/esp32/main_esp32/idf_component.yml b/ports/esp32/main_esp32/idf_component.yml index 5dabbc00ba73..11f078f69f76 100644 --- a/ports/esp32/main_esp32/idf_component.yml +++ b/ports/esp32/main_esp32/idf_component.yml @@ -2,4 +2,4 @@ dependencies: espressif/mdns: "~1.1.0" idf: - version: ">=5.0.4" + version: ">=5.2.0" diff --git a/ports/esp32/main_esp32c3/idf_component.yml b/ports/esp32/main_esp32c3/idf_component.yml index 5dabbc00ba73..11f078f69f76 100644 --- a/ports/esp32/main_esp32c3/idf_component.yml +++ b/ports/esp32/main_esp32c3/idf_component.yml @@ -2,4 +2,4 @@ dependencies: espressif/mdns: "~1.1.0" idf: - version: ">=5.0.4" + version: ">=5.2.0" diff --git a/ports/esp32/main_esp32c6/idf_component.yml b/ports/esp32/main_esp32c6/idf_component.yml index 5bbab6d8c3bd..11f078f69f76 100644 --- a/ports/esp32/main_esp32c6/idf_component.yml +++ b/ports/esp32/main_esp32c6/idf_component.yml @@ -2,4 +2,4 @@ dependencies: espressif/mdns: "~1.1.0" idf: - version: ">=5.1.0" + version: ">=5.2.0" diff --git a/ports/esp32/main_esp32s2/idf_component.yml b/ports/esp32/main_esp32s2/idf_component.yml index 05ab2f29a8d3..2ee00b287786 100644 --- a/ports/esp32/main_esp32s2/idf_component.yml +++ b/ports/esp32/main_esp32s2/idf_component.yml @@ -3,4 +3,4 @@ dependencies: espressif/mdns: "~1.1.0" espressif/esp_tinyusb: "~1.0.0" idf: - version: ">=5.0.4" + version: ">=5.2.0" diff --git a/ports/esp32/main_esp32s3/idf_component.yml b/ports/esp32/main_esp32s3/idf_component.yml index 05ab2f29a8d3..2ee00b287786 100644 --- a/ports/esp32/main_esp32s3/idf_component.yml +++ b/ports/esp32/main_esp32s3/idf_component.yml @@ -3,4 +3,4 @@ dependencies: espressif/mdns: "~1.1.0" espressif/esp_tinyusb: "~1.0.0" idf: - version: ">=5.0.4" + version: ">=5.2.0" diff --git a/ports/esp32/modesp32.c b/ports/esp32/modesp32.c index 0a73a0faf06e..164b1918261f 100644 --- a/ports/esp32/modesp32.c +++ b/ports/esp32/modesp32.c @@ -53,7 +53,6 @@ static mp_obj_t esp32_wake_on_touch(const mp_obj_t wake) { if (machine_rtc_config.ext0_pin != -1) { mp_raise_ValueError(MP_ERROR_TEXT("no resources")); } - // mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("touchpad wakeup not available for this version of ESP-IDF")); machine_rtc_config.wake_on_touch = mp_obj_is_true(wake); return mp_const_none; diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index 9b58d77529be..0c1b94d02d94 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -45,7 +45,7 @@ #define MICROPY_PY_MACHINE_SDCARD_ENTRY #endif -#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +#if SOC_TOUCH_SENSOR_SUPPORTED #define MICROPY_PY_MACHINE_TOUCH_PAD_ENTRY { MP_ROM_QSTR(MP_QSTR_TouchPad), MP_ROM_PTR(&machine_touchpad_type) }, #else #define MICROPY_PY_MACHINE_TOUCH_PAD_ENTRY @@ -110,24 +110,11 @@ static void mp_machine_set_freq(size_t n_args, const mp_obj_t *args) { mp_raise_ValueError(MP_ERROR_TEXT("frequency must be 20MHz, 40MHz, 80Mhz, 160MHz or 240MHz")); #endif } - #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) - esp_pm_config_t pm; - #else - #if CONFIG_IDF_TARGET_ESP32 - esp_pm_config_esp32_t pm; - #elif CONFIG_IDF_TARGET_ESP32C3 - esp_pm_config_esp32c3_t pm; - #elif CONFIG_IDF_TARGET_ESP32C6 - esp_pm_config_esp32c6_t pm; - #elif CONFIG_IDF_TARGET_ESP32S2 - esp_pm_config_esp32s2_t pm; - #elif CONFIG_IDF_TARGET_ESP32S3 - esp_pm_config_esp32s3_t pm; - #endif - #endif - pm.max_freq_mhz = freq; - pm.min_freq_mhz = freq; - pm.light_sleep_enable = false; + esp_pm_config_t pm = { + .max_freq_mhz = freq, + .min_freq_mhz = freq, + .light_sleep_enable = false, + }; esp_err_t ret = esp_pm_configure(&pm); if (ret != ESP_OK) { mp_raise_ValueError(NULL); @@ -147,30 +134,34 @@ static void machine_sleep_helper(wake_type_t wake_type, size_t n_args, const mp_ esp_sleep_enable_timer_wakeup(((uint64_t)expiry) * 1000); } - #if !(CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6) - + #if SOC_PM_SUPPORT_EXT0_WAKEUP if (machine_rtc_config.ext0_pin != -1 && (machine_rtc_config.ext0_wake_types & wake_type)) { esp_sleep_enable_ext0_wakeup(machine_rtc_config.ext0_pin, machine_rtc_config.ext0_level ? 1 : 0); } + #endif + #if SOC_PM_SUPPORT_EXT1_WAKEUP if (machine_rtc_config.ext1_pins != 0) { esp_sleep_enable_ext1_wakeup( machine_rtc_config.ext1_pins, machine_rtc_config.ext1_level ? ESP_EXT1_WAKEUP_ANY_HIGH : ESP_EXT1_WAKEUP_ALL_LOW); } + #endif + #if SOC_TOUCH_SENSOR_SUPPORTED if (machine_rtc_config.wake_on_touch) { if (esp_sleep_enable_touchpad_wakeup() != ESP_OK) { mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("esp_sleep_enable_touchpad_wakeup() failed")); } } + #endif + #if SOC_ULP_SUPPORTED if (machine_rtc_config.wake_on_ulp) { if (esp_sleep_enable_ulp_wakeup() != ESP_OK) { mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("esp_sleep_enable_ulp_wakeup() failed")); } } - #endif switch (wake_type) { diff --git a/ports/esp32/modnetwork_globals.h b/ports/esp32/modnetwork_globals.h index c6092bd14217..1aad785ee3d9 100644 --- a/ports/esp32/modnetwork_globals.h +++ b/ports/esp32/modnetwork_globals.h @@ -33,13 +33,9 @@ { MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_WPA3_PSK), MP_ROM_INT(WIFI_AUTH_WPA2_WPA3_PSK) }, { MP_ROM_QSTR(MP_QSTR_AUTH_WAPI_PSK), MP_ROM_INT(WIFI_AUTH_WAPI_PSK) }, { MP_ROM_QSTR(MP_QSTR_AUTH_OWE), MP_ROM_INT(WIFI_AUTH_OWE) }, -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 5) && ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 1, 0) || ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 2) { MP_ROM_QSTR(MP_QSTR_AUTH_WPA3_ENT_192), MP_ROM_INT(WIFI_AUTH_WPA3_ENT_192) }, -#endif -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) { MP_ROM_QSTR(MP_QSTR_AUTH_WPA3_EXT_PSK), MP_ROM_INT(WIFI_AUTH_WPA3_EXT_PSK) }, { MP_ROM_QSTR(MP_QSTR_AUTH_WPA3_EXT_PSK_MIXED_MODE), MP_ROM_INT(WIFI_AUTH_WPA3_EXT_PSK_MIXED_MODE) }, -#endif { MP_ROM_QSTR(MP_QSTR_AUTH_MAX), MP_ROM_INT(WIFI_AUTH_MAX) }, #endif @@ -75,12 +71,14 @@ { MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(STAT_GOT_IP)}, // Errors from the ESP-IDF { MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(WIFI_REASON_NO_AP_FOUND)}, -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) { MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND_IN_RSSI_THRESHOLD), MP_ROM_INT(WIFI_REASON_NO_AP_FOUND_IN_RSSI_THRESHOLD)}, { MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD), MP_ROM_INT(WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD)}, { MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND_W_COMPATIBLE_SECURITY), MP_ROM_INT(WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY)}, -#endif { MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(WIFI_REASON_AUTH_FAIL)}, { MP_ROM_QSTR(MP_QSTR_STAT_BEACON_TIMEOUT), MP_ROM_INT(WIFI_REASON_BEACON_TIMEOUT)}, +#if !MICROPY_PREVIEW_VERSION_2 +// Deprecated, use STAT_CONNECT_FAIL same as other ports { MP_ROM_QSTR(MP_QSTR_STAT_ASSOC_FAIL), MP_ROM_INT(WIFI_REASON_ASSOC_FAIL)}, +#endif +{ MP_ROM_QSTR(MP_QSTR_STAT_CONNECT_FAIL), MP_ROM_INT(WIFI_REASON_ASSOC_FAIL)}, { MP_ROM_QSTR(MP_QSTR_STAT_HANDSHAKE_TIMEOUT), MP_ROM_INT(WIFI_REASON_HANDSHAKE_TIMEOUT)}, diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index e36d12bc056a..b5b7d63a5633 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -215,6 +215,10 @@ #else #define MICROPY_HW_USB_VID (CONFIG_TINYUSB_DESC_CUSTOM_VID) #endif + +#ifndef MICROPY_HW_ENABLE_USB_RUNTIME_DEVICE +#define MICROPY_HW_ENABLE_USB_RUNTIME_DEVICE (1) // Support machine.USBDevice +#endif #endif #ifndef MICROPY_HW_USB_PID @@ -292,12 +296,17 @@ void *esp_native_code_commit(void *, size_t, void *); MP_THREAD_GIL_ENTER(); \ } while (0); #else +#if CONFIG_IDF_TARGET_ARCH_RISCV +#define MICROPY_PY_WAIT_FOR_INTERRUPT asm volatile ("wfi\n") +#else +#define MICROPY_PY_WAIT_FOR_INTERRUPT asm volatile ("waiti 0\n") +#endif #define MICROPY_EVENT_POLL_HOOK \ do { \ extern void mp_handle_pending(bool); \ mp_handle_pending(true); \ MICROPY_PY_SOCKET_EVENTS_HANDLER \ - asm ("waiti 0"); \ + MICROPY_PY_WAIT_FOR_INTERRUPT; \ } while (0); #endif diff --git a/ports/esp32/mpthreadport.c b/ports/esp32/mpthreadport.c index eac1e5ea3668..f436ebb80a7a 100644 --- a/ports/esp32/mpthreadport.c +++ b/ports/esp32/mpthreadport.c @@ -41,12 +41,6 @@ #define MP_THREAD_DEFAULT_STACK_SIZE (MP_THREAD_MIN_STACK_SIZE + MICROPY_STACK_CHECK_MARGIN) #define MP_THREAD_PRIORITY (ESP_TASK_PRIO_MIN + 1) -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) && !CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP -#define FREERTOS_TASK_DELETE_HOOK vTaskPreDeletionHook -#else -#define FREERTOS_TASK_DELETE_HOOK vPortCleanUpTCB -#endif - // this structure forms a linked list, one node per active thread typedef struct _mp_thread_t { TaskHandle_t id; // system id of thread @@ -76,7 +70,7 @@ void mp_thread_init(void *stack, uint32_t stack_len) { // memory barrier to ensure above data is committed __sync_synchronize(); - // FREERTOS_TASK_DELETE_HOOK needs the thread ready after thread_mutex is ready + // vTaskPreDeletionHook needs the thread ready after thread_mutex is ready thread = &thread_entry0; } @@ -180,9 +174,10 @@ void mp_thread_finish(void) { mp_thread_mutex_unlock(&thread_mutex); } -// This is called from the FreeRTOS idle task and is not within Python context, -// so MP_STATE_THREAD is not valid and it does not have the GIL. -void FREERTOS_TASK_DELETE_HOOK(void *tcb) { +// This is called either from vTaskDelete() or from the FreeRTOS idle task, so +// may not be within Python context. Therefore MP_STATE_THREAD may not be valid +// and it does not have the GIL. +void vTaskPreDeletionHook(void *tcb) { if (thread == NULL) { // threading not yet initialised return; @@ -243,7 +238,7 @@ void mp_thread_deinit(void) { // No tasks left to delete break; } else { - // Call FreeRTOS to delete the task (it will call FREERTOS_TASK_DELETE_HOOK) + // Call FreeRTOS to delete the task (it will call vTaskPreDeletionHook) vTaskDelete(id); } } @@ -251,7 +246,7 @@ void mp_thread_deinit(void) { #else -void FREERTOS_TASK_DELETE_HOOK(void *tcb) { +void vTaskPreDeletionHook(void *tcb) { } #endif // MICROPY_PY_THREAD diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c index 416e02e12db8..e1a8c957857c 100644 --- a/ports/esp32/network_lan.c +++ b/ports/esp32/network_lan.c @@ -30,8 +30,6 @@ #include "py/runtime.h" #include "py/mphal.h" -#include "esp_idf_version.h" - #if MICROPY_PY_NETWORK_LAN #include "esp_eth.h" diff --git a/ports/esp32/network_wlan.c b/ports/esp32/network_wlan.c index 6509b4fc6aae..fed81d28cb6a 100644 --- a/ports/esp32/network_wlan.c +++ b/ports/esp32/network_wlan.c @@ -113,7 +113,6 @@ static void network_wlan_wifi_event_handler(void *event_handler_arg, esp_event_b // AP may not exist, or it may have momentarily dropped out; try to reconnect. message = "no AP found"; break; - #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) case WIFI_REASON_NO_AP_FOUND_IN_RSSI_THRESHOLD: // No AP with RSSI within given threshold exists, or it may have momentarily dropped out; try to reconnect. message = "no AP with RSSI within threshold found"; @@ -126,7 +125,6 @@ static void network_wlan_wifi_event_handler(void *event_handler_arg, esp_event_b // No AP with compatible security exists, or it may have momentarily dropped out; try to reconnect. message = "no AP with compatible security found"; break; - #endif case WIFI_REASON_AUTH_FAIL: // Password may be wrong, or it just failed to connect; try to reconnect. message = "authentication failed"; @@ -367,14 +365,12 @@ static mp_obj_t network_wlan_status(size_t n_args, const mp_obj_t *args) { return MP_OBJ_NEW_SMALL_INT(STAT_GOT_IP); } else if (wifi_sta_disconn_reason == WIFI_REASON_NO_AP_FOUND) { return MP_OBJ_NEW_SMALL_INT(WIFI_REASON_NO_AP_FOUND); - #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) } else if (wifi_sta_disconn_reason == WIFI_REASON_NO_AP_FOUND_IN_RSSI_THRESHOLD) { return MP_OBJ_NEW_SMALL_INT(WIFI_REASON_NO_AP_FOUND_IN_RSSI_THRESHOLD); } else if (wifi_sta_disconn_reason == WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD) { return MP_OBJ_NEW_SMALL_INT(WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD); } else if (wifi_sta_disconn_reason == WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY) { return MP_OBJ_NEW_SMALL_INT(WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY); - #endif } else if ((wifi_sta_disconn_reason == WIFI_REASON_AUTH_FAIL) || (wifi_sta_disconn_reason == WIFI_REASON_CONNECTION_FAIL)) { // wrong password return MP_OBJ_NEW_SMALL_INT(WIFI_REASON_AUTH_FAIL); @@ -761,12 +757,11 @@ static const mp_rom_map_elem_t wlan_if_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_SEC_WPA2_WPA3), MP_ROM_INT(WIFI_AUTH_WPA2_WPA3_PSK) }, { MP_ROM_QSTR(MP_QSTR_SEC_WAPI), MP_ROM_INT(WIFI_AUTH_WAPI_PSK) }, { MP_ROM_QSTR(MP_QSTR_SEC_OWE), MP_ROM_INT(WIFI_AUTH_OWE) }, - #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 5) && ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 1, 0) || ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 2) { MP_ROM_QSTR(MP_QSTR_SEC_WPA3_ENT_192), MP_ROM_INT(WIFI_AUTH_WPA3_ENT_192) }, - #endif - #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) { MP_ROM_QSTR(MP_QSTR_SEC_WPA3_EXT_PSK), MP_ROM_INT(WIFI_AUTH_WPA3_EXT_PSK) }, { MP_ROM_QSTR(MP_QSTR_SEC_WPA3_EXT_PSK_MIXED_MODE), MP_ROM_INT(WIFI_AUTH_WPA3_EXT_PSK_MIXED_MODE) }, + #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) + { MP_ROM_QSTR(MP_QSTR_SEC_DPP), MP_ROM_INT(WIFI_AUTH_DPP) }, #endif { MP_ROM_QSTR(MP_QSTR_PM_NONE), MP_ROM_INT(WIFI_PS_NONE) }, @@ -775,12 +770,12 @@ static const mp_rom_map_elem_t wlan_if_locals_dict_table[] = { }; static MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table); -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) +_Static_assert(WIFI_AUTH_MAX == 14, "Synchronize WIFI_AUTH_XXX constants with the ESP-IDF. Look at esp-idf/components/esp_wifi/include/esp_wifi_types_generic.h"); +#elif ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) _Static_assert(WIFI_AUTH_MAX == 13, "Synchronize WIFI_AUTH_XXX constants with the ESP-IDF. Look at esp-idf/components/esp_wifi/include/esp_wifi_types.h"); -#elif ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 5) && ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 1, 0) || ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 2) -_Static_assert(WIFI_AUTH_MAX == 11, "Synchronize WIFI_AUTH_XXX constants with the ESP-IDF. Look at esp-idf/components/esp_wifi/include/esp_wifi_types.h"); #else -_Static_assert(WIFI_AUTH_MAX == 10, "Synchronize WIFI_AUTH_XXX constants with the ESP-IDF. Look at esp-idf/components/esp_wifi/include/esp_wifi_types.h"); +#error "Error in macro logic, all supported versions should be covered." #endif MP_DEFINE_CONST_OBJ_TYPE( diff --git a/ports/esp32/uart.c b/ports/esp32/uart.c index 8336268509ec..491314e04d10 100644 --- a/ports/esp32/uart.c +++ b/ports/esp32/uart.c @@ -51,11 +51,7 @@ static void uart_irq_handler(void *arg); void uart_stdout_init(void) { uart_hal_context_t repl_hal = REPL_HAL_DEFN(); - #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 2, 0) - uart_sclk_t sclk; - #else soc_module_clk_t sclk; - #endif uint32_t sclk_freq; uart_hal_get_sclk(&repl_hal, &sclk); // To restore SCLK after uart_hal_init() resets it diff --git a/ports/esp32/usb_serial_jtag.c b/ports/esp32/usb_serial_jtag.c index 32eb806e7295..c4834e56f962 100644 --- a/ports/esp32/usb_serial_jtag.c +++ b/ports/esp32/usb_serial_jtag.c @@ -35,10 +35,13 @@ #include "soc/periph_defs.h" #include "freertos/portmacro.h" -#define USB_SERIAL_JTAG_BUF_SIZE (64) +// Number of bytes in the input buffer, and number of bytes for output chunking. +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) +#define USB_SERIAL_JTAG_PACKET_SZ_BYTES (64) +#endif static DRAM_ATTR portMUX_TYPE rx_mux = portMUX_INITIALIZER_UNLOCKED; -static uint8_t rx_buf[USB_SERIAL_JTAG_BUF_SIZE]; +static uint8_t rx_buf[USB_SERIAL_JTAG_PACKET_SZ_BYTES]; static volatile bool terminal_connected = false; static void usb_serial_jtag_handle_rx(void) { @@ -48,8 +51,8 @@ static void usb_serial_jtag_handle_rx(void) { portENTER_CRITICAL(&rx_mux); } size_t req_len = ringbuf_free(&stdin_ringbuf); - if (req_len > USB_SERIAL_JTAG_BUF_SIZE) { - req_len = USB_SERIAL_JTAG_BUF_SIZE; + if (req_len > USB_SERIAL_JTAG_PACKET_SZ_BYTES) { + req_len = USB_SERIAL_JTAG_PACKET_SZ_BYTES; } size_t len = usb_serial_jtag_ll_read_rxfifo(rx_buf, req_len); for (size_t i = 0; i < len; ++i) { diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 6504127755e8..83d80a7c963f 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -23,7 +23,6 @@ #define MICROPY_OPT_MATH_FACTORIAL (0) #define MICROPY_REPL_EMACS_KEYS (0) #define MICROPY_PY_BUILTINS_COMPLEX (0) -#define MICROPY_PY_FUNCTION_ATTRS (0) #define MICROPY_PY_DELATTR_SETATTR (0) #define MICROPY_PY_BUILTINS_STR_CENTER (0) #define MICROPY_PY_BUILTINS_STR_PARTITION (0) diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index e98073d33626..3a9550cc974d 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -78,6 +78,7 @@ INC += -I$(TOP)/lib/oofatfs INC += -I$(TOP)/lib/tinyusb/hw INC += -I$(TOP)/lib/tinyusb/hw/bsp/teensy_40 INC += -I$(TOP)/lib/tinyusb/src +INC += -I$(TOP)/shared/tinyusb INC += -I. INC += -Ihal @@ -215,7 +216,7 @@ SRC_C += \ sdio.c \ systick.c \ ticks.c \ - tusb_port.c \ + usbd.c \ SHARED_SRC_C += \ shared/libc/printf.c \ @@ -234,6 +235,7 @@ SHARED_SRC_C += \ shared/timeutils/timeutils.c \ shared/tinyusb/mp_usbd.c \ shared/tinyusb/mp_usbd_cdc.c \ + shared/tinyusb/mp_usbd_descriptor.c \ # Set flash driver name, base address and internal flash flag, based on the flash type. ifeq ($(MICROPY_HW_FLASH_TYPE),$(filter $(MICROPY_HW_FLASH_TYPE),qspi_nor_flash)) @@ -343,6 +345,7 @@ CFLAGS += \ -DBOARD_$(BOARD) \ -DBOARD_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE) \ -DCFG_TUSB_MCU=OPT_MCU_MIMXRT1XXX \ + -DCFG_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED \ -DCLOCK_CONFIG_H='' \ -DCPU_$(MCU_SERIES)$(MCU_CORE) \ -DCPU_$(MCU_VARIANT) \ diff --git a/ports/mimxrt/machine_rtc.c b/ports/mimxrt/machine_rtc.c index 294942cf5a03..0d6fc54c8b67 100644 --- a/ports/mimxrt/machine_rtc.c +++ b/ports/mimxrt/machine_rtc.c @@ -394,7 +394,9 @@ static const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_alarm), MP_ROM_PTR(&machine_rtc_alarm_obj) }, { MP_ROM_QSTR(MP_QSTR_alarm_left), MP_ROM_PTR(&machine_rtc_alarm_left_obj) }, { MP_ROM_QSTR(MP_QSTR_alarm_cancel), MP_ROM_PTR(&machine_rtc_alarm_cancel_obj) }, + #if !MICROPY_PREVIEW_VERSION_2 { MP_ROM_QSTR(MP_QSTR_cancel), MP_ROM_PTR(&machine_rtc_alarm_cancel_obj) }, + #endif { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_rtc_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_ALARM0), MP_ROM_INT(0) }, }; diff --git a/ports/mimxrt/mpconfigport.h b/ports/mimxrt/mpconfigport.h index 5ef6695c1425..146c86015afd 100644 --- a/ports/mimxrt/mpconfigport.h +++ b/ports/mimxrt/mpconfigport.h @@ -118,10 +118,12 @@ uint32_t trng_random_u32(void); #define MICROPY_PY_ONEWIRE (1) // fatfs configuration used in ffconf.h -#define MICROPY_FATFS_ENABLE_LFN (1) +#define MICROPY_FATFS_ENABLE_LFN (2) +#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ +#define MICROPY_FATFS_USE_LABEL (1) #define MICROPY_FATFS_RPATH (2) +#define MICROPY_FATFS_MULTI_PARTITION (1) #define MICROPY_FATFS_MAX_SS (4096) -#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ #ifndef MICROPY_PY_NETWORK #define MICROPY_PY_NETWORK (1) @@ -188,6 +190,14 @@ extern const struct _mp_obj_type_t mp_network_cyw43_type; #define MP_STATE_PORT MP_STATE_VM // Miscellaneous settings +#ifndef MICROPY_HW_USB_VID +#define MICROPY_HW_USB_VID (0xf055) +#endif + +#ifndef MICROPY_HW_USB_PID +#define MICROPY_HW_USB_PID (0x9802) +#endif + #ifndef MICROPY_EVENT_POLL_HOOK #define MICROPY_EVENT_POLL_HOOK \ do { \ diff --git a/ports/mimxrt/tusb_port.c b/ports/mimxrt/tusb_port.c deleted file mode 100644 index f81200e2caa8..000000000000 --- a/ports/mimxrt/tusb_port.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "tusb.h" -#include "py/mphal.h" - -#ifndef MICROPY_HW_USB_VID -#define MICROPY_HW_USB_VID (0xf055) -#endif - -#ifndef MICROPY_HW_USB_PID -#define MICROPY_HW_USB_PID (0x9802) -#endif - -#ifndef MICROPY_HW_USB_MANUFACTURER_STRING -#define MICROPY_HW_USB_MANUFACTURER_STRING ("MicroPython") -#endif - -#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN) -#define USBD_MAX_POWER_MA (250) - -#define USBD_ITF_CDC (0) // needs 2 interfaces -#define USBD_ITF_MAX (2) - -#define USBD_CDC_EP_CMD (0x81) -#define USBD_CDC_EP_OUT (0x02) -#define USBD_CDC_EP_IN (0x82) -#define USBD_CDC_CMD_MAX_SIZE (8) -#define USBD_CDC_IN_OUT_MAX_SIZE (512) - -#define USBD_STR_0 (0x00) -#define USBD_STR_MANUF (0x01) -#define USBD_STR_PRODUCT (0x02) -#define USBD_STR_SERIAL (0x03) -#define USBD_STR_CDC (0x04) - -// Note: descriptors returned from callbacks must exist long enough for transfer to complete - -static const tusb_desc_device_t usbd_desc_device = { - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = MICROPY_HW_USB_VID, - .idProduct = MICROPY_HW_USB_PID, - .bcdDevice = 0x0100, - .iManufacturer = USBD_STR_MANUF, - .iProduct = USBD_STR_PRODUCT, - .iSerialNumber = USBD_STR_SERIAL, - .bNumConfigurations = 1, -}; - -static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = { - TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN, - TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA), - - TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD, - USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE), -}; - -static const char *const usbd_desc_str[] = { - [USBD_STR_MANUF] = MICROPY_HW_USB_MANUFACTURER_STRING, - [USBD_STR_PRODUCT] = MICROPY_HW_BOARD_NAME, - [USBD_STR_SERIAL] = "00000000000000000000", - [USBD_STR_CDC] = "Board CDC", -}; - -const uint8_t *tud_descriptor_device_cb(void) { - return (const uint8_t *)&usbd_desc_device; -} - -const uint8_t *tud_descriptor_configuration_cb(uint8_t index) { - (void)index; - return usbd_desc_cfg; -} - -const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { - #define DESC_STR_MAX (20) - static uint16_t desc_str[DESC_STR_MAX]; - static const char hexchr[16] = "0123456789ABCDEF"; - - memset(desc_str, 0, sizeof(desc_str)); - - uint8_t len; - if (index == 0) { - desc_str[1] = 0x0409; // supported language is English - len = 1; - } else { - if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) { - return NULL; - } - if (index == USBD_STR_SERIAL) { - uint8_t uid[8]; - mp_hal_get_unique_id(uid); - // store it as a hex string - for (len = 0; len < 16; len += 2) { - desc_str[1 + len] = hexchr[uid[len / 2] >> 4]; - desc_str[1 + len + 1] = hexchr[uid[len / 2] & 0x0f]; - } - } else { - const char *str = usbd_desc_str[index]; - for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) { - desc_str[1 + len] = str[len]; - } - } - } - - // first byte is length (including header), second byte is string type - desc_str[0] = (TUSB_DESC_STRING << 8) | (2 * len + 2); - - return desc_str; -} diff --git a/ports/mimxrt/tusb_config.h b/ports/mimxrt/usbd.c similarity index 71% rename from ports/mimxrt/tusb_config.h rename to ports/mimxrt/usbd.c index 607f36446f85..47126ddc017a 100644 --- a/ports/mimxrt/tusb_config.h +++ b/ports/mimxrt/usbd.c @@ -1,7 +1,9 @@ /* + * This file is part of the MicroPython project, http://micropython.org/ + * * The MIT License (MIT) * - * Copyright (c) 2020 Jim Mussared + * Copyright (c) 2024 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 @@ -20,18 +22,21 @@ * 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_MIMXRT_TUSB_CONFIG_H -#define MICROPY_INCLUDED_MIMXRT_TUSB_CONFIG_H -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#include "py/mpconfig.h" + +#if MICROPY_HW_ENABLE_USBDEV -#define CFG_TUSB_OS (OPT_OS_NONE) +#include "py/mphal.h" +#include "mp_usbd.h" +#include "string.h" +#include "tusb.h" -#define CFG_TUD_CDC (1) -#define CFG_TUD_CDC_RX_BUFSIZE (512) -#define CFG_TUD_CDC_TX_BUFSIZE (512) -#define CFG_TUD_CDC_PERSISTENT_TX_BUFF (1) +void mp_usbd_port_get_serial_number(char *serial_buf) { + uint8_t uid[8]; + mp_hal_get_unique_id(uid); + mp_usbd_hex_str(serial_buf, uid, sizeof(uid)); +} -#endif // MICROPY_INCLUDED_MIMXRT_TUSB_CONFIG_H +#endif diff --git a/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/mpconfigboard.h b/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/mpconfigboard.h index a4bb1d899e06..65642bf23422 100644 --- a/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/mpconfigboard.h +++ b/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/mpconfigboard.h @@ -13,6 +13,7 @@ #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_PWM (1) +#define MICROPY_PY_MACHINE_TIMER_NRF (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) diff --git a/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/pins.csv b/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/pins.csv index 972dd9d3bdcb..52e3df400e0b 100644 --- a/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/pins.csv +++ b/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/pins.csv @@ -80,3 +80,7 @@ TX,P35 RX,P42 I2C_SCL,P2 I2C_SDA,P31 +LED_RED,P24 +LED_GREEN,P16 +LED_BLUE,P6 +LED_YELLOW,P13 diff --git a/ports/qemu/Makefile b/ports/qemu/Makefile index 62601324d6a9..237e1e9514c6 100644 --- a/ports/qemu/Makefile +++ b/ports/qemu/Makefile @@ -19,10 +19,10 @@ QSTR_DEFS = qstrdefsport.h MICROPY_ROM_TEXT_COMPRESSION ?= 1 ifeq ($(QEMU_ARCH),arm) -FROZEN_MANIFEST ?= "freeze('test-frzmpy')" +FROZEN_MANIFEST ?= "require('unittest'); freeze('test-frzmpy')" endif ifeq ($(QEMU_ARCH),riscv32) -FROZEN_MANIFEST ?= "freeze('test-frzmpy', ('frozen_const.py', 'frozen_viper.py', 'native_frozen_align.py'))" +FROZEN_MANIFEST ?= "require('unittest'); freeze('test-frzmpy', ('frozen_const.py', 'frozen_viper.py', 'native_frozen_align.py'))" endif # include py core make definitions diff --git a/ports/renesas-ra/mpconfigport.h b/ports/renesas-ra/mpconfigport.h index 307dac24ce58..bd936061fa40 100644 --- a/ports/renesas-ra/mpconfigport.h +++ b/ports/renesas-ra/mpconfigport.h @@ -167,7 +167,7 @@ #endif // fatfs configuration used in ffconf.h -#define MICROPY_FATFS_ENABLE_LFN (1) +#define MICROPY_FATFS_ENABLE_LFN (2) #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ #define MICROPY_FATFS_USE_LABEL (1) #define MICROPY_FATFS_RPATH (2) diff --git a/ports/rp2/Makefile b/ports/rp2/Makefile index f950bc7b9089..afa21cc7a438 100644 --- a/ports/rp2/Makefile +++ b/ports/rp2/Makefile @@ -2,6 +2,8 @@ # # This is a simple wrapper around cmake +include ../../py/verbose.mk + # Select the board to build for: ifdef BOARD_DIR # Custom board path - remove trailing slash and get the final component of @@ -28,7 +30,9 @@ else BUILD ?= build-$(BOARD) endif -$(VERBOSE)MAKESILENT = -s +ifeq ($(BUILD_VERBOSE),1) +MAKE_ARGS += VERBOSE=1 # Picked up in Makefile generated by CMake +endif CMAKE_ARGS += -DMICROPY_BOARD=$(BOARD) -DMICROPY_BOARD_DIR="$(abspath $(BOARD_DIR))" @@ -56,7 +60,7 @@ HELP_BUILD_ERROR ?= "See \033[1;31mhttps://github.com/micropython/micropython/wi all: [ -e $(BUILD)/Makefile ] || cmake -S . -B $(BUILD) -DPICO_BUILD_DOCS=0 ${CMAKE_ARGS} - $(MAKE) $(MAKESILENT) -C $(BUILD) || (echo -e $(HELP_BUILD_ERROR); false) + $(MAKE) $(MAKE_ARGS) -C $(BUILD) || (echo -e $(HELP_BUILD_ERROR); false) clean: $(RM) -rf $(BUILD) diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 15eeab4f34b0..8f4e846ba13b 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -178,7 +178,7 @@ #define MICROPY_HW_SOFT_TIMER_ALARM_NUM (2) // fatfs configuration -#define MICROPY_FATFS_ENABLE_LFN (1) +#define MICROPY_FATFS_ENABLE_LFN (2) #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ #define MICROPY_FATFS_RPATH (2) #if MICROPY_HW_USB_MSC diff --git a/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h b/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h index d09a074402e7..99b92a3793f0 100644 --- a/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h +++ b/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h @@ -29,9 +29,11 @@ typedef unsigned int mp_uint_t; // must be pointer size #define MICROPY_HW_ENABLE_TIMER (1) #define MICROPY_HW_ENABLE_SDCARD (0) #define MICROPY_HW_ENABLE_MMCARD (0) +#define MICROPY_HW_ENTER_BOOTLOADER_VIA_RESET (0) // Flash storage config #define MICROPY_HW_SPIFLASH_ENABLE_CACHE (1) +#define MICROPY_HW_SPIFLASH_SOFT_RESET (1) #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #define MICROPY_BOARD_STARTUP GIGA_board_startup @@ -231,7 +233,7 @@ extern struct _spi_bdev_t spi_bdev; // Timing configuration for 200MHz/2=100MHz (10ns) #define MICROPY_HW_SDRAM_CLOCK_PERIOD 2 #define MICROPY_HW_SDRAM_CAS_LATENCY 2 -#define MICROPY_HW_SDRAM_FREQUENCY (100000) // 100 MHz +#define MICROPY_HW_SDRAM_FREQUENCY_KHZ (100000) // 100 MHz #define MICROPY_HW_SDRAM_TIMING_TMRD (2) #define MICROPY_HW_SDRAM_TIMING_TXSR (7) #define MICROPY_HW_SDRAM_TIMING_TRAS (5) diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h b/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h index 796a9fae923b..7bb75091e8bd 100644 --- a/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h +++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h @@ -29,9 +29,11 @@ typedef unsigned int mp_uint_t; // must be pointer size #define MICROPY_HW_ENABLE_TIMER (1) #define MICROPY_HW_ENABLE_SDCARD (0) #define MICROPY_HW_ENABLE_MMCARD (0) +#define MICROPY_HW_ENTER_BOOTLOADER_VIA_RESET (0) // Flash storage config #define MICROPY_HW_SPIFLASH_ENABLE_CACHE (1) +#define MICROPY_HW_SPIFLASH_SOFT_RESET (1) #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #define MICROPY_BOARD_STARTUP NICLAV_board_startup diff --git a/ports/stm32/boards/ARDUINO_OPTA/mpconfigboard.h b/ports/stm32/boards/ARDUINO_OPTA/mpconfigboard.h index 869522e1ee70..f52c8a26a81d 100644 --- a/ports/stm32/boards/ARDUINO_OPTA/mpconfigboard.h +++ b/ports/stm32/boards/ARDUINO_OPTA/mpconfigboard.h @@ -25,9 +25,11 @@ typedef unsigned int mp_uint_t; // must be pointer size #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_TIMER (1) +#define MICROPY_HW_ENTER_BOOTLOADER_VIA_RESET (0) // Flash storage config #define MICROPY_HW_SPIFLASH_ENABLE_CACHE (1) +#define MICROPY_HW_SPIFLASH_SOFT_RESET (1) #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #define MICROPY_BOARD_STARTUP OPTA_board_startup diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h b/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h index 860a0f688b2d..6b77b16093fb 100644 --- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h +++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h @@ -29,9 +29,11 @@ typedef unsigned int mp_uint_t; // must be pointer size #define MICROPY_HW_ENABLE_TIMER (1) #define MICROPY_HW_ENABLE_SDCARD (1) #define MICROPY_HW_ENABLE_MMCARD (0) +#define MICROPY_HW_ENTER_BOOTLOADER_VIA_RESET (0) // Flash storage config #define MICROPY_HW_SPIFLASH_ENABLE_CACHE (1) +#define MICROPY_HW_SPIFLASH_SOFT_RESET (1) #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #define MICROPY_BOARD_STARTUP PORTENTA_board_startup @@ -245,7 +247,7 @@ extern struct _spi_bdev_t spi_bdev; // Timing configuration for 200MHz/2=100MHz (10ns) #define MICROPY_HW_SDRAM_CLOCK_PERIOD 2 #define MICROPY_HW_SDRAM_CAS_LATENCY 2 -#define MICROPY_HW_SDRAM_FREQUENCY (100000) // 100 MHz +#define MICROPY_HW_SDRAM_FREQUENCY_KHZ (100000) // 100 MHz #define MICROPY_HW_SDRAM_TIMING_TMRD (2) #define MICROPY_HW_SDRAM_TIMING_TXSR (7) #define MICROPY_HW_SDRAM_TIMING_TRAS (5) diff --git a/ports/stm32/boards/STM32F429DISC/mpconfigboard.h b/ports/stm32/boards/STM32F429DISC/mpconfigboard.h index 5d9287242b74..92e8ca411b45 100644 --- a/ports/stm32/boards/STM32F429DISC/mpconfigboard.h +++ b/ports/stm32/boards/STM32F429DISC/mpconfigboard.h @@ -100,6 +100,7 @@ #define MICROPY_HW_SDRAM_BURST_LENGTH 2 #define MICROPY_HW_SDRAM_CAS_LATENCY 3 +#define MICROPY_HW_SDRAM_FREQUENCY_KHZ (90000) // 90 MHz #define MICROPY_HW_SDRAM_COLUMN_BITS_NUM 8 #define MICROPY_HW_SDRAM_ROW_BITS_NUM 12 #define MICROPY_HW_SDRAM_MEM_BUS_WIDTH 16 @@ -109,6 +110,7 @@ #define MICROPY_HW_SDRAM_RBURST (0) #define MICROPY_HW_SDRAM_WRITE_PROTECTION (0) #define MICROPY_HW_SDRAM_AUTOREFRESH_NUM (4) +#define MICROPY_HW_SDRAM_REFRESH_CYCLES 8192 #define MICROPY_HW_FMC_SDCKE1 (pin_B5) #define MICROPY_HW_FMC_SDNE1 (pin_B6) diff --git a/ports/stm32/boards/STM32F769DISC/mpconfigboard.h b/ports/stm32/boards/STM32F769DISC/mpconfigboard.h index f899091d201c..017de9c06839 100644 --- a/ports/stm32/boards/STM32F769DISC/mpconfigboard.h +++ b/ports/stm32/boards/STM32F769DISC/mpconfigboard.h @@ -141,6 +141,7 @@ extern struct _spi_bdev_t spi_bdev; #define MICROPY_HW_SDRAM_BURST_LENGTH 1 #define MICROPY_HW_SDRAM_CAS_LATENCY 2 +#define MICROPY_HW_SDRAM_FREQUENCY_KHZ (90000) // 90 MHz #define MICROPY_HW_SDRAM_COLUMN_BITS_NUM 8 #define MICROPY_HW_SDRAM_ROW_BITS_NUM 12 #define MICROPY_HW_SDRAM_MEM_BUS_WIDTH 32 @@ -150,6 +151,7 @@ extern struct _spi_bdev_t spi_bdev; #define MICROPY_HW_SDRAM_RBURST (1) #define MICROPY_HW_SDRAM_WRITE_PROTECTION (0) #define MICROPY_HW_SDRAM_AUTOREFRESH_NUM (8) +#define MICROPY_HW_SDRAM_REFRESH_CYCLES 8192 // See pins.csv for CPU pin mapping #define MICROPY_HW_FMC_SDCKE0 (pyb_pin_FMC_SDCKE0) diff --git a/ports/stm32/boards/STM32F7DISC/mpconfigboard.h b/ports/stm32/boards/STM32F7DISC/mpconfigboard.h index cf7061902ee7..d4b21484ad4b 100644 --- a/ports/stm32/boards/STM32F7DISC/mpconfigboard.h +++ b/ports/stm32/boards/STM32F7DISC/mpconfigboard.h @@ -111,6 +111,7 @@ void STM32F7DISC_board_early_init(void); #define MICROPY_HW_SDRAM_BURST_LENGTH 1 #define MICROPY_HW_SDRAM_CAS_LATENCY 2 +#define MICROPY_HW_SDRAM_FREQUENCY_KHZ (90000) // 90 MHz #define MICROPY_HW_SDRAM_COLUMN_BITS_NUM 8 #define MICROPY_HW_SDRAM_ROW_BITS_NUM 12 #define MICROPY_HW_SDRAM_MEM_BUS_WIDTH 16 @@ -120,6 +121,7 @@ void STM32F7DISC_board_early_init(void); #define MICROPY_HW_SDRAM_RBURST (1) #define MICROPY_HW_SDRAM_WRITE_PROTECTION (0) #define MICROPY_HW_SDRAM_AUTOREFRESH_NUM (8) +#define MICROPY_HW_SDRAM_REFRESH_CYCLES 8192 #define MICROPY_HW_FMC_SDCKE0 (pin_C3) #define MICROPY_HW_FMC_SDNE0 (pin_H3) diff --git a/ports/stm32/i2c.h b/ports/stm32/i2c.h index 04a7e928bdbd..a48076842cbb 100644 --- a/ports/stm32/i2c.h +++ b/ports/stm32/i2c.h @@ -50,6 +50,7 @@ void i2c_init0(void); int pyb_i2c_init(I2C_HandleTypeDef *i2c); int pyb_i2c_init_freq(const pyb_i2c_obj_t *self, mp_int_t freq); uint32_t pyb_i2c_get_baudrate(I2C_HandleTypeDef *i2c); +void pyb_i2c_deinit_all(void); void i2c_ev_irq_handler(mp_uint_t i2c_id); void i2c_er_irq_handler(mp_uint_t i2c_id); diff --git a/ports/stm32/main.c b/ports/stm32/main.c index df483602dc90..ea870ef0da7c 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -678,6 +678,10 @@ void stm32_main(uint32_t reset_mode) { soft_timer_deinit(); timer_deinit(); uart_deinit_all(); + spi_deinit_all(); + #if MICROPY_PY_PYB_LEGACY && MICROPY_HW_ENABLE_HW_I2C + pyb_i2c_deinit_all(); + #endif #if MICROPY_HW_ENABLE_CAN can_deinit_all(); #endif diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index c6ba83d1bd29..dc0a767fb07e 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -157,7 +157,7 @@ #endif // fatfs configuration used in ffconf.h -#define MICROPY_FATFS_ENABLE_LFN (1) +#define MICROPY_FATFS_ENABLE_LFN (2) #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ #define MICROPY_FATFS_USE_LABEL (1) #define MICROPY_FATFS_RPATH (2) diff --git a/ports/stm32/pyb_i2c.c b/ports/stm32/pyb_i2c.c index 0529d3bd56e4..7e1489010d09 100644 --- a/ports/stm32/pyb_i2c.c +++ b/ports/stm32/pyb_i2c.c @@ -428,6 +428,15 @@ int pyb_i2c_init_freq(const pyb_i2c_obj_t *self, mp_int_t freq) { return pyb_i2c_init(self->i2c); } +void pyb_i2c_deinit_all(void) { + for (int i = 0; i < MP_ARRAY_SIZE(pyb_i2c_obj); i++) { + const pyb_i2c_obj_t *pyb_i2c = &pyb_i2c_obj[i]; + if (pyb_i2c->i2c != NULL) { + i2c_deinit(pyb_i2c->i2c); + } + } +} + static void i2c_reset_after_error(I2C_HandleTypeDef *i2c) { // wait for bus-busy flag to be cleared, with a timeout for (int timeout = 50; timeout > 0; --timeout) { diff --git a/ports/stm32/sdram.c b/ports/stm32/sdram.c index e99f34d2262a..7104eb68e8ff 100644 --- a/ports/stm32/sdram.c +++ b/ports/stm32/sdram.c @@ -245,15 +245,15 @@ static void sdram_init_seq(SDRAM_HandleTypeDef /* Send the command */ HAL_SDRAM_SendCommand(hsdram, command, 0x1000); - /* Step 8: Set the refresh rate counter + /* Step 8: Set the refresh rate counter. + Assuming 90MHz frequency, 8192 refresh cycles and 64ms refresh rate: RefreshRate = 64 ms / 8192 cyc = 7.8125 us/cyc - RefreshCycles = 7.8125 us * 90 MHz = 703 According to the formula on p.1665 of the reference manual, we also need to subtract 20 from the value, so the target refresh rate is 703 - 20 = 683. */ - #define REFRESH_COUNT (MICROPY_HW_SDRAM_REFRESH_RATE * 90000 / 8192 - 20) + #define REFRESH_COUNT (MICROPY_HW_SDRAM_REFRESH_RATE * MICROPY_HW_SDRAM_FREQUENCY_KHZ / MICROPY_HW_SDRAM_REFRESH_CYCLES - 20) HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT); #if defined(STM32F7) || defined(STM32H7) diff --git a/ports/stm32/spi.c b/ports/stm32/spi.c index 607b3fe685a4..aa459119c146 100644 --- a/ports/stm32/spi.c +++ b/ports/stm32/spi.c @@ -545,6 +545,15 @@ void spi_deinit(const spi_t *spi_obj) { } } +void spi_deinit_all(void) { + for (int i = 0; i < MP_ARRAY_SIZE(spi_obj); i++) { + const spi_t *spi = &spi_obj[i]; + if (spi->spi != NULL) { + spi_deinit(spi); + } + } +} + static HAL_StatusTypeDef spi_wait_dma_finished(const spi_t *spi, uint32_t t_start, uint32_t timeout) { volatile HAL_SPI_StateTypeDef *state = &spi->spi->State; for (;;) { diff --git a/ports/stm32/spi.h b/ports/stm32/spi.h index a8bc9d2cfdbe..204038a92f35 100644 --- a/ports/stm32/spi.h +++ b/ports/stm32/spi.h @@ -67,6 +67,7 @@ extern const mp_obj_type_t pyb_spi_type; void spi_init0(void); int spi_init(const spi_t *spi, bool enable_nss_pin); void spi_deinit(const spi_t *spi_obj); +void spi_deinit_all(void); int spi_find_index(mp_obj_t id); void spi_set_params(const spi_t *spi_obj, uint32_t prescale, int32_t baudrate, int32_t polarity, int32_t phase, int32_t bits, int32_t firstbit); diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index d999e57462ed..acfdbd84eb2b 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -1089,7 +1089,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_deinit_obj, pyb_timer_deinit); /// - `callback` - as per TimerChannel.callback() /// /// - `pin` None (the default) or a Pin object. If specified (and not None) -/// this will cause the alternate function of the the indicated pin +/// this will cause the alternate function of the indicated pin /// to be configured for this timer channel. An error will be raised if /// the pin doesn't support any alternate functions for this timer channel. /// @@ -1197,7 +1197,7 @@ static mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma mp_obj_t pin_obj = args[2].u_obj; if (pin_obj != mp_const_none) { if (!mp_obj_is_type(pin_obj, &pin_type)) { - mp_raise_ValueError(MP_ERROR_TEXT("pin argument needs to be be a Pin type")); + mp_raise_ValueError(MP_ERROR_TEXT("pin argument needs to be a Pin type")); } const machine_pin_obj_t *pin = MP_OBJ_TO_PTR(pin_obj); const pin_af_obj_t *af = pin_find_af(pin, AF_FN_TIM, self->tim_id); diff --git a/ports/unix/Makefile b/ports/unix/Makefile index f02e6c6355ab..88fa1af04545 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -48,6 +48,10 @@ CWARN = -Wall -Werror CWARN += -Wextra -Wno-unused-parameter -Wpointer-arith -Wdouble-promotion -Wfloat-conversion CFLAGS += $(INC) $(CWARN) -std=gnu99 -DUNIX $(COPT) -I$(VARIANT_DIR) $(CFLAGS_EXTRA) +# Force the use of 64-bits for file sizes in C library functions on 32-bit platforms. +# This option has no effect on 64-bit builds. +CFLAGS += -D_FILE_OFFSET_BITS=64 + # Debugging/Optimization ifdef DEBUG COPT ?= -Og diff --git a/ports/windows/Makefile b/ports/windows/Makefile index cf0a927014b1..115d1a61ef51 100644 --- a/ports/windows/Makefile +++ b/ports/windows/Makefile @@ -42,6 +42,10 @@ INC += -I$(VARIANT_DIR) CFLAGS += $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Werror -std=gnu99 -DUNIX -D__USE_MINGW_ANSI_STDIO=1 $(COPT) $(CFLAGS_EXTRA) LDFLAGS += -lm -lbcrypt $(LDFLAGS_EXTRA) +# Force the use of 64-bits for file sizes in C library functions on 32-bit platforms. +# This option has no effect on 64-bit builds. +CFLAGS += -D_FILE_OFFSET_BITS=64 + # Debugging/Optimization ifdef DEBUG CFLAGS += -g diff --git a/py/emitglue.c b/py/emitglue.c index 444e480477e5..27cbb349ef60 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -115,7 +115,7 @@ void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, cons #endif #elif MICROPY_EMIT_ARM #if (defined(__linux__) && defined(__GNUC__)) || __ARM_ARCH == 7 - __builtin___clear_cache((void *)fun_data, (uint8_t *)fun_data + fun_len); + __builtin___clear_cache((void *)fun_data, (char *)fun_data + fun_len); #elif defined(__arm__) // Flush I-cache and D-cache. asm volatile ( diff --git a/py/misc.h b/py/misc.h index 8ac80bb7b3e3..2629d0c46cc5 100644 --- a/py/misc.h +++ b/py/misc.h @@ -357,7 +357,7 @@ static inline uint32_t mp_clzll(unsigned long long x) { // Microsoft don't ship _BitScanReverse64 on Win32, so emulate it static inline uint32_t mp_clzll(unsigned long long x) { unsigned long h = x >> 32; - return h ? mp_clzl(h) : (mp_clzl(x) + 32); + return h ? mp_clzl(h) : (mp_clzl((unsigned long)x) + 32); } #endif diff --git a/py/mkenv.mk b/py/mkenv.mk index b52dafbc9d0f..4656d1136658 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -12,22 +12,7 @@ endif THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) TOP := $(patsubst %/py/mkenv.mk,%,$(THIS_MAKEFILE)) -# Turn on increased build verbosity by defining BUILD_VERBOSE in your main -# Makefile or in your environment. You can also use V=1 on the make command -# line. - -ifeq ("$(origin V)", "command line") -BUILD_VERBOSE=$(V) -endif -ifndef BUILD_VERBOSE -$(info Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.) -BUILD_VERBOSE = 0 -endif -ifeq ($(BUILD_VERBOSE),0) -Q = @ -else -Q = -endif +include $(TOP)/py/verbose.mk # default settings; can be overridden in main Makefile diff --git a/py/mkrules.mk b/py/mkrules.mk index 0dc1cdfe15ac..875ddee8523b 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -252,7 +252,11 @@ submodules: $(ECHO) "Updating submodules: $(GIT_SUBMODULES)" ifneq ($(GIT_SUBMODULES),) $(Q)cd $(TOP) && git submodule sync $(GIT_SUBMODULES) - $(Q)cd $(TOP) && git submodule update --init $(GIT_SUBMODULES) + # If available, do blobless partial clones of submodules to save time and space. + # A blobless partial clone lazily fetches data as needed, but has all the metadata available (tags, etc.). + # Fallback to standard submodule update if blobless isn't available (earlier than 2.36.0) + $(Q)cd $(TOP) && git submodule update --init --filter=blob:none $(GIT_SUBMODULES) || \ + git submodule update --init $(GIT_SUBMODULES) endif .PHONY: submodules diff --git a/py/verbose.mk b/py/verbose.mk new file mode 100644 index 000000000000..734623a21e80 --- /dev/null +++ b/py/verbose.mk @@ -0,0 +1,16 @@ +# Turn on increased build verbosity by defining BUILD_VERBOSE in your main +# Makefile or in your environment. You can also use V=1 on the make command +# line. + +ifeq ("$(origin V)", "command line") +BUILD_VERBOSE=$(V) +endif +ifndef BUILD_VERBOSE +$(info Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.) +BUILD_VERBOSE = 0 +endif +ifeq ($(BUILD_VERBOSE),0) +Q = @ +else +Q = +endif diff --git a/shared/runtime/gchelper_generic.c b/shared/runtime/gchelper_generic.c index 093723137405..45b2e4f7d848 100644 --- a/shared/runtime/gchelper_generic.c +++ b/shared/runtime/gchelper_generic.c @@ -101,6 +101,10 @@ static void gc_helper_get_regs(gc_helper_regs_t arr) { // Fallback implementation, prefer gchelper_thumb1.s or gchelper_thumb2.s static void gc_helper_get_regs(gc_helper_regs_t arr) { + #ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wuninitialized" + #endif register long r4 asm ("r4"); register long r5 asm ("r5"); register long r6 asm ("r6"); @@ -121,6 +125,9 @@ static void gc_helper_get_regs(gc_helper_regs_t arr) { arr[7] = r11; arr[8] = r12; arr[9] = r13; + #ifdef __clang__ + #pragma clang diagnostic pop + #endif } #elif defined(__aarch64__) diff --git a/shared/tinyusb/mp_usbd_descriptor.c b/shared/tinyusb/mp_usbd_descriptor.c index be3473b6b914..d0c8845b6808 100644 --- a/shared/tinyusb/mp_usbd_descriptor.c +++ b/shared/tinyusb/mp_usbd_descriptor.c @@ -34,6 +34,7 @@ #define USBD_CDC_CMD_MAX_SIZE (8) #define USBD_CDC_IN_OUT_MAX_SIZE ((CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED) ? 512 : 64) +#define USBD_MSC_IN_OUT_MAX_SIZE ((CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED) ? 512 : 64) const tusb_desc_device_t mp_usbd_builtin_desc_dev = { .bLength = sizeof(tusb_desc_device_t), @@ -61,7 +62,7 @@ const uint8_t mp_usbd_builtin_desc_cfg[MP_USBD_BUILTIN_DESC_CFG_LEN] = { USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE), #endif #if CFG_TUD_MSC - TUD_MSC_DESCRIPTOR(USBD_ITF_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), + TUD_MSC_DESCRIPTOR(USBD_ITF_MSC, USBD_STR_MSC, EPNUM_MSC_OUT, EPNUM_MSC_IN, USBD_MSC_IN_OUT_MAX_SIZE), #endif }; diff --git a/tests/README.md b/tests/README.md index b39833aa096f..28c1b3a0852c 100644 --- a/tests/README.md +++ b/tests/README.md @@ -15,6 +15,32 @@ That will run tests on the `/dev/ttyACM0` serial port. You can also use shortcu device names like `a` for `/dev/ttyACM` and `c` for `COM`. Use `./run-tests.py --help` to see all of the device possibilites, and other options. +There are three kinds of tests: + +* Tests that use `unittest`: these tests require `unittest` to be installed on the + target (eg via `mpremote mip install unittest`), and are used to test things that are + MicroPython-specific, such as behaviour that is different to CPython, modules that + aren't available in CPython, and hardware tests. These tests are run only under + MicroPython and the test passes if the `unittest` runner prints "OK" at the end of the + run. Other output may be printed, eg for use as diagnostics, and this output does not + affect the result of the test. + +* Tests with a corresponding `.exp` file: similar to the `unittest` tests, these tests + are for features that generally cannot be run under CPython. In this case the test is + run under MicroPython only and the output from MicroPython is compared against the + provided `.exp` file. The test passes if the output matches exactly. + +* Tests without a corresponding `.exp` file (and don't use `unittest`): these tests are + used to test MicroPython behaviour that should precisely match CPython. These tests + are first run under CPython and the output captured, and then run under MicroPython + and the output compared to the CPython output. The test passes if the output matches + exactly. If the output differs then the test fails and the outputs are saved in a + `.exp` and a `.out` file respectively. + +In all three cases above, the test can usually be run directly on the target MicroPython +instance, either using the unix port with `micropython `, or on a board with +`mpremote run `. This is useful for creating and debugging tests. + Tests of capabilities not supported on all platforms should be written to check for the capability being present. If it is not, the test should merely output 'SKIP' followed by the line terminator, and call @@ -27,15 +53,6 @@ condition a test. The run-tests.py script uses small scripts in the feature_check directory to check whether each such feature is present, and skips the relevant tests if not. -Tests are generally verified by running the test both in MicroPython and -in CPython and comparing the outputs. If the output differs the test fails -and the outputs are saved in a .out and a .exp file respectively. -For tests that cannot be run in CPython, for example because they use -the machine module, a .exp file can be provided next to the test's .py -file. A convenient way to generate that is to run the test, let it fail -(because CPython cannot run it) and then copy the .out file (but not -before checking it manually!) - When creating new tests, anything that relies on float support should go in the float/ subdirectory. Anything that relies on import x, where x is not a built-in module, should go in the import/ subdirectory. diff --git a/tests/extmod/machine1.py b/tests/extmod/machine1.py index 90e6d17174fb..2f1c0681f64d 100644 --- a/tests/extmod/machine1.py +++ b/tests/extmod/machine1.py @@ -8,39 +8,36 @@ print("SKIP") raise SystemExit -print(machine.mem8) +import unittest -try: - machine.mem16[1] -except ValueError: - print("ValueError") -try: - machine.mem16[1] = 1 -except ValueError: - print("ValueError") +class Test(unittest.TestCase): + def test_mem8_print(self): + self.assertEqual(repr(machine.mem8), "<8-bit memory>") -try: - del machine.mem8[0] -except TypeError: - print("TypeError") + def test_alignment(self): + with self.assertRaises(ValueError): + machine.mem16[1] -try: - machine.mem8[0:1] -except TypeError: - print("TypeError") + with self.assertRaises(ValueError): + machine.mem16[1] = 1 -try: - machine.mem8[0:1] = 10 -except TypeError: - print("TypeError") + def test_operations(self): + with self.assertRaises(TypeError): + del machine.mem8[0] -try: - machine.mem8["hello"] -except TypeError: - print("TypeError") + with self.assertRaises(TypeError): + machine.mem8[0:1] -try: - machine.mem8["hello"] = 10 -except TypeError: - print("TypeError") + with self.assertRaises(TypeError): + machine.mem8[0:1] = 10 + + with self.assertRaises(TypeError): + machine.mem8["hello"] + + with self.assertRaises(TypeError): + machine.mem8["hello"] = 10 + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/extmod/machine1.py.exp b/tests/extmod/machine1.py.exp deleted file mode 100644 index 250485969086..000000000000 --- a/tests/extmod/machine1.py.exp +++ /dev/null @@ -1,8 +0,0 @@ -<8-bit memory> -ValueError -ValueError -TypeError -TypeError -TypeError -TypeError -TypeError diff --git a/tests/extmod_hardware/machine_pwm.py b/tests/extmod_hardware/machine_pwm.py index 7e9fd266e3f8..014030be5c60 100755 --- a/tests/extmod_hardware/machine_pwm.py +++ b/tests/extmod_hardware/machine_pwm.py @@ -1,122 +1,166 @@ -# Test machine.PWM, frequncy and duty cycle (using machine.time_hardware_pulse_us). +# Test machine.PWM, frequncy and duty cycle (using machine.time_pulse_us). # # IMPORTANT: This test requires hardware connections: the PWM-output and pulse-input -# pins must be wired together. +# pins must be wired together (see the variable `pwm_pulse_pins`). -import sys, time +import sys +import time try: - from machine import time_hardware_pulse_us, Pin, PWM + from machine import time_pulse_us, Pin, PWM except ImportError: print("SKIP") raise SystemExit -FREQS1 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) -FREQS2 = (50, 100, 500, 1_000, 2_000, 5_000, 10_000) -FREQS3 = (100_000, 1_000_000, 10_000_000, 20_000_000, 40_000_000) -FREQS = FREQS1 + FREQS2 + FREQS3 -FREQS = FREQS2 - -print("Test frequencies:", FREQS) - -DUTY_MAX = 65536 -DUTY_LEVELS = 8 # 4 # 16 # +import unittest +pwm_freq_limit = 1000000 freq_margin_per_thousand = 0 duty_margin_per_thousand = 0 timing_margin_us = 5 # Configure pins based on the target. if "esp32" in sys.platform: - pwm_pin = 26 # 4 # 2 # - pulse_pin = 27 # 5 # 2 # + pwm_pulse_pins = ((4, 5),) freq_margin_per_thousand = 2 duty_margin_per_thousand = 1 timing_margin_us = 20 elif "esp8266" in sys.platform: - pwm_pin = 4 - pulse_pin = 5 + pwm_pulse_pins = ((4, 5),) + pwm_freq_limit = 1_000 duty_margin_per_thousand = 3 timing_margin_us = 50 elif "mimxrt" in sys.platform: - pwm_pin = "D0" - pulse_pin = "D1" + if "Teensy" in sys.implementation._machine: + # Teensy 4.x + pwm_pulse_pins = ( + ("D0", "D1"), # FLEXPWM X and UART 1 + ("D2", "D3"), # FLEXPWM A/B + ("D11", "D12"), # QTMR and MOSI/MISO of SPI 0 + ) + else: + pwm_pulse_pins = (("D0", "D1"),) elif "rp2" in sys.platform: - pwm_pin = "GPIO0" - pulse_pin = "GPIO1" + pwm_pulse_pins = (("GPIO0", "GPIO1"),) elif "samd" in sys.platform: - pwm_pin = "D0" - pulse_pin = "D1" + pwm_pulse_pins = (("D0", "D1"),) + if "SAMD21" in sys.implementation._machine: + # MCU is too slow to capture short pulses. + pwm_freq_limit = 2_000 else: print("Please add support for this test on this platform.") raise SystemExit -def test_freq_duty(pulse_in, pwm, freq, duty_u16): - print("freq= {:<8} duty_u16 = {:<5} = {:6.2f}% :".format(freq, duty_u16, duty_u16 * 100 / DUTY_MAX), end="") +# Test a specific frequency and duty cycle. +def _test_freq_duty(self, pulse_in, pwm, freq, duty_u16): + print("freq={:<5} duty_u16={:<5} :".format(freq, duty_u16), end="") - # Keep values ​​stable during calculations and prints - pwm_freq = pwm.freq() - pwm_duty_u16 = pwm.duty_u16() # Check configured freq/duty_u16 is within error bound. - freq_error = abs(pwm_freq - freq) * 1000 // freq - duty_error = abs(pwm_duty_u16 - duty_u16) * 1000 // (duty_u16 or 1) - print("", freq_error <= freq_margin_per_thousand or (freq, pwm_freq), end="") - print("", duty_error <= duty_margin_per_thousand or (duty_u16, pwm_duty_u16), end="") + freq_error = abs(pwm.freq() - freq) * 1000 // freq + duty_error = abs(pwm.duty_u16() - duty_u16) * 1000 // (duty_u16 or 1) + print(" freq={} freq_er={}".format(pwm.freq(), freq_error), end="") + print(" duty={} duty_er={}".format(pwm.duty_u16(), duty_error), end="") print(" :", end="") + self.assertLessEqual(freq_error, freq_margin_per_thousand) + self.assertLessEqual(duty_error, duty_margin_per_thousand) # Calculate expected timing. expected_total_us = 1_000_000 // freq - expected_high_us = expected_total_us * duty_u16 // DUTY_MAX + expected_high_us = expected_total_us * duty_u16 // 65535 expected_low_us = expected_total_us - expected_high_us expected_us = (expected_low_us, expected_high_us) timeout = 2 * expected_total_us - if duty_u16 == 0 or duty_u16 == DUTY_MAX: + # Wait for output to settle. + time_pulse_us(pulse_in, 0, timeout) + time_pulse_us(pulse_in, 1, timeout) + + if duty_u16 == 0 or duty_u16 == 65535: # Expect a constant output level. no_pulse = ( - time_hardware_pulse_us(pulse_in, 0, timeout) < 0 and time_hardware_pulse_us(pulse_in, 1, timeout) < 0 + time_pulse_us(pulse_in, 0, timeout) < 0 and time_pulse_us(pulse_in, 1, timeout) < 0 ) + self.assertTrue(no_pulse) if expected_high_us == 0: # Expect a constant low level. - print("", 0, no_pulse and pulse_in() == 0) + self.assertEqual(pulse_in(), 0) else: # Expect a constant high level. - print(" ", 1, no_pulse and pulse_in() == 1) + self.assertEqual(pulse_in(), 1) else: # Test timing of low and high pulse. n_averaging = 10 for level in (0, 1): t = 0 + time_pulse_us(pulse_in, level, timeout) for _ in range(n_averaging): - t += time_hardware_pulse_us(pulse_in, level, timeout) + t += time_pulse_us(pulse_in, level, timeout) t //= n_averaging expected = expected_us[level] - print("", level, abs(t - expected) <= timing_margin_us or (expected, t), end="") - print() - - -def test(): - pulse_in = Pin(pulse_pin, Pin.IN) - pwm = PWM(pwm_pin) - - for freq in FREQS: - pwm.freq(freq) - for duty in range(0, DUTY_LEVELS + 1): - duty_u16 = DUTY_MAX * duty // DUTY_LEVELS - if 0 and sys.platform == "esp32": - # TODO why is this bit needed to get it working on esp32? - # Note: do not need in #10854 - import time - - pwm.init(freq=freq, duty_u16=duty_u16) - time.sleep(0.1) - pwm.duty_u16(duty_u16) - if sys.platform == "esp32": - time.sleep(1/freq) # wait for duty stabilization during one period of the PWM signal - test_freq_duty(pulse_in, pwm, freq, duty_u16) - print() - pwm.deinit() - - -test() + print(" level={} timing_er={}".format(level, abs(t - expected)), end="") + self.assertLessEqual(abs(t - expected), timing_margin_us) + + print() + + +# Test a specific frequency with multiple duty cycles. +def _test_freq(self, freq): + print() + self.pwm.freq(freq) + for duty in (0, 10, 25, 50, 75, 90, 100): + duty_u16 = duty * 65535 // 100 + if sys.platform == "esp32": + # TODO why is this bit needed to get it working on esp32? + self.pwm.init(freq=freq, duty_u16=duty_u16) + time.sleep(0.1) + self.pwm.duty_u16(duty_u16) + _test_freq_duty(self, self.pulse_in, self.pwm, freq, duty_u16) + + +# Given a set of pins, this test class will test multiple frequencies and duty cycles. +class TestBase: + @classmethod + def setUpClass(cls): + print("set up pins:", cls.pwm_pin, cls.pulse_pin) + cls.pwm = PWM(cls.pwm_pin) + cls.pulse_in = Pin(cls.pulse_pin, Pin.IN) + + @classmethod + def tearDownClass(cls): + cls.pwm.deinit() + + def test_freq_50(self): + _test_freq(self, 50) + + def test_freq_100(self): + _test_freq(self, 100) + + def test_freq_500(self): + _test_freq(self, 500) + + def test_freq_1000(self): + _test_freq(self, 1000) + + @unittest.skipIf(pwm_freq_limit < 2000, "frequency too high") + def test_freq_2000(self): + _test_freq(self, 2000) + + @unittest.skipIf(pwm_freq_limit < 5000, "frequency too high") + def test_freq_5000(self): + _test_freq(self, 5000) + + @unittest.skipIf(pwm_freq_limit < 10000, "frequency too high") + def test_freq_10000(self): + _test_freq(self, 10000) + + +# Generate test classes, one for each set of pins to test. +for pwm, pulse in pwm_pulse_pins: + cls_name = "Test_{}_{}".format(pwm, pulse) + globals()[cls_name] = type( + cls_name, (TestBase, unittest.TestCase), {"pwm_pin": pwm, "pulse_pin": pulse} + ) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/net_hosted/connect_nonblock_xfer.py b/tests/net_hosted/connect_nonblock_xfer.py index 23620908afbc..2c8e12473fe5 100644 --- a/tests/net_hosted/connect_nonblock_xfer.py +++ b/tests/net_hosted/connect_nonblock_xfer.py @@ -1,15 +1,14 @@ # test that socket.connect() on a non-blocking socket raises EINPROGRESS # and that an immediate write/send/read/recv does the right thing +import unittest import errno import select import socket import ssl # only mbedTLS supports non-blocking mode -if not hasattr(ssl, "MBEDTLS_VERSION"): - print("SKIP") - raise SystemExit +ssl_supports_nonblocking = hasattr(ssl, "MBEDTLS_VERSION") # get the name of an errno error code @@ -24,34 +23,43 @@ def errno_name(er): # do_connect establishes the socket and wraps it if tls is True. # If handshake is true, the initial connect (and TLS handshake) is # allowed to be performed before returning. -def do_connect(peer_addr, tls, handshake): +def do_connect(self, peer_addr, tls, handshake): s = socket.socket() s.setblocking(False) try: - # print("Connecting to", peer_addr) + print("Connecting to", peer_addr) s.connect(peer_addr) + self.fail() except OSError as er: print("connect:", errno_name(er.errno)) + self.assertEqual(er.errno, errno.EINPROGRESS) + # wrap with ssl/tls if desired if tls: + print("wrap socket") ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - try: - s = ssl_context.wrap_socket(s, do_handshake_on_connect=handshake) - print("wrap ok: True") - except Exception as e: - print("wrap er:", e) + s = ssl_context.wrap_socket(s, do_handshake_on_connect=handshake) + return s -# poll a socket and print out the result -def poll(s): +# poll a socket and check the result +def poll(self, s, expect_writable): poller = select.poll() poller.register(s) - print("poll: ", poller.poll(0)) + result = poller.poll(0) + print("poll:", result) + if expect_writable: + self.assertEqual(len(result), 1) + self.assertEqual(result[0][1], select.POLLOUT) + else: + self.assertEqual(result, []) + +# do_test runs the test against a specific peer address. +def do_test(self, peer_addr, tls, handshake): + print() -# test runs the test against a specific peer address. -def test(peer_addr, tls, handshake): # MicroPython plain and TLS sockets have read/write hasRW = True @@ -62,54 +70,66 @@ def test(peer_addr, tls, handshake): # connect + send # non-blocking send should raise EAGAIN if hasSR: - s = do_connect(peer_addr, tls, handshake) - poll(s) - try: + s = do_connect(self, peer_addr, tls, handshake) + poll(self, s, False) + with self.assertRaises(OSError) as ctx: ret = s.send(b"1234") - print("send ok:", ret) # shouldn't get here - except OSError as er: - print("send er:", errno_name(er.errno)) + print("send error:", errno_name(ctx.exception.errno)) + self.assertEqual(ctx.exception.errno, errno.EAGAIN) s.close() # connect + write # non-blocking write should return None if hasRW: - s = do_connect(peer_addr, tls, handshake) - poll(s) + s = do_connect(self, peer_addr, tls, handshake) + poll(self, s, tls and handshake) ret = s.write(b"1234") - print("write: ", ret) + print("write:", ret) + if tls and handshake: + self.assertEqual(ret, 4) + else: + self.assertIsNone(ret) s.close() # connect + recv # non-blocking recv should raise EAGAIN if hasSR: - s = do_connect(peer_addr, tls, handshake) - poll(s) - try: + s = do_connect(self, peer_addr, tls, handshake) + poll(self, s, False) + with self.assertRaises(OSError) as ctx: ret = s.recv(10) - print("recv ok:", ret) # shouldn't get here - except OSError as er: - print("recv er:", errno_name(er.errno)) + print("recv error:", errno_name(ctx.exception.errno)) + self.assertEqual(ctx.exception.errno, errno.EAGAIN) s.close() # connect + read # non-blocking read should return None if hasRW: - s = do_connect(peer_addr, tls, handshake) - poll(s) + s = do_connect(self, peer_addr, tls, handshake) + poll(self, s, tls and handshake) ret = s.read(10) - print("read: ", ret) + print("read:", ret) + self.assertIsNone(ret) s.close() -if __name__ == "__main__": +class Test(unittest.TestCase): # these tests use a non-existent test IP address, this way the connect takes forever and # we can see EAGAIN/None (https://tools.ietf.org/html/rfc5737) - print("--- Plain sockets to nowhere ---") - test(socket.getaddrinfo("192.0.2.1", 80)[0][-1], False, False) - print("--- SSL sockets to nowhere ---") - test(socket.getaddrinfo("192.0.2.1", 443)[0][-1], True, False) - print("--- Plain sockets ---") - test(socket.getaddrinfo("micropython.org", 80)[0][-1], False, False) - print("--- SSL sockets ---") - test(socket.getaddrinfo("micropython.org", 443)[0][-1], True, True) + def test_plain_sockets_to_nowhere(self): + do_test(self, socket.getaddrinfo("192.0.2.1", 80)[0][-1], False, False) + + @unittest.skipIf(not ssl_supports_nonblocking, "SSL doesn't support non-blocking") + def test_ssl_sockets_to_nowhere(self): + do_test(self, socket.getaddrinfo("192.0.2.1", 443)[0][-1], True, False) + + def test_plain_sockets(self): + do_test(self, socket.getaddrinfo("micropython.org", 80)[0][-1], False, False) + + @unittest.skipIf(not ssl_supports_nonblocking, "SSL doesn't support non-blocking") + def test_ssl_sockets(self): + do_test(self, socket.getaddrinfo("micropython.org", 443)[0][-1], True, True) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/net_hosted/connect_nonblock_xfer.py.exp b/tests/net_hosted/connect_nonblock_xfer.py.exp deleted file mode 100644 index c5498a03873a..000000000000 --- a/tests/net_hosted/connect_nonblock_xfer.py.exp +++ /dev/null @@ -1,44 +0,0 @@ ---- Plain sockets to nowhere --- -connect: EINPROGRESS -poll: [] -send er: EAGAIN -connect: EINPROGRESS -poll: [] -write: None -connect: EINPROGRESS -poll: [] -recv er: EAGAIN -connect: EINPROGRESS -poll: [] -read: None ---- SSL sockets to nowhere --- -connect: EINPROGRESS -wrap ok: True -poll: [] -write: None -connect: EINPROGRESS -wrap ok: True -poll: [] -read: None ---- Plain sockets --- -connect: EINPROGRESS -poll: [] -send er: EAGAIN -connect: EINPROGRESS -poll: [] -write: None -connect: EINPROGRESS -poll: [] -recv er: EAGAIN -connect: EINPROGRESS -poll: [] -read: None ---- SSL sockets --- -connect: EINPROGRESS -wrap ok: True -poll: [(, 4)] -write: 4 -connect: EINPROGRESS -wrap ok: True -poll: [(, 4)] -read: None diff --git a/tests/ports/stm32_hardware/dma_alignment.py b/tests/ports/stm32_hardware/dma_alignment.py index 1836b25d86d5..1c271d48e725 100644 --- a/tests/ports/stm32_hardware/dma_alignment.py +++ b/tests/ports/stm32_hardware/dma_alignment.py @@ -1,43 +1,59 @@ -from machine import SPI # Regression test for DMA for DCache coherency bugs with cache line # written originally for https://github.com/micropython/micropython/issues/13471 # IMPORTANT: This test requires SPI2 MISO (pin Y8 on Pyboard D) to be connected to GND +import unittest +from machine import SPI + SPI_NUM = 2 +BAUDRATE = 5_000_000 + + +class Test(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.spi = SPI(SPI_NUM, baudrate=BAUDRATE) + cls.skip_slow_test = False + + def test_variable_offset_fixed_length(self): + buf = bytearray(1024) + for offs in range(0, len(buf)): + v = memoryview(buf)[offs : offs + 128] + self.spi.readinto(v, 0xFF) + ok = all(b == 0x00 for b in v) + if not ok: + print(offs, v.hex()) + self.skip_slow_test = True + self.assertTrue(ok) + + def test_variable_offset_and_lengths(self): + # this takes around 30s to run, so skipped if already failing + if self.skip_slow_test: + self.skipTest("already failing") + + buf = bytearray(1024) + for op_len in range(1, 66): + print(op_len) + wr = b"\xff" * op_len + for offs in range(1, len(buf) - op_len - 1): + # Place some "sentinel" values before and after the DMA buffer + before = offs & 0xFF + after = (~offs) & 0xFF + buf[offs - 1] = before + buf[offs + op_len] = after + v = memoryview(buf)[offs : offs + op_len] + self.spi.write_readinto(wr, v) + ok = ( + all(b == 0x00 for b in v) + and buf[offs - 1] == before + and buf[offs + op_len] == after + ) + if not ok: + print(v.hex()) + print(hex(op_len), hex(offs), hex(buf[offs - 1]), hex(buf[offs + op_len])) + self.assertTrue(ok) + -spi = SPI(SPI_NUM, baudrate=5_000_000) -buf = bytearray(1024) -ok = True - -for offs in range(0, len(buf)): - v = memoryview(buf)[offs : offs + 128] - spi.readinto(v, 0xFF) - if not all(b == 0x00 for b in v): - print(offs, v.hex()) - ok = False - -print("Variable offset fixed length " + ("OK" if ok else "FAIL")) - -# this takes around 30s to run, so skipped if already failing -if ok: - for op_len in range(1, 66): - wr = b"\xFF" * op_len - for offs in range(1, len(buf) - op_len - 1): - # Place some "sentinel" values before and after the DMA buffer - before = offs & 0xFF - after = (~offs) & 0xFF - buf[offs - 1] = before - buf[offs + op_len] = after - v = memoryview(buf)[offs : offs + op_len] - spi.write_readinto(wr, v) - if ( - not all(b == 0x00 for b in v) - or buf[offs - 1] != before - or buf[offs + op_len] != after - ): - print(v.hex()) - print(hex(op_len), hex(offs), hex(buf[offs - 1]), hex(buf[offs + op_len])) - ok = False - - print("Variable offset and lengths " + ("OK" if ok else "FAIL")) +if __name__ == "__main__": + unittest.main() diff --git a/tests/ports/stm32_hardware/dma_alignment.py.exp b/tests/ports/stm32_hardware/dma_alignment.py.exp deleted file mode 100644 index e890e0081c4b..000000000000 --- a/tests/ports/stm32_hardware/dma_alignment.py.exp +++ /dev/null @@ -1,2 +0,0 @@ -Variable offset fixed length OK -Variable offset and lengths OK diff --git a/tests/run-tests.py b/tests/run-tests.py index d0feb4bcd663..6fe45707bb6c 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -508,6 +508,10 @@ def run_feature_check(pyb, args, test_file): return run_micropython(pyb, args, test_file_path, test_file_path, is_special=True) +class TestError(Exception): + pass + + class ThreadSafeCounter: def __init__(self, start=0): self._value = start @@ -862,29 +866,10 @@ def run_one_test(test_file): skipped_tests.append(test_name) return - # get expected output - test_file_expected = test_file + ".exp" - if os.path.isfile(test_file_expected): - # expected output given by a file, so read that in - with open(test_file_expected, "rb") as f: - output_expected = f.read() - else: - # run CPython to work out expected output - try: - output_expected = subprocess.check_output( - CPYTHON3_CMD + [test_file_abspath], - cwd=os.path.dirname(test_file), - stderr=subprocess.STDOUT, - ) - except subprocess.CalledProcessError: - output_expected = b"CPYTHON3 CRASH" - - # canonical form for all host platforms is to use \n for end-of-line - output_expected = output_expected.replace(b"\r\n", b"\n") - - # run MicroPython + # Run the test on the MicroPython target. output_mupy = run_micropython(pyb, args, test_file, test_file_abspath) + # Check if the target requested to skip this test. if output_mupy == b"SKIP\n": if pyb is not None and hasattr(pyb, "read_until"): # Running on a target over a serial connection, and the target requested @@ -896,22 +881,96 @@ def run_one_test(test_file): skipped_tests.append(test_name) return - testcase_count.add(len(output_expected.splitlines())) + # Look at the output of the test to see if unittest was used. + uses_unittest = False + output_mupy_lines = output_mupy.splitlines() + if any( + line == b"ImportError: no module named 'unittest'" for line in output_mupy_lines[-3:] + ): + raise TestError( + ( + "error: test {} requires unittest".format(test_file), + "(eg run `mpremote mip install unittest` to install it)", + ) + ) + elif ( + len(output_mupy_lines) > 4 + and output_mupy_lines[-4] == b"-" * 70 + and output_mupy_lines[-2] == b"" + ): + # look for unittest summary + unittest_ran_match = re.match(rb"Ran (\d+) tests$", output_mupy_lines[-3]) + unittest_result_match = re.match( + b"(" + rb"(OK)( \(skipped=(\d+)\))?" + b"|" + rb"(FAILED) \(failures=(\d+), errors=(\d+)\)" + b")$", + output_mupy_lines[-1], + ) + uses_unittest = unittest_ran_match and unittest_result_match + + # Determine the expected output. + if uses_unittest: + # Expected output is result of running unittest. + output_expected = None + else: + test_file_expected = test_file + ".exp" + if os.path.isfile(test_file_expected): + # Expected output given by a file, so read that in. + with open(test_file_expected, "rb") as f: + output_expected = f.read() + else: + # Run CPython to work out expected output. + try: + output_expected = subprocess.check_output( + CPYTHON3_CMD + [test_file_abspath], + cwd=os.path.dirname(test_file), + stderr=subprocess.STDOUT, + ) + except subprocess.CalledProcessError: + output_expected = b"CPYTHON3 CRASH" + + # Canonical form for all host platforms is to use \n for end-of-line. + output_expected = output_expected.replace(b"\r\n", b"\n") + + # Work out if test passed or not. + test_passed = False + extra_info = "" + if uses_unittest: + test_passed = unittest_result_match.group(2) == b"OK" + num_test_cases = int(unittest_ran_match.group(1)) + extra_info = "unittest: {} ran".format(num_test_cases) + if test_passed and unittest_result_match.group(4) is not None: + num_skipped = int(unittest_result_match.group(4)) + num_test_cases -= num_skipped + extra_info += ", {} skipped".format(num_skipped) + elif not test_passed: + num_failures = int(unittest_result_match.group(6)) + num_errors = int(unittest_result_match.group(7)) + extra_info += ", {} failures, {} errors".format(num_failures, num_errors) + extra_info = "(" + extra_info + ")" + testcase_count.add(num_test_cases) + else: + testcase_count.add(len(output_expected.splitlines())) + test_passed = output_expected == output_mupy filename_expected = os.path.join(result_dir, test_basename + ".exp") filename_mupy = os.path.join(result_dir, test_basename + ".out") - if output_expected == output_mupy: - print("pass ", test_file) + # Print test summary, update counters, and save .exp/.out files if needed. + if test_passed: + print("pass ", test_file, extra_info) passed_count.increment() rm_f(filename_expected) rm_f(filename_mupy) else: - with open(filename_expected, "wb") as f: - f.write(output_expected) + print("FAIL ", test_file, extra_info) + if output_expected is not None: + with open(filename_expected, "wb") as f: + f.write(output_expected) with open(filename_mupy, "wb") as f: f.write(output_mupy) - print("FAIL ", test_file) failed_tests.append((test_name, test_file)) test_count.increment() @@ -919,12 +978,17 @@ def run_one_test(test_file): if pyb: num_threads = 1 - if num_threads > 1: - pool = ThreadPool(num_threads) - pool.map(run_one_test, tests) - else: - for test in tests: - run_one_test(test) + try: + if num_threads > 1: + pool = ThreadPool(num_threads) + pool.map(run_one_test, tests) + else: + for test in tests: + run_one_test(test) + except TestError as er: + for line in er.args[0]: + print(line) + sys.exit(1) print( "{} tests performed ({} individual testcases)".format( @@ -1090,11 +1154,18 @@ def main(): args = cmd_parser.parse_args() if args.print_failures: - for exp in glob(os.path.join(args.result_dir, "*.exp")): - testbase = exp[:-4] + for out in glob(os.path.join(args.result_dir, "*.out")): + testbase = out[:-4] print() print("FAILURE {0}".format(testbase)) - os.system("{0} {1}.exp {1}.out".format(DIFF, testbase)) + if os.path.exists(testbase + ".exp"): + # Show diff of expected and actual output. + os.system("{0} {1}.exp {1}.out".format(DIFF, testbase)) + else: + # No expected output, just show the actual output (eg from a unittest). + with open(out) as f: + for line in f: + print(line, end="") sys.exit(0) @@ -1189,8 +1260,15 @@ def main(): tests = args.files if not args.keep_path: - # clear search path to make sure tests use only builtin modules and those in extmod - os.environ["MICROPYPATH"] = ".frozen" + os.pathsep + base_path("../extmod") + # Clear search path to make sure tests use only builtin modules, those in + # extmod, and a path to unittest in case it's needed. + os.environ["MICROPYPATH"] = ( + ".frozen" + + os.pathsep + + base_path("../extmod") + + os.pathsep + + base_path("../lib/micropython-lib/python-stdlib/unittest") + ) try: os.makedirs(args.result_dir, exist_ok=True) diff --git a/tools/ci.sh b/tools/ci.sh index 4e6f09b0bb85..33559d339160 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -651,9 +651,6 @@ function ci_unix_settrace_stackless_run_tests { } function ci_unix_macos_build { - # Install pkg-config to configure libffi paths. - brew install pkg-config - make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/unix submodules #make ${MAKEOPTS} -C ports/unix deplibs @@ -685,10 +682,8 @@ function ci_unix_qemu_mips_build { } function ci_unix_qemu_mips_run_tests { - # Issues with MIPS tests: - # - (i)listdir does not work, it always returns the empty list (it's an issue with the underlying C call) file ./ports/unix/build-coverage/micropython - (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py --exclude 'vfs_posix.*\.py') + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py) } function ci_unix_qemu_arm_setup {