diff --git a/.github/workflows/code_formatting.yml b/.github/workflows/code_formatting.yml index 81a2715f1b..cab0ae55b2 100644 --- a/.github/workflows/code_formatting.yml +++ b/.github/workflows/code_formatting.yml @@ -10,7 +10,7 @@ jobs: code-formatting: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 - name: Install packages run: source tools/ci.sh && ci_code_formatting_setup @@ -22,7 +22,7 @@ jobs: code-spelling: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 - name: Install packages run: source tools/ci.sh && ci_code_spell_setup diff --git a/.github/workflows/code_size.yml b/.github/workflows/code_size.yml index 5d955703b6..56097a6d3e 100644 --- a/.github/workflows/code_size.yml +++ b/.github/workflows/code_size.yml @@ -20,7 +20,7 @@ jobs: build: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 100 - name: Install packages diff --git a/.github/workflows/commit_formatting.yml b/.github/workflows/commit_formatting.yml index 0b27038f2d..a651f8a13a 100644 --- a/.github/workflows/commit_formatting.yml +++ b/.github/workflows/commit_formatting.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: '100' - uses: actions/setup-python@v4 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e9b1700747..afc3166f3d 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 - name: Install Python packages run: pip install Sphinx diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 450805a6bd..6613f10662 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -18,7 +18,7 @@ jobs: embedding: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build run: make -C examples/embedding -f micropython_embed.mk && make -C examples/embedding - name: Run diff --git a/.github/workflows/mpremote.yml b/.github/workflows/mpremote.yml index 14aef03e07..5b9465d7fe 100644 --- a/.github/workflows/mpremote.yml +++ b/.github/workflows/mpremote.yml @@ -11,7 +11,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: # Setting this to zero means fetch all history and tags, # which hatch-vcs can use to discover the version tag. diff --git a/.github/workflows/mpy_format.yml b/.github/workflows/mpy_format.yml index 66abb19b81..baa02ce08d 100644 --- a/.github/workflows/mpy_format.yml +++ b/.github/workflows/mpy_format.yml @@ -17,7 +17,7 @@ jobs: test: runs-on: ubuntu-20.04 # use 20.04 to get python2 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_mpy_format_setup - name: Test mpy-tool.py diff --git a/.github/workflows/ports.yml b/.github/workflows/ports.yml index fb574ad981..1f262b0ba4 100644 --- a/.github/workflows/ports.yml +++ b/.github/workflows/ports.yml @@ -17,6 +17,6 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build ports download metadata run: mkdir boards && ./tools/autobuild/build-downloads.py . ./boards diff --git a/.github/workflows/ports_cc3200.yml b/.github/workflows/ports_cc3200.yml index b58bc24b58..f178a14058 100644 --- a/.github/workflows/ports_cc3200.yml +++ b/.github/workflows/ports_cc3200.yml @@ -21,7 +21,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_cc3200_setup - name: Build diff --git a/.github/workflows/ports_esp32.yml b/.github/workflows/ports_esp32.yml index 2cc9f592bf..9403aa656b 100644 --- a/.github/workflows/ports_esp32.yml +++ b/.github/workflows/ports_esp32.yml @@ -21,7 +21,7 @@ jobs: build_idf50: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_esp32_idf50_setup - name: Build diff --git a/.github/workflows/ports_esp8266.yml b/.github/workflows/ports_esp8266.yml index ba89d5e952..5236edf40b 100644 --- a/.github/workflows/ports_esp8266.yml +++ b/.github/workflows/ports_esp8266.yml @@ -21,7 +21,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_esp8266_setup && ci_esp8266_path >> $GITHUB_PATH - name: Build diff --git a/.github/workflows/ports_mimxrt.yml b/.github/workflows/ports_mimxrt.yml index d915625341..614d745807 100644 --- a/.github/workflows/ports_mimxrt.yml +++ b/.github/workflows/ports_mimxrt.yml @@ -21,7 +21,7 @@ jobs: build: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_mimxrt_setup - name: Build diff --git a/.github/workflows/ports_nrf.yml b/.github/workflows/ports_nrf.yml index 8921121780..d9cffb9778 100644 --- a/.github/workflows/ports_nrf.yml +++ b/.github/workflows/ports_nrf.yml @@ -21,7 +21,7 @@ jobs: build: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_nrf_setup - name: Build diff --git a/.github/workflows/ports_powerpc.yml b/.github/workflows/ports_powerpc.yml index a15c4da97f..c41b13e5dd 100644 --- a/.github/workflows/ports_powerpc.yml +++ b/.github/workflows/ports_powerpc.yml @@ -21,7 +21,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_powerpc_setup - name: Build diff --git a/.github/workflows/ports_qemu-arm.yml b/.github/workflows/ports_qemu-arm.yml index 93ec4da767..db3cd7871d 100644 --- a/.github/workflows/ports_qemu-arm.yml +++ b/.github/workflows/ports_qemu-arm.yml @@ -22,7 +22,7 @@ jobs: build_and_test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_qemu_arm_setup - name: Build and run test suite diff --git a/.github/workflows/ports_renesas-ra.yml b/.github/workflows/ports_renesas-ra.yml index 33e17a385a..b1a30c2f11 100644 --- a/.github/workflows/ports_renesas-ra.yml +++ b/.github/workflows/ports_renesas-ra.yml @@ -21,7 +21,7 @@ jobs: build_renesas_ra_board: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_renesas_ra_setup - name: Build diff --git a/.github/workflows/ports_rp2.yml b/.github/workflows/ports_rp2.yml index f042ff1151..5741b75d2a 100644 --- a/.github/workflows/ports_rp2.yml +++ b/.github/workflows/ports_rp2.yml @@ -21,7 +21,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_rp2_setup - name: Build diff --git a/.github/workflows/ports_samd.yml b/.github/workflows/ports_samd.yml index 9833a2fae2..5bf1826cd1 100644 --- a/.github/workflows/ports_samd.yml +++ b/.github/workflows/ports_samd.yml @@ -21,7 +21,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_samd_setup - name: Build diff --git a/.github/workflows/ports_stm32.yml b/.github/workflows/ports_stm32.yml index b278ea862c..0b781a93c1 100644 --- a/.github/workflows/ports_stm32.yml +++ b/.github/workflows/ports_stm32.yml @@ -21,7 +21,7 @@ jobs: build_pyb: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_stm32_setup - name: Build @@ -30,7 +30,7 @@ jobs: build_nucleo: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_stm32_setup - name: Build diff --git a/.github/workflows/ports_teensy.yml b/.github/workflows/ports_teensy.yml index f129960325..291c8e303c 100644 --- a/.github/workflows/ports_teensy.yml +++ b/.github/workflows/ports_teensy.yml @@ -21,7 +21,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_teensy_setup - name: Build diff --git a/.github/workflows/ports_unix.yml b/.github/workflows/ports_unix.yml index 87c58055b9..04dfd78525 100644 --- a/.github/workflows/ports_unix.yml +++ b/.github/workflows/ports_unix.yml @@ -23,7 +23,7 @@ jobs: minimal: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build run: source tools/ci.sh && ci_unix_minimal_build - name: Run main test suite @@ -35,7 +35,7 @@ jobs: reproducible: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build with reproducible date run: source tools/ci.sh && ci_unix_minimal_build env: @@ -46,7 +46,7 @@ jobs: standard: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build run: source tools/ci.sh && ci_unix_standard_build - name: Run main test suite @@ -58,7 +58,7 @@ jobs: coverage: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_unix_coverage_setup - name: Build @@ -87,7 +87,7 @@ jobs: coverage_32bit: runs-on: ubuntu-20.04 # use 20.04 to get libffi-dev:i386 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_unix_32bit_setup - name: Build @@ -105,7 +105,7 @@ jobs: nanbox: runs-on: ubuntu-20.04 # use 20.04 to get python2, and libffi-dev:i386 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_unix_32bit_setup - name: Build @@ -119,7 +119,7 @@ jobs: float: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build run: source tools/ci.sh && ci_unix_float_build - name: Run main test suite @@ -131,7 +131,7 @@ jobs: stackless_clang: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_unix_clang_setup - name: Build @@ -145,7 +145,7 @@ jobs: float_clang: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_unix_clang_setup - name: Build @@ -159,7 +159,7 @@ jobs: settrace: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build run: source tools/ci.sh && ci_unix_settrace_build - name: Run main test suite @@ -171,7 +171,7 @@ jobs: settrace_stackless: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build run: source tools/ci.sh && ci_unix_settrace_stackless_build - name: Run main test suite @@ -183,7 +183,7 @@ jobs: macos: runs-on: macos-11.0 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: python-version: '3.8' @@ -198,7 +198,7 @@ jobs: qemu_mips: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_unix_qemu_mips_setup - name: Build @@ -212,7 +212,7 @@ jobs: qemu_arm: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_unix_qemu_arm_setup - name: Build diff --git a/.github/workflows/ports_webassembly.yml b/.github/workflows/ports_webassembly.yml index 2e0865662f..880f15ab34 100644 --- a/.github/workflows/ports_webassembly.yml +++ b/.github/workflows/ports_webassembly.yml @@ -20,7 +20,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_webassembly_setup - name: Build diff --git a/.github/workflows/ports_windows.yml b/.github/workflows/ports_windows.yml index b31718c591..4b1f4ea791 100644 --- a/.github/workflows/ports_windows.yml +++ b/.github/workflows/ports_windows.yml @@ -21,7 +21,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_windows_setup - name: Build diff --git a/.github/workflows/ports_zephyr.yml b/.github/workflows/ports_zephyr.yml index f64401b316..f6f328c927 100644 --- a/.github/workflows/ports_zephyr.yml +++ b/.github/workflows/ports_zephyr.yml @@ -20,7 +20,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_zephyr_setup - name: Install Zephyr diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml index b8e43dc78f..806d95e895 100644 --- a/.github/workflows/ruff.yml +++ b/.github/workflows/ruff.yml @@ -5,6 +5,6 @@ jobs: ruff: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: pip install --user ruff - run: ruff --format=github . diff --git a/docs/develop/gettingstarted.rst b/docs/develop/gettingstarted.rst index c2d3816d42..34ca1c9c63 100644 --- a/docs/develop/gettingstarted.rst +++ b/docs/develop/gettingstarted.rst @@ -100,7 +100,7 @@ For the stm32 port, the ARM cross-compiler is required: .. code-block:: bash - $ sudo apt-get install arm-none-eabi-gcc arm-none-eabi-binutils arm-none-eabi-newlib + $ sudo apt-get install gcc-arm-none-eabi libnewlib-arm-none-eabi See the `ARM GCC toolchain `_ @@ -228,7 +228,7 @@ You can also specify which board to use: .. code-block:: bash $ cd ports/stm32 - $ make submodules + $ make BOARD= submodules $ make BOARD= See `ports/stm32/boards `_ diff --git a/docs/esp32/tutorial/img/mem32_gpio_output.jpg b/docs/esp32/tutorial/img/mem32_gpio_output.jpg new file mode 100755 index 0000000000..5544202871 Binary files /dev/null and b/docs/esp32/tutorial/img/mem32_gpio_output.jpg differ diff --git a/docs/esp32/tutorial/peripheral_access.rst b/docs/esp32/tutorial/peripheral_access.rst index 3304c341de..ecdec101f7 100644 --- a/docs/esp32/tutorial/peripheral_access.rst +++ b/docs/esp32/tutorial/peripheral_access.rst @@ -42,3 +42,83 @@ for this: The MCPWM0 peripheral is in bit position 17 of the above two registers, hence the value of ``DPORT_PWM0_CLK_EN``. + +Synchronous access to pins directly via registers +------------------------------------------------- + +The following code shows how to access pins directly via registers. It has been +tested on a generic ESP32 board. It configures pins 16, 17, 32 and 33 in output +mode via registers, and switches pin output values via registers. Pins 16 and +17 are switched simultaneously. + +.. code-block:: python3 + + from micropython import const + from machine import mem32, Pin + + GPIO_OUT_REG = const(0x3FF44004) # GPIO 0-31 output register + GPIO_OUT1_REG = const(0x3FF44010) # GPIO 32-39 output register + + GPIO_ENABLE_REG = const(0x3FF44020) # GPIO 0-31 output enable register + GPIO_ENABLE1_REG = const(0x3FF4402C) # GPIO 32-39 output enable register + + M16 = 1 << 16 # Pin(16) bit mask + M17 = 1 << 17 # Pin(17) bit mask + + M32 = 1 << (32-32) # Pin(32) bit mask + M33 = 1 << (33-32) # Pin(33) bit mask + + # Enable pin output mode like + # p16 = Pin(16, mode=Pin.OUT) + # p17 = Pin(17, mode=Pin.OUT) + # p32 = Pin(32, mode=Pin.OUT) + # p33 = Pin(33, mode=Pin.OUT) + mem32[GPIO_ENABLE_REG] = mem32[GPIO_ENABLE_REG] | M16 | M17 + mem32[GPIO_ENABLE1_REG] = mem32[GPIO_ENABLE1_REG] | M32 | M33 + + print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG])) + + # Set outputs to 1 like + # p16(1) + # p17(1) + # p32(1) + # p33(1) + mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] | M16 | M17 + mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] | M32 | M33 + + print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG])) + + # Set outputs to 0 like + # p16(0) + # p17(0) + # p32(0) + # p33(0) + mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] & ~(M16 | M17) + mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] & ~(M32 | M33) + + print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG])) + + while True: + # Set outputs to 1 + mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] | M16 | M17 + mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] | M32 | M33 + + # Set outputs to 0 + mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] & ~(M16 | M17) + mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] & ~(M32 | M33) + + +Output is:: + + 0x0 0x0 + 0x30000 0x3 + 0x0 0x0 + +Pins 16 and 17 are switched synchronously: + +.. image:: img/mem32_gpio_output.jpg + +Same image on pins 32 and 33. + +Note that pins 34-36 and 39 are inputs only. Also pins 1 and 3 are Tx, Rx of the REPL UART, +pins 6-11 are connected to the built-in SPI flash. diff --git a/docs/library/deflate.rst b/docs/library/deflate.rst index 9752af5925..fad5778705 100644 --- a/docs/library/deflate.rst +++ b/docs/library/deflate.rst @@ -41,9 +41,15 @@ Classes to 1024 bytes. Valid values are ``5`` to ``15`` inclusive (corresponding to window sizes of 32 to 32k bytes). - If *wbits* is set to ``0`` (the default), then a window size of 256 bytes - will be used (corresponding to *wbits* set to ``8``), except when - :ref:`decompressing a zlib stream `. + If *wbits* is set to ``0`` (the default), then for compression a window size + of 256 bytes will be used (as if *wbits* was set to 8). For decompression, it + depends on the format: + + * ``RAW`` will use 256 bytes (corresponding to *wbits* set to 8). + * ``ZLIB`` (or ``AUTO`` with zlib detected) will use the value from the zlib + header. + * ``GZIP`` (or ``AUTO`` with gzip detected) will use 32 kilobytes + (corresponding to *wbits* set to 15). See the :ref:`window size ` notes below for more information about the window size, zlib, and gzip streams. @@ -134,44 +140,43 @@ Deflate window size ------------------- The window size limits how far back in the stream the (de)compressor can -reference. Increasing the window size will improve compression, but will -require more memory. +reference. Increasing the window size will improve compression, but will require +more memory and make the compressor slower. -However, just because a given window size is used for compression, this does not -mean that the stream will require the same size window for decompression, as -the stream may not reference data as far back as the window allows (for example, -if the length of the input is smaller than the window size). +If an input stream was compressed a given window size, then `DeflateIO` +using a smaller window size will fail mid-way during decompression with +:exc:`OSError`, but only if a back-reference actually refers back further +than the decompressor's window size. This means it may be possible to decompress +with a smaller window size. For example, this would trivially be the case if the +original uncompressed data is shorter than the window size. -If the decompressor uses a smaller window size than necessary for the input data -stream, it will fail mid-way through decompression with :exc:`OSError`. +Decompression +~~~~~~~~~~~~~ -.. _deflate_wbits_zlib: +The zlib format includes a header which specifies the window size that was used +to compress the data. This indicates the maximum window size required to +decompress this stream. If this header value is less than the specified *wbits* +value (or if *wbits* is unset), then the header value will be used. -The zlib format includes a header which specifies the window size used to -compress the data (which due to the above, may be larger than the size required -for the decompressor). +The gzip format does not include the window size in the header, and assumes that +all gzip compressors (e.g. the ``gzip`` utility, or CPython's implementation of +:class:`gzip.GzipFile`) use the maximum window size of 32kiB. For this reason, +if the *wbits* parameter is not set, the decompressor will use a 32 kiB window +size (corresponding to *wbits* set to 15). This means that to be able to +decompress an arbitrary gzip stream, you must have at least this much RAM +available. If you control the source data, consider instead using the zlib +format with a smaller window size. -If this header value is lower than the specified *wbits* value, then the header -value will be used instead in order to reduce the memory allocation size. If -the *wbits* parameter is zero (the default), then the header value will only be -used if it is less than the maximum value of ``15`` (which is default value -used by most compressors [#f1]_). +The raw format has no header and therefore does not include any information +about the window size. If *wbits* is not set, then it will default to a window +size of 256 bytes, which may not be large enough for a given stream. Therefore +it is recommended that you should always explicitly set *wbits* if using the raw +format. -In other words, if the source zlib stream has been compressed with a custom window -size (i.e. less than ``15``), then using the default *wbits* parameter of zero -will decompress any such stream. +Compression +~~~~~~~~~~~ -The gzip file format does not include the window size in the header. -Additionally, most compressor libraries (including CPython's implementation -of :class:`gzip.GzipFile`) will default to the maximum possible window size. -This makes it difficult to decompress most gzip streams on MicroPython unless -your board has a lot of free RAM. - -If you control the source of the compressed data, then prefer to use the zlib -format, with a window size that is suitable for your target device. - -.. rubric:: Footnotes - -.. [#f1] The assumption here is that if the header value is the default used by - most compressors, then nothing is known about the likely required window - size and we should ignore it. +For compression, MicroPython will default to a window size of 256 bytes for all +formats. This provides a reasonable amount of compression with minimal memory +usage and fast compression time, and will generate output that will work with +any decompressor. diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index efdd6c1be2..d6b4051a2f 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -51,13 +51,20 @@ Functions buffers and other data. This data is useful to get a sense of how much memory is available to ESP-IDF and the networking stack in particular. It may shed some light on situations where ESP-IDF operations fail due to allocation failures. - The information returned is *not* useful to troubleshoot Python allocation failures, - use `micropython.mem_info()` instead. The capabilities parameter corresponds to ESP-IDF's ``MALLOC_CAP_XXX`` values but the two most useful ones are predefined as `esp32.HEAP_DATA` for data heap regions and `esp32.HEAP_EXEC` for executable regions as used by the native code emitter. + Free IDF heap memory in the `esp32.HEAP_DATA` region is available to be + automatically added to the MicroPython heap to prevent a MicroPython + allocation from failing. However, the information returned here is otherwise + *not* useful to troubleshoot Python allocation failures, use + `micropython.mem_info()` instead. The "max new split" value in + `micropython.mem_info()` output corresponds to the largest free block of + ESP-IDF heap that could be automatically added on demand to the MicroPython + heap. + The return value is a list of 4-tuples, where each 4-tuple corresponds to one heap and contains: the total bytes, the free bytes, the largest free block, and the minimum free seen over time. @@ -107,6 +114,11 @@ methods to enable over-the-air (OTA) updates. Sets the partition as the boot partition. + .. note:: Do not enter :func:`deepsleep` after changing + the OTA boot partition, without first performing a hard + :func:`reset` or power cycle. This ensures the bootloader + will validate the new image before booting. + .. method:: Partition.get_next_update() Gets the next update partition after this one, and returns a new Partition object. diff --git a/docs/library/index.rst b/docs/library/index.rst index ae5d3e7d71..4a7f78ecf3 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -71,6 +71,7 @@ library. json.rst math.rst os.rst + platform.rst random.rst re.rst select.rst diff --git a/docs/library/neopixel.rst b/docs/library/neopixel.rst index 543f258812..edcbc9345c 100644 --- a/docs/library/neopixel.rst +++ b/docs/library/neopixel.rst @@ -9,9 +9,7 @@ This module provides a driver for WS2818 / NeoPixel LEDs. .. note:: This module is only included by default on the ESP8266, ESP32 and RP2 ports. On STM32 / Pyboard and others, you can either install the ``neopixel`` package using :term:`mip`, or you can download the module - directly from - `_ - and copy it to the filesystem. + directly from :term:`micropython-lib` and copy it to the filesystem. class NeoPixel -------------- diff --git a/docs/library/network.rst b/docs/library/network.rst index b13c84123c..a14d6192ea 100644 --- a/docs/library/network.rst +++ b/docs/library/network.rst @@ -171,8 +171,8 @@ The following are functions available in the network module. .. function:: hostname([name]) - Get or set the hostname that will identify this device on the network. It is - applied to all interfaces. + Get or set the hostname that will identify this device on the network. It will + be used by all interfaces. This hostname is used for: * Sending to the DHCP server in the client request. (If using DHCP) @@ -182,6 +182,12 @@ The following are functions available in the network module. If the function is called without parameters, it returns the current hostname. + A change in hostname is typically only applied during connection. For DHCP + this is because the hostname is part of the DHCP client request, and the + implementation of mDNS in most ports only initialises the hostname once + during connection. For this reason, you must set the hostname before + activating/connecting your network interfaces. + The default hostname is typically the name of the board. .. function:: phy_mode([mode]) diff --git a/docs/library/platform.rst b/docs/library/platform.rst new file mode 100644 index 0000000000..c091477d84 --- /dev/null +++ b/docs/library/platform.rst @@ -0,0 +1,38 @@ +:mod:`platform` -- access to underlying platform’s identifying data +=================================================================== + +.. module:: platform + :synopsis: access to underlying platform’s identifying data + +|see_cpython_module| :mod:`python:platform`. + +This module tries to retrieve as much platform-identifying data as possible. It +makes this information available via function APIs. + +Functions +--------- + +.. function:: platform() + + Returns a string identifying the underlying platform. This string is composed + of several substrings in the following order, delimited by dashes (``-``): + + - the name of the platform system (e.g. Unix, Windows or MicroPython) + - the MicroPython version + - the architecture of the platform + - the version of the underlying platform + - the concatenation of the name of the libc that MicroPython is linked to + and its corresponding version. + + For example, this could be + ``"MicroPython-1.20.0-xtensa-IDFv4.2.4-with-newlib3.0.0"``. + +.. function:: python_compiler() + + Returns a string identifying the compiler used for compiling MicroPython. + +.. function:: libc_ver() + + Returns a tuple of strings *(lib, version)*, where *lib* is the name of the + libc that MicroPython is linked to, and *version* the corresponding version + of this libc. diff --git a/docs/library/stm.rst b/docs/library/stm.rst index a181d6044c..970ab18834 100644 --- a/docs/library/stm.rst +++ b/docs/library/stm.rst @@ -102,3 +102,39 @@ the second CPU, the RF core. Execute a HCI command on the SYS channel. The execution is synchronous. Returns a bytes object with the result of the SYS command. + +Functions specific to STM32WLxx MCUs +------------------------------------ + +These functions are available on STM32WLxx microcontrollers, and interact with +the integrated "SUBGHZ" radio modem peripheral. + +.. function:: subghz_cs(level) + + Sets the internal SPI CS pin attached to the radio peripheral. The ``level`` + argument is active-low: a truthy value means "CS pin high" and de-asserts the + signal, a falsey value means "CS pin low" and asserts the signal. + + The internal-only SPI bus corresponding to this CS signal can be instantiated + using :ref:`machine.SPI()` ``id`` value ``"SUBGHZ"``. + +.. function:: subghz_irq(handler) + + Sets the internal SUBGHZ radio interrupt handler to the provided + function. The handler function is called as a "hard" interrupt in response to + radio peripheral interrupts. See :ref:`isr_rules` for more information about + interrupt handlers in MicroPython. + + Calling this function with the handler argument set to None disables the IRQ. + + Due to a hardware limitation, each time this IRQ fires MicroPython disables + it before calling the handler. In order to receive another interrupt, Python + code should call ``subghz_irq()`` to set the handler again. This has the side + effect of re-enabling the IRQ. + +.. function:: subghz_is_busy() + + Return a ``bool`` corresponding to the internal "RFBUSYS" signal from the + radio peripheral. Before sending a new command to the radio over SPI then + this function should be polled until it returns ``False``, to confirm the + busy signal is de-asserted. diff --git a/drivers/cyw43/cywbt.c b/drivers/cyw43/cywbt.c index 006fd28e90..bc6674ea2e 100644 --- a/drivers/cyw43/cywbt.c +++ b/drivers/cyw43/cywbt.c @@ -29,8 +29,6 @@ #include "py/runtime.h" #include "py/mphal.h" -#include "pin_static_af.h" -#include "uart.h" #include "extmod/mpbthci.h" #if MICROPY_PY_NETWORK_CYW43 @@ -38,33 +36,41 @@ #include "lib/cyw43-driver/src/cyw43_config.h" #include "lib/cyw43-driver/firmware/cyw43_btfw_4343A1.h" -// Provided by the port. -extern pyb_uart_obj_t mp_bluetooth_hci_uart_obj; - // Provided by the port, and also possibly shared with the stack. extern uint8_t mp_bluetooth_hci_cmd_buf[4 + 256]; /******************************************************************************/ // CYW BT HCI low-level driver +#ifdef CYW43_PIN_BT_CTS +// This code is not portable and currently only builds on stm32 port. + +#include "pin_static_af.h" +#include "uart.h" + +// Provided by the port. +extern pyb_uart_obj_t mp_bluetooth_hci_uart_obj; + STATIC void cywbt_wait_cts_low(void) { - mp_hal_pin_config(pyb_pin_BT_CTS, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); + mp_hal_pin_config(CYW43_PIN_BT_CTS, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); for (int i = 0; i < 200; ++i) { - if (mp_hal_pin_read(pyb_pin_BT_CTS) == 0) { + if (mp_hal_pin_read(CYW43_PIN_BT_CTS) == 0) { break; } mp_hal_delay_ms(1); } - mp_hal_pin_config_alt(pyb_pin_BT_CTS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_UART, mp_bluetooth_hci_uart_obj.uart_id); + mp_hal_pin_config_alt(CYW43_PIN_BT_CTS, MP_HAL_PIN_MODE_ALT, + MP_HAL_PIN_PULL_UP, AF_FN_UART, mp_bluetooth_hci_uart_obj.uart_id); } +#endif STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) { - uart_tx_strn(&mp_bluetooth_hci_uart_obj, (void*)buf, len); - for (int i = 0; i < 6; ++i) { - while (!uart_rx_any(&mp_bluetooth_hci_uart_obj)) { + mp_bluetooth_hci_uart_write((void *)buf, len); + for (int c, i = 0; i < 6; ++i) { + while ((c = mp_bluetooth_hci_uart_readchar()) == -1) { MICROPY_EVENT_POLL_HOOK } - buf[i] = uart_rx_char(&mp_bluetooth_hci_uart_obj); + buf[i] = c; } // expect a command complete event (event 0x0e) @@ -80,11 +86,11 @@ STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) { */ int sz = buf[2] - 3; - for (int i = 0; i < sz; ++i) { - while (!uart_rx_any(&mp_bluetooth_hci_uart_obj)) { + for (int c, i = 0; i < sz; ++i) { + while ((c = mp_bluetooth_hci_uart_readchar()) == -1) { MICROPY_EVENT_POLL_HOOK } - buf[i] = uart_rx_char(&mp_bluetooth_hci_uart_obj); + buf[i] = c; } return 0; @@ -150,12 +156,15 @@ STATIC int cywbt_download_firmware(const uint8_t *firmware) { // RF switch must select high path during BT patch boot #if MICROPY_HW_ENABLE_RF_SWITCH - mp_hal_pin_config(pyb_pin_WL_GPIO_1, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); + mp_hal_pin_config(CYW43_PIN_WL_GPIO_1, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); #endif mp_hal_delay_ms(10); // give some time for CTS to go high + #ifdef CYW43_PIN_BT_CTS cywbt_wait_cts_low(); + #endif #if MICROPY_HW_ENABLE_RF_SWITCH - mp_hal_pin_config(pyb_pin_WL_GPIO_1, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_DOWN, 0); // Select chip antenna (could also select external) + // Select chip antenna (could also select external) + mp_hal_pin_config(CYW43_PIN_WL_GPIO_1, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_DOWN, 0); #endif mp_bluetooth_hci_uart_set_baudrate(115200); @@ -168,25 +177,33 @@ STATIC int cywbt_download_firmware(const uint8_t *firmware) { int mp_bluetooth_hci_controller_init(void) { // This is called immediately after the UART is initialised during stack initialisation. - mp_hal_pin_output(pyb_pin_BT_REG_ON); - mp_hal_pin_low(pyb_pin_BT_REG_ON); - mp_hal_pin_input(pyb_pin_BT_HOST_WAKE); - mp_hal_pin_output(pyb_pin_BT_DEV_WAKE); - mp_hal_pin_low(pyb_pin_BT_DEV_WAKE); + mp_hal_pin_output(CYW43_PIN_BT_REG_ON); + mp_hal_pin_low(CYW43_PIN_BT_REG_ON); + #ifdef CYW43_PIN_BT_HOST_WAKE + mp_hal_pin_input(CYW43_PIN_BT_HOST_WAKE); + #endif + #ifdef CYW43_PIN_BT_DEV_WAKE + mp_hal_pin_output(CYW43_PIN_BT_DEV_WAKE); + mp_hal_pin_low(CYW43_PIN_BT_DEV_WAKE); + #endif #if MICROPY_HW_ENABLE_RF_SWITCH // TODO don't select antenna if wifi is enabled - mp_hal_pin_config(pyb_pin_WL_GPIO_4, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); // RF-switch power - mp_hal_pin_high(pyb_pin_WL_GPIO_4); // Turn the RF-switch on + mp_hal_pin_config(CYW43_PIN_WL_GPIO_4, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); // RF-switch power + mp_hal_pin_high(CYW43_PIN_WL_GPIO_4); // Turn the RF-switch on #endif uint8_t buf[256]; - mp_hal_pin_low(pyb_pin_BT_REG_ON); + mp_hal_pin_low(CYW43_PIN_BT_REG_ON); mp_bluetooth_hci_uart_set_baudrate(115200); mp_hal_delay_ms(100); - mp_hal_pin_high(pyb_pin_BT_REG_ON); + mp_hal_pin_high(CYW43_PIN_BT_REG_ON); + #ifdef CYW43_PIN_BT_CTS cywbt_wait_cts_low(); + #else + mp_hal_delay_ms(100); + #endif // Reset cywbt_hci_cmd(0x03, 0x0003, 0, NULL); @@ -197,7 +214,7 @@ int mp_bluetooth_hci_controller_init(void) { mp_bluetooth_hci_uart_set_baudrate(MICROPY_HW_BLE_UART_BAUDRATE_DOWNLOAD_FIRMWARE); #endif - cywbt_download_firmware((const uint8_t*)&cyw43_btfw_4343A1[0]); + cywbt_download_firmware((const uint8_t *)&cyw43_btfw_4343A1[0]); // Reset cywbt_hci_cmd(0x03, 0x0003, 0, NULL); @@ -219,31 +236,33 @@ int mp_bluetooth_hci_controller_init(void) { // cywbt_hci_cmd(0x03, 0x0013, 248, buf); // Configure sleep mode - cywbt_hci_cmd(0x3f, 0x27, 12, (const uint8_t*)"\x01\x02\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00"); + cywbt_hci_cmd(0x3f, 0x27, 12, (const uint8_t *)"\x01\x02\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00"); // HCI_Write_LE_Host_Support - cywbt_hci_cmd(3, 109, 2, (const uint8_t*)"\x01\x00"); + cywbt_hci_cmd(3, 109, 2, (const uint8_t *)"\x01\x00"); - mp_hal_pin_high(pyb_pin_BT_DEV_WAKE); // let sleep + #ifdef CYW43_PIN_BT_DEV_WAKE + mp_hal_pin_high(CYW43_PIN_BT_DEV_WAKE); // let sleep + #endif return 0; } int mp_bluetooth_hci_controller_deinit(void) { - mp_hal_pin_low(pyb_pin_BT_REG_ON); + mp_hal_pin_low(CYW43_PIN_BT_REG_ON); return 0; } -#ifdef pyb_pin_BT_DEV_WAKE +#ifdef CYW43_PIN_BT_DEV_WAKE STATIC uint32_t bt_sleep_ticks; #endif int mp_bluetooth_hci_controller_sleep_maybe(void) { - #ifdef pyb_pin_BT_DEV_WAKE - if (mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 0) { + #ifdef CYW43_PIN_BT_DEV_WAKE + if (mp_hal_pin_read(CYW43_PIN_BT_DEV_WAKE) == 0) { if (mp_hal_ticks_ms() - bt_sleep_ticks > 500) { - mp_hal_pin_high(pyb_pin_BT_DEV_WAKE); // let sleep + mp_hal_pin_high(CYW43_PIN_BT_DEV_WAKE); // let sleep } } #endif @@ -251,8 +270,8 @@ int mp_bluetooth_hci_controller_sleep_maybe(void) { } bool mp_bluetooth_hci_controller_woken(void) { - #ifdef pyb_pin_BT_HOST_WAKE - bool host_wake = mp_hal_pin_read(pyb_pin_BT_HOST_WAKE); + #ifdef CYW43_PIN_BT_HOST_WAKE + bool host_wake = mp_hal_pin_read(CYW43_PIN_BT_HOST_WAKE); /* // this is just for info/tracing purposes static bool last_host_wake = false; @@ -268,11 +287,11 @@ bool mp_bluetooth_hci_controller_woken(void) { } int mp_bluetooth_hci_controller_wakeup(void) { - #ifdef pyb_pin_BT_DEV_WAKE + #ifdef CYW43_PIN_BT_DEV_WAKE bt_sleep_ticks = mp_hal_ticks_ms(); - if (mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 1) { - mp_hal_pin_low(pyb_pin_BT_DEV_WAKE); // wake up + if (mp_hal_pin_read(CYW43_PIN_BT_DEV_WAKE) == 1) { + mp_hal_pin_low(CYW43_PIN_BT_DEV_WAKE); // wake up // Use delay_us rather than delay_ms to prevent running the scheduler (which // might result in more BLE operations). mp_hal_delay_us(5000); // can't go lower than this diff --git a/examples/asmled.py b/examples/asmled.py index 09a06c184a..4ff35dfdf8 100644 --- a/examples/asmled.py +++ b/examples/asmled.py @@ -1,5 +1,9 @@ # flash LED #1 using inline assembler # this version is overly verbose and uses word stores +# +# ruff: noqa: F821 - @asm_thumb decorator adds names to function scope + + @micropython.asm_thumb def flash_led(r0): movw(r1, (stm.GPIOA + stm.GPIO_BSRRL) & 0xFFFF) diff --git a/examples/asmsum.py b/examples/asmsum.py index f2c7f285ba..2d8c2b2c99 100644 --- a/examples/asmsum.py +++ b/examples/asmsum.py @@ -1,3 +1,6 @@ +# ruff: noqa: F821 - @asm_thumb decorator adds names to function scope + + @micropython.asm_thumb def asm_sum_words(r0, r1): # r0 = len diff --git a/examples/bluetooth/ble_advertising.py b/examples/bluetooth/ble_advertising.py index eed527f55d..2fe17d640b 100644 --- a/examples/bluetooth/ble_advertising.py +++ b/examples/bluetooth/ble_advertising.py @@ -1,5 +1,9 @@ # Helpers for generating BLE advertising payloads. +# A more fully-featured (and easier to use) version of this is implemented in +# aioble. This code is provided just as a basic example. See +# https://github.com/micropython/micropython-lib/tree/master/micropython/bluetooth/aioble + from micropython import const import struct import bluetooth @@ -19,6 +23,8 @@ _ADV_TYPE_UUID32_MORE = const(0x4) _ADV_TYPE_UUID128_MORE = const(0x6) _ADV_TYPE_APPEARANCE = const(0x19) +_ADV_MAX_PAYLOAD = const(31) + # Generate a payload to be passed to gap_advertise(adv_data=...). def advertising_payload(limited_disc=False, br_edr=False, name=None, services=None, appearance=0): @@ -50,6 +56,9 @@ def advertising_payload(limited_disc=False, br_edr=False, name=None, services=No if appearance: _append(_ADV_TYPE_APPEARANCE, struct.pack(" _ADV_MAX_PAYLOAD: + raise ValueError("advertising payload too large") + return payload diff --git a/examples/bluetooth/ble_bonding_peripheral.py b/examples/bluetooth/ble_bonding_peripheral.py index bd7596dbcb..c3ae5f262a 100644 --- a/examples/bluetooth/ble_bonding_peripheral.py +++ b/examples/bluetooth/ble_bonding_peripheral.py @@ -4,6 +4,11 @@ # any connected central every 10 seconds. # # Work-in-progress demo of implementing bonding and passkey auth. +# +# This example demonstrates the low-level bluetooth module. For most +# applications, we recommend using the higher-level aioble library, which +# includes an implementation of the secret store. See +# https://github.com/micropython/micropython-lib/tree/master/micropython/bluetooth/aioble import bluetooth import random diff --git a/examples/bluetooth/ble_simple_central.py b/examples/bluetooth/ble_simple_central.py index 3c0cf2a0d4..caf6333472 100644 --- a/examples/bluetooth/ble_simple_central.py +++ b/examples/bluetooth/ble_simple_central.py @@ -1,6 +1,11 @@ # This example finds and connects to a peripheral running the # UART service (e.g. ble_simple_peripheral.py). +# This example demonstrates the low-level bluetooth module. For most +# applications, we recommend using the higher-level aioble library which takes +# care of all IRQ handling and connection management. See +# https://github.com/micropython/micropython-lib/tree/master/micropython/bluetooth/aioble + import bluetooth import random import struct diff --git a/examples/bluetooth/ble_simple_peripheral.py b/examples/bluetooth/ble_simple_peripheral.py index 0ebe431764..bdb5ed88c7 100644 --- a/examples/bluetooth/ble_simple_peripheral.py +++ b/examples/bluetooth/ble_simple_peripheral.py @@ -1,5 +1,10 @@ # This example demonstrates a UART periperhal. +# This example demonstrates the low-level bluetooth module. For most +# applications, we recommend using the higher-level aioble library which takes +# care of all IRQ handling and connection management. See +# https://github.com/micropython/micropython-lib/tree/master/micropython/bluetooth/aioble + import bluetooth import random import struct diff --git a/examples/bluetooth/ble_temperature.py b/examples/bluetooth/ble_temperature.py index e6378ebee7..acd77127ad 100644 --- a/examples/bluetooth/ble_temperature.py +++ b/examples/bluetooth/ble_temperature.py @@ -3,6 +3,12 @@ # The sensor's local value updates every second, and it will notify # any connected central every 10 seconds. +# This example demonstrates the low-level bluetooth module. For most +# applications, we recommend using the higher-level aioble library which takes +# care of all IRQ handling and connection management. See +# https://github.com/micropython/micropython-lib/tree/master/micropython/bluetooth/aioble +# and in particular the temp_sensor.py example included with aioble. + import bluetooth import random import struct diff --git a/examples/bluetooth/ble_temperature_central.py b/examples/bluetooth/ble_temperature_central.py index afa914672c..fe1c70636f 100644 --- a/examples/bluetooth/ble_temperature_central.py +++ b/examples/bluetooth/ble_temperature_central.py @@ -1,5 +1,11 @@ # This example finds and connects to a BLE temperature sensor (e.g. the one in ble_temperature.py). +# This example demonstrates the low-level bluetooth module. For most +# applications, we recommend using the higher-level aioble library which takes +# care of all IRQ handling and connection management. See +# https://github.com/micropython/micropython-lib/tree/master/micropython/bluetooth/aioble +# and in particular the temp_client.py example included with aioble. + import bluetooth import random import struct diff --git a/examples/bluetooth/ble_uart_peripheral.py b/examples/bluetooth/ble_uart_peripheral.py index b4e352be9f..0de4fe2ed4 100644 --- a/examples/bluetooth/ble_uart_peripheral.py +++ b/examples/bluetooth/ble_uart_peripheral.py @@ -1,5 +1,10 @@ # This example demonstrates a peripheral implementing the Nordic UART Service (NUS). +# This example demonstrates the low-level bluetooth module. For most +# applications, we recommend using the higher-level aioble library which takes +# care of all IRQ handling and connection management. See +# https://github.com/micropython/micropython-lib/tree/master/micropython/bluetooth/aioble + import bluetooth from ble_advertising import advertising_payload diff --git a/examples/bluetooth/ble_uart_repl.py b/examples/bluetooth/ble_uart_repl.py index 7d92c1f318..5812a5cc13 100644 --- a/examples/bluetooth/ble_uart_repl.py +++ b/examples/bluetooth/ble_uart_repl.py @@ -7,6 +7,7 @@ import bluetooth import io import os import micropython +from micropython import const import machine from ble_uart_peripheral import BLEUART diff --git a/examples/hwapi/hwconfig_z_96b_carbon.py b/examples/hwapi/hwconfig_z_96b_carbon.py index 97fd57a07f..d4f98139bc 100644 --- a/examples/hwapi/hwconfig_z_96b_carbon.py +++ b/examples/hwapi/hwconfig_z_96b_carbon.py @@ -1,4 +1,4 @@ -from machine import Signal +from machine import Pin, Signal # 96Boards Carbon board # USR1 - User controlled led, connected to PD2 diff --git a/examples/natmod/README.md b/examples/natmod/README.md new file mode 100644 index 0000000000..0cc4010ef4 --- /dev/null +++ b/examples/natmod/README.md @@ -0,0 +1,74 @@ +# Dynamic Native Modules + +Dynamic Native Modules are .mpy files that contain native machine code from a +language other than Python. For more info see [the documentation] +(https://docs.micropython.org/en/latest/develop/natmod.html). + +This should not be confused with [User C Modules] +(https://docs.micropython.org/en/latest/develop/cmodules.html) which are a +mechanism to add additional out-of-tree modules into the firmware build. + +## Examples + +This directory contains several examples of writing dynamic native modules, in +two main categories: + +1. Feature examples. + + * `features0` - A module containing a single "factorial" function which + demonstrates working with integers. + + * `features1` - A module that demonstrates some common tasks: + - defining simple functions exposed to Python + - defining local, helper C functions + - defining constant integers and strings exposed to Python + - getting and creating integer objects + - creating Python lists + - raising exceptions + - allocating memory + - BSS and constant data (rodata) + - relocated pointers in rodata + + * `features2` - This is a hybrid module containing both Python and C code, + and additionally the C code is spread over multiple files. It also + demonstrates using floating point (only when the target supports + hardware floating point). + + * `features3` - A module that shows how to use types, constant objects, + and creating dictionary instances. + + * `features4` - A module that demonstrates how to define a class. + +2. Dynamic version of existing built-ins. + + This provides a way to add missing functionality to firmware that doesn't + include certain built-in modules. See the `heapq`, `random`, `re`, + `deflate`, `btree`, and `framebuf` directories. + + So for example, if your firmware was compiled with `MICROPY_PY_FRAMEBUF` + disabled (e.g. to save flash space), then it would not include the + `framebuf` module. The `framebuf` native module provides a way to add the + `framebuf` module dynamically. + + The way these work is they define a dynamic native module which + `#include`'s the original module and then does the necessary + initialisation of the module's globals dict. + +## Build instructions + +To compile an example, you need to have the same toolchain available as +required for your target port. e.g. `arm-none-eabi-gcc` for any ARM Cortex M +target. See the port instructions for details. + +You also need to have the `pyelftools` Python package available, either via +your system package manager or installed from PyPI in a virtual environment +with `pip`. + +Each example provides a Makefile. You should specify the `ARCH` argument to +make (one of x86, x64, armv6m, armv7m, xtensa, xtensawin): + +``` +$ cd features0 +$ make ARCH=armv7m +$ mpremote cp features0.mpy : +``` diff --git a/examples/natmod/btree/btree_py.py b/examples/natmod/btree/btree_py.py index bd53c084a1..461b045c98 100644 --- a/examples/natmod/btree/btree_py.py +++ b/examples/natmod/btree/btree_py.py @@ -1,3 +1,7 @@ # Implemented in Python to support keyword arguments + +# ruff: noqa: F821 - this file is evaluated with C-defined names in scope + + def open(stream, *, flags=0, cachesize=0, pagesize=0, minkeypage=0): return _open(stream, flags, cachesize, pagesize, minkeypage) diff --git a/examples/natmod/features2/test.py b/examples/natmod/features2/test.py index 5ac80120d7..af79b9692c 100644 --- a/examples/natmod/features2/test.py +++ b/examples/natmod/features2/test.py @@ -1,5 +1,7 @@ # This Python code will be merged with the C code in main.c +# ruff: noqa: F821 - this file is evaluated with C-defined names in scope + import array diff --git a/examples/natmod/features4/Makefile b/examples/natmod/features4/Makefile new file mode 100644 index 0000000000..f76a31a7cc --- /dev/null +++ b/examples/natmod/features4/Makefile @@ -0,0 +1,14 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module +MOD = features4 + +# Source files (.c or .py) +SRC = features4.c + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +# Include to get the rules for compiling and linking the module +include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/features4/features4.c b/examples/natmod/features4/features4.c new file mode 100644 index 0000000000..336f4ecf64 --- /dev/null +++ b/examples/natmod/features4/features4.c @@ -0,0 +1,73 @@ +/* + This example extends on features0 but demonstrates how to define a class. + + The Factorial class constructor takes an integer, and then the calculate + method can be called to get the factorial. + + >>> import features4 + >>> f = features4.Factorial(4) + >>> f.calculate() + 24 +*/ + +// Include the header file to get access to the MicroPython API +#include "py/dynruntime.h" + +// This is type(Factorial) +mp_obj_full_type_t mp_type_factorial; + +// This is the internal state of a Factorial instance. +typedef struct { + mp_obj_base_t base; + mp_int_t n; +} mp_obj_factorial_t; + +// Essentially Factorial.__new__ (but also kind of __init__). +// Takes a single argument (the number to find the factorial of) +STATIC mp_obj_t factorial_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args_in) { + mp_arg_check_num(n_args, n_kw, 1, 1, false); + + mp_obj_factorial_t *o = mp_obj_malloc(mp_obj_factorial_t, type); + o->n = mp_obj_get_int(args_in[0]); + + return MP_OBJ_FROM_PTR(o); +} + +STATIC mp_int_t factorial_helper(mp_int_t x) { + if (x == 0) { + return 1; + } + return x * factorial_helper(x - 1); +} + +// Implements Factorial.calculate() +STATIC mp_obj_t factorial_calculate(mp_obj_t self_in) { + mp_obj_factorial_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int(factorial_helper(self->n)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_calculate_obj, factorial_calculate); + +// Locals dict for the Factorial type (will have a single method, calculate, +// added in mpy_init). +mp_map_elem_t factorial_locals_dict_table[1]; +STATIC MP_DEFINE_CONST_DICT(factorial_locals_dict, factorial_locals_dict_table); + +// This is the entry point and is called when the module is imported +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + // This must be first, it sets up the globals dict and other things + MP_DYNRUNTIME_INIT_ENTRY + + // Initialise the type. + mp_type_factorial.base.type = (void*)&mp_type_type; + mp_type_factorial.flags = MP_TYPE_FLAG_NONE; + mp_type_factorial.name = MP_QSTR_Factorial; + MP_OBJ_TYPE_SET_SLOT(&mp_type_factorial, make_new, factorial_make_new, 0); + factorial_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_calculate), MP_OBJ_FROM_PTR(&factorial_calculate_obj) }; + MP_OBJ_TYPE_SET_SLOT(&mp_type_factorial, locals_dict, (void*)&factorial_locals_dict, 1); + + // Make the Factorial type available on the module. + mp_store_global(MP_QSTR_Factorial, MP_OBJ_FROM_PTR(&mp_type_factorial)); + + // This must be last, it restores the globals dict + MP_DYNRUNTIME_INIT_EXIT +} diff --git a/examples/rp2/pio_1hz.py b/examples/rp2/pio_1hz.py index 84d761fa14..3ffab79d56 100644 --- a/examples/rp2/pio_1hz.py +++ b/examples/rp2/pio_1hz.py @@ -1,6 +1,8 @@ # Example using PIO to blink an LED and raise an IRQ at 1Hz. # Note: this does not work on Pico W because it uses Pin(25) for LED output. +# ruff: noqa: F821 - @asm_pio decorator adds names to function scope + import time from machine import Pin import rp2 diff --git a/examples/rp2/pio_exec.py b/examples/rp2/pio_exec.py index ce39f2df84..3bea51f8dd 100644 --- a/examples/rp2/pio_exec.py +++ b/examples/rp2/pio_exec.py @@ -5,6 +5,8 @@ # - using set_init and set_base # - using StateMachine.exec +# ruff: noqa: F821 - @asm_pio decorator adds names to function scope + import time from machine import Pin import rp2 diff --git a/examples/rp2/pio_pinchange.py b/examples/rp2/pio_pinchange.py index 767c8e78c2..4a210e7f39 100644 --- a/examples/rp2/pio_pinchange.py +++ b/examples/rp2/pio_pinchange.py @@ -8,6 +8,8 @@ # - setting an irq handler for a StateMachine # - instantiating 2x StateMachine's with the same program and different pins +# ruff: noqa: F821 - @asm_pio decorator adds names to function scope + import time from machine import Pin import rp2 diff --git a/examples/rp2/pio_pwm.py b/examples/rp2/pio_pwm.py index 176a238091..24fd6b85a3 100644 --- a/examples/rp2/pio_pwm.py +++ b/examples/rp2/pio_pwm.py @@ -1,5 +1,7 @@ # Example of using PIO for PWM, and fading the brightness of an LED +# ruff: noqa: F821 - @asm_pio decorator adds names to function scope + from machine import Pin from rp2 import PIO, StateMachine, asm_pio from time import sleep diff --git a/examples/rp2/pio_uart_rx.py b/examples/rp2/pio_uart_rx.py index 080b6bd639..f46aaa6a5e 100644 --- a/examples/rp2/pio_uart_rx.py +++ b/examples/rp2/pio_uart_rx.py @@ -8,6 +8,8 @@ # - PIO irq handler # - using the second core via _thread +# ruff: noqa: F821 - @asm_pio decorator adds names to function scope + import _thread from machine import Pin, UART from rp2 import PIO, StateMachine, asm_pio diff --git a/examples/rp2/pio_uart_tx.py b/examples/rp2/pio_uart_tx.py index 5e4af8f6cc..04abf2d0d1 100644 --- a/examples/rp2/pio_uart_tx.py +++ b/examples/rp2/pio_uart_tx.py @@ -1,5 +1,7 @@ # Example using PIO to create a UART TX interface +# ruff: noqa: F821 - @asm_pio decorator adds names to function scope + from machine import Pin from rp2 import PIO, StateMachine, asm_pio diff --git a/examples/rp2/pio_ws2812.py b/examples/rp2/pio_ws2812.py index dd021a9d56..6de21ab8b7 100644 --- a/examples/rp2/pio_ws2812.py +++ b/examples/rp2/pio_ws2812.py @@ -1,5 +1,7 @@ # Example using PIO to drive a set of WS2812 LEDs. +# ruff: noqa: F821 - @asm_pio decorator adds names to function scope + import array, time from machine import Pin import rp2 diff --git a/examples/rp2/pwm_fade.py b/examples/rp2/pwm_fade.py index 5b7089c6b1..6672f3443f 100644 --- a/examples/rp2/pwm_fade.py +++ b/examples/rp2/pwm_fade.py @@ -1,6 +1,8 @@ # Example using PWM to fade an LED. # Note: this does not work on Pico W because it uses Pin(25) for LED output. +# ruff: noqa: F821 - @asm_pio decorator adds names to function scope + import time from machine import Pin, PWM diff --git a/extmod/extmod.cmake b/extmod/extmod.cmake index 305cdee942..c8756a682e 100644 --- a/extmod/extmod.cmake +++ b/extmod/extmod.cmake @@ -60,51 +60,62 @@ set(MICROPY_SOURCE_EXTMOD if(MICROPY_PY_BTREE) set(MICROPY_LIB_BERKELEY_DIR "${MICROPY_DIR}/lib/berkeley-db-1.xx") + string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/berkeley-db-1.xx) - add_library(micropy_extmod_btree OBJECT - ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_close.c - ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_conv.c - ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_debug.c - ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_delete.c - ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_get.c - ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_open.c - ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_overflow.c - ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_page.c - ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_put.c - ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_search.c - ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_seq.c - ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_split.c - ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_utils.c - ${MICROPY_LIB_BERKELEY_DIR}/mpool/mpool.c - ) + if(ECHO_SUBMODULES) + # No-op, we're just doing submodule/variant discovery. + # Cannot run the add_library/target_include_directories rules (even though + # the build won't run) because IDF will attempt verify the files exist. + elseif(NOT EXISTS ${MICROPY_LIB_BERKELEY_DIR}/README) + # Regular build, submodule not initialised -- fail with a clear error. + message(FATAL_ERROR " MICROPY_PY_BTREE is enabled but the berkeley-db submodule is not initialised.\n Run 'make BOARD=${MICROPY_BOARD} submodules'") + else() + # Regular build, we have the submodule. + add_library(micropy_extmod_btree OBJECT + ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_close.c + ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_conv.c + ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_debug.c + ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_delete.c + ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_get.c + ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_open.c + ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_overflow.c + ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_page.c + ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_put.c + ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_search.c + ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_seq.c + ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_split.c + ${MICROPY_LIB_BERKELEY_DIR}/btree/bt_utils.c + ${MICROPY_LIB_BERKELEY_DIR}/mpool/mpool.c + ) - target_include_directories(micropy_extmod_btree PRIVATE - ${MICROPY_LIB_BERKELEY_DIR}/PORT/include - ) + target_include_directories(micropy_extmod_btree PRIVATE + ${MICROPY_LIB_BERKELEY_DIR}/PORT/include + ) - target_compile_definitions(micropy_extmod_btree PRIVATE - __DBINTERFACE_PRIVATE=1 - mpool_error=printf - abort=abort_ - "virt_fd_t=void*" - ) + target_compile_definitions(micropy_extmod_btree PRIVATE + __DBINTERFACE_PRIVATE=1 + mpool_error=printf + abort=abort_ + "virt_fd_t=void*" + ) - # The include directories and compile definitions below are needed to build - # modbtree.c and should be added to the main MicroPython target. + # The include directories and compile definitions below are needed to build + # modbtree.c and should be added to the main MicroPython target. - list(APPEND MICROPY_INC_CORE - "${MICROPY_LIB_BERKELEY_DIR}/PORT/include" - ) + list(APPEND MICROPY_INC_CORE + "${MICROPY_LIB_BERKELEY_DIR}/PORT/include" + ) - list(APPEND MICROPY_DEF_CORE - MICROPY_PY_BTREE=1 - __DBINTERFACE_PRIVATE=1 - "virt_fd_t=void*" - ) + list(APPEND MICROPY_DEF_CORE + MICROPY_PY_BTREE=1 + __DBINTERFACE_PRIVATE=1 + "virt_fd_t=void*" + ) - list(APPEND MICROPY_SOURCE_EXTMOD - ${MICROPY_EXTMOD_DIR}/modbtree.c - ) + list(APPEND MICROPY_SOURCE_EXTMOD + ${MICROPY_EXTMOD_DIR}/modbtree.c + ) + endif() endif() # Library for mbedtls diff --git a/extmod/moddeflate.c b/extmod/moddeflate.c index 1d8a8acf73..560ee3f0ab 100644 --- a/extmod/moddeflate.c +++ b/extmod/moddeflate.c @@ -54,6 +54,8 @@ typedef enum { DEFLATEIO_FORMAT_MAX = DEFLATEIO_FORMAT_GZIP, } deflateio_format_t; +// This is used when the wbits is unset in the DeflateIO constructor. Default +// to the smallest window size (faster compression, less RAM usage, etc). const int DEFLATEIO_DEFAULT_WBITS = 8; typedef struct { @@ -114,24 +116,32 @@ STATIC bool deflateio_init_read(mp_obj_deflateio_t *self) { // Don't modify self->window_bits as it may also be used for write. int wbits = self->window_bits; - // Parse the header if we're in NONE/ZLIB/GZIP modes. - if (self->format != DEFLATEIO_FORMAT_RAW) { - int header_wbits = wbits; + if (self->format == DEFLATEIO_FORMAT_RAW) { + if (wbits == 0) { + // The docs recommends always setting wbits explicitly when using + // RAW, but we still allow a default. + wbits = DEFLATEIO_DEFAULT_WBITS; + } + } else { + // Parse the header if we're in NONE/ZLIB/GZIP modes. + int header_wbits; int header_type = uzlib_parse_zlib_gzip_header(&self->read->decomp, &header_wbits); - if ((self->format == DEFLATEIO_FORMAT_ZLIB && header_type != UZLIB_HEADER_ZLIB) || (self->format == DEFLATEIO_FORMAT_GZIP && header_type != UZLIB_HEADER_GZIP)) { + if (header_type < 0) { + // Stream header was invalid. return false; } - if (wbits == 0 && header_wbits < 15) { - // If the header specified something lower than the default, then - // use that instead. + if ((self->format == DEFLATEIO_FORMAT_ZLIB && header_type != UZLIB_HEADER_ZLIB) || (self->format == DEFLATEIO_FORMAT_GZIP && header_type != UZLIB_HEADER_GZIP)) { + // Not what we expected. + return false; + } + // header_wbits will either be 15 (gzip) or 8-15 (zlib). + if (wbits == 0 || header_wbits < wbits) { + // If the header specified something lower, then use that instead. + // No point doing a bigger allocation than we need to. wbits = header_wbits; } } - if (wbits == 0) { - wbits = DEFLATEIO_DEFAULT_WBITS; - } - size_t window_len = 1 << wbits; self->read->window = m_new(uint8_t, window_len); @@ -163,6 +173,7 @@ STATIC bool deflateio_init_write(mp_obj_deflateio_t *self) { int wbits = self->window_bits; if (wbits == 0) { + // Same default wbits for all formats. wbits = DEFLATEIO_DEFAULT_WBITS; } size_t window_len = 1 << wbits; diff --git a/extmod/modlwip.c b/extmod/modlwip.c index 0d4c03c68a..c881f0df6a 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -1377,7 +1377,8 @@ STATIC mp_obj_t lwip_socket_setsockopt(size_t n_args, const mp_obj_t *args) { switch (opt) { // level: SOL_SOCKET - case SOF_REUSEADDR: { + case SOF_REUSEADDR: + case SOF_BROADCAST: { mp_int_t val = mp_obj_get_int(args[3]); // Options are common for UDP and TCP pcb's. if (val) { @@ -1786,6 +1787,7 @@ STATIC const mp_rom_map_elem_t mp_module_lwip_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(1) }, { MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(SOF_REUSEADDR) }, + { MP_ROM_QSTR(MP_QSTR_SO_BROADCAST), MP_ROM_INT(SOF_BROADCAST) }, { MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(0) }, { MP_ROM_QSTR(MP_QSTR_IP_ADD_MEMBERSHIP), MP_ROM_INT(IP_ADD_MEMBERSHIP) }, diff --git a/extmod/modnetwork.h b/extmod/modnetwork.h index 4786596e9b..e775612fe7 100644 --- a/extmod/modnetwork.h +++ b/extmod/modnetwork.h @@ -43,6 +43,7 @@ // Common option flags per-socket. #define MOD_NETWORK_SO_REUSEADDR (0x0004) +#define MOD_NETWORK_SO_BROADCAST (0x0020) #define MOD_NETWORK_SO_KEEPALIVE (0x0008) #define MOD_NETWORK_SO_SNDTIMEO (0x1005) #define MOD_NETWORK_SO_RCVTIMEO (0x1006) diff --git a/extmod/modselect.c b/extmod/modselect.c index 3d7ccbd995..d665a10827 100644 --- a/extmod/modselect.c +++ b/extmod/modselect.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2014 Damien P. George + * Copyright (c) 2014-2023 Damien P. George * Copyright (c) 2015-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -26,10 +26,6 @@ */ #include "py/mpconfig.h" -#if MICROPY_PY_SELECT - -#include - #include "py/runtime.h" #include "py/obj.h" #include "py/objlist.h" @@ -37,51 +33,248 @@ #include "py/mperrno.h" #include "py/mphal.h" -// Flags for poll() +#if MICROPY_PY_SELECT + +#if MICROPY_PY_SELECT_SELECT && MICROPY_PY_SELECT_POSIX_OPTIMISATIONS +#error "select.select is not supported with MICROPY_PY_SELECT_POSIX_OPTIMISATIONS" +#endif + +#if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS + +#include + +#if !((MP_STREAM_POLL_RD) == (POLLIN) && \ + (MP_STREAM_POLL_WR) == (POLLOUT) && \ + (MP_STREAM_POLL_ERR) == (POLLERR) && \ + (MP_STREAM_POLL_HUP) == (POLLHUP) && \ + (MP_STREAM_POLL_NVAL) == (POLLNVAL)) +#error "With MICROPY_PY_SELECT_POSIX_OPTIMISATIONS enabled, POLL constants must match" +#endif + +// When non-file-descriptor objects are on the list to be polled (the polling of +// which involves repeatedly calling ioctl(MP_STREAM_POLL)), this variable sets +// the period between polling these objects. +#define MICROPY_PY_SELECT_IOCTL_CALL_PERIOD_MS (1) + +#endif + +// Flags for ipoll() #define FLAG_ONESHOT (1) +// A single pollable object. typedef struct _poll_obj_t { mp_obj_t obj; mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode); - mp_uint_t flags; - mp_uint_t flags_ret; + #if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS + // If the pollable object has an associated file descriptor, then pollfd points to an entry + // in poll_set_t::pollfds, and the events/revents fields for this object are stored in the + // pollfd entry (and the nonfd_* members are unused). + // Otherwise the object is a non-file-descriptor object and pollfd==NULL, and the events/ + // revents fields are stored in the nonfd_* members (which are named as such so that code + // doesn't accidentally mix the use of these members when this optimisation is used). + struct pollfd *pollfd; + uint16_t nonfd_events; + uint16_t nonfd_revents; + #else + mp_uint_t events; + mp_uint_t revents; + #endif } poll_obj_t; -STATIC void poll_map_add(mp_map_t *poll_map, const mp_obj_t *obj, mp_uint_t obj_len, mp_uint_t flags, bool or_flags) { +// A set of pollable objects. +typedef struct _poll_set_t { + // Map containing a dict with key=object to poll, value=its corresponding poll_obj_t. + mp_map_t map; + + #if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS + // Array of pollfd entries for objects that have a file descriptor. + unsigned short alloc; // memory allocated for pollfds + unsigned short max_used; // maximum number of used entries in pollfds + unsigned short used; // actual number of used entries in pollfds + struct pollfd *pollfds; + #endif +} poll_set_t; + +STATIC void poll_set_init(poll_set_t *poll_set, size_t n) { + mp_map_init(&poll_set->map, n); + #if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS + poll_set->alloc = 0; + poll_set->max_used = 0; + poll_set->used = 0; + poll_set->pollfds = NULL; + #endif +} + +#if MICROPY_PY_SELECT_SELECT +STATIC void poll_set_deinit(poll_set_t *poll_set) { + mp_map_deinit(&poll_set->map); +} +#endif + +#if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS + +STATIC mp_uint_t poll_obj_get_events(poll_obj_t *poll_obj) { + assert(poll_obj->pollfd == NULL); + return poll_obj->nonfd_events; +} + +STATIC void poll_obj_set_events(poll_obj_t *poll_obj, mp_uint_t events) { + if (poll_obj->pollfd != NULL) { + poll_obj->pollfd->events = events; + } else { + poll_obj->nonfd_events = events; + } +} + +STATIC mp_uint_t poll_obj_get_revents(poll_obj_t *poll_obj) { + if (poll_obj->pollfd != NULL) { + return poll_obj->pollfd->revents; + } else { + return poll_obj->nonfd_revents; + } +} + +STATIC void poll_obj_set_revents(poll_obj_t *poll_obj, mp_uint_t revents) { + if (poll_obj->pollfd != NULL) { + poll_obj->pollfd->revents = revents; + } else { + poll_obj->nonfd_revents = revents; + } +} + +STATIC struct pollfd *poll_set_add_fd(poll_set_t *poll_set, int fd) { + struct pollfd *free_slot = NULL; + + if (poll_set->used == poll_set->max_used) { + // No free slots below max_used, so expand max_used (and possibly allocate). + if (poll_set->max_used >= poll_set->alloc) { + poll_set->pollfds = m_renew(struct pollfd, poll_set->pollfds, poll_set->alloc, poll_set->alloc + 4); + poll_set->alloc += 4; + } + free_slot = &poll_set->pollfds[poll_set->max_used++]; + } else { + // There should be a free slot below max_used. + for (unsigned int i = 0; i < poll_set->max_used; ++i) { + struct pollfd *slot = &poll_set->pollfds[i]; + if (slot->fd == -1) { + free_slot = slot; + break; + } + } + assert(free_slot != NULL); + } + + free_slot->fd = fd; + ++poll_set->used; + + return free_slot; +} + +static inline bool poll_set_all_are_fds(poll_set_t *poll_set) { + return poll_set->map.used == poll_set->used; +} + +#else + +static inline mp_uint_t poll_obj_get_events(poll_obj_t *poll_obj) { + return poll_obj->events; +} + +static inline void poll_obj_set_events(poll_obj_t *poll_obj, mp_uint_t events) { + poll_obj->events = events; +} + +static inline mp_uint_t poll_obj_get_revents(poll_obj_t *poll_obj) { + return poll_obj->revents; +} + +static inline void poll_obj_set_revents(poll_obj_t *poll_obj, mp_uint_t revents) { + poll_obj->revents = revents; +} + +#endif + +STATIC void poll_set_add_obj(poll_set_t *poll_set, const mp_obj_t *obj, mp_uint_t obj_len, mp_uint_t events, bool or_events) { for (mp_uint_t i = 0; i < obj_len; i++) { - mp_map_elem_t *elem = mp_map_lookup(poll_map, mp_obj_id(obj[i]), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); + mp_map_elem_t *elem = mp_map_lookup(&poll_set->map, mp_obj_id(obj[i]), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); if (elem->value == MP_OBJ_NULL) { // object not found; get its ioctl and add it to the poll list - const mp_stream_p_t *stream_p = mp_get_stream_raise(obj[i], MP_STREAM_OP_IOCTL); + + // If an exception is raised below when adding the new object then the map entry for that + // object remains unpopulated, and methods like poll() may crash. This case is not handled. + poll_obj_t *poll_obj = m_new_obj(poll_obj_t); poll_obj->obj = obj[i]; + + #if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS + int fd = -1; + if (mp_obj_is_int(obj[i])) { + // A file descriptor integer passed in as the object, so use it directly. + fd = mp_obj_get_int(obj[i]); + if (fd < 0) { + mp_raise_ValueError(NULL); + } + poll_obj->ioctl = NULL; + } else { + // An object passed in. Check if it has a file descriptor. + const mp_stream_p_t *stream_p = mp_get_stream_raise(obj[i], MP_STREAM_OP_IOCTL); + poll_obj->ioctl = stream_p->ioctl; + int err; + mp_uint_t res = stream_p->ioctl(obj[i], MP_STREAM_GET_FILENO, 0, &err); + if (res != MP_STREAM_ERROR) { + fd = res; + } + } + if (fd >= 0) { + // Object has a file descriptor so add it to pollfds. + poll_obj->pollfd = poll_set_add_fd(poll_set, fd); + } else { + // Object doesn't have a file descriptor. + poll_obj->pollfd = NULL; + } + #else + const mp_stream_p_t *stream_p = mp_get_stream_raise(obj[i], MP_STREAM_OP_IOCTL); poll_obj->ioctl = stream_p->ioctl; - poll_obj->flags = flags; - poll_obj->flags_ret = 0; + #endif + + poll_obj_set_events(poll_obj, events); + poll_obj_set_revents(poll_obj, 0); elem->value = MP_OBJ_FROM_PTR(poll_obj); } else { - // object exists; update its flags - if (or_flags) { - ((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags |= flags; - } else { - ((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags = flags; + // object exists; update its events + poll_obj_t *poll_obj = (poll_obj_t *)MP_OBJ_TO_PTR(elem->value); + #if MICROPY_PY_SELECT_SELECT + if (or_events) { + events |= poll_obj_get_events(poll_obj); } + #else + (void)or_events; + #endif + poll_obj_set_events(poll_obj, events); } } } -// poll each object in the map -STATIC mp_uint_t poll_map_poll(mp_map_t *poll_map, size_t *rwx_num) { +// For each object in the poll set, poll it once. +STATIC mp_uint_t poll_set_poll_once(poll_set_t *poll_set, size_t *rwx_num) { mp_uint_t n_ready = 0; - for (mp_uint_t i = 0; i < poll_map->alloc; ++i) { - if (!mp_map_slot_is_filled(poll_map, i)) { + for (mp_uint_t i = 0; i < poll_set->map.alloc; ++i) { + if (!mp_map_slot_is_filled(&poll_set->map, i)) { continue; } - poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_map->table[i].value); + poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_set->map.table[i].value); + + #if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS + if (poll_obj->pollfd != NULL) { + // Object has file descriptor so will be polled separately by poll(). + continue; + } + #endif + int errcode; - mp_int_t ret = poll_obj->ioctl(poll_obj->obj, MP_STREAM_POLL, poll_obj->flags, &errcode); - poll_obj->flags_ret = ret; + mp_int_t ret = poll_obj->ioctl(poll_obj->obj, MP_STREAM_POLL, poll_obj_get_events(poll_obj), &errcode); + poll_obj_set_revents(poll_obj, ret); if (ret == -1) { // error doing ioctl @@ -91,6 +284,7 @@ STATIC mp_uint_t poll_map_poll(mp_map_t *poll_map, size_t *rwx_num) { if (ret != 0) { // object is ready n_ready += 1; + #if MICROPY_PY_SELECT_SELECT if (rwx_num != NULL) { if (ret & MP_STREAM_POLL_RD) { rwx_num[0] += 1; @@ -102,11 +296,82 @@ STATIC mp_uint_t poll_map_poll(mp_map_t *poll_map, size_t *rwx_num) { rwx_num[2] += 1; } } + #else + (void)rwx_num; + #endif } } return n_ready; } +STATIC mp_uint_t poll_set_poll_until_ready_or_timeout(poll_set_t *poll_set, size_t *rwx_num, mp_uint_t timeout) { + mp_uint_t start_ticks = mp_hal_ticks_ms(); + + #if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS + + for (;;) { + MP_THREAD_GIL_EXIT(); + + // Compute the timeout. + int t = MICROPY_PY_SELECT_IOCTL_CALL_PERIOD_MS; + if (poll_set_all_are_fds(poll_set)) { + // All our pollables are file descriptors, so we can use a blocking + // poll and let it (the underlying system) handle the timeout. + if (timeout == (mp_uint_t)-1) { + t = -1; + } else { + mp_uint_t delta = mp_hal_ticks_ms() - start_ticks; + if (delta >= timeout) { + t = 0; + } else { + t = timeout - delta; + } + } + } + + // Call system poll for those objects that have a file descriptor. + int n_ready = poll(poll_set->pollfds, poll_set->max_used, t); + + MP_THREAD_GIL_ENTER(); + + // The call to poll() may have been interrupted, but per PEP 475 we must retry if the + // signal is EINTR (this implements a special case of calling MP_HAL_RETRY_SYSCALL()). + if (n_ready == -1) { + int err = errno; + if (err != EINTR) { + mp_raise_OSError(err); + } + n_ready = 0; + } + + // Explicitly poll any objects that do not have a file descriptor. + if (!poll_set_all_are_fds(poll_set)) { + n_ready += poll_set_poll_once(poll_set, rwx_num); + } + + // Return if an object is ready, or if the timeout expired. + if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_ticks >= timeout)) { + return n_ready; + } + + // This would be MICROPY_EVENT_POLL_HOOK but the call to poll() above already includes a delay. + mp_handle_pending(true); + } + + #else + + for (;;) { + // poll the objects + mp_uint_t n_ready = poll_set_poll_once(poll_set, rwx_num); + if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_ticks >= timeout)) { + return n_ready; + } + MICROPY_EVENT_POLL_HOOK + } + + #endif +} + #if MICROPY_PY_SELECT_SELECT // select(rlist, wlist, xlist[, timeout]) STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) { @@ -133,52 +398,46 @@ STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) { } // merge separate lists and get the ioctl function for each object - mp_map_t poll_map; - mp_map_init(&poll_map, rwx_len[0] + rwx_len[1] + rwx_len[2]); - poll_map_add(&poll_map, r_array, rwx_len[0], MP_STREAM_POLL_RD, true); - poll_map_add(&poll_map, w_array, rwx_len[1], MP_STREAM_POLL_WR, true); - poll_map_add(&poll_map, x_array, rwx_len[2], MP_STREAM_POLL_ERR | MP_STREAM_POLL_HUP, true); + poll_set_t poll_set; + poll_set_init(&poll_set, rwx_len[0] + rwx_len[1] + rwx_len[2]); + poll_set_add_obj(&poll_set, r_array, rwx_len[0], MP_STREAM_POLL_RD, true); + poll_set_add_obj(&poll_set, w_array, rwx_len[1], MP_STREAM_POLL_WR, true); + poll_set_add_obj(&poll_set, x_array, rwx_len[2], MP_STREAM_POLL_ERR | MP_STREAM_POLL_HUP, true); - mp_uint_t start_tick = mp_hal_ticks_ms(); + // poll all objects rwx_len[0] = rwx_len[1] = rwx_len[2] = 0; - for (;;) { - // poll the objects - mp_uint_t n_ready = poll_map_poll(&poll_map, rwx_len); + poll_set_poll_until_ready_or_timeout(&poll_set, rwx_len, timeout); - if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_tick >= timeout)) { - // one or more objects are ready, or we had a timeout - mp_obj_t list_array[3]; - list_array[0] = mp_obj_new_list(rwx_len[0], NULL); - list_array[1] = mp_obj_new_list(rwx_len[1], NULL); - list_array[2] = mp_obj_new_list(rwx_len[2], NULL); - rwx_len[0] = rwx_len[1] = rwx_len[2] = 0; - for (mp_uint_t i = 0; i < poll_map.alloc; ++i) { - if (!mp_map_slot_is_filled(&poll_map, i)) { - continue; - } - poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_map.table[i].value); - if (poll_obj->flags_ret & MP_STREAM_POLL_RD) { - ((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[0]))->items[rwx_len[0]++] = poll_obj->obj; - } - if (poll_obj->flags_ret & MP_STREAM_POLL_WR) { - ((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[1]))->items[rwx_len[1]++] = poll_obj->obj; - } - if ((poll_obj->flags_ret & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) { - ((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[2]))->items[rwx_len[2]++] = poll_obj->obj; - } - } - mp_map_deinit(&poll_map); - return mp_obj_new_tuple(3, list_array); + // one or more objects are ready, or we had a timeout + mp_obj_t list_array[3]; + list_array[0] = mp_obj_new_list(rwx_len[0], NULL); + list_array[1] = mp_obj_new_list(rwx_len[1], NULL); + list_array[2] = mp_obj_new_list(rwx_len[2], NULL); + rwx_len[0] = rwx_len[1] = rwx_len[2] = 0; + for (mp_uint_t i = 0; i < poll_set.map.alloc; ++i) { + if (!mp_map_slot_is_filled(&poll_set.map, i)) { + continue; + } + poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_set.map.table[i].value); + if (poll_obj->revents & MP_STREAM_POLL_RD) { + ((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[0]))->items[rwx_len[0]++] = poll_obj->obj; + } + if (poll_obj->revents & MP_STREAM_POLL_WR) { + ((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[1]))->items[rwx_len[1]++] = poll_obj->obj; + } + if ((poll_obj->revents & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) { + ((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[2]))->items[rwx_len[2]++] = poll_obj->obj; } - MICROPY_EVENT_POLL_HOOK } + poll_set_deinit(&poll_set); + return mp_obj_new_tuple(3, list_array); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_select_select_obj, 3, 4, select_select); #endif // MICROPY_PY_SELECT_SELECT typedef struct _mp_obj_poll_t { mp_obj_base_t base; - mp_map_t poll_map; + poll_set_t poll_set; short iter_cnt; short iter_idx; int flags; @@ -189,13 +448,13 @@ typedef struct _mp_obj_poll_t { // register(obj[, eventmask]) STATIC mp_obj_t poll_register(size_t n_args, const mp_obj_t *args) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); - mp_uint_t flags; + mp_uint_t events; if (n_args == 3) { - flags = mp_obj_get_int(args[2]); + events = mp_obj_get_int(args[2]); } else { - flags = MP_STREAM_POLL_RD | MP_STREAM_POLL_WR; + events = MP_STREAM_POLL_RD | MP_STREAM_POLL_WR; } - poll_map_add(&self->poll_map, &args[1], 1, flags, false); + poll_set_add_obj(&self->poll_set, &args[1], 1, events, false); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register); @@ -203,7 +462,21 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register); // unregister(obj) STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); - mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP_REMOVE_IF_FOUND); + mp_map_elem_t *elem = mp_map_lookup(&self->poll_set.map, mp_obj_id(obj_in), MP_MAP_LOOKUP_REMOVE_IF_FOUND); + + #if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS + if (elem != NULL) { + poll_obj_t *poll_obj = (poll_obj_t *)MP_OBJ_TO_PTR(elem->value); + if (poll_obj->pollfd != NULL) { + poll_obj->pollfd->fd = -1; + --self->poll_set.used; + } + elem->value = MP_OBJ_NULL; + } + #else + (void)elem; + #endif + // TODO raise KeyError if obj didn't exist in map return mp_const_none; } @@ -212,11 +485,11 @@ MP_DEFINE_CONST_FUN_OBJ_2(poll_unregister_obj, poll_unregister); // modify(obj, eventmask) STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); - mp_map_elem_t *elem = mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP); + mp_map_elem_t *elem = mp_map_lookup(&self->poll_set.map, mp_obj_id(obj_in), MP_MAP_LOOKUP); if (elem == NULL) { mp_raise_OSError(MP_ENOENT); } - ((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags = mp_obj_get_int(eventmask_in); + poll_obj_set_events((poll_obj_t *)MP_OBJ_TO_PTR(elem->value), mp_obj_get_int(eventmask_in)); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify); @@ -241,18 +514,7 @@ STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) { self->flags = flags; - mp_uint_t start_tick = mp_hal_ticks_ms(); - mp_uint_t n_ready; - for (;;) { - // poll the objects - n_ready = poll_map_poll(&self->poll_map, NULL); - if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_tick >= timeout)) { - break; - } - MICROPY_EVENT_POLL_HOOK - } - - return n_ready; + return poll_set_poll_until_ready_or_timeout(&self->poll_set, NULL, timeout); } STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) { @@ -262,23 +524,19 @@ STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) { // one or more objects are ready, or we had a timeout mp_obj_list_t *ret_list = MP_OBJ_TO_PTR(mp_obj_new_list(n_ready, NULL)); n_ready = 0; - for (mp_uint_t i = 0; i < self->poll_map.alloc; ++i) { - if (!mp_map_slot_is_filled(&self->poll_map, i)) { + for (mp_uint_t i = 0; i < self->poll_set.map.alloc; ++i) { + if (!mp_map_slot_is_filled(&self->poll_set.map, i)) { continue; } - poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_map.table[i].value); - if (poll_obj->flags_ret != 0) { - mp_obj_t tuple[2] = {poll_obj->obj, MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret)}; + poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_set.map.table[i].value); + if (poll_obj_get_revents(poll_obj) != 0) { + mp_obj_t tuple[2] = {poll_obj->obj, MP_OBJ_NEW_SMALL_INT(poll_obj_get_revents(poll_obj))}; ret_list->items[n_ready++] = mp_obj_new_tuple(2, tuple); - if (self->flags & FLAG_ONESHOT) { - // Don't poll next time, until new event flags will be set explicitly - poll_obj->flags = 0; - } } } return MP_OBJ_FROM_PTR(ret_list); } -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 3, poll_poll); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 2, poll_poll); STATIC mp_obj_t poll_ipoll(size_t n_args, const mp_obj_t *args) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); @@ -304,19 +562,19 @@ STATIC mp_obj_t poll_iternext(mp_obj_t self_in) { self->iter_cnt--; - for (mp_uint_t i = self->iter_idx; i < self->poll_map.alloc; ++i) { + for (mp_uint_t i = self->iter_idx; i < self->poll_set.map.alloc; ++i) { self->iter_idx++; - if (!mp_map_slot_is_filled(&self->poll_map, i)) { + if (!mp_map_slot_is_filled(&self->poll_set.map, i)) { continue; } - poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_map.table[i].value); - if (poll_obj->flags_ret != 0) { + poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_set.map.table[i].value); + if (poll_obj_get_revents(poll_obj) != 0) { mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->ret_tuple); t->items[0] = poll_obj->obj; - t->items[1] = MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret); + t->items[1] = MP_OBJ_NEW_SMALL_INT(poll_obj_get_revents(poll_obj)); if (self->flags & FLAG_ONESHOT) { - // Don't poll next time, until new event flags will be set explicitly - poll_obj->flags = 0; + // Don't poll next time, until new event mask will be set explicitly + poll_obj_set_events(poll_obj, 0); } return MP_OBJ_FROM_PTR(t); } @@ -347,7 +605,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( // poll() STATIC mp_obj_t select_poll(void) { mp_obj_poll_t *poll = mp_obj_malloc(mp_obj_poll_t, &mp_type_poll); - mp_map_init(&poll->poll_map, 0); + poll_set_init(&poll->poll_set, 0); poll->iter_cnt = 0; poll->ret_tuple = MP_OBJ_NULL; return MP_OBJ_FROM_PTR(poll); diff --git a/extmod/modsocket.c b/extmod/modsocket.c index 488b6d1712..72a32e3cba 100644 --- a/extmod/modsocket.c +++ b/extmod/modsocket.c @@ -631,6 +631,7 @@ STATIC const mp_rom_map_elem_t mp_module_socket_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(MOD_NETWORK_SOL_SOCKET) }, { MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(MOD_NETWORK_SO_REUSEADDR) }, + { MP_ROM_QSTR(MP_QSTR_SO_BROADCAST), MP_ROM_INT(MOD_NETWORK_SO_BROADCAST) }, { MP_ROM_QSTR(MP_QSTR_SO_KEEPALIVE), MP_ROM_INT(MOD_NETWORK_SO_KEEPALIVE) }, { MP_ROM_QSTR(MP_QSTR_SO_SNDTIMEO), MP_ROM_INT(MOD_NETWORK_SO_SNDTIMEO) }, { MP_ROM_QSTR(MP_QSTR_SO_RCVTIMEO), MP_ROM_INT(MOD_NETWORK_SO_RCVTIMEO) }, diff --git a/extmod/modssl_mbedtls.c b/extmod/modssl_mbedtls.c index 6d78d7d1b3..449952594c 100644 --- a/extmod/modssl_mbedtls.c +++ b/extmod/modssl_mbedtls.c @@ -168,6 +168,12 @@ STATIC mp_obj_t ssl_context_make_new(const mp_obj_type_t *type_in, size_t n_args mbedtls_debug_set_threshold(3); #endif + // Whenever the PSA interface is used (if MBEDTLS_PSA_CRYPTO), psa_crypto_init() needs to be called before any TLS related operations. + // TLSv1.3 depends on the PSA interface, TLSv1.2 only uses the PSA stack if MBEDTLS_USE_PSA_CRYPTO is defined. + #if defined(MBEDTLS_SSL_PROTO_TLS1_3) || defined(MBEDTLS_USE_PSA_CRYPTO) + psa_crypto_init(); + #endif + const byte seed[] = "upy"; int ret = mbedtls_ctr_drbg_seed(&self->ctr_drbg, mbedtls_entropy_func, &self->entropy, seed, sizeof(seed)); if (ret != 0) { @@ -394,6 +400,7 @@ STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t return MP_OBJ_FROM_PTR(o); cleanup: + o->sock = MP_OBJ_NULL; mbedtls_ssl_free(&o->ssl); mbedtls_raise_error(ret); } @@ -436,6 +443,14 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc // renegotiation. ret = MP_EWOULDBLOCK; o->poll_mask = MP_STREAM_POLL_WR; + #if defined(MBEDTLS_SSL_PROTO_TLS1_3) + } else if (ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET) { + // It appears a new session ticket being issued by the server right after + // completed handshake is not uncommon and shouldn't be treated as fatal. + // mbedtls itself states "This error code is experimental and may be + // changed or removed without notice." + ret = MP_EWOULDBLOCK; + #endif } else { o->last_error = ret; } @@ -486,15 +501,20 @@ STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i mp_uint_t ret = 0; uintptr_t saved_arg = 0; mp_obj_t sock = self->sock; - if (sock == MP_OBJ_NULL || (request != MP_STREAM_CLOSE && self->last_error != 0)) { - // Closed or error socket: - return MP_STREAM_POLL_NVAL; - } if (request == MP_STREAM_CLOSE) { + if (sock == MP_OBJ_NULL) { + // Already closed socket, do nothing. + return 0; + } self->sock = MP_OBJ_NULL; mbedtls_ssl_free(&self->ssl); } else if (request == MP_STREAM_POLL) { + if (sock == MP_OBJ_NULL || self->last_error != 0) { + // Closed or error socket, return NVAL flag. + return MP_STREAM_POLL_NVAL; + } + // If the library signaled us that it needs reading or writing, only check that direction, // but save what the caller asked because we need to restore it later if (self->poll_mask && (arg & MP_STREAM_POLL_RDWR)) { @@ -514,6 +534,10 @@ STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i } } } + } else { + // Unsupported ioctl. + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; } // Pass all requests down to the underlying socket diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index cfc56df99f..488593230c 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -153,12 +153,17 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_ switch (request) { case MP_STREAM_FLUSH: { int ret; + // fsync(stdin/stdout/stderr) may fail with EINVAL (or ENOTSUP on macos), + // but don't propagate that error out. Because data is not buffered by + // us, and stdin/out/err.flush() should just be a no-op. + #ifdef __APPLE__ + #define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL || err == ENOTSUP) + #else + #define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL) + #endif MP_HAL_RETRY_SYSCALL(ret, fsync(o->fd), { - if (err == EINVAL + if (VFS_POSIX_STREAM_STDIO_ERR_CATCH && (o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO)) { - // fsync(stdin/stdout/stderr) may fail with EINVAL, but don't propagate that - // error out. Because data is not buffered by us, and stdin/out/err.flush() - // should just be a no-op. return 0; } *errcode = err; @@ -188,7 +193,7 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_ return 0; case MP_STREAM_GET_FILENO: return o->fd; - #if MICROPY_PY_SELECT + #if MICROPY_PY_SELECT && !MICROPY_PY_SELECT_POSIX_OPTIMISATIONS case MP_STREAM_POLL: { #ifdef _WIN32 mp_raise_NotImplementedError(MP_ERROR_TEXT("poll on file not available on win32")); @@ -209,6 +214,15 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_ if (pfd.revents & POLLOUT) { ret |= MP_STREAM_POLL_WR; } + if (pfd.revents & POLLERR) { + ret |= MP_STREAM_POLL_ERR; + } + if (pfd.revents & POLLHUP) { + ret |= MP_STREAM_POLL_HUP; + } + if (pfd.revents & POLLNVAL) { + ret |= MP_STREAM_POLL_NVAL; + } } return ret; #endif @@ -260,12 +274,58 @@ STATIC const mp_stream_p_t vfs_posix_textio_stream_p = { .is_text = true, }; +#if MICROPY_PY_SYS_STDIO_BUFFER + +const mp_obj_vfs_posix_file_t mp_sys_stdin_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDIN_FILENO}; +const mp_obj_vfs_posix_file_t mp_sys_stdout_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDOUT_FILENO}; +const mp_obj_vfs_posix_file_t mp_sys_stderr_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDERR_FILENO}; + +// Forward declarations. +const mp_obj_vfs_posix_file_t mp_sys_stdin_obj; +const mp_obj_vfs_posix_file_t mp_sys_stdout_obj; +const mp_obj_vfs_posix_file_t mp_sys_stderr_obj; + +STATIC void vfs_posix_textio_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + if (dest[0] != MP_OBJ_NULL) { + // These objects are read-only. + return; + } + + if (attr == MP_QSTR_buffer) { + // Implement the `buffer` attribute only on std{in,out,err} instances. + if (MP_OBJ_TO_PTR(self_in) == &mp_sys_stdin_obj) { + dest[0] = MP_OBJ_FROM_PTR(&mp_sys_stdin_buffer_obj); + return; + } + if (MP_OBJ_TO_PTR(self_in) == &mp_sys_stdout_obj) { + dest[0] = MP_OBJ_FROM_PTR(&mp_sys_stdout_buffer_obj); + return; + } + if (MP_OBJ_TO_PTR(self_in) == &mp_sys_stderr_obj) { + dest[0] = MP_OBJ_FROM_PTR(&mp_sys_stderr_buffer_obj); + return; + } + } + + // Any other attribute - forward to locals dict. + dest[1] = MP_OBJ_SENTINEL; +}; + +#define VFS_POSIX_TEXTIO_TYPE_ATTR attr, vfs_posix_textio_attr, + +#else + +#define VFS_POSIX_TEXTIO_TYPE_ATTR + +#endif // MICROPY_PY_SYS_STDIO_BUFFER + MP_DEFINE_CONST_OBJ_TYPE( mp_type_vfs_posix_textio, MP_QSTR_TextIOWrapper, MP_TYPE_FLAG_ITER_IS_STREAM, print, vfs_posix_file_print, protocol, &vfs_posix_textio_stream_p, + VFS_POSIX_TEXTIO_TYPE_ATTR locals_dict, &vfs_posix_rawfile_locals_dict ); diff --git a/lib/uzlib/header.c b/lib/uzlib/header.c index edd2b08ab5..9c48d91391 100644 --- a/lib/uzlib/header.c +++ b/lib/uzlib/header.c @@ -108,6 +108,10 @@ int uzlib_parse_zlib_gzip_header(uzlib_uncomp_t *d, int *wbits) d->checksum_type = UZLIB_CHKSUM_CRC; d->checksum = ~0; + /* gzip does not include the window size in the header, as it is expected that a + compressor will use wbits=15 (32kiB).*/ + *wbits = 15; + return UZLIB_HEADER_GZIP; } else { /* check checksum */ diff --git a/mpy-cross/mpy_cross/__init__.py b/mpy-cross/mpy_cross/__init__.py index 8eadbc8352..5020033e8c 100644 --- a/mpy-cross/mpy_cross/__init__.py +++ b/mpy-cross/mpy_cross/__init__.py @@ -100,7 +100,7 @@ def compile(src, dest=None, src_path=None, opt=None, march=None, mpy_cross=None, if not src: raise ValueError("src is required") if not os.path.exists(src): - raise CrossCompileError("Input .py file not found: {}.".format(src_py)) + raise CrossCompileError("Input .py file not found: {}.".format(src)) args = [] diff --git a/ports/cc3200/Makefile b/ports/cc3200/Makefile index 61af0bfd98..f89a927c0e 100644 --- a/ports/cc3200/Makefile +++ b/ports/cc3200/Makefile @@ -7,6 +7,8 @@ endif # Make 'release' the default build type BTYPE ?= release +# Make the 'application' by default ('bootloader' can be built explicitly) +BTARGET ?= application # Port for flashing firmware PORT ?= /dev/ttyUSB1 diff --git a/ports/cc3200/application.mk b/ports/cc3200/application.mk index 5021e4ff3c..f4487d69d4 100644 --- a/ports/cc3200/application.mk +++ b/ports/cc3200/application.mk @@ -198,7 +198,7 @@ WIPY_IP ?= '192.168.1.1' WIPY_USER ?= 'micro' WIPY_PWD ?= 'python' -all: $(BUILD)/mcuimg.bin +all: $(BUILD)/firmware.zip .PHONY: deploy-ota @@ -219,6 +219,10 @@ $(BUILD)/mcuimg.bin: $(BUILD)/application.bin $(ECHO) "Create $@" $(Q)$(SHELL) $(APP_SIGN) $(BUILD) +$(BUILD)/firmware.zip: $(BUILD)/mcuimg.bin + $(ECHO) "Create $@" + $(Q)$(ZIP) -j $@ $< + MAKE_PINS = boards/make-pins.py BOARD_PINS = boards/$(BOARD)/pins.csv AF_FILE = boards/cc3200_af.csv diff --git a/ports/cc3200/boards/WIPY/board.json b/ports/cc3200/boards/WIPY/board.json index d8293b2481..f615953af7 100644 --- a/ports/cc3200/boards/WIPY/board.json +++ b/ports/cc3200/boards/WIPY/board.json @@ -5,13 +5,11 @@ "docs": "https://docs.pycom.io/datasheets/development/wipy3/", "features": [ "BLE", - "Breadboard Friendly", - "MicroSD", + "External Flash", "RGB LED", - "SPI Flash", - "WiFi" + "WiFi", + "microSD" ], - "id": "wipy", "images": [ "wipy.jpg" ], diff --git a/ports/cc3200/mpthreadport.c b/ports/cc3200/mpthreadport.c index 4b6f27d578..5b4771f395 100644 --- a/ports/cc3200/mpthreadport.c +++ b/ports/cc3200/mpthreadport.c @@ -89,6 +89,10 @@ void mp_thread_set_state(mp_state_thread_t *state) { vTaskSetThreadLocalStoragePointer(NULL, 0, state); } +mp_uint_t mp_thread_get_id(void) { + return (mp_uint_t)xTaskGetCurrentTaskHandle(); +} + void mp_thread_start(void) { mp_thread_mutex_lock(&thread_mutex, 1); for (mp_thread_t *th = thread; th != NULL; th = th->next) { @@ -111,7 +115,7 @@ STATIC void freertos_entry(void *arg) { } } -void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { +mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { // store thread entry function into a global variable so we can access it ext_thread_entry = entry; @@ -148,6 +152,9 @@ void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { // adjust stack_size to provide room to recover from hitting the limit *stack_size -= 512; + + MP_STATIC_ASSERT(sizeof(mp_uint_t) >= sizeof(TaskHandle_t)); + return (mp_uint_t)id; } void mp_thread_finish(void) { diff --git a/ports/cc3200/tools/uniflash.py b/ports/cc3200/tools/uniflash.py index 83445a12d3..2fa2c02f45 100644 --- a/ports/cc3200/tools/uniflash.py +++ b/ports/cc3200/tools/uniflash.py @@ -41,7 +41,7 @@ def execute(command): if exitCode == 0: return cmd_log else: - raise ProcessException(command, exitCode, output) + raise subprocess.CalledProcessError(exitCode, command, output) def main(): diff --git a/ports/esp32/CMakeLists.txt b/ports/esp32/CMakeLists.txt index 4e29e96109..94047a0482 100644 --- a/ports/esp32/CMakeLists.txt +++ b/ports/esp32/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.12) # Set the board if it's not already set. if(NOT MICROPY_BOARD) - set(MICROPY_BOARD GENERIC) + set(MICROPY_BOARD ESP32_GENERIC) endif() # Set the board directory and check that it exists. diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 7c8c225dfb..bf275ffe66 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -8,17 +8,25 @@ ifdef BOARD_DIR # the path as the board name. BOARD ?= $(notdir $(BOARD_DIR:/=)) else -# If not given on the command line, then default to GENERIC. -BOARD ?= GENERIC +# If not given on the command line, then default to ESP32_GENERIC. +BOARD ?= ESP32_GENERIC BOARD_DIR ?= boards/$(BOARD) endif ifeq ($(wildcard $(BOARD_DIR)/.),) +ifeq ($(findstring boards/GENERIC,$(BOARD_DIR)),boards/GENERIC) +$(warning The GENERIC* boards have been renamed to ESP32_GENERIC*) +endif $(error Invalid BOARD specified: $(BOARD_DIR)) endif -# If the build directory is not given, make it reflect the board name. +# If the build directory is not given, make it reflect the board name (and +# optionally the board variant). +ifneq ($(BOARD_VARIANT),) +BUILD ?= build-$(BOARD)-$(BOARD_VARIANT) +else BUILD ?= build-$(BOARD) +endif # Device serial settings. PORT ?= /dev/ttyUSB0 @@ -26,12 +34,6 @@ BAUD ?= 460800 PYTHON ?= python3 -# Would be good to use cmake to discover submodules (see how rp2/Makefile does -# it), but on ESP32 the same trick doesn't work because "idf.py build" fails -# on berkeley-db dependency before printing out the submodule list. -# For now just force the submodule dependencies here. -GIT_SUBMODULES += lib/berkeley-db-1.xx lib/micropython-lib - .PHONY: all clean deploy erase submodules FORCE CMAKE_ARGS = @@ -40,20 +42,24 @@ ifdef USER_C_MODULES CMAKE_ARGS += -DUSER_C_MODULES=${USER_C_MODULES} endif -IDFPY_FLAGS += -D MICROPY_BOARD=$(BOARD) -D MICROPY_BOARD_DIR=$(abspath $(BOARD_DIR)) -B $(BUILD) $(CMAKE_ARGS) +IDFPY_FLAGS += -D MICROPY_BOARD=$(BOARD) -D MICROPY_BOARD_DIR=$(abspath $(BOARD_DIR)) $(CMAKE_ARGS) ifdef FROZEN_MANIFEST IDFPY_FLAGS += -D MICROPY_FROZEN_MANIFEST=$(FROZEN_MANIFEST) endif +ifdef BOARD_VARIANT + IDFPY_FLAGS += -D MICROPY_BOARD_VARIANT=$(BOARD_VARIANT) +endif + HELP_BUILD_ERROR ?= "See \033[1;31mhttps://github.com/micropython/micropython/wiki/Build-Troubleshooting\033[0m" define RUN_IDF_PY - idf.py $(IDFPY_FLAGS) -p $(PORT) -b $(BAUD) $(1) + idf.py $(IDFPY_FLAGS) -B $(BUILD) -p $(PORT) -b $(BAUD) $(1) endef all: - idf.py $(IDFPY_FLAGS) build || (echo -e $(HELP_BUILD_ERROR); false) + idf.py $(IDFPY_FLAGS) -B $(BUILD) build || (echo -e $(HELP_BUILD_ERROR); false) @$(PYTHON) makeimg.py \ $(BUILD)/sdkconfig \ $(BUILD)/bootloader/bootloader.bin \ @@ -85,5 +91,12 @@ size-components: size-files: $(call RUN_IDF_PY,size-files) +# Running the build with ECHO_SUBMODULES set will trigger py/mkrules.cmake to +# print out the value of the GIT_SUBMODULES variable, prefixed with +# "GIT_SUBMODULES", and then abort. This extracts out that line from the idf.py +# output and passes the list of submodules to py/mkrules.mk which does the +# `git submodule init` on each. submodules: - $(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="$(GIT_SUBMODULES)" submodules + @GIT_SUBMODULES=$$(idf.py $(IDFPY_FLAGS) -B $(BUILD)/submodules -D ECHO_SUBMODULES=1 build 2>&1 | \ + grep '^GIT_SUBMODULES=' | cut -d= -f2); \ + $(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="$${GIT_SUBMODULES}" submodules diff --git a/ports/esp32/README.md b/ports/esp32/README.md index 2d5b05b926..169de4073b 100644 --- a/ports/esp32/README.md +++ b/ports/esp32/README.md @@ -93,7 +93,7 @@ $ make submodules $ make ``` -This will produce a combined `firmware.bin` image in the `build-GENERIC/` +This will produce a combined `firmware.bin` image in the `build-ESP32_GENERIC/` subdirectory (this firmware image is made up of: bootloader.bin, partitions.bin and micropython.bin). @@ -123,12 +123,12 @@ To flash the MicroPython firmware to your ESP32 use: $ make deploy ``` -The default ESP32 board build by the above commands is the `GENERIC` one, which -should work on most ESP32 modules. You can specify a different board by passing -`BOARD=` to the make commands, for example: +The default ESP32 board build by the above commands is the `ESP32_GENERIC` +one, which should work on most ESP32 modules. You can specify a different +board by passing `BOARD=` to the make commands, for example: ```bash -$ make BOARD=GENERIC_SPIRAM +$ make BOARD=ESP32_GENERIC_S3 ``` Note: the above "make" commands are thin wrappers for the underlying `idf.py` @@ -137,10 +137,25 @@ for example: ```bash $ idf.py build -$ idf.py -D MICROPY_BOARD=GENERIC_SPIRAM build +$ idf.py -D MICROPY_BOARD=ESP32_GENERIC build $ idf.py flash ``` +Some boards also support "variants", which are allow for small variations of +an otherwise similar board. For example different flash sizes or features. For +example to build the `OTA` variant of `ESP32_GENERIC`. + +```bash +$ make BOARD=ESP32_GENERIC BOARD_VARIANT=OTA +``` + +or to enable octal-SPIRAM support for the `ESP32_GENERIC_S3` board: + +```bash +$ make BOARD=ESP32_GENERIC BOARD_VARIANT=SPIRAM_OCT +``` + + Getting a Python prompt on the device ------------------------------------- @@ -202,10 +217,10 @@ antenna = machine.Pin(16, machine.Pin.OUT, value=0) Defining a custom ESP32 board ----------------------------- -The default ESP-IDF configuration settings are provided by the `GENERIC` -board definition in the directory `boards/GENERIC`. For a custom configuration +The default ESP-IDF configuration settings are provided by the `ESP32_GENERIC` +board definition in the directory `boards/ESP32_GENERIC`. For a custom configuration you can define your own board directory. Start a new board configuration by -copying an existing one (like `GENERIC`) and modifying it to suit your board. +copying an existing one (like `ESP32_GENERIC`) and modifying it to suit your board. MicroPython specific configuration values are defined in the board-specific `mpconfigboard.h` file, which is included by `mpconfigport.h`. Additional diff --git a/ports/esp32/boards/ARDUINO_NANO_ESP32/board.json b/ports/esp32/boards/ARDUINO_NANO_ESP32/board.json index afb24e1049..77aa192959 100644 --- a/ports/esp32/boards/ARDUINO_NANO_ESP32/board.json +++ b/ports/esp32/boards/ARDUINO_NANO_ESP32/board.json @@ -5,9 +5,10 @@ "docs": "", "features": [ "BLE", - "WiFi", + "External Flash", + "RGB LED", "USB-C", - "RGB LED" + "WiFi" ], "images": [ "ABX00092_01.iso_1000x750.jpg" diff --git a/ports/esp32/boards/ARDUINO_NANO_ESP32/deploy.md b/ports/esp32/boards/ARDUINO_NANO_ESP32/deploy.md index b600a55b64..bb32ba7559 100644 --- a/ports/esp32/boards/ARDUINO_NANO_ESP32/deploy.md +++ b/ports/esp32/boards/ARDUINO_NANO_ESP32/deploy.md @@ -4,5 +4,10 @@ This board can programmed via DFU bootloader, using e.g. [dfu-util](http://dfu-u To enter the DFU bootloader, double tap the reset (blue) button, or you can use `machine.bootloader()` from the MicroPython REPL. ```bash -dfu-util -d 0x2341:0x0070 -R -D build-ARDUINO_NANO_ESP32/micropython.bin +dfu-util -d 0x2341:0x0070 -R -D build-ARDUINO_NANO_ESP32/micropython.app-bin ``` + +Please note that the DFU bootloader comes factory flashed. Should you for any reason erase the +entire flash, the DFU bootloader will have to be re-installed. Please follow the instructions +[here](https://support.arduino.cc/hc/en-us/articles/9810414060188-Reset-the-Arduino-bootloader-on-the-Nano-ESP32) +to do so. diff --git a/ports/esp32/boards/GENERIC/board.json b/ports/esp32/boards/ESP32_GENERIC/board.json similarity index 56% rename from ports/esp32/boards/GENERIC/board.json rename to ports/esp32/boards/ESP32_GENERIC/board.json index a52d58007d..0db38c25d3 100644 --- a/ports/esp32/boards/GENERIC/board.json +++ b/ports/esp32/boards/ESP32_GENERIC/board.json @@ -5,18 +5,22 @@ "docs": "", "features": [ "BLE", + "External Flash", "WiFi" ], - "id": "esp32", "images": [ "esp32_devkitc.jpg" ], "mcu": "esp32", - "product": "ESP32", + "product": "ESP32 / WROOM", "thumbnail": "", "url": "https://www.espressif.com/en/products/modules", "variants": { - "idf3": "Compiled with IDF 3.x" + "IDF3": "Compiled with IDF 3.x", + "D2WD": "ESP32 D2WD", + "SPIRAM": "Support for SPIRAM / WROVER", + "UNICORE": "ESP32 Unicore", + "OTA": "Support for OTA" }, "vendor": "Espressif" } diff --git a/ports/esp32/boards/ESP32_GENERIC/board.md b/ports/esp32/boards/ESP32_GENERIC/board.md new file mode 100644 index 0000000000..8a669411d0 --- /dev/null +++ b/ports/esp32/boards/ESP32_GENERIC/board.md @@ -0,0 +1,9 @@ +The following files are firmware that should work on most ESP32-based boards +with 4MiB of flash, including WROOM WROVER, SOLO, PICO, and MINI modules. + +If your board is based on a WROVER module, or otherwise has SPIRAM (also known +as PSRAM), then use the "spiram" variant. + +The "d2wd" variant is for ESP32-D2WD chips (with 2MiB flash), and "unicore" is +for single-core ESP32 chips (e.g. the "SOLO" modules). The "ota" variant sets +up the partition table to allow for Over-the-Air updates. diff --git a/ports/esp32/boards/ESP32_GENERIC/mpconfigboard.cmake b/ports/esp32/boards/ESP32_GENERIC/mpconfigboard.cmake new file mode 100644 index 0000000000..74cb591c07 --- /dev/null +++ b/ports/esp32/boards/ESP32_GENERIC/mpconfigboard.cmake @@ -0,0 +1,48 @@ +set(SDKCONFIG_DEFAULTS + boards/sdkconfig.base + boards/sdkconfig.ble +) + +if(MICROPY_BOARD_VARIANT STREQUAL "D2WD") + set(SDKCONFIG_DEFAULTS + ${SDKCONFIG_DEFAULTS} + boards/ESP32_GENERIC/sdkconfig.d2wd + ) + + list(APPEND MICROPY_DEF_BOARD + MICROPY_HW_MCU_NAME="ESP32-D2WD" + ) +endif() + +if(MICROPY_BOARD_VARIANT STREQUAL "OTA") + set(SDKCONFIG_DEFAULTS + ${SDKCONFIG_DEFAULTS} + boards/ESP32_GENERIC/sdkconfig.ota + ) + + list(APPEND MICROPY_DEF_BOARD + MICROPY_HW_BOARD_NAME="Generic ESP32 module with OTA" + ) +endif() + +if(MICROPY_BOARD_VARIANT STREQUAL "SPIRAM") + set(SDKCONFIG_DEFAULTS + ${SDKCONFIG_DEFAULTS} + boards/sdkconfig.spiram + ) + + list(APPEND MICROPY_DEF_BOARD + MICROPY_HW_BOARD_NAME="Generic ESP32 module with SPIRAM" + ) +endif() + +if(MICROPY_BOARD_VARIANT STREQUAL "UNICORE") + set(SDKCONFIG_DEFAULTS + ${SDKCONFIG_DEFAULTS} + boards/ESP32_GENERIC/sdkconfig.unicore + ) + + list(APPEND MICROPY_DEF_BOARD + MICROPY_HW_MCU_NAME="ESP32-UNICORE" + ) +endif() diff --git a/ports/esp32/boards/ESP32_GENERIC/mpconfigboard.h b/ports/esp32/boards/ESP32_GENERIC/mpconfigboard.h new file mode 100644 index 0000000000..7171a84bb3 --- /dev/null +++ b/ports/esp32/boards/ESP32_GENERIC/mpconfigboard.h @@ -0,0 +1,10 @@ +// Both of these can be set by mpconfigboard.cmake if a BOARD_VARIANT is +// specified. + +#ifndef MICROPY_HW_BOARD_NAME +#define MICROPY_HW_BOARD_NAME "Generic ESP32 module" +#endif + +#ifndef MICROPY_HW_MCU_NAME +#define MICROPY_HW_MCU_NAME "ESP32" +#endif diff --git a/ports/esp32/boards/GENERIC_D2WD/sdkconfig.board b/ports/esp32/boards/ESP32_GENERIC/sdkconfig.d2wd similarity index 100% rename from ports/esp32/boards/GENERIC_D2WD/sdkconfig.board rename to ports/esp32/boards/ESP32_GENERIC/sdkconfig.d2wd diff --git a/ports/esp32/boards/GENERIC_OTA/sdkconfig.board b/ports/esp32/boards/ESP32_GENERIC/sdkconfig.ota similarity index 72% rename from ports/esp32/boards/GENERIC_OTA/sdkconfig.board rename to ports/esp32/boards/ESP32_GENERIC/sdkconfig.ota index 7ff939aa99..4a164aa6f8 100644 --- a/ports/esp32/boards/GENERIC_OTA/sdkconfig.board +++ b/ports/esp32/boards/ESP32_GENERIC/sdkconfig.ota @@ -1,6 +1,6 @@ CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-ota.csv" +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-4MiB-ota.csv" # Reduce firmware size to fit in the OTA partition. CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y diff --git a/ports/esp32/boards/GENERIC_UNICORE/sdkconfig.board b/ports/esp32/boards/ESP32_GENERIC/sdkconfig.unicore similarity index 100% rename from ports/esp32/boards/GENERIC_UNICORE/sdkconfig.board rename to ports/esp32/boards/ESP32_GENERIC/sdkconfig.unicore diff --git a/ports/esp32/boards/GENERIC_C3/board.json b/ports/esp32/boards/ESP32_GENERIC_C3/board.json similarity index 92% rename from ports/esp32/boards/GENERIC_C3/board.json rename to ports/esp32/boards/ESP32_GENERIC_C3/board.json index 6cc326bf14..4a81d227a0 100644 --- a/ports/esp32/boards/GENERIC_C3/board.json +++ b/ports/esp32/boards/ESP32_GENERIC_C3/board.json @@ -5,9 +5,9 @@ "docs": "", "features": [ "BLE", + "External Flash", "WiFi" ], - "id": "esp32c3", "images": [ "esp32c3_devkitmini.jpg" ], diff --git a/ports/esp32/boards/ESP32_GENERIC_C3/board.md b/ports/esp32/boards/ESP32_GENERIC_C3/board.md new file mode 100644 index 0000000000..1604b879c5 --- /dev/null +++ b/ports/esp32/boards/ESP32_GENERIC_C3/board.md @@ -0,0 +1,7 @@ +The following files are firmware images that should work on most +ESP32-C3-based boards with 4MiB of flash, including WROOM and MINI modules, +that use the revision 3 silicon (or newer). + +USB serial/JTAG support is enabled on pin 18 and 19. Note that this +is not a full USB stack, the C3 just provides a CDC/ACM class serial +and JTAG interface. diff --git a/ports/esp32/boards/GENERIC_C3/mpconfigboard.cmake b/ports/esp32/boards/ESP32_GENERIC_C3/mpconfigboard.cmake similarity index 69% rename from ports/esp32/boards/GENERIC_C3/mpconfigboard.cmake rename to ports/esp32/boards/ESP32_GENERIC_C3/mpconfigboard.cmake index 38bf7388fa..429366afac 100644 --- a/ports/esp32/boards/GENERIC_C3/mpconfigboard.cmake +++ b/ports/esp32/boards/ESP32_GENERIC_C3/mpconfigboard.cmake @@ -3,4 +3,5 @@ set(IDF_TARGET esp32c3) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base boards/sdkconfig.ble + boards/ESP32_GENERIC_C3/sdkconfig.c3usb ) diff --git a/ports/esp32/boards/GENERIC_C3/mpconfigboard.h b/ports/esp32/boards/ESP32_GENERIC_C3/mpconfigboard.h similarity index 71% rename from ports/esp32/boards/GENERIC_C3/mpconfigboard.h rename to ports/esp32/boards/ESP32_GENERIC_C3/mpconfigboard.h index d403e70e46..42e77ecb1a 100644 --- a/ports/esp32/boards/GENERIC_C3/mpconfigboard.h +++ b/ports/esp32/boards/ESP32_GENERIC_C3/mpconfigboard.h @@ -6,3 +6,6 @@ #define MICROPY_HW_ENABLE_SDCARD (0) #define MICROPY_PY_MACHINE_DAC (0) #define MICROPY_PY_MACHINE_I2S (0) + +// Enable UART REPL for modules that have an external USB-UART and don't use native USB. +#define MICROPY_HW_ENABLE_UART_REPL (1) diff --git a/ports/esp32/boards/GENERIC_C3_USB/sdkconfig.board b/ports/esp32/boards/ESP32_GENERIC_C3/sdkconfig.c3usb similarity index 100% rename from ports/esp32/boards/GENERIC_C3_USB/sdkconfig.board rename to ports/esp32/boards/ESP32_GENERIC_C3/sdkconfig.c3usb diff --git a/ports/esp32/boards/GENERIC_S2/board.json b/ports/esp32/boards/ESP32_GENERIC_S2/board.json similarity index 86% rename from ports/esp32/boards/GENERIC_S2/board.json rename to ports/esp32/boards/ESP32_GENERIC_S2/board.json index dbd3b5b015..35d06f2f7e 100644 --- a/ports/esp32/boards/GENERIC_S2/board.json +++ b/ports/esp32/boards/ESP32_GENERIC_S2/board.json @@ -5,6 +5,8 @@ "docs": "", "features": [ "BLE", + "External Flash", + "External RAM", "WiFi" ], "images": [ diff --git a/ports/esp32/boards/ESP32_GENERIC_S2/board.md b/ports/esp32/boards/ESP32_GENERIC_S2/board.md new file mode 100644 index 0000000000..3e46c02467 --- /dev/null +++ b/ports/esp32/boards/ESP32_GENERIC_S2/board.md @@ -0,0 +1,6 @@ +The following files are firmware that should work on most ESP32-S2-based +boards with 4MiB of flash, including WROOM, WROVER, and MINI modules. + +This firmware supports configurations with and without SPIRAM (also known as +PSRAM) and will auto-detect a connected SPIRAM chip at startup and allocate +the MicroPython heap accordingly. diff --git a/ports/esp32/boards/GENERIC_S2/mpconfigboard.cmake b/ports/esp32/boards/ESP32_GENERIC_S2/mpconfigboard.cmake similarity index 76% rename from ports/esp32/boards/GENERIC_S2/mpconfigboard.cmake rename to ports/esp32/boards/ESP32_GENERIC_S2/mpconfigboard.cmake index 59ca906f4d..76d185d90d 100644 --- a/ports/esp32/boards/GENERIC_S2/mpconfigboard.cmake +++ b/ports/esp32/boards/ESP32_GENERIC_S2/mpconfigboard.cmake @@ -3,4 +3,5 @@ set(IDF_TARGET esp32s2) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base boards/sdkconfig.usb + boards/sdkconfig.spiram_sx ) diff --git a/ports/esp32/boards/ESP32_GENERIC_S2/mpconfigboard.h b/ports/esp32/boards/ESP32_GENERIC_S2/mpconfigboard.h new file mode 100644 index 0000000000..aaea41bcde --- /dev/null +++ b/ports/esp32/boards/ESP32_GENERIC_S2/mpconfigboard.h @@ -0,0 +1,8 @@ +#define MICROPY_HW_BOARD_NAME "Generic ESP32S2 module" +#define MICROPY_HW_MCU_NAME "ESP32S2" + +#define MICROPY_PY_BLUETOOTH (0) +#define MICROPY_HW_ENABLE_SDCARD (0) + +// Enable UART REPL for modules that have an external USB-UART and don't use native USB. +#define MICROPY_HW_ENABLE_UART_REPL (1) diff --git a/ports/esp32/boards/GENERIC_S3/board.json b/ports/esp32/boards/ESP32_GENERIC_S3/board.json similarity index 66% rename from ports/esp32/boards/GENERIC_S3/board.json rename to ports/esp32/boards/ESP32_GENERIC_S3/board.json index 0db9b32503..671936c922 100644 --- a/ports/esp32/boards/GENERIC_S3/board.json +++ b/ports/esp32/boards/ESP32_GENERIC_S3/board.json @@ -5,6 +5,8 @@ "docs": "", "features": [ "BLE", + "External Flash", + "External RAM", "WiFi" ], "images": [ @@ -14,5 +16,8 @@ "product": "ESP32-S3", "thumbnail": "", "url": "https://www.espressif.com/en/products/modules", - "vendor": "Espressif" + "vendor": "Espressif", + "variants": { + "SPIRAM_OCT": "Support for Octal-SPIRAM" + } } diff --git a/ports/esp32/boards/ESP32_GENERIC_S3/board.md b/ports/esp32/boards/ESP32_GENERIC_S3/board.md new file mode 100644 index 0000000000..cc902eeb89 --- /dev/null +++ b/ports/esp32/boards/ESP32_GENERIC_S3/board.md @@ -0,0 +1,7 @@ +The following files are firmware that should work on most ESP32-S3-based +boards with 8MiB of flash, including WROOM and MINI modules. + +This firmware supports configurations with and without SPIRAM (also known as +PSRAM) and will auto-detect a connected SPIRAM chip at startup and allocate +the MicroPython heap accordingly. However if your board has Octal SPIRAM, then +use the "spiram-oct" variant. diff --git a/ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.cmake b/ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.cmake new file mode 100644 index 0000000000..36b4fe5624 --- /dev/null +++ b/ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.cmake @@ -0,0 +1,21 @@ +set(IDF_TARGET esp32s3) + +set(SDKCONFIG_DEFAULTS + boards/sdkconfig.base + boards/sdkconfig.usb + boards/sdkconfig.ble + boards/sdkconfig.spiram_sx + boards/ESP32_GENERIC_S3/sdkconfig.board +) + +if(MICROPY_BOARD_VARIANT STREQUAL "SPIRAM_OCT") + set(SDKCONFIG_DEFAULTS + ${SDKCONFIG_DEFAULTS} + boards/sdkconfig.240mhz + boards/sdkconfig.spiram_oct + ) + + list(APPEND MICROPY_DEF_BOARD + MICROPY_HW_BOARD_NAME="Generic ESP32S3 module with Octal-SPIRAM" + ) +endif() diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h b/ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.h similarity index 70% rename from ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h rename to ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.h index 1a8560a2d7..8d369c7db0 100644 --- a/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h +++ b/ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.h @@ -1,4 +1,7 @@ -#define MICROPY_HW_BOARD_NAME "ESP32S3 module (spiram)" +#ifndef MICROPY_HW_BOARD_NAME +// Can be set by mpconfigboard.cmake. +#define MICROPY_HW_BOARD_NAME "Generic ESP32S3 module" +#endif #define MICROPY_HW_MCU_NAME "ESP32S3" #define MICROPY_PY_MACHINE_DAC (0) diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/sdkconfig.board b/ports/esp32/boards/ESP32_GENERIC_S3/sdkconfig.board similarity index 100% rename from ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/sdkconfig.board rename to ports/esp32/boards/ESP32_GENERIC_S3/sdkconfig.board diff --git a/ports/esp32/boards/ESP32_S2_WROVER/board.json b/ports/esp32/boards/ESP32_S2_WROVER/board.json deleted file mode 100644 index 7ebc84415c..0000000000 --- a/ports/esp32/boards/ESP32_S2_WROVER/board.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "deploy": [ - "../deploy_s2.md" - ], - "docs": "", - "features": [ - "BLE", - "SPIRAM", - "WiFi" - ], - "images": [ - "ESP32-S2-WROVER_L_0.jpg" - ], - "mcu": "esp32s2", - "product": "ESP32-S2 WROVER", - "thumbnail": "", - "url": "https://www.espressif.com/en/products/modules", - "vendor": "Espressif" -} diff --git a/ports/esp32/boards/ESP32_S2_WROVER/mpconfigboard.cmake b/ports/esp32/boards/ESP32_S2_WROVER/mpconfigboard.cmake deleted file mode 100644 index 056c9ab4a6..0000000000 --- a/ports/esp32/boards/ESP32_S2_WROVER/mpconfigboard.cmake +++ /dev/null @@ -1,8 +0,0 @@ -set(IDF_TARGET esp32s2) - -set(SDKCONFIG_DEFAULTS - boards/sdkconfig.base - boards/sdkconfig.spiram_sx - boards/sdkconfig.usb - boards/ESP32_S2_WROVER/sdkconfig.board -) diff --git a/ports/esp32/boards/ESP32_S2_WROVER/mpconfigboard.h b/ports/esp32/boards/ESP32_S2_WROVER/mpconfigboard.h deleted file mode 100644 index a96262c607..0000000000 --- a/ports/esp32/boards/ESP32_S2_WROVER/mpconfigboard.h +++ /dev/null @@ -1,8 +0,0 @@ -#define MICROPY_HW_BOARD_NAME "ESP32-S2-WROVER" -#define MICROPY_HW_MCU_NAME "ESP32-S2" - -#define MICROPY_PY_BLUETOOTH (0) -#define MICROPY_HW_ENABLE_SDCARD (0) - -#define MICROPY_HW_I2C0_SCL (7) -#define MICROPY_HW_I2C0_SDA (6) diff --git a/ports/esp32/boards/ESP32_S2_WROVER/sdkconfig.board b/ports/esp32/boards/ESP32_S2_WROVER/sdkconfig.board deleted file mode 100644 index 40a8e3047c..0000000000 --- a/ports/esp32/boards/ESP32_S2_WROVER/sdkconfig.board +++ /dev/null @@ -1,10 +0,0 @@ -CONFIG_ESPTOOLPY_FLASHMODE_QIO=y -CONFIG_ESPTOOLPY_FLASHFREQ_80M=y -CONFIG_ESPTOOLPY_AFTER_NORESET=y - -CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y -CONFIG_USB_AND_UART=y - -# LWIP -CONFIG_LWIP_LOCAL_HOSTNAME="ESP32-S2-WROVER" -# end of LWIP diff --git a/ports/esp32/boards/GENERIC/board.md b/ports/esp32/boards/GENERIC/board.md deleted file mode 100644 index efb2b2cab7..0000000000 --- a/ports/esp32/boards/GENERIC/board.md +++ /dev/null @@ -1 +0,0 @@ -The following files are firmware for ESP32-based boards without external SPIRAM. diff --git a/ports/esp32/boards/GENERIC/mpconfigboard.cmake b/ports/esp32/boards/GENERIC/mpconfigboard.cmake deleted file mode 100644 index ac60dc8630..0000000000 --- a/ports/esp32/boards/GENERIC/mpconfigboard.cmake +++ /dev/null @@ -1,4 +0,0 @@ -set(SDKCONFIG_DEFAULTS - boards/sdkconfig.base - boards/sdkconfig.ble -) diff --git a/ports/esp32/boards/GENERIC/mpconfigboard.h b/ports/esp32/boards/GENERIC/mpconfigboard.h deleted file mode 100644 index 644807f78e..0000000000 --- a/ports/esp32/boards/GENERIC/mpconfigboard.h +++ /dev/null @@ -1,2 +0,0 @@ -#define MICROPY_HW_BOARD_NAME "ESP32 module" -#define MICROPY_HW_MCU_NAME "ESP32" diff --git a/ports/esp32/boards/GENERIC_C3_USB/board.json b/ports/esp32/boards/GENERIC_C3_USB/board.json deleted file mode 100644 index 23f9a8eb20..0000000000 --- a/ports/esp32/boards/GENERIC_C3_USB/board.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "deploy": [ - "../deploy_c3.md" - ], - "docs": "", - "features": [ - "BLE", - "WiFi" - ], - "id": "esp32c3-usb", - "images": [ - "esp32c3_devkitmini.jpg" - ], - "mcu": "esp32c3", - "product": "ESP32-C3 with USB", - "thumbnail": "", - "url": "https://www.espressif.com/en/products/modules", - "vendor": "Espressif" -} diff --git a/ports/esp32/boards/GENERIC_C3_USB/mpconfigboard.cmake b/ports/esp32/boards/GENERIC_C3_USB/mpconfigboard.cmake deleted file mode 100644 index 7436eead87..0000000000 --- a/ports/esp32/boards/GENERIC_C3_USB/mpconfigboard.cmake +++ /dev/null @@ -1,7 +0,0 @@ -set(IDF_TARGET esp32c3) - -set(SDKCONFIG_DEFAULTS - boards/sdkconfig.base - boards/sdkconfig.ble - boards/GENERIC_C3_USB/sdkconfig.board -) diff --git a/ports/esp32/boards/GENERIC_C3_USB/mpconfigboard.h b/ports/esp32/boards/GENERIC_C3_USB/mpconfigboard.h deleted file mode 100644 index d403e70e46..0000000000 --- a/ports/esp32/boards/GENERIC_C3_USB/mpconfigboard.h +++ /dev/null @@ -1,8 +0,0 @@ -// This configuration is for a generic ESP32C3 board with 4MiB (or more) of flash. - -#define MICROPY_HW_BOARD_NAME "ESP32C3 module" -#define MICROPY_HW_MCU_NAME "ESP32C3" - -#define MICROPY_HW_ENABLE_SDCARD (0) -#define MICROPY_PY_MACHINE_DAC (0) -#define MICROPY_PY_MACHINE_I2S (0) diff --git a/ports/esp32/boards/GENERIC_D2WD/board.json b/ports/esp32/boards/GENERIC_D2WD/board.json deleted file mode 100644 index 39fce46bca..0000000000 --- a/ports/esp32/boards/GENERIC_D2WD/board.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "deploy": [ - "../deploy.md" - ], - "docs": "", - "features": [ - "BLE", - "WiFi" - ], - "id": "esp32-d2wd", - "images": [ - "generic_d2wd.jpg" - ], - "mcu": "esp32", - "product": "ESP32 D2WD", - "thumbnail": "", - "url": "https://www.espressif.com/en/products/modules", - "vendor": "Espressif" -} diff --git a/ports/esp32/boards/GENERIC_D2WD/mpconfigboard.cmake b/ports/esp32/boards/GENERIC_D2WD/mpconfigboard.cmake deleted file mode 100644 index 88cc7a730e..0000000000 --- a/ports/esp32/boards/GENERIC_D2WD/mpconfigboard.cmake +++ /dev/null @@ -1,5 +0,0 @@ -set(SDKCONFIG_DEFAULTS - boards/sdkconfig.base - boards/sdkconfig.ble - boards/GENERIC_D2WD/sdkconfig.board -) diff --git a/ports/esp32/boards/GENERIC_D2WD/mpconfigboard.h b/ports/esp32/boards/GENERIC_D2WD/mpconfigboard.h deleted file mode 100644 index 8923d46fd1..0000000000 --- a/ports/esp32/boards/GENERIC_D2WD/mpconfigboard.h +++ /dev/null @@ -1,2 +0,0 @@ -#define MICROPY_HW_BOARD_NAME "Generic ESP32-D2WD module" -#define MICROPY_HW_MCU_NAME "ESP32-D2WD" diff --git a/ports/esp32/boards/GENERIC_OTA/board.json b/ports/esp32/boards/GENERIC_OTA/board.json deleted file mode 100644 index 97756a9fb2..0000000000 --- a/ports/esp32/boards/GENERIC_OTA/board.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "deploy": [ - "../deploy.md" - ], - "docs": "", - "features": [ - "BLE", - "WiFi" - ], - "id": "esp32-ota", - "images": [ - "esp32_devkitc.jpg" - ], - "mcu": "esp32", - "product": "ESP32 with OTA support", - "thumbnail": "", - "url": "https://www.espressif.com/en/products/modules", - "vendor": "Espressif" -} diff --git a/ports/esp32/boards/GENERIC_OTA/mpconfigboard.cmake b/ports/esp32/boards/GENERIC_OTA/mpconfigboard.cmake deleted file mode 100644 index 8bc9d507af..0000000000 --- a/ports/esp32/boards/GENERIC_OTA/mpconfigboard.cmake +++ /dev/null @@ -1,5 +0,0 @@ -set(SDKCONFIG_DEFAULTS - boards/sdkconfig.base - boards/sdkconfig.ble - boards/GENERIC_OTA/sdkconfig.board -) diff --git a/ports/esp32/boards/GENERIC_OTA/mpconfigboard.h b/ports/esp32/boards/GENERIC_OTA/mpconfigboard.h deleted file mode 100644 index ff39c4b2b7..0000000000 --- a/ports/esp32/boards/GENERIC_OTA/mpconfigboard.h +++ /dev/null @@ -1,2 +0,0 @@ -#define MICROPY_HW_BOARD_NAME "4MB/OTA module" -#define MICROPY_HW_MCU_NAME "ESP32" diff --git a/ports/esp32/boards/GENERIC_S2/mpconfigboard.h b/ports/esp32/boards/GENERIC_S2/mpconfigboard.h deleted file mode 100644 index c4f86a8fc6..0000000000 --- a/ports/esp32/boards/GENERIC_S2/mpconfigboard.h +++ /dev/null @@ -1,8 +0,0 @@ -#define MICROPY_HW_BOARD_NAME "ESP32S2 module" -#define MICROPY_HW_MCU_NAME "ESP32S2" - -#define MICROPY_PY_BLUETOOTH (0) -#define MICROPY_HW_ENABLE_SDCARD (0) - -// Enable UART REPL for modules that have an external USB-UART and don't use native USB. -#define MICROPY_HW_ENABLE_UART_REPL (1) diff --git a/ports/esp32/boards/GENERIC_S3/mpconfigboard.cmake b/ports/esp32/boards/GENERIC_S3/mpconfigboard.cmake deleted file mode 100644 index 3d83f89044..0000000000 --- a/ports/esp32/boards/GENERIC_S3/mpconfigboard.cmake +++ /dev/null @@ -1,8 +0,0 @@ -set(IDF_TARGET esp32s3) - -set(SDKCONFIG_DEFAULTS - boards/sdkconfig.base - boards/sdkconfig.usb - boards/sdkconfig.ble - boards/GENERIC_S3/sdkconfig.board -) diff --git a/ports/esp32/boards/GENERIC_S3/mpconfigboard.h b/ports/esp32/boards/GENERIC_S3/mpconfigboard.h deleted file mode 100644 index b8f5fb2560..0000000000 --- a/ports/esp32/boards/GENERIC_S3/mpconfigboard.h +++ /dev/null @@ -1,10 +0,0 @@ -#define MICROPY_HW_BOARD_NAME "ESP32S3 module" -#define MICROPY_HW_MCU_NAME "ESP32S3" - -#define MICROPY_PY_MACHINE_DAC (0) - -// Enable UART REPL for modules that have an external USB-UART and don't use native USB. -#define MICROPY_HW_ENABLE_UART_REPL (1) - -#define MICROPY_HW_I2C0_SCL (9) -#define MICROPY_HW_I2C0_SDA (8) diff --git a/ports/esp32/boards/GENERIC_S3/sdkconfig.board b/ports/esp32/boards/GENERIC_S3/sdkconfig.board deleted file mode 100644 index a36b971162..0000000000 --- a/ports/esp32/boards/GENERIC_S3/sdkconfig.board +++ /dev/null @@ -1,9 +0,0 @@ -CONFIG_ESPTOOLPY_FLASHMODE_QIO=y -CONFIG_ESPTOOLPY_FLASHFREQ_80M=y -CONFIG_ESPTOOLPY_AFTER_NORESET=y - -CONFIG_ESPTOOLPY_FLASHSIZE_4MB= -CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y -CONFIG_ESPTOOLPY_FLASHSIZE_16MB= -CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-8MiB.csv" diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM/board.json b/ports/esp32/boards/GENERIC_S3_SPIRAM/board.json deleted file mode 100644 index 3b405d4a12..0000000000 --- a/ports/esp32/boards/GENERIC_S3_SPIRAM/board.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "deploy": [ - "../deploy_s3.md" - ], - "docs": "", - "features": [ - "BLE", - "WiFi" - ], - "images": [ - "generic_s3.jpg" - ], - "mcu": "esp32s3", - "product": "Generic ESP32-S3 (SPIRAM)", - "thumbnail": "", - "url": "https://www.espressif.com/en/products/modules", - "vendor": "Espressif" -} diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.cmake b/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.cmake deleted file mode 100644 index e0b92dcd26..0000000000 --- a/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(IDF_TARGET esp32s3) - -set(SDKCONFIG_DEFAULTS - boards/sdkconfig.base - boards/sdkconfig.usb - boards/sdkconfig.ble - boards/sdkconfig.spiram_sx - boards/GENERIC_S3_SPIRAM/sdkconfig.board -) diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM/sdkconfig.board b/ports/esp32/boards/GENERIC_S3_SPIRAM/sdkconfig.board deleted file mode 100644 index a36b971162..0000000000 --- a/ports/esp32/boards/GENERIC_S3_SPIRAM/sdkconfig.board +++ /dev/null @@ -1,9 +0,0 @@ -CONFIG_ESPTOOLPY_FLASHMODE_QIO=y -CONFIG_ESPTOOLPY_FLASHFREQ_80M=y -CONFIG_ESPTOOLPY_AFTER_NORESET=y - -CONFIG_ESPTOOLPY_FLASHSIZE_4MB= -CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y -CONFIG_ESPTOOLPY_FLASHSIZE_16MB= -CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-8MiB.csv" diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/board.json b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/board.json deleted file mode 100644 index f3ca177ef9..0000000000 --- a/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/board.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "deploy": [ - "../deploy_s3.md" - ], - "docs": "", - "features": [ - "BLE", - "WiFi" - ], - "images": [ - "generic_s3.jpg" - ], - "mcu": "esp32s3", - "product": "Generic ESP32-S3 (SPIRAM Octal)", - "thumbnail": "", - "url": "https://www.espressif.com/en/products/modules", - "vendor": "Espressif" -} diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.h b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.h deleted file mode 100644 index 88f6835c94..0000000000 --- a/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.h +++ /dev/null @@ -1,10 +0,0 @@ -#define MICROPY_HW_BOARD_NAME "ESP32S3 module (spiram octal)" -#define MICROPY_HW_MCU_NAME "ESP32S3" - -#define MICROPY_PY_MACHINE_DAC (0) - -// Enable UART REPL for modules that have an external USB-UART and don't use native USB. -#define MICROPY_HW_ENABLE_UART_REPL (1) - -#define MICROPY_HW_I2C0_SCL (9) -#define MICROPY_HW_I2C0_SDA (8) diff --git a/ports/esp32/boards/GENERIC_SPIRAM/board.md b/ports/esp32/boards/GENERIC_SPIRAM/board.md deleted file mode 100644 index c638f63dd3..0000000000 --- a/ports/esp32/boards/GENERIC_SPIRAM/board.md +++ /dev/null @@ -1 +0,0 @@ -The following files are firmware for ESP32-based boards with external SPIRAM (also known as PSRAM). diff --git a/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.cmake b/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.cmake deleted file mode 100644 index 2e1d799b93..0000000000 --- a/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.cmake +++ /dev/null @@ -1,5 +0,0 @@ -set(SDKCONFIG_DEFAULTS - boards/sdkconfig.base - boards/sdkconfig.ble - boards/sdkconfig.spiram -) diff --git a/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.h b/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.h deleted file mode 100644 index a5982e47e5..0000000000 --- a/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.h +++ /dev/null @@ -1,2 +0,0 @@ -#define MICROPY_HW_BOARD_NAME "ESP32 module (spiram)" -#define MICROPY_HW_MCU_NAME "ESP32" diff --git a/ports/esp32/boards/GENERIC_UNICORE/board.json b/ports/esp32/boards/GENERIC_UNICORE/board.json deleted file mode 100644 index 8fed71a018..0000000000 --- a/ports/esp32/boards/GENERIC_UNICORE/board.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "deploy": [ - "../deploy.md" - ], - "docs": "", - "features": [ - "BLE", - "WiFi" - ], - "id": "esp32-unicore", - "images": [ - "generic_unicore.jpg" - ], - "mcu": "esp32", - "product": "ESP32 Unicore", - "thumbnail": "", - "url": "https://www.espressif.com/en/products/modules", - "vendor": "Espressif" -} diff --git a/ports/esp32/boards/GENERIC_UNICORE/board.md b/ports/esp32/boards/GENERIC_UNICORE/board.md deleted file mode 100644 index b41c167498..0000000000 --- a/ports/esp32/boards/GENERIC_UNICORE/board.md +++ /dev/null @@ -1 +0,0 @@ -The following files are daily firmware for single-core ESP32-based boards without external SPIRAM. diff --git a/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.cmake b/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.cmake deleted file mode 100644 index 2f34688c8c..0000000000 --- a/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.cmake +++ /dev/null @@ -1,5 +0,0 @@ -set(SDKCONFIG_DEFAULTS - boards/sdkconfig.base - boards/sdkconfig.ble - boards/GENERIC_UNICORE/sdkconfig.board -) diff --git a/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h b/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h deleted file mode 100644 index 5d0624b9c3..0000000000 --- a/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h +++ /dev/null @@ -1,2 +0,0 @@ -#define MICROPY_HW_BOARD_NAME "ESP32 Unicore module" -#define MICROPY_HW_MCU_NAME "ESP32-UNICORE" diff --git a/ports/esp32/boards/LILYGO_TTGO_LORA32/board.json b/ports/esp32/boards/LILYGO_TTGO_LORA32/board.json index 9dd76b5792..525551df3b 100644 --- a/ports/esp32/boards/LILYGO_TTGO_LORA32/board.json +++ b/ports/esp32/boards/LILYGO_TTGO_LORA32/board.json @@ -5,10 +5,11 @@ "docs": "", "features": [ "BLE", + "Display", + "External Flash", "LoRa", - "OLED", "SDCard", - "USB-MICRO", + "USB", "WiFi" ], "images": [ diff --git a/ports/esp32/boards/LOLIN_C3_MINI/board.json b/ports/esp32/boards/LOLIN_C3_MINI/board.json index f47c672fa4..c9b91641e5 100644 --- a/ports/esp32/boards/LOLIN_C3_MINI/board.json +++ b/ports/esp32/boards/LOLIN_C3_MINI/board.json @@ -5,6 +5,7 @@ "docs": "", "features": [ "BLE", + "External Flash", "USB-C", "WiFi" ], diff --git a/ports/esp32/boards/LOLIN_S2_MINI/board.json b/ports/esp32/boards/LOLIN_S2_MINI/board.json index 41e62a0228..a45d0434d9 100644 --- a/ports/esp32/boards/LOLIN_S2_MINI/board.json +++ b/ports/esp32/boards/LOLIN_S2_MINI/board.json @@ -4,7 +4,8 @@ ], "docs": "", "features": [ - "SPIRAM", + "External Flash", + "External RAM", "USB-C", "WiFi" ], diff --git a/ports/esp32/boards/LOLIN_S2_MINI/sdkconfig.board b/ports/esp32/boards/LOLIN_S2_MINI/sdkconfig.board index cbb3ad06d9..00ccc281ea 100644 --- a/ports/esp32/boards/LOLIN_S2_MINI/sdkconfig.board +++ b/ports/esp32/boards/LOLIN_S2_MINI/sdkconfig.board @@ -1,6 +1,5 @@ CONFIG_ESPTOOLPY_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHFREQ_80M=y -CONFIG_USB_AND_UART=y # LWIP CONFIG_LWIP_LOCAL_HOSTNAME="LOLIN_S2_MINI" # end of LWIP diff --git a/ports/esp32/boards/LOLIN_S2_PICO/board.json b/ports/esp32/boards/LOLIN_S2_PICO/board.json index 43322b87b0..6c72e60f80 100644 --- a/ports/esp32/boards/LOLIN_S2_PICO/board.json +++ b/ports/esp32/boards/LOLIN_S2_PICO/board.json @@ -4,10 +4,10 @@ ], "docs": "", "features": [ - "Breadboard Friendly", - "OLED", - "SPIRAM", - "STEMMA QT/QWIIC", + "Display", + "External Flash", + "External RAM", + "JST-SH", "USB-C", "WiFi" ], diff --git a/ports/esp32/boards/LOLIN_S2_PICO/sdkconfig.board b/ports/esp32/boards/LOLIN_S2_PICO/sdkconfig.board index eadff2f1b9..a49f3936e7 100644 --- a/ports/esp32/boards/LOLIN_S2_PICO/sdkconfig.board +++ b/ports/esp32/boards/LOLIN_S2_PICO/sdkconfig.board @@ -1,6 +1,5 @@ CONFIG_ESPTOOLPY_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHFREQ_80M=y -CONFIG_USB_AND_UART=y # LWIP CONFIG_LWIP_LOCAL_HOSTNAME="LOLIN_S2_PICO" # end of LWIP diff --git a/ports/esp32/boards/M5STACK_ATOM/board.json b/ports/esp32/boards/M5STACK_ATOM/board.json index 9d1886887c..4b6c09db3a 100644 --- a/ports/esp32/boards/M5STACK_ATOM/board.json +++ b/ports/esp32/boards/M5STACK_ATOM/board.json @@ -4,9 +4,9 @@ ], "docs": "", "features": [ - "Grove", + "External Flash", "IMU", - "Infrared", + "JST-PH", "RGB LED", "USB-C", "WiFi" diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/board.json b/ports/esp32/boards/OLIMEX_ESP32_POE/board.json index 84b6680d59..e62b960ccd 100644 --- a/ports/esp32/boards/OLIMEX_ESP32_POE/board.json +++ b/ports/esp32/boards/OLIMEX_ESP32_POE/board.json @@ -5,12 +5,12 @@ "docs": "", "features": [ "BLE", - "WiFi", - "MicroSD", "Battery Charging", "Ethernet", + "External Flash", "PoE", - "Breadboard friendly" + "WiFi", + "microSD" ], "images": [ "ESP32-POE-ISO-1.jpg" diff --git a/ports/esp32/boards/SIL_WESP32/board.json b/ports/esp32/boards/SIL_WESP32/board.json index 050620d618..50dd2cc660 100644 --- a/ports/esp32/boards/SIL_WESP32/board.json +++ b/ports/esp32/boards/SIL_WESP32/board.json @@ -6,10 +6,10 @@ "features": [ "BLE", "Ethernet", + "External Flash", "PoE", "WiFi" ], - "id": "wesp32", "images": [ "wesp32-iso.jpg", "wesp32-top.jpg" @@ -18,5 +18,5 @@ "product": "SIL WESP32", "thumbnail": "", "url": "https://wesp32.com/", - "vendor": "Silicognition LLC" + "vendor": "Silicognition" } diff --git a/ports/esp32/boards/UM_FEATHERS2/board.json b/ports/esp32/boards/UM_FEATHERS2/board.json index fa5b213db0..4de9a7d4f7 100644 --- a/ports/esp32/boards/UM_FEATHERS2/board.json +++ b/ports/esp32/boards/UM_FEATHERS2/board.json @@ -5,17 +5,17 @@ "docs": "", "features": [ "Battery Charging", + "External Flash", + "External RAM", "Feather", + "JST-SH", "RGB LED", - "SPIRAM", - "STEMMA QT/QWIIC", "USB-C", "WiFi" ], "features_non_filterable": [ "Second LDO" ], - "id": "featherS2", "images": [ "unexpectedmaker_feathers2.jpg" ], diff --git a/ports/esp32/boards/UM_FEATHERS2/pins.csv b/ports/esp32/boards/UM_FEATHERS2/pins.csv new file mode 100644 index 0000000000..edb7273f32 --- /dev/null +++ b/ports/esp32/boards/UM_FEATHERS2/pins.csv @@ -0,0 +1,12 @@ +AMB_LIGHT,GPIO4 +I2C_SCL,GPIO8 +I2C_SDA,GPIO9 +LDO2_PWR,GPIO21 +LED_BLUE,GPIO13 +RGB_DATA,GPIO40 +RGB_CLK,GPIO45 +SPI_MOSI,GPIO35 +SPI_SCK,GPIO36 +SPI_MISO,GPIO37 +UART0_TX,GPIO43 +UART0_RX,GPIO44 diff --git a/ports/esp32/boards/UM_FEATHERS2/sdkconfig.board b/ports/esp32/boards/UM_FEATHERS2/sdkconfig.board index b23755dea7..c2e1c2b3d3 100644 --- a/ports/esp32/boards/UM_FEATHERS2/sdkconfig.board +++ b/ports/esp32/boards/UM_FEATHERS2/sdkconfig.board @@ -2,6 +2,8 @@ CONFIG_ESPTOOLPY_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHFREQ_80M=y CONFIG_ESPTOOLPY_AFTER_NORESET=y +CONFIG_SPIRAM_MEMTEST= + CONFIG_ESPTOOLPY_FLASHSIZE_4MB= CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y CONFIG_PARTITION_TABLE_CUSTOM=y diff --git a/ports/esp32/boards/UM_FEATHERS2NEO/board.json b/ports/esp32/boards/UM_FEATHERS2NEO/board.json index d809485e86..dfa1f46dc3 100644 --- a/ports/esp32/boards/UM_FEATHERS2NEO/board.json +++ b/ports/esp32/boards/UM_FEATHERS2NEO/board.json @@ -5,17 +5,17 @@ "docs": "", "features": [ "Battery Charging", + "External Flash", + "External RAM", "Feather", + "JST-SH", "RGB LED", - "SPIRAM", - "STEMMA QT/QWIIC", "USB-C", "WiFi" ], "features_non_filterable": [ "5x5 RGB LED Matrix" ], - "id": "featherS2neo", "images": [ "FeatherS2_Neo_White_Product2.jpg" ], diff --git a/ports/esp32/boards/UM_FEATHERS2NEO/pins.csv b/ports/esp32/boards/UM_FEATHERS2NEO/pins.csv new file mode 100644 index 0000000000..48e933dc95 --- /dev/null +++ b/ports/esp32/boards/UM_FEATHERS2NEO/pins.csv @@ -0,0 +1,14 @@ +I2C_SCL,GPIO8 +I2C_SDA,GPIO9 +LED_BLUE,GPIO13 +RGB_DATA,GPIO40 +RGB_PWR,GPIO39 +RGB_MATRIX_DATA,GPIO21 +RGB_MATRIX_DATA,GPIO4 +SPI_MOSI,GPIO35 +SPI_SCK,GPIO36 +SPI_MISO,GPIO37 +UART0_TX,GPIO43 +UART0_RX,GPIO44 +VBAT_SENSE,GPIO2 +VBUS_SENSE,GPIO34 diff --git a/ports/esp32/boards/UM_FEATHERS2NEO/sdkconfig.board b/ports/esp32/boards/UM_FEATHERS2NEO/sdkconfig.board index b2c6979a70..a624f7fd97 100644 --- a/ports/esp32/boards/UM_FEATHERS2NEO/sdkconfig.board +++ b/ports/esp32/boards/UM_FEATHERS2NEO/sdkconfig.board @@ -1,6 +1,5 @@ CONFIG_ESPTOOLPY_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHFREQ_80M=y -CONFIG_USB_AND_UART=y CONFIG_ESPTOOLPY_AFTER_NORESET=y # LWIP diff --git a/ports/esp32/boards/UM_FEATHERS3/board.json b/ports/esp32/boards/UM_FEATHERS3/board.json index 68423cca5e..235d52a12d 100644 --- a/ports/esp32/boards/UM_FEATHERS3/board.json +++ b/ports/esp32/boards/UM_FEATHERS3/board.json @@ -4,18 +4,17 @@ ], "docs": "", "features": [ - "Battery Charging", - "RGB LED", - "SPIRAM", - "USB-C", - "WiFi", "BLE", - "STEMMA QT/QWIIC", - "Feather" + "Battery Charging", + "External Flash", + "External RAM", + "Feather", + "JST-SH", + "RGB LED", + "USB-C", + "WiFi" ], - "features_non_filterable": [ - ], - "id": "feathers3", + "features_non_filterable": [], "images": [ "unexpectedmaker_feathers3.jpg" ], diff --git a/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h b/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h index 91ea5056d1..488a588442 100644 --- a/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h +++ b/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h @@ -7,6 +7,9 @@ #define MICROPY_HW_I2C0_SCL (9) #define MICROPY_HW_I2C0_SDA (8) +#define MICROPY_HW_I2C1_SCL (15) +#define MICROPY_HW_I2C1_SDA (16) + #define MICROPY_HW_SPI1_MOSI (35) #define MICROPY_HW_SPI1_MISO (37) #define MICROPY_HW_SPI1_SCK (36) diff --git a/ports/esp32/boards/UM_FEATHERS3/pins.csv b/ports/esp32/boards/UM_FEATHERS3/pins.csv new file mode 100644 index 0000000000..38240bc33e --- /dev/null +++ b/ports/esp32/boards/UM_FEATHERS3/pins.csv @@ -0,0 +1,15 @@ +AMB_LIGHT,GPIO4 +I2C_SCL,GPIO9 +I2C_SDA,GPIO8 +I2C_SCL2,GPIO15 +I2C_SDA2,GPIO16 +LDO2_PWR,GPIO39 +LED_BLUE,GPIO13 +SPI_MOSI,GPIO35 +SPI_SCK,GPIO36 +SPI_MISO,GPIO37 +RGB_DATA,GPIO40 +UART0_TX,GPIO43 +UART0_RX,GPIO44 +VBAT_SENSE,GPIO2 +VBUS_SENSE,GPIO34 diff --git a/ports/esp32/boards/UM_FEATHERS3/sdkconfig.board b/ports/esp32/boards/UM_FEATHERS3/sdkconfig.board index 804944ab24..3c8df5e2a8 100644 --- a/ports/esp32/boards/UM_FEATHERS3/sdkconfig.board +++ b/ports/esp32/boards/UM_FEATHERS3/sdkconfig.board @@ -5,6 +5,7 @@ CONFIG_ESPTOOLPY_AFTER_NORESET=y CONFIG_ESPTOOLPY_FLASHSIZE_4MB= CONFIG_ESPTOOLPY_FLASHSIZE_8MB= CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y +CONFIG_SPIRAM_MEMTEST= CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-16MiB.csv" diff --git a/ports/esp32/boards/UM_NANOS3/board.json b/ports/esp32/boards/UM_NANOS3/board.json new file mode 100644 index 0000000000..2eb40ac3c9 --- /dev/null +++ b/ports/esp32/boards/UM_NANOS3/board.json @@ -0,0 +1,25 @@ +{ + "deploy": [ + "deploy.md" + ], + "docs": "", + "features": [ + "Battery Charging", + "RGB LED", + "SPIRAM", + "WiFi", + "BLE" + ], + "features_non_filterable": [ + "TinyPICO Nano Compatible" + ], + "id": "nanos3", + "images": [ + "unexpectedmaker_nanos3.jpg" + ], + "mcu": "esp32s3", + "product": "NanoS3", + "thumbnail": "", + "url": "https://nanos3.io", + "vendor": "Unexpected Maker" +} diff --git a/ports/esp32/boards/UM_NANOS3/board.md b/ports/esp32/boards/UM_NANOS3/board.md new file mode 100644 index 0000000000..9cb5310f63 --- /dev/null +++ b/ports/esp32/boards/UM_NANOS3/board.md @@ -0,0 +1 @@ +The following files are firmware for the NanoS3. diff --git a/ports/esp32/boards/UM_NANOS3/deploy.md b/ports/esp32/boards/UM_NANOS3/deploy.md new file mode 100644 index 0000000000..725cff4946 --- /dev/null +++ b/ports/esp32/boards/UM_NANOS3/deploy.md @@ -0,0 +1,52 @@ +Program your board using the latest version of the esptool.py program, found [here](https://github.com/espressif/esptool). + +To flash or erase your NanoS3, you have to first put it into download mode. +To do this, follow these steps: + +- Press and hold the [BOOT] button +- Press and release the [RESET] button +- Release the [BOOT] button + +Now the board is in download mode and the native USB will have enumerated as a serial device. + +If you are putting MicroPython on your board for the first time then you should +first erase the entire flash using: + +### Linux +```bash +esptool.py --chip esp32s3 --port /dev/ttyACM0 erase_flash +``` + +### Mac +Please do a `ls /dev/cu.usbm*` to determine the port your board has enumerated as. +```bash +esptool.py --chip esp32s3 --port /dev/cu.usbmodem01 erase_flash +``` + +### Windows +Change (X) to whatever COM port is being used by the board +```bash +esptool --chip esp32s3 --port COM(X) erase_flash +``` + +Now download the version of the firmware you would like to install from the options below, +then use the following command to program the firmware starting at address 0x0, +remembering to replace `nanos3-micropython-firmware-version.bin` with the name of +the firmware you just downloaded: + +### Linux +```bash +esptool.py --chip esp32s3 --port /dev/ttyACM0 write_flash -z 0x0 nanos3-micropython-firmware-version.bin +``` + +### Mac +Please do a `ls /dev/cu.usbm*` to determine the port your board has enumerated as. +```bash +esptool.py --chip esp32s3 --port /dev/cu.usbmodem01 write_flash -z 0x0 nanos3-micropython-firmware-version.bin +``` + +### Windows +Change (X) to whatever COM port is being used by the board +```bash +esptool --chip esp32s3 --port COM(X) write_flash -z 0x0 nanos3-micropython-firmware-version.bin +``` diff --git a/ports/esp32/boards/UM_NANOS3/manifest.py b/ports/esp32/boards/UM_NANOS3/manifest.py new file mode 100644 index 0000000000..7ae2ed15d9 --- /dev/null +++ b/ports/esp32/boards/UM_NANOS3/manifest.py @@ -0,0 +1,2 @@ +include("$(PORT_DIR)/boards/manifest.py") +freeze("modules") diff --git a/ports/esp32/boards/UM_NANOS3/modules/nanos3.py b/ports/esp32/boards/UM_NANOS3/modules/nanos3.py new file mode 100644 index 0000000000..b3d57f121a --- /dev/null +++ b/ports/esp32/boards/UM_NANOS3/modules/nanos3.py @@ -0,0 +1,46 @@ +# NanoS3 Helper Library +# MIT license; Copyright (c) 2023 Seon Rozenblum - Unexpected Maker +# +# Project home: +# https://nanos3.io + +# Import required libraries +from micropython import const +from machine import Pin, ADC +import time + +# TinyS3 Hardware Pin Assignments + +# RGB LED Pins +RGB_DATA = const(41) +RGB_PWR = const(42) + +# SPI +SPI_MOSI = const(35) +SPI_MISO = const(37) +SPI_CLK = const(36) + +# I2C +I2C_SDA = const(8) +I2C_SCL = const(9) + + +# Helper functions +def set_pixel_power(state): + """Enable or Disable power to the onboard NeoPixel to either show colour, or to reduce power for deep sleep.""" + Pin(RGB_PWR, Pin.OUT).value(state) + + +# NeoPixel rainbow colour wheel +def rgb_color_wheel(wheel_pos): + """Color wheel to allow for cycling through the rainbow of RGB colors.""" + wheel_pos = wheel_pos % 255 + + if wheel_pos < 85: + return 255 - wheel_pos * 3, 0, wheel_pos * 3 + elif wheel_pos < 170: + wheel_pos -= 85 + return 0, wheel_pos * 3, 255 - wheel_pos * 3 + else: + wheel_pos -= 170 + return wheel_pos * 3, 255 - wheel_pos * 3, 0 diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.cmake b/ports/esp32/boards/UM_NANOS3/mpconfigboard.cmake similarity index 64% rename from ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.cmake rename to ports/esp32/boards/UM_NANOS3/mpconfigboard.cmake index 7a767c49d4..6c7f34009e 100644 --- a/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.cmake +++ b/ports/esp32/boards/UM_NANOS3/mpconfigboard.cmake @@ -6,6 +6,7 @@ set(SDKCONFIG_DEFAULTS boards/sdkconfig.ble boards/sdkconfig.240mhz boards/sdkconfig.spiram_sx - boards/sdkconfig.spiram_oct - boards/GENERIC_S3_SPIRAM_OCT/sdkconfig.board + boards/UM_TINYS3/sdkconfig.board ) + +set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py) diff --git a/ports/esp32/boards/UM_NANOS3/mpconfigboard.h b/ports/esp32/boards/UM_NANOS3/mpconfigboard.h new file mode 100644 index 0000000000..1c2782bfb7 --- /dev/null +++ b/ports/esp32/boards/UM_NANOS3/mpconfigboard.h @@ -0,0 +1,12 @@ +#define MICROPY_HW_BOARD_NAME "NanoS3" +#define MICROPY_HW_MCU_NAME "ESP32-S3-FN8" +#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "NanoS3" + +#define MICROPY_PY_MACHINE_DAC (0) + +#define MICROPY_HW_I2C0_SCL (9) +#define MICROPY_HW_I2C0_SDA (8) + +#define MICROPY_HW_SPI1_MOSI (35) +#define MICROPY_HW_SPI1_MISO (37) +#define MICROPY_HW_SPI1_SCK (36) diff --git a/ports/esp32/boards/UM_NANOS3/pins.csv b/ports/esp32/boards/UM_NANOS3/pins.csv new file mode 100644 index 0000000000..44880f82ba --- /dev/null +++ b/ports/esp32/boards/UM_NANOS3/pins.csv @@ -0,0 +1,10 @@ +I2C_SCL,GPIO8 +I2C_SDA,GPIO9 +SPI_SS,GPIO34 +SPI_MOSI,GPIO35 +SPI_SCK,GPIO36 +SPI_MISO,GPIO37 +RGB_DATA,GPIO41 +RGB_PWR,GPIO42 +UART0_TX,GPIO43 +UART0_RX,GPIO44 diff --git a/ports/esp32/boards/UM_NANOS3/sdkconfig.board b/ports/esp32/boards/UM_NANOS3/sdkconfig.board new file mode 100644 index 0000000000..969bbc5be7 --- /dev/null +++ b/ports/esp32/boards/UM_NANOS3/sdkconfig.board @@ -0,0 +1,19 @@ +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_ESPTOOLPY_AFTER_NORESET=y + +CONFIG_ESPTOOLPY_FLASHSIZE_4MB= +CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y +CONFIG_ESPTOOLPY_FLASHSIZE_16MB= +CONFIG_SPIRAM_MEMTEST= +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-8MiB.csv" + +CONFIG_LWIP_LOCAL_HOSTNAME="UMNanoS3" + +CONFIG_TINYUSB_DESC_CUSTOM_VID=0x303A +CONFIG_TINYUSB_DESC_CUSTOM_PID=0x817A +CONFIG_TINYUSB_DESC_BCD_DEVICE=0x0100 +CONFIG_TINYUSB_DESC_MANUFACTURER_STRING="Unexpected Maker" +CONFIG_TINYUSB_DESC_PRODUCT_STRING="NanoS3" +CONFIG_TINYUSB_DESC_SERIAL_STRING="_ns3_" diff --git a/ports/esp32/boards/UM_PROS3/board.json b/ports/esp32/boards/UM_PROS3/board.json index 0122e4b991..8efc4e5ab5 100644 --- a/ports/esp32/boards/UM_PROS3/board.json +++ b/ports/esp32/boards/UM_PROS3/board.json @@ -4,18 +4,17 @@ ], "docs": "", "features": [ - "Battery Charging", - "RGB LED", - "SPIRAM", - "USB-C", - "WiFi", "BLE", - "STEMMA QT/QWIIC", - "Feather" + "Battery Charging", + "External Flash", + "External RAM", + "Feather", + "JST-SH", + "RGB LED", + "USB-C", + "WiFi" ], - "features_non_filterable": [ - ], - "id": "pros3", + "features_non_filterable": [], "images": [ "unexpectedmaker_pros3.jpg" ], diff --git a/ports/esp32/boards/UM_PROS3/pins.csv b/ports/esp32/boards/UM_PROS3/pins.csv new file mode 100644 index 0000000000..c0d4149d75 --- /dev/null +++ b/ports/esp32/boards/UM_PROS3/pins.csv @@ -0,0 +1,12 @@ +I2C_SCL,GPIO8 +I2C_SDA,GPIO9 +VBAT_SENSE,GPIO10 +LDO2_PWR,GPIO17 +RGB_DATA,GPIO18 +VBUS_SENSE,GPIO33 +SPI_SS,GPIO34 +SPI_MOSI,GPIO35 +SPI_SCK,GPIO36 +SPI_MISO,GPIO37 +UART0_TX,GPIO43 +UART0_RX,GPIO44 diff --git a/ports/esp32/boards/UM_PROS3/sdkconfig.board b/ports/esp32/boards/UM_PROS3/sdkconfig.board index 71511e3c52..5d1ac0f684 100644 --- a/ports/esp32/boards/UM_PROS3/sdkconfig.board +++ b/ports/esp32/boards/UM_PROS3/sdkconfig.board @@ -5,6 +5,7 @@ CONFIG_ESPTOOLPY_AFTER_NORESET=y CONFIG_ESPTOOLPY_FLASHSIZE_4MB= CONFIG_ESPTOOLPY_FLASHSIZE_8MB= CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y +CONFIG_SPIRAM_MEMTEST= CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-16MiB.csv" diff --git a/ports/esp32/boards/UM_TINYPICO/board.json b/ports/esp32/boards/UM_TINYPICO/board.json index 9f1783a9f1..bf0b3d2c8c 100644 --- a/ports/esp32/boards/UM_TINYPICO/board.json +++ b/ports/esp32/boards/UM_TINYPICO/board.json @@ -4,17 +4,17 @@ ], "docs": "", "features": [ - "Battery Charging", "BLE", + "Battery Charging", + "External Flash", + "External RAM", "RGB LED", - "SPIRAM", "USB-C", "WiFi" ], "features_non_filterable": [ "TinyPICO Compatible" ], - "id": "tinypico", "images": [ "tinypico-v2-both.jpg" ], @@ -23,7 +23,7 @@ "thumbnail": "", "url": "https://www.tinypico.com/", "variants": { - "idf3": "Compiled with IDF 3.x" + "IDF3": "Compiled with IDF 3.x" }, "vendor": "Unexpected Maker" } diff --git a/ports/esp32/boards/UM_TINYPICO/pins.csv b/ports/esp32/boards/UM_TINYPICO/pins.csv new file mode 100644 index 0000000000..a8ab074cce --- /dev/null +++ b/ports/esp32/boards/UM_TINYPICO/pins.csv @@ -0,0 +1,12 @@ +I2C_SCL,GPIO22 +I2C_SDA,GPIO21 +RGB_DATA,GPIO2 +RGB_CLK,GPIO12 +RGB_PWR,GPIO13 +SPI_SS,GPIO5 +SPI_MOSI,GPIO23 +SPI_SCK,GPIO18 +SPI_MISO,GPIO19 +VBAT_SENSE,GPIO35 +VBAT_CHRG,GPIO34 +VBUS_SENSE,GPIO9 diff --git a/ports/esp32/boards/UM_TINYS2/board.json b/ports/esp32/boards/UM_TINYS2/board.json index e7068170cb..1b4c934dfa 100644 --- a/ports/esp32/boards/UM_TINYS2/board.json +++ b/ports/esp32/boards/UM_TINYS2/board.json @@ -5,16 +5,16 @@ "docs": "", "features": [ "Battery Charging", + "External Flash", + "External RAM", + "JST-SH", "RGB LED", - "SPIRAM", - "STEMMA QT/QWIIC", "USB-C", "WiFi" ], "features_non_filterable": [ "TinyPICO Compatible" ], - "id": "tinys2", "images": [ "TinyS2+Product+Shot.jpg" ], diff --git a/ports/esp32/boards/UM_TINYS2/pins.csv b/ports/esp32/boards/UM_TINYS2/pins.csv new file mode 100644 index 0000000000..1ef7b2ecc8 --- /dev/null +++ b/ports/esp32/boards/UM_TINYS2/pins.csv @@ -0,0 +1,12 @@ +I2C_SCL,GPIO8 +I2C_SDA,GPIO9 +RGB_DATA,GPIO1 +RGB_PWR,GPIO2 +SPI_SS,GPIO14 +SPI_MOSI,GPIO35 +SPI_SCK,GPIO36 +SPI_MISO,GPIO37 +UART0_TX,GPIO43 +UART0_RX,GPIO44 +VBAT_SENSE,GPIO3 +VBUS_SENSE,GPIO21 diff --git a/ports/esp32/boards/UM_TINYS2/sdkconfig.board b/ports/esp32/boards/UM_TINYS2/sdkconfig.board index 09e0deb078..0a2097e242 100644 --- a/ports/esp32/boards/UM_TINYS2/sdkconfig.board +++ b/ports/esp32/boards/UM_TINYS2/sdkconfig.board @@ -1,6 +1,5 @@ CONFIG_ESPTOOLPY_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHFREQ_80M=y -CONFIG_USB_AND_UART=y CONFIG_ESPTOOLPY_AFTER_NORESET=y # LWIP diff --git a/ports/esp32/boards/UM_TINYS3/board.json b/ports/esp32/boards/UM_TINYS3/board.json index 73482a6284..27ae46a249 100644 --- a/ports/esp32/boards/UM_TINYS3/board.json +++ b/ports/esp32/boards/UM_TINYS3/board.json @@ -4,17 +4,17 @@ ], "docs": "", "features": [ + "BLE", "Battery Charging", + "External Flash", + "External RAM", "RGB LED", - "SPIRAM", "USB-C", - "WiFi", - "BLE" + "WiFi" ], "features_non_filterable": [ "TinyPICO Compatible" ], - "id": "tinys3", "images": [ "unexpectedmaker_tinys3.jpg" ], diff --git a/ports/esp32/boards/UM_TINYS3/pins.csv b/ports/esp32/boards/UM_TINYS3/pins.csv new file mode 100644 index 0000000000..1fad949a44 --- /dev/null +++ b/ports/esp32/boards/UM_TINYS3/pins.csv @@ -0,0 +1,12 @@ +I2C_SCL,GPIO8 +I2C_SDA,GPIO9 +RGB_DATA,GPIO18 +RGB_PWR,GPIO19 +SPI_SS,GPIO34 +SPI_MOSI,GPIO35 +SPI_SCK,GPIO36 +SPI_MISO,GPIO37 +UART0_TX,GPIO43 +UART0_RX,GPIO44 +VBAT_SENSE,GPIO10 +VBUS_SENSE,GPIO33 diff --git a/ports/esp32/boards/UM_TINYS3/sdkconfig.board b/ports/esp32/boards/UM_TINYS3/sdkconfig.board index c22e78eaea..7b913a565f 100644 --- a/ports/esp32/boards/UM_TINYS3/sdkconfig.board +++ b/ports/esp32/boards/UM_TINYS3/sdkconfig.board @@ -5,6 +5,7 @@ CONFIG_ESPTOOLPY_AFTER_NORESET=y CONFIG_ESPTOOLPY_FLASHSIZE_4MB= CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y CONFIG_ESPTOOLPY_FLASHSIZE_16MB= +CONFIG_SPIRAM_MEMTEST= CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-8MiB.csv" diff --git a/ports/esp32/boards/sdkconfig.base b/ports/esp32/boards/sdkconfig.base index bf6c3f45c5..4b7c852332 100644 --- a/ports/esp32/boards/sdkconfig.base +++ b/ports/esp32/boards/sdkconfig.base @@ -13,6 +13,7 @@ CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR=y # Bootloader config CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y +CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y # Change default log level to "ERROR" (instead of "INFO") CONFIG_LOG_DEFAULT_LEVEL_INFO=n @@ -49,6 +50,15 @@ CONFIG_LWIP_PPP_CHAP_SUPPORT=y # Use 4kiB output buffer instead of default 16kiB CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +# Allow mbedTLS to allocate from PSRAM or internal memory +# +# (The ESP-IDF default is internal-only, partly for physical security to prevent +# possible information leakage from unencrypted PSRAM contents on the original +# ESP32 - no PSRAM encryption on that chip. MicroPython doesn't support flash +# encryption and is already storing the Python heap in PSRAM so this isn't a +# significant factor in overall physical security.) +CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC=y + # ULP coprocessor support # Only on: ESP32, ESP32S2, ESP32S3 CONFIG_ULP_COPROC_ENABLED=y @@ -58,7 +68,7 @@ CONFIG_ULP_COPROC_RESERVE_MEM=2040 # For cmake build CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-4MiB.csv" # To reduce iRAM usage CONFIG_ESP32_WIFI_IRAM_OPT=n diff --git a/ports/esp32/boards/sdkconfig.spiram b/ports/esp32/boards/sdkconfig.spiram index 74d35f7b4a..4dfc63624b 100644 --- a/ports/esp32/boards/sdkconfig.spiram +++ b/ports/esp32/boards/sdkconfig.spiram @@ -3,7 +3,11 @@ CONFIG_SPIRAM=y CONFIG_SPIRAM_CACHE_WORKAROUND=y CONFIG_SPIRAM_IGNORE_NOTFOUND=y -CONFIG_SPIRAM_USE_CAPS_ALLOC=y +CONFIG_SPIRAM_USE_MALLOC=y + +# This is the threshold for preferring small allocations from internal memory +# first, before failing over to PSRAM. +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=8192 # SPIRAM increases the size of the firmware and overflows iram0_0_seg, due # to PSRAM bug workarounds. Apply some options to reduce the firmware size. diff --git a/ports/esp32/boards/sdkconfig.spiram_sx b/ports/esp32/boards/sdkconfig.spiram_sx index 329a507337..efe53ada41 100644 --- a/ports/esp32/boards/sdkconfig.spiram_sx +++ b/ports/esp32/boards/sdkconfig.spiram_sx @@ -7,4 +7,8 @@ CONFIG_SPIRAM_SPEED_80M=y CONFIG_SPIRAM=y CONFIG_SPIRAM_BOOT_INIT=y CONFIG_SPIRAM_IGNORE_NOTFOUND=y -CONFIG_SPIRAM_USE_CAPS_ALLOC=y +CONFIG_SPIRAM_USE_MALLOC=y + +# This is the threshold for preferring small allocations from internal memory +# first, before failing over to PSRAM. +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=8192 diff --git a/ports/esp32/esp32_common.cmake b/ports/esp32/esp32_common.cmake index 37a19316b6..f5219048f3 100644 --- a/ports/esp32/esp32_common.cmake +++ b/ports/esp32/esp32_common.cmake @@ -11,6 +11,9 @@ endif() # Include core source components. include(${MICROPY_DIR}/py/py.cmake) +# CMAKE_BUILD_EARLY_EXPANSION is set during the component-discovery phase of +# `idf.py build`, so none of the extmod/usermod (and in reality, most of the +# micropython) rules need to happen. Specifically, you cannot invoke add_library. if(NOT CMAKE_BUILD_EARLY_EXPANSION) # Enable extmod components that will be configured by extmod.cmake. # A board may also have enabled additional components. @@ -167,6 +170,7 @@ set(MICROPY_CROSS_FLAGS -march=xtensawin) # Set compile options for this port. target_compile_definitions(${MICROPY_TARGET} PUBLIC ${MICROPY_DEF_CORE} + ${MICROPY_DEF_BOARD} MICROPY_ESP_IDF_4=1 MICROPY_VFS_FAT=1 MICROPY_VFS_LFS2=1 diff --git a/ports/esp32/gccollect.c b/ports/esp32/gccollect.c index 6fa287de28..4b6dd8ab61 100644 --- a/ports/esp32/gccollect.c +++ b/ports/esp32/gccollect.c @@ -39,30 +39,25 @@ #include "xtensa/hal.h" -static void gc_collect_inner(int level) { +// The level argument must be volatile to force the compiler to emit code that +// will call this function recursively, to nest the C stack. +static void gc_collect_inner(volatile unsigned int level) { if (level < XCHAL_NUM_AREGS / 8) { + // Go deeper on the stack to spill more registers from the register window. gc_collect_inner(level + 1); - if (level != 0) { - return; - } - } - - if (level == XCHAL_NUM_AREGS / 8) { - // get the sp + } else { + // Deep enough so that all registers are on the C stack, now trace the stack. volatile uint32_t sp = (uint32_t)esp_cpu_get_sp(); gc_collect_root((void **)sp, ((mp_uint_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t)); - return; } - - // trace root pointers from any threads - #if MICROPY_PY_THREAD - mp_thread_gc_others(); - #endif } void gc_collect(void) { gc_collect_start(); gc_collect_inner(0); + #if MICROPY_PY_THREAD + mp_thread_gc_others(); + #endif gc_collect_end(); } @@ -80,3 +75,13 @@ void gc_collect(void) { } #endif + +#if MICROPY_GC_SPLIT_HEAP_AUTO + +// The largest new region that is available to become Python heap is the largest +// free block in the ESP-IDF system heap. +size_t gc_get_max_new_split(void) { + return heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT); +} + +#endif diff --git a/ports/esp32/machine_uart.c b/ports/esp32/machine_uart.c index e7b2b8376b..0b4f5890ba 100644 --- a/ports/esp32/machine_uart.c +++ b/ports/esp32/machine_uart.c @@ -153,9 +153,11 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co if (args[ARG_txbuf].u_int >= 0 || args[ARG_rxbuf].u_int >= 0) { // must reinitialise driver to change the tx/rx buffer size + #if MICROPY_HW_ENABLE_UART_REPL if (self->uart_num == MICROPY_HW_UART_REPL) { mp_raise_ValueError(MP_ERROR_TEXT("UART buffer size is fixed")); } + #endif if (args[ARG_txbuf].u_int >= 0) { self->txbuf = args[ARG_txbuf].u_int; @@ -353,8 +355,11 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, #endif } + #if MICROPY_HW_ENABLE_UART_REPL // Only reset the driver if it's not the REPL UART. - if (uart_num != MICROPY_HW_UART_REPL) { + if (uart_num != MICROPY_HW_UART_REPL) + #endif + { // Remove any existing configuration uart_driver_delete(self->uart_num); @@ -467,8 +472,17 @@ STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t siz time_to_wait = pdMS_TO_TICKS(self->timeout); } + bool release_gil = time_to_wait > 0; + if (release_gil) { + MP_THREAD_GIL_EXIT(); + } + int bytes_read = uart_read_bytes(self->uart_num, buf_in, size, time_to_wait); + if (release_gil) { + MP_THREAD_GIL_ENTER(); + } + if (bytes_read <= 0) { *errcode = MP_EAGAIN; return MP_STREAM_ERROR; diff --git a/ports/esp32/main.c b/ports/esp32/main.c index 3a172e6f8d..1420dd579c 100644 --- a/ports/esp32/main.c +++ b/ports/esp32/main.c @@ -75,6 +75,10 @@ #define MP_TASK_STACK_LIMIT_MARGIN (1024) #endif +// Initial Python heap size. This starts small but adds new heap areas on +// demand due to settings MICROPY_GC_SPLIT_HEAP & MICROPY_GC_SPLIT_HEAP_AUTO +#define MP_TASK_HEAP_SIZE (64 * 1024) + int vprintf_null(const char *format, va_list ap) { // do nothing: this is used as a log target during raw repl mode return 0; @@ -85,10 +89,10 @@ void mp_task(void *pvParameter) { #if MICROPY_PY_THREAD mp_thread_init(pxTaskGetStackStart(NULL), MP_TASK_STACK_SIZE / sizeof(uintptr_t)); #endif - #if CONFIG_USB_OTG_SUPPORTED - usb_init(); - #elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG + #if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG usb_serial_jtag_init(); + #elif CONFIG_USB_OTG_SUPPORTED + usb_init(); #endif #if MICROPY_HW_ENABLE_UART_REPL uart_stdout_init(); @@ -100,19 +104,13 @@ void mp_task(void *pvParameter) { ESP_LOGE("esp_init", "can't create event loop: 0x%x\n", err); } - // Allocate the uPy heap using malloc and get the largest available region, - // limiting to 1/2 total available memory to leave memory for the OS. - // When SPIRAM is enabled, this will allocate from SPIRAM. - uint32_t caps = MALLOC_CAP_8BIT; - size_t heap_total = heap_caps_get_total_size(caps); - size_t mp_task_heap_size = MIN(heap_caps_get_largest_free_block(caps), heap_total / 2); - void *mp_task_heap = heap_caps_malloc(mp_task_heap_size, caps); + void *mp_task_heap = MP_PLAT_ALLOC_HEAP(MP_TASK_HEAP_SIZE); soft_reset: // initialise the stack pointer for the main thread mp_stack_set_top((void *)sp); mp_stack_set_limit(MP_TASK_STACK_SIZE - MP_TASK_STACK_LIMIT_MARGIN); - gc_init(mp_task_heap, mp_task_heap + mp_task_heap_size); + gc_init(mp_task_heap, mp_task_heap + MP_TASK_HEAP_SIZE); mp_init(); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); readline_init0(); diff --git a/ports/esp32/modnetwork.h b/ports/esp32/modnetwork.h index 79bf9973ca..e57b80657f 100644 --- a/ports/esp32/modnetwork.h +++ b/ports/esp32/modnetwork.h @@ -57,6 +57,8 @@ MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_ifconfig_obj); MP_DECLARE_CONST_FUN_OBJ_KW(esp_network_config_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_phy_mode_obj); +mp_obj_t esp_ifname(esp_netif_t *netif); + NORETURN void esp_exceptions_helper(esp_err_t e); static inline void esp_exceptions(esp_err_t e) { diff --git a/ports/esp32/modsocket.c b/ports/esp32/modsocket.c index ba1fe096f6..fe76b5f760 100644 --- a/ports/esp32/modsocket.c +++ b/ports/esp32/modsocket.c @@ -386,7 +386,8 @@ STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { switch (opt) { // level: SOL_SOCKET - case SO_REUSEADDR: { + case SO_REUSEADDR: + case SO_BROADCAST: { int val = mp_obj_get_int(args[3]); int ret = lwip_setsockopt(self->fd, SOL_SOCKET, opt, &val, sizeof(int)); if (ret != 0) { @@ -395,6 +396,18 @@ STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { break; } + case SO_BINDTODEVICE: { + size_t len; + const char *val = mp_obj_str_get_data(args[3], &len); + char ifname[NETIF_NAMESIZE] = {0}; + memcpy(&ifname, val, len); + int ret = lwip_setsockopt(self->fd, SOL_SOCKET, opt, &ifname, NETIF_NAMESIZE); + if (ret != 0) { + mp_raise_OSError(errno); + } + break; + } + #if MICROPY_PY_SOCKET_EVENTS // level: SOL_SOCKET // special "register callback" option @@ -858,6 +871,8 @@ STATIC const mp_rom_map_elem_t mp_module_socket_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(IPPROTO_IP) }, { MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(SOL_SOCKET) }, { MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(SO_REUSEADDR) }, + { MP_ROM_QSTR(MP_QSTR_SO_BROADCAST), MP_ROM_INT(SO_BROADCAST) }, + { MP_ROM_QSTR(MP_QSTR_SO_BINDTODEVICE), MP_ROM_INT(SO_BINDTODEVICE) }, { MP_ROM_QSTR(MP_QSTR_IP_ADD_MEMBERSHIP), MP_ROM_INT(IP_ADD_MEMBERSHIP) }, }; diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index aa13eaf2fe..ae73e02e41 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -68,6 +68,9 @@ #define MICROPY_PY_THREAD_GIL (1) #define MICROPY_PY_THREAD_GIL_VM_DIVISOR (32) +#define MICROPY_GC_SPLIT_HEAP (1) +#define MICROPY_GC_SPLIT_HEAP_AUTO (1) + // extended modules #ifndef MICROPY_ESPNOW #define MICROPY_ESPNOW (1) @@ -136,7 +139,6 @@ #define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (esp_rom_get_cpu_ticks_per_us() * 1000000 / 200) // roughly #define MICROPY_PY_SSL (1) #define MICROPY_SSL_MBEDTLS (1) -#define MICROPY_PY_SSL_FINALISER (1) #define MICROPY_PY_WEBSOCKET (1) #define MICROPY_PY_WEBREPL (1) #define MICROPY_PY_ONEWIRE (1) diff --git a/ports/esp32/mphalport.c b/ports/esp32/mphalport.c index 63a674c24b..d7003a1437 100644 --- a/ports/esp32/mphalport.c +++ b/ports/esp32/mphalport.c @@ -111,10 +111,10 @@ void mp_hal_stdout_tx_strn(const char *str, size_t len) { if (release_gil) { MP_THREAD_GIL_EXIT(); } - #if CONFIG_USB_OTG_SUPPORTED - usb_tx_strn(str, len); - #elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG + #if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG usb_serial_jtag_tx_strn(str, len); + #elif CONFIG_USB_OTG_SUPPORTED + usb_tx_strn(str, len); #endif #if MICROPY_HW_ENABLE_UART_REPL uart_stdout_tx_strn(str, len); diff --git a/ports/esp32/mpthreadport.c b/ports/esp32/mpthreadport.c index e6c7e9bc80..74dbc14797 100644 --- a/ports/esp32/mpthreadport.c +++ b/ports/esp32/mpthreadport.c @@ -98,6 +98,10 @@ void mp_thread_set_state(mp_state_thread_t *state) { vTaskSetThreadLocalStoragePointer(NULL, 1, state); } +mp_uint_t mp_thread_get_id(void) { + return (mp_uint_t)xTaskGetCurrentTaskHandle(); +} + void mp_thread_start(void) { mp_thread_mutex_lock(&thread_mutex, 1); for (mp_thread_t *th = thread; th != NULL; th = th->next) { @@ -120,7 +124,7 @@ STATIC void freertos_entry(void *arg) { } } -void mp_thread_create_ex(void *(*entry)(void *), void *arg, size_t *stack_size, int priority, char *name) { +mp_uint_t mp_thread_create_ex(void *(*entry)(void *), void *arg, size_t *stack_size, int priority, char *name) { // store thread entry function into a global variable so we can access it ext_thread_entry = entry; @@ -154,10 +158,12 @@ void mp_thread_create_ex(void *(*entry)(void *), void *arg, size_t *stack_size, *stack_size -= 1024; mp_thread_mutex_unlock(&thread_mutex); + + return (mp_uint_t)th->id; } -void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { - mp_thread_create_ex(entry, arg, stack_size, MP_THREAD_PRIORITY, "mp_thread"); +mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { + return mp_thread_create_ex(entry, arg, stack_size, MP_THREAD_PRIORITY, "mp_thread"); } void mp_thread_finish(void) { diff --git a/ports/esp32/network_common.c b/ports/esp32/network_common.c index 082943e2ae..ca07f3c06b 100644 --- a/ports/esp32/network_common.c +++ b/ports/esp32/network_common.c @@ -41,6 +41,7 @@ #include "esp_log.h" #include "esp_netif.h" #include "esp_wifi.h" +#include "lwip/sockets.h" // #include "lwip/dns.h" NORETURN void esp_exceptions_helper(esp_err_t e) { @@ -153,6 +154,15 @@ STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_ifconfig_obj, 1, 2, esp_ifconfig); +mp_obj_t esp_ifname(esp_netif_t *netif) { + char ifname[NETIF_NAMESIZE + 1] = {0}; + mp_obj_t ret = mp_const_none; + if (esp_netif_get_netif_impl_name(netif, ifname) == ESP_OK && ifname[0] != 0) { + ret = mp_obj_new_str((char *)ifname, strlen(ifname)); + } + return ret; +} + STATIC mp_obj_t esp_phy_mode(size_t n_args, const mp_obj_t *args) { return mp_const_none; } diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c index fe3ff6f772..8557700446 100644 --- a/ports/esp32/network_lan.c +++ b/ports/esp32/network_lan.c @@ -393,6 +393,10 @@ STATIC mp_obj_t lan_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs esp_eth_ioctl(self->eth_handle, ETH_CMD_G_MAC_ADDR, mac); return mp_obj_new_bytes(mac, sizeof(mac)); } + case MP_QSTR_ifname: { + val = esp_ifname(self->base.netif); + break; + } default: mp_raise_ValueError(MP_ERROR_TEXT("unknown config param")); } diff --git a/ports/esp32/network_ppp.c b/ports/esp32/network_ppp.c index caad7eb48b..ea0dd1706e 100644 --- a/ports/esp32/network_ppp.c +++ b/ports/esp32/network_ppp.c @@ -114,6 +114,8 @@ static void pppos_client_task(void *self_in) { self->client_task_handle = NULL; vTaskDelete(NULL); + for (;;) { + } } STATIC mp_obj_t ppp_active(size_t n_args, const mp_obj_t *args) { @@ -266,11 +268,56 @@ STATIC mp_obj_t ppp_isconnected(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(ppp_isconnected_obj, ppp_isconnected); +STATIC mp_obj_t ppp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { + if (n_args != 1 && kwargs->used != 0) { + mp_raise_TypeError(MP_ERROR_TEXT("either pos or kw args are allowed")); + } + ppp_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); + + if (kwargs->used != 0) { + for (size_t i = 0; i < kwargs->alloc; i++) { + if (mp_map_slot_is_filled(kwargs, i)) { + switch (mp_obj_str_get_qstr(kwargs->table[i].key)) { + default: + break; + } + } + } + return mp_const_none; + } + + if (n_args != 2) { + mp_raise_TypeError(MP_ERROR_TEXT("can query only one param")); + } + + mp_obj_t val = mp_const_none; + + switch (mp_obj_str_get_qstr(args[1])) { + case MP_QSTR_ifname: { + if (self->pcb != NULL) { + struct netif *pppif = ppp_netif(self->pcb); + char ifname[NETIF_NAMESIZE + 1] = {0}; + netif_index_to_name(netif_get_index(pppif), ifname); + if (ifname[0] != 0) { + val = mp_obj_new_str((char *)ifname, strlen(ifname)); + } + } + break; + } + default: + mp_raise_ValueError(MP_ERROR_TEXT("unknown config param")); + } + + return val; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ppp_config_obj, 1, ppp_config); + STATIC const mp_rom_map_elem_t ppp_if_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&ppp_active_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&ppp_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&ppp_isconnected_obj) }, { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&ppp_status_obj) }, + { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&ppp_config_obj) }, { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&ppp_ifconfig_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&ppp_delete_obj) }, { MP_ROM_QSTR(MP_QSTR_AUTH_NONE), MP_ROM_INT(PPPAUTHTYPE_NONE) }, diff --git a/ports/esp32/network_wlan.c b/ports/esp32/network_wlan.c index 8287731c31..58af9f3bc3 100644 --- a/ports/esp32/network_wlan.c +++ b/ports/esp32/network_wlan.c @@ -622,6 +622,10 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_ val = MP_OBJ_NEW_SMALL_INT(channel); break; } + case MP_QSTR_ifname: { + val = esp_ifname(self->netif); + break; + } case MP_QSTR_hostname: case MP_QSTR_dhcp_hostname: { // TODO: Deprecated. Use network.hostname() instead. diff --git a/ports/esp32/partitions-ota.csv b/ports/esp32/partitions-4MiB-ota.csv similarity index 100% rename from ports/esp32/partitions-ota.csv rename to ports/esp32/partitions-4MiB-ota.csv diff --git a/ports/esp32/partitions.csv b/ports/esp32/partitions-4MiB.csv similarity index 100% rename from ports/esp32/partitions.csv rename to ports/esp32/partitions-4MiB.csv diff --git a/ports/esp32/uart.c b/ports/esp32/uart.c index 358d434709..fc69e279e3 100644 --- a/ports/esp32/uart.c +++ b/ports/esp32/uart.c @@ -26,14 +26,16 @@ * THE SOFTWARE. */ -#include - -#include "hal/uart_hal.h" #include "py/runtime.h" #include "py/mphal.h" #include "uart.h" +#if MICROPY_HW_ENABLE_UART_REPL + +#include +#include "hal/uart_hal.h" + // Backwards compatibility for when MICROPY_HW_UART_REPL was a ESP-IDF UART // driver enum. Only UART_NUM_0 was supported with that version of the driver. #define UART_NUM_0 0 @@ -118,3 +120,5 @@ STATIC void IRAM_ATTR uart_irq_handler(void *arg) { } } } + +#endif // MICROPY_HW_ENABLE_UART_REPL diff --git a/ports/esp32/uart.h b/ports/esp32/uart.h index 6410db24c9..3d88eed825 100644 --- a/ports/esp32/uart.h +++ b/ports/esp32/uart.h @@ -30,9 +30,11 @@ // Whether to enable the REPL on a UART. #ifndef MICROPY_HW_ENABLE_UART_REPL -#define MICROPY_HW_ENABLE_UART_REPL (!CONFIG_USB_OTG_SUPPORTED && !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG) +#define MICROPY_HW_ENABLE_UART_REPL (!CONFIG_USB_OTG_SUPPORTED && !CONFIG_ESP_CONSOLE_USB_CDC && !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG) #endif +#if MICROPY_HW_ENABLE_UART_REPL + #ifndef MICROPY_HW_UART_REPL #define MICROPY_HW_UART_REPL (0) #endif @@ -44,4 +46,6 @@ void uart_stdout_init(void); int uart_stdout_tx_strn(const char *str, size_t len); +#endif // MICROPY_HW_ENABLE_UART_REPL + #endif // MICROPY_INCLUDED_ESP32_UART_H diff --git a/ports/esp32/usb.c b/ports/esp32/usb.c index b9d99676d3..2e417755c9 100644 --- a/ports/esp32/usb.c +++ b/ports/esp32/usb.c @@ -28,7 +28,7 @@ #include "py/mphal.h" #include "usb.h" -#if CONFIG_USB_OTG_SUPPORTED +#if CONFIG_USB_OTG_SUPPORTED && !CONFIG_ESP_CONSOLE_USB_CDC && !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG #include "esp_timer.h" #ifndef NO_QSTR @@ -97,4 +97,4 @@ void usb_tx_strn(const char *str, size_t len) { } } -#endif // CONFIG_USB_OTG_SUPPORTED +#endif // CONFIG_USB_OTG_SUPPORTED && !CONFIG_ESP_CONSOLE_USB_CDC && !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index 1cdcafa031..e4c907c57a 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -4,17 +4,25 @@ ifdef BOARD_DIR # the path as the board name. BOARD ?= $(notdir $(BOARD_DIR:/=)) else -# If not given on the command line, then default to GENERIC. -BOARD ?= GENERIC +# If not given on the command line, then default to ESP8266_GENERIC. +BOARD ?= ESP8266_GENERIC BOARD_DIR ?= boards/$(BOARD) endif ifeq ($(wildcard $(BOARD_DIR)/.),) +ifeq ($(findstring boards/GENERIC,$(BOARD_DIR)),boards/GENERIC) +$(warning The GENERIC* boards have been renamed to ESP8266_GENERIC) +endif $(error Invalid BOARD specified: $(BOARD_DIR)) endif -# If the build directory is not given, make it reflect the board name. +# If the build directory is not given, make it reflect the board name (and +# optionally the board variant). +ifneq ($(BOARD_VARIANT),) +BUILD ?= build-$(BOARD)-$(BOARD_VARIANT) +else BUILD ?= build-$(BOARD) +endif include ../../py/mkenv.mk @@ -40,7 +48,7 @@ include $(TOP)/extmod/extmod.mk GIT_SUBMODULES += lib/axtls lib/berkeley-db-1.xx -FWBIN = $(BUILD)/firmware-combined.bin +FWBIN = $(BUILD)/firmware.bin PORT ?= /dev/ttyACM0 BAUD ?= 115200 FLASH_MODE ?= qio @@ -202,7 +210,7 @@ FROZEN_EXTRA_DEPS = $(CONFVARS_FILE) .PHONY: deploy -deploy: $(BUILD)/firmware-combined.bin +deploy: $(FWBIN) $(ECHO) "Writing $< to the board" $(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash --verify --flash_size=$(FLASH_SIZE) --flash_mode=$(FLASH_MODE) 0 $< @@ -213,20 +221,26 @@ erase: reset: echo -e "\r\nimport machine; machine.reset()\r\n" >$(PORT) +ifeq ($(BOARD_VARIANT),OTA) +$(FWBIN): $(BUILD)/firmware.elf + $(ECHO) "Create $@" + $(Q)esptool.py elf2image $^ + $(Q)$(PYTHON) makeimg.py $(BUILD)/firmware.elf-0x00000.bin $(BUILD)/firmware.elf-0x[0-5][1-f]000.bin $(BUILD)/firmware-ota.bin + + $(Q)cat $(YAOTA8266)/yaota8266.bin $(BUILD)/firmware-ota.bin > $@ + $(Q)$(PYTHON) $(YAOTA8266)/ota-client/ota_client.py sign $@ +else $(FWBIN): $(BUILD)/firmware.elf $(ECHO) "Create $@" $(Q)esptool.py elf2image $^ $(Q)$(PYTHON) makeimg.py $(BUILD)/firmware.elf-0x00000.bin $(BUILD)/firmware.elf-0x[0-5][1-f]000.bin $@ +endif $(BUILD)/firmware.elf: $(OBJ) $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) $(Q)$(SIZE) $@ -ota: - rm -f $(BUILD)/firmware.elf $(BUILD)/firmware.elf*.bin - $(MAKE) LD_FILES=boards/esp8266_ota.ld FWBIN=$(BUILD)/firmware-ota.bin - include $(TOP)/py/mkrules.mk clean-modules: diff --git a/ports/esp8266/README.md b/ports/esp8266/README.md index 1e0cae2139..561c771403 100644 --- a/ports/esp8266/README.md +++ b/ports/esp8266/README.md @@ -23,6 +23,9 @@ Supported features include: Documentation is available at http://docs.micropython.org/en/latest/esp8266/quickref.html. +The default build requires a 2MiB flash chip, but see below for support for +1MiB and 512kiB options. + Build instructions ------------------ @@ -67,10 +70,10 @@ Then to compile the ESP8266 firmware: ``` $ cd ports/esp8266 -$ docker run --rm -v $HOME:$HOME -u $UID -w $PWD larsks/esp-open-sdk make -j BOARD=GENERIC +$ docker run --rm -v $HOME:$HOME -u $UID -w $PWD larsks/esp-open-sdk make -j BOARD=ESP8266_GENERIC ``` -This will produce binary images in the `build-GENERIC/` subdirectory. +This will produce binary images in the `build-ESP8266_GENERIC/` subdirectory. Substitute the board for whichever board you're using. __Building with a local toolchain__ @@ -106,10 +109,10 @@ Then to compile the ESP8266 firmware: ``` $ cd ports/esp8266 -$ make -j BOARD=GENERIC +$ make -j BOARD=ESP8266_GENERIC ``` -This will produce binary images in the `build-GENERIC/` subdirectory. +This will produce binary images in the `build-ESP8266_GENERIC/` subdirectory. Substitute the board for whichever board you're using. @@ -149,26 +152,30 @@ $ make PORT=/dev/ttyUSB0 FLASH_MODE=qio FLASH_SIZE=32m deploy (note that flash size is in megabits) If you want to flash manually using `esptool.py` directly, the image produced is -`build-GENERIC/firmware-combined.bin`, to be flashed at 0x00000. +`build-ESP8266_GENERIC/firmware.bin`, to be flashed at 0x00000. -The default board definition is the directory `boards/GENERIC`. +The default board definition is the directory `boards/ESP8266_GENERIC`. For a custom configuration you can define your own board in the directory `boards/`. -The `BOARD` variable can be set on the make command line, for example: +__Reduced FlashROM variants__ + +The normal build described above requires modules with at least 2MiB of +FlashROM onboard. There's a special configuration for 512kiB modules, which can +be built with the `FLASH_512K` variant. This configuration is highly limited, +lacks filesystem support, WebREPL, and has many other features disabled. It's +mostly suitable for advanced users who are interested to fine-tune options to +achieve a required setup. If you are an end user, please consider using a +module with at least 2MiB of FlashROM. + +A variant is also provided for 1MiB modules which just lacks the included +micropython-lib packages. + +The variant can be set on the make command line, for example: ```bash -$ make BOARD=GENERIC_512K +$ make BOARD=ESP8266_GENERIC BOARD_VARIANT=FLASH_512K +$ make BOARD=ESP8266_GENERIC BOARD_VARIANT=FLASH_1M ``` -__512KB FlashROM version__ - -The normal build described above requires modules with at least 1MB of FlashROM -onboard. There's a special configuration for 512KB modules, which can be -built with `make BOARD=GENERIC_512K`. This configuration is highly limited, lacks -filesystem support, WebREPL, and has many other features disabled. It's mostly -suitable for advanced users who are interested to fine-tune options to achieve a -required setup. If you are an end user, please consider using a module with at -least 1MB of FlashROM. - First start ----------- diff --git a/ports/esp8266/boards/ESP8266_GENERIC/_boot.py b/ports/esp8266/boards/ESP8266_GENERIC/_boot.py new file mode 100644 index 0000000000..16da8bc4c3 --- /dev/null +++ b/ports/esp8266/boards/ESP8266_GENERIC/_boot.py @@ -0,0 +1,6 @@ +# Minimal _boot.py for the 512kiB variant. Does not set up a block device or +# filesystem. Other variants use esp8266/modules/_boot.py. + +import gc + +gc.threshold((gc.mem_free() + gc.mem_alloc()) // 4) diff --git a/ports/esp32/boards/GENERIC_SPIRAM/board.json b/ports/esp8266/boards/ESP8266_GENERIC/board.json similarity index 56% rename from ports/esp32/boards/GENERIC_SPIRAM/board.json rename to ports/esp8266/boards/ESP8266_GENERIC/board.json index afb57b2ed1..2b3a6b5507 100644 --- a/ports/esp32/boards/GENERIC_SPIRAM/board.json +++ b/ports/esp8266/boards/ESP8266_GENERIC/board.json @@ -4,20 +4,20 @@ ], "docs": "", "features": [ - "BLE", - "SPIRAM", + "External Flash", "WiFi" ], - "id": "esp32spiram", "images": [ - "esp32_psram.jpg" + "esp8266.jpg" ], - "mcu": "esp32", - "product": "ESP32 with SPIRAM", + "mcu": "esp8266", + "product": "ESP8266", "thumbnail": "", "url": "https://www.espressif.com/en/products/modules", "variants": { - "idf3": "Compiled with IDF 3.x" + "OTA": "OTA compatible", + "FLASH_1M": "1MiB flash", + "FLASH_512K": "512kiB flash" }, "vendor": "Espressif" } diff --git a/ports/esp8266/boards/GENERIC/board.md b/ports/esp8266/boards/ESP8266_GENERIC/board.md similarity index 58% rename from ports/esp8266/boards/GENERIC/board.md rename to ports/esp8266/boards/ESP8266_GENERIC/board.md index fa0cf410d6..96fbab617a 100644 --- a/ports/esp8266/boards/GENERIC/board.md +++ b/ports/esp8266/boards/ESP8266_GENERIC/board.md @@ -1,6 +1,13 @@ -The following are daily builds of the ESP8266 firmware for boards with at -least 2MiB of flash. They have the latest features and bug fixes, WebREPL is -not automatically started, and debugging is enabled by default. +The following are daily builds of the ESP8266 firmware. This will work on +boards with at least 2MiB of flash. They have the latest features and bug +fixes, WebREPL is not automatically started, and debugging is enabled by +default. + +For boards with 1MiB or 512kiB of flash, two variants are provided with reduced +functionality. The 1MiB variant removes asyncio and FAT-filesystem support as +well as some modules from micropython-lib. The 512kiB variant further removes +all filesystem support, as well as framebuffer support, some Python language +features, and has less detailed error messages. Note: v1.12-334 and newer (including v1.13) require an ESP8266 module with 2MiB of flash or more, and use littlefs as the filesystem by default. When diff --git a/ports/esp8266/boards/GENERIC/manifest.py b/ports/esp8266/boards/ESP8266_GENERIC/manifest_2MiB.py similarity index 100% rename from ports/esp8266/boards/GENERIC/manifest.py rename to ports/esp8266/boards/ESP8266_GENERIC/manifest_2MiB.py diff --git a/ports/esp8266/boards/GENERIC_512K/manifest.py b/ports/esp8266/boards/ESP8266_GENERIC/manifest_512kiB.py similarity index 100% rename from ports/esp8266/boards/GENERIC_512K/manifest.py rename to ports/esp8266/boards/ESP8266_GENERIC/manifest_512kiB.py diff --git a/ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.h b/ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.h new file mode 100644 index 0000000000..3a9c40e795 --- /dev/null +++ b/ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.h @@ -0,0 +1,52 @@ +#if defined(MICROPY_ESP8266_2M) + +#define MICROPY_HW_BOARD_NAME "ESP module" +#define MICROPY_HW_MCU_NAME "ESP8266" + +#define MICROPY_PERSISTENT_CODE_LOAD (1) +#define MICROPY_EMIT_XTENSA (1) +#define MICROPY_EMIT_INLINE_XTENSA (1) + +#define MICROPY_DEBUG_PRINTERS (1) +#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) + +#define MICROPY_READER_VFS (MICROPY_VFS) +#define MICROPY_VFS (1) + +#define MICROPY_PY_CRYPTOLIB (1) + +#elif defined(MICROPY_ESP8266_1M) + +#define MICROPY_HW_BOARD_NAME "ESP module (1M)" +#define MICROPY_HW_MCU_NAME "ESP8266" + +#define MICROPY_PERSISTENT_CODE_LOAD (1) +#define MICROPY_EMIT_XTENSA (1) +#define MICROPY_EMIT_INLINE_XTENSA (1) + +#define MICROPY_DEBUG_PRINTERS (1) +#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) + +#define MICROPY_READER_VFS (MICROPY_VFS) +#define MICROPY_VFS (1) + + +#define MICROPY_PY_CRYPTOLIB (1) + +#elif defined(MICROPY_ESP8266_512K) + +#define MICROPY_HW_BOARD_NAME "ESP module (512K)" +#define MICROPY_HW_MCU_NAME "ESP8266" + +#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) + +#define MICROPY_PY_FSTRINGS (0) +#define MICROPY_PY_BUILTINS_SLICE_ATTRS (0) +#define MICROPY_PY_ALL_SPECIAL_METHODS (0) +#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0) +#define MICROPY_PY_SYS_STDIO_BUFFER (0) +#define MICROPY_PY_ASYNCIO (0) +#define MICROPY_PY_RE_SUB (0) +#define MICROPY_PY_FRAMEBUF (0) + +#endif diff --git a/ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.mk b/ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.mk new file mode 100644 index 0000000000..2eb78d7e85 --- /dev/null +++ b/ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.mk @@ -0,0 +1,50 @@ +ifeq ($(BOARD_VARIANT),) +LD_FILES = boards/esp8266_2MiB.ld + +MICROPY_ESPNOW ?= 1 +MICROPY_PY_BTREE ?= 1 +MICROPY_VFS_FAT ?= 1 +MICROPY_VFS_LFS2 ?= 1 + +# Add asyncio and extra micropython-lib packages (in addition to the port manifest). +FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest_2MiB.py + +# Configure mpconfigboard.h. +CFLAGS += -DMICROPY_ESP8266_2M +endif + +ifeq ($(BOARD_VARIANT),FLASH_1M) +LD_FILES = boards/esp8266_1MiB.ld + +MICROPY_ESPNOW ?= 1 +MICROPY_PY_BTREE ?= 1 +MICROPY_VFS_LFS2 ?= 1 + +# Note: Implicitly uses the port manifest. + +# Configure mpconfigboard.h. +CFLAGS += -DMICROPY_ESP8266_1M +endif + +ifeq ($(BOARD_VARIANT),OTA) +LD_FILES = boards/esp8266_ota.ld + +MICROPY_ESPNOW ?= 1 +MICROPY_PY_BTREE ?= 1 +MICROPY_VFS_LFS2 ?= 1 + +# Note: Implicitly uses the port manifest. + +# Configure mpconfigboard.h. +CFLAGS += -DMICROPY_ESP8266_1M +endif + +ifeq ($(BOARD_VARIANT),FLASH_512K) +LD_FILES = boards/esp8266_512kiB.ld + +# Note: Use the minimal manifest.py. +FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest_512kiB.py + +# Configure mpconfigboard.h. +CFLAGS += -DMICROPY_ESP8266_512K +endif diff --git a/ports/esp8266/boards/GENERIC/board.json b/ports/esp8266/boards/GENERIC/board.json deleted file mode 100644 index 46c2659d8a..0000000000 --- a/ports/esp8266/boards/GENERIC/board.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "deploy": [ - "../deploy.md" - ], - "docs": "", - "features": [ - "WiFi" - ], - "id": "esp8266", - "images": [], - "mcu": "esp8266", - "product": "ESP8266 with 2MiB+ flash", - "thumbnail": "", - "url": "https://www.espressif.com/en/products/modules", - "variants": { - "ota": "OTA compatible" - }, - "vendor": "Espressif" -} diff --git a/ports/esp8266/boards/GENERIC/mpconfigboard.h b/ports/esp8266/boards/GENERIC/mpconfigboard.h deleted file mode 100644 index 52c93f83a3..0000000000 --- a/ports/esp8266/boards/GENERIC/mpconfigboard.h +++ /dev/null @@ -1,14 +0,0 @@ -#define MICROPY_HW_BOARD_NAME "ESP module" -#define MICROPY_HW_MCU_NAME "ESP8266" - -#define MICROPY_PERSISTENT_CODE_LOAD (1) -#define MICROPY_EMIT_XTENSA (1) -#define MICROPY_EMIT_INLINE_XTENSA (1) - -#define MICROPY_DEBUG_PRINTERS (1) -#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) - -#define MICROPY_READER_VFS (MICROPY_VFS) -#define MICROPY_VFS (1) - -#define MICROPY_PY_CRYPTOLIB (1) diff --git a/ports/esp8266/boards/GENERIC/mpconfigboard.mk b/ports/esp8266/boards/GENERIC/mpconfigboard.mk deleted file mode 100644 index 8d7babdc84..0000000000 --- a/ports/esp8266/boards/GENERIC/mpconfigboard.mk +++ /dev/null @@ -1,8 +0,0 @@ -LD_FILES = boards/esp8266_2m.ld - -MICROPY_ESPNOW ?= 1 -MICROPY_PY_BTREE ?= 1 -MICROPY_VFS_FAT ?= 1 -MICROPY_VFS_LFS2 ?= 1 - -FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py diff --git a/ports/esp8266/boards/GENERIC_1M/board.json b/ports/esp8266/boards/GENERIC_1M/board.json deleted file mode 100644 index 2ef4bd99fa..0000000000 --- a/ports/esp8266/boards/GENERIC_1M/board.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "deploy": [ - "../deploy.md" - ], - "docs": "", - "features": [ - "WiFi" - ], - "id": "esp8266-1m", - "images": [], - "mcu": "esp8266", - "product": "ESP8266 with 1MiB flash", - "thumbnail": "", - "url": "https://www.espressif.com/en/products/modules", - "vendor": "Espressif" -} diff --git a/ports/esp8266/boards/GENERIC_1M/board.md b/ports/esp8266/boards/GENERIC_1M/board.md deleted file mode 100644 index 17cc6e3a6b..0000000000 --- a/ports/esp8266/boards/GENERIC_1M/board.md +++ /dev/null @@ -1,5 +0,0 @@ -The following are daily builds of the ESP8266 firmware tailored for modules with -only 1MiB of flash. This firmware uses littlefs as the filesystem. -When upgrading from older firmware that uses a FAT filesystem please backup your files -first, and either erase all flash before upgrading, or after upgrading execute -`os.VfsLfs2.mkfs(bdev)`. diff --git a/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h b/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h deleted file mode 100644 index 41752e692b..0000000000 --- a/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h +++ /dev/null @@ -1,17 +0,0 @@ -#define MICROPY_HW_BOARD_NAME "ESP module (1M)" -#define MICROPY_HW_MCU_NAME "ESP8266" - -#define MICROPY_PERSISTENT_CODE_LOAD (1) -#define MICROPY_EMIT_XTENSA (1) -#define MICROPY_EMIT_INLINE_XTENSA (1) - -#define MICROPY_DEBUG_PRINTERS (1) -#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) - -#define MICROPY_READER_VFS (MICROPY_VFS) -#define MICROPY_VFS (1) - -#define MICROPY_PY_FSTRINGS (0) -#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0) -#define MICROPY_PY_ASYNCIO (0) -#define MICROPY_PY_CRYPTOLIB (1) diff --git a/ports/esp8266/boards/GENERIC_1M/mpconfigboard.mk b/ports/esp8266/boards/GENERIC_1M/mpconfigboard.mk deleted file mode 100644 index adc31702e0..0000000000 --- a/ports/esp8266/boards/GENERIC_1M/mpconfigboard.mk +++ /dev/null @@ -1,5 +0,0 @@ -LD_FILES = boards/esp8266_1m.ld - -MICROPY_ESPNOW ?= 1 -MICROPY_PY_BTREE ?= 1 -MICROPY_VFS_LFS2 ?= 1 diff --git a/ports/esp8266/boards/GENERIC_512K/_boot.py b/ports/esp8266/boards/GENERIC_512K/_boot.py deleted file mode 100644 index 1a55cfd36c..0000000000 --- a/ports/esp8266/boards/GENERIC_512K/_boot.py +++ /dev/null @@ -1,3 +0,0 @@ -import gc - -gc.threshold((gc.mem_free() + gc.mem_alloc()) // 4) diff --git a/ports/esp8266/boards/GENERIC_512K/board.json b/ports/esp8266/boards/GENERIC_512K/board.json deleted file mode 100644 index 10050592cf..0000000000 --- a/ports/esp8266/boards/GENERIC_512K/board.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "deploy": [ - "../deploy.md" - ], - "docs": "", - "features": [ - "WiFi" - ], - "id": "esp8266-512k", - "images": [], - "mcu": "esp8266", - "product": "ESP8266 with 512kiB flash", - "thumbnail": "", - "url": "https://www.espressif.com/en/products/modules", - "vendor": "Espressif" -} diff --git a/ports/esp8266/boards/GENERIC_512K/board.md b/ports/esp8266/boards/GENERIC_512K/board.md deleted file mode 100644 index 1f6e2c7907..0000000000 --- a/ports/esp8266/boards/GENERIC_512K/board.md +++ /dev/null @@ -1,3 +0,0 @@ -The following are daily builds of the ESP8266 firmware tailored for modules with -only 512kiB of flash. Certain features are disabled to get the firmware down -to this size. diff --git a/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h b/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h deleted file mode 100644 index c29e23d5ad..0000000000 --- a/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h +++ /dev/null @@ -1,13 +0,0 @@ -#define MICROPY_HW_BOARD_NAME "ESP module (512K)" -#define MICROPY_HW_MCU_NAME "ESP8266" - -#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) - -#define MICROPY_PY_FSTRINGS (0) -#define MICROPY_PY_BUILTINS_SLICE_ATTRS (0) -#define MICROPY_PY_ALL_SPECIAL_METHODS (0) -#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0) -#define MICROPY_PY_SYS_STDIO_BUFFER (0) -#define MICROPY_PY_ASYNCIO (0) -#define MICROPY_PY_RE_SUB (0) -#define MICROPY_PY_FRAMEBUF (0) diff --git a/ports/esp8266/boards/GENERIC_512K/mpconfigboard.mk b/ports/esp8266/boards/GENERIC_512K/mpconfigboard.mk deleted file mode 100644 index 120351909b..0000000000 --- a/ports/esp8266/boards/GENERIC_512K/mpconfigboard.mk +++ /dev/null @@ -1,3 +0,0 @@ -LD_FILES = boards/esp8266_512k.ld - -FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py diff --git a/ports/esp8266/boards/esp8266_1m.ld b/ports/esp8266/boards/esp8266_1MiB.ld similarity index 100% rename from ports/esp8266/boards/esp8266_1m.ld rename to ports/esp8266/boards/esp8266_1MiB.ld diff --git a/ports/esp8266/boards/esp8266_2m.ld b/ports/esp8266/boards/esp8266_2MiB.ld similarity index 100% rename from ports/esp8266/boards/esp8266_2m.ld rename to ports/esp8266/boards/esp8266_2MiB.ld diff --git a/ports/esp8266/boards/esp8266_512k.ld b/ports/esp8266/boards/esp8266_512kiB.ld similarity index 100% rename from ports/esp8266/boards/esp8266_512k.ld rename to ports/esp8266/boards/esp8266_512kiB.ld diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index 63cba7d7a6..ead206e5e2 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -216,6 +216,7 @@ SRC_C += \ pendsv.c \ pin.c \ sdcard.c \ + sdio.c \ systick.c \ ticks.c \ tusb_port.c \ @@ -263,6 +264,14 @@ else SRC_HAL_C += hal/$(FLEXSPI_FLASH_TYPE)_config.c endif +ifeq ($(MICROPY_PY_BLUETOOTH),1) +SRC_C += mpbthciport.c +endif # MICROPY_PY_BLUETOOTH + +ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) +SRC_C += mpnimbleport.c +endif + # Math library source files ifeq ($(MICROPY_FLOAT_IMPL),double) LIBM_SRC_C += $(addprefix lib/libm_dbl/,\ @@ -397,6 +406,10 @@ CFLAGS += \ -DFSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE=1 endif +ifdef MICROPY_HW_FLASH_CLK + CFLAGS += -DMICROPY_HW_FLASH_CLK=$(MICROPY_HW_FLASH_CLK) +endif + CFLAGS += $(CFLAGS_EXTRA) MPY_CROSS_FLAGS += -march=armv7m @@ -444,6 +457,7 @@ OBJ += $(PY_O) OBJ += $(LIBM_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_SS:.S=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_TINYUSB_C:.c=.o)) diff --git a/ports/mimxrt/board_init.c b/ports/mimxrt/board_init.c index 78001862f0..88de27ea77 100644 --- a/ports/mimxrt/board_init.c +++ b/ports/mimxrt/board_init.c @@ -39,6 +39,7 @@ #include CLOCK_CONFIG_H #include "modmachine.h" +#include "irq.h" const uint8_t dcd_data[] = { 0x00 }; @@ -63,6 +64,7 @@ void board_init(void) { // 1ms tick timer SysTick_Config(SystemCoreClock / 1000); + NVIC_SetPriority(SysTick_IRQn, IRQ_PRI_SYSTICK); // USB0 usb_phy0_init(0b0111, 0b0110, 0b0110); // Configure nominal values for D_CAL and TXCAL45DP/DN diff --git a/ports/mimxrt/boards/ADAFRUIT_METRO_M7/board.json b/ports/mimxrt/boards/ADAFRUIT_METRO_M7/board.json index c96e9b08fe..9f260b3a00 100644 --- a/ports/mimxrt/boards/ADAFRUIT_METRO_M7/board.json +++ b/ports/mimxrt/boards/ADAFRUIT_METRO_M7/board.json @@ -4,16 +4,12 @@ ], "docs": "", "features": [ - "USB-C", - "SPI", - "I2C", - "UART", + "BLE", + "External Flash", + "JST-SH", "RGB LED", - "QSPI Flash", - "QWIIC", - "JLink", - "WiFi", - "BLE" + "USB-C", + "WiFi" ], "images": [ "Metro_M7.jpg" diff --git a/ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.h b/ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.h index ac9cf97058..7d759df5e6 100644 --- a/ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.h +++ b/ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.h @@ -23,6 +23,12 @@ { 0 }, { 0 }, \ { IOMUXC_GPIO_AD_02_LPUART4_TXD }, { IOMUXC_GPIO_AD_01_LPUART4_RXD }, +#define IOMUX_TABLE_UART_CTS_RTS \ + { IOMUXC_GPIO_08_LPUART1_CTS_B }, { IOMUXC_GPIO_07_LPUART1_RTS_B }, \ + { IOMUXC_GPIO_AD_14_LPUART3_CTS_B }, { 0 }, \ + { 0 }, { 0 }, \ + { IOMUXC_GPIO_AD_14_LPUART4_CTS_B }, { 0 }, + #define MICROPY_HW_SPI_INDEX { 1 } #define IOMUX_TABLE_SPI \ diff --git a/ports/mimxrt/boards/MIMXRT1010_EVK/board.json b/ports/mimxrt/boards/MIMXRT1010_EVK/board.json index 4bf9ce0524..3fc3403c06 100644 --- a/ports/mimxrt/boards/MIMXRT1010_EVK/board.json +++ b/ports/mimxrt/boards/MIMXRT1010_EVK/board.json @@ -4,12 +4,10 @@ ], "docs": "", "features": [ - "MicroUSB", + "Audio Codec", + "External Flash", "Microphone", - "AudioCodec", - "SPDIF", - "OpenSDA", - "JLink" + "USB" ], "images": [ "i.MXRT1010-TOP.jpg" diff --git a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h index eff9e9c2cd..26811fdab8 100644 --- a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h @@ -23,6 +23,12 @@ { IOMUXC_GPIO_08_LPUART3_TXD }, { IOMUXC_GPIO_AD_07_LPUART3_RXD }, \ { IOMUXC_GPIO_AD_02_LPUART4_TXD }, { IOMUXC_GPIO_AD_01_LPUART4_RXD }, +#define IOMUX_TABLE_UART_CTS_RTS \ + { IOMUXC_GPIO_08_LPUART1_CTS_B }, { IOMUXC_GPIO_07_LPUART1_RTS_B }, \ + { 0 }, { 0 }, \ + { 0 }, { 0 }, \ + { IOMUXC_GPIO_AD_14_LPUART4_CTS_B }, { IOMUXC_GPIO_AD_13_LPUART4_RTS_B }, + #define MICROPY_HW_SPI_INDEX { 1 } #define IOMUX_TABLE_SPI \ diff --git a/ports/mimxrt/boards/MIMXRT1015_EVK/board.json b/ports/mimxrt/boards/MIMXRT1015_EVK/board.json index 78044c134e..d0bdd920bc 100644 --- a/ports/mimxrt/boards/MIMXRT1015_EVK/board.json +++ b/ports/mimxrt/boards/MIMXRT1015_EVK/board.json @@ -4,13 +4,10 @@ ], "docs": "", "features": [ - "MicroSD", - "MicroUSB", + "Audio Codec", + "External Flash", "Microphone", - "AudioCodec", - "CAN", - "OpenSDA", - "JLink" + "USB" ], "images": [ "MIMXRT1015-EVK-TOP.jpg" diff --git a/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h index f37ba824f4..655bb62c27 100644 --- a/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h @@ -28,6 +28,12 @@ { IOMUXC_GPIO_AD_B0_14_LPUART3_TX }, { IOMUXC_GPIO_AD_B0_15_LPUART3_RX }, \ { IOMUXC_GPIO_EMC_32_LPUART4_TX }, { IOMUXC_GPIO_EMC_33_LPUART4_RX }, \ +#define IOMUX_TABLE_UART_CTS_RTS \ + { IOMUXC_GPIO_AD_B0_08_LPUART1_CTS_B }, { IOMUXC_GPIO_AD_B0_09_LPUART1_RTS_B }, \ + { 0 }, { 0 }, \ + { IOMUXC_GPIO_AD_B0_12_LPUART3_CTS_B }, { IOMUXC_GPIO_AD_B0_13_LPUART3_RTS_B }, \ + { 0 }, { 0 }, + #define MICROPY_HW_SPI_INDEX { 1 } #define IOMUX_TABLE_SPI \ diff --git a/ports/mimxrt/boards/MIMXRT1020_EVK/board.json b/ports/mimxrt/boards/MIMXRT1020_EVK/board.json index cc74c25fed..4da224fc99 100644 --- a/ports/mimxrt/boards/MIMXRT1020_EVK/board.json +++ b/ports/mimxrt/boards/MIMXRT1020_EVK/board.json @@ -4,15 +4,14 @@ ], "docs": "", "features": [ - "Ethernet", - "SDRAM", - "MicroSD", - "MicroUSB", - "Microphone", - "AudioCodec", + "Audio Codec", "CAN", - "OpenSDA", - "JLink" + "Ethernet", + "External Flash", + "External RAM", + "Microphone", + "USB", + "microSD" ], "images": [ "MIMXRT-1020-EVKBD.jpg" diff --git a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h index 390e91814d..8b7316c8da 100644 --- a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h @@ -34,6 +34,16 @@ { 0 }, { 0 }, \ { IOMUXC_GPIO_SD_B1_02_LPUART8_TX }, { IOMUXC_GPIO_SD_B1_03_LPUART8_RX }, +#define IOMUX_TABLE_UART_CTS_RTS \ + { IOMUXC_GPIO_AD_B0_08_LPUART1_CTS_B }, { IOMUXC_GPIO_AD_B0_09_LPUART1_RTS_B }, \ + { IOMUXC_GPIO_AD_B1_06_LPUART2_CTS_B }, { IOMUXC_GPIO_AD_B1_07_LPUART2_RTS_B }, \ + { IOMUXC_GPIO_AD_B0_12_LPUART3_CTS_B }, { IOMUXC_GPIO_AD_B0_13_LPUART3_RTS_B }, \ + { IOMUXC_GPIO_EMC_00_LPUART4_CTS_B }, { IOMUXC_GPIO_EMC_01_LPUART4_RTS_B }, \ + { IOMUXC_GPIO_EMC_36_LPUART5_CTS_B }, { IOMUXC_GPIO_EMC_37_LPUART5_RTS_B }, \ + { 0 }, { 0 }, \ + { 0 }, { 0 }, \ + { IOMUXC_GPIO_EMC_24_LPUART8_CTS_B }, { IOMUXC_GPIO_EMC_25_LPUART8_RTS_B }, + #define MICROPY_HW_SPI_INDEX { 1, 3 } #define IOMUX_TABLE_SPI \ diff --git a/ports/mimxrt/boards/MIMXRT1050_EVK/board.json b/ports/mimxrt/boards/MIMXRT1050_EVK/board.json index d99ad9fcfd..d7c82358cc 100644 --- a/ports/mimxrt/boards/MIMXRT1050_EVK/board.json +++ b/ports/mimxrt/boards/MIMXRT1050_EVK/board.json @@ -4,16 +4,14 @@ ], "docs": "", "features": [ - "Ethernet", - "SDRAM", - "MicroSD", - "MicroUSB", - "Microphone", - "AudioCodec", - "SPDIF", + "Audio Codec", "CAN", - "OpenSDA", - "JLink" + "Ethernet", + "External Flash", + "External RAM", + "Microphone", + "USB", + "microSD" ], "images": [ "IMX_RT1050-EVKB_TOP-LR.jpg" diff --git a/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h index 134c9637ea..74666562a8 100644 --- a/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h @@ -30,6 +30,16 @@ { 0 }, { 0 }, \ { IOMUXC_GPIO_AD_B1_10_LPUART8_TX }, { IOMUXC_GPIO_AD_B1_11_LPUART8_RX }, +#define IOMUX_TABLE_UART_CTS_RTS \ + { IOMUXC_GPIO_AD_B0_14_LPUART1_CTS_B }, { IOMUXC_GPIO_AD_B0_15_LPUART1_RTS_B }, \ + { IOMUXC_GPIO_AD_B1_00_LPUART2_CTS_B }, { IOMUXC_GPIO_AD_B1_01_LPUART2_RTS_B }, \ + { IOMUXC_GPIO_AD_B1_04_LPUART3_CTS_B }, { IOMUXC_GPIO_AD_B1_05_LPUART3_RTS_B }, \ + { 0 }, { 0 }, \ + { 0 }, { 0 }, \ + { IOMUXC_GPIO_EMC_30_LPUART6_CTS_B }, { IOMUXC_GPIO_EMC_29_LPUART6_RTS_B }, \ + { 0 }, { 0 }, \ + { IOMUXC_GPIO_SD_B0_02_LPUART8_CTS_B }, { IOMUXC_GPIO_SD_B0_03_LPUART8_RTS_B }, + #define MICROPY_HW_SPI_INDEX { 1 } #define IOMUX_TABLE_SPI \ diff --git a/ports/mimxrt/boards/MIMXRT1060_EVK/board.json b/ports/mimxrt/boards/MIMXRT1060_EVK/board.json index 67a3818ee2..73c0cd1395 100644 --- a/ports/mimxrt/boards/MIMXRT1060_EVK/board.json +++ b/ports/mimxrt/boards/MIMXRT1060_EVK/board.json @@ -4,17 +4,15 @@ ], "docs": "", "features": [ - "Ethernet", - "SDRAM", - "MicroSD", - "MicroUSB", - "Microphone", - "AudioCodec", - "SPDIF", + "Audio Codec", "CAN", "Camera", - "OpenSDA", - "JLink" + "Ethernet", + "External Flash", + "External RAM", + "Microphone", + "USB", + "microSD" ], "images": [ "X-MIMXRT1060-EVK-BOARD-BOTTOM.jpg" diff --git a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h index 01ae3ba303..824f9977c2 100644 --- a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h @@ -30,6 +30,16 @@ { 0 }, { 0 }, \ { IOMUXC_GPIO_AD_B1_10_LPUART8_TX }, { IOMUXC_GPIO_AD_B1_11_LPUART8_RX }, +#define IOMUX_TABLE_UART_CTS_RTS \ + { IOMUXC_GPIO_AD_B0_14_LPUART1_CTS_B }, { IOMUXC_GPIO_AD_B0_15_LPUART1_RTS_B }, \ + { IOMUXC_GPIO_AD_B1_00_LPUART2_CTS_B }, { IOMUXC_GPIO_AD_B1_01_LPUART2_RTS_B }, \ + { IOMUXC_GPIO_AD_B1_04_LPUART3_CTS_B }, { IOMUXC_GPIO_AD_B1_05_LPUART3_RTS_B }, \ + { 0 }, { 0 }, \ + { 0 }, { 0 }, \ + { IOMUXC_GPIO_EMC_30_LPUART6_CTS_B }, { IOMUXC_GPIO_EMC_29_LPUART6_RTS_B }, \ + { 0 }, { 0 }, \ + { IOMUXC_GPIO_SD_B0_02_LPUART8_CTS_B }, { IOMUXC_GPIO_SD_B0_03_LPUART8_RTS_B }, + #define MICROPY_HW_SPI_INDEX { 1 } #define IOMUX_TABLE_SPI \ diff --git a/ports/mimxrt/boards/MIMXRT1062_af.csv b/ports/mimxrt/boards/MIMXRT1062_af.csv index 9b83efeddc..d2f0b22023 100644 --- a/ports/mimxrt/boards/MIMXRT1062_af.csv +++ b/ports/mimxrt/boards/MIMXRT1062_af.csv @@ -123,3 +123,6 @@ GPIO_SD_B1_08,USDHC2_DATA4,FLEXSPI_A_DATA0,LPUART7_TXD,SAI1_TX_BCLK,LPSPI2_SOUT, GPIO_SD_B1_09,USDHC2_DATA5,FLEXSPI_A_DATA1,LPUART7_RXD,SAI1_TX_SYNC,LPSPI2_SIN,GPIO3_IO09,,,,,,,ALT5 GPIO_SD_B1_10,USDHC2_DATA6,FLEXSPI_A_DATA2,LPUART2_RXD,LPI2C2_SDA,LPSPI2_PCS2,GPIO3_IO10,,,,,,,ALT5 GPIO_SD_B1_11,USDHC2_DATA7,FLEXSPI_A_DATA3,LPUART2_TXD,LPI2C2_SCL,LPSPI2_PCS3,GPIO3_IO11,,,,,,,ALT5 +WAKEUP,,,,,,GPIO5_IO00,,NMI,,,,,ALT5 +PMIC_ON_REQ,SNVS_PMIC_ON_REQ,,,,,GPIO5_IO01,,,,,,,ALT0 +PMIC_STBY_REQ,CCM_PMIC_STBY_REQ,,,,,GPIO5_IO02,,,,,,,ALT0 diff --git a/ports/mimxrt/boards/MIMXRT1064_EVK/board.json b/ports/mimxrt/boards/MIMXRT1064_EVK/board.json index ef12336c44..a573009d38 100644 --- a/ports/mimxrt/boards/MIMXRT1064_EVK/board.json +++ b/ports/mimxrt/boards/MIMXRT1064_EVK/board.json @@ -4,17 +4,15 @@ ], "docs": "", "features": [ - "Ethernet", - "SDRAM", - "MicroSD", - "MicroUSB", - "Microphone", - "AudioAmp", - "SPDIF", + "Audio Codec", "CAN", "Camera", - "OpenSDA", - "JLink" + "Ethernet", + "External Flash", + "External RAM", + "Microphone", + "USB", + "microSD" ], "images": [ "MIMXRT1064EVK-TOP.jpg" diff --git a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h index b6752c3e1b..cb64d2b9d2 100644 --- a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h @@ -30,6 +30,16 @@ { 0 }, { 0 }, \ { IOMUXC_GPIO_AD_B1_10_LPUART8_TX }, { IOMUXC_GPIO_AD_B1_11_LPUART8_RX }, +#define IOMUX_TABLE_UART_CTS_RTS \ + { IOMUXC_GPIO_AD_B0_14_LPUART1_CTS_B }, { IOMUXC_GPIO_AD_B0_15_LPUART1_RTS_B }, \ + { IOMUXC_GPIO_AD_B1_00_LPUART2_CTS_B }, { IOMUXC_GPIO_AD_B1_01_LPUART2_RTS_B }, \ + { IOMUXC_GPIO_AD_B1_04_LPUART3_CTS_B }, { IOMUXC_GPIO_AD_B1_05_LPUART3_RTS_B }, \ + { 0 }, { 0 }, \ + { 0 }, { 0 }, \ + { IOMUXC_GPIO_EMC_30_LPUART6_CTS_B }, { IOMUXC_GPIO_EMC_29_LPUART6_RTS_B }, \ + { 0 }, { 0 }, \ + { IOMUXC_GPIO_SD_B0_02_LPUART8_CTS_B }, { IOMUXC_GPIO_SD_B0_03_LPUART8_RTS_B }, + #define MICROPY_HW_SPI_INDEX { 1 } #define IOMUX_TABLE_SPI \ diff --git a/ports/mimxrt/boards/MIMXRT1170_EVK/board.json b/ports/mimxrt/boards/MIMXRT1170_EVK/board.json index 01e554751b..73453b45a6 100644 --- a/ports/mimxrt/boards/MIMXRT1170_EVK/board.json +++ b/ports/mimxrt/boards/MIMXRT1170_EVK/board.json @@ -4,18 +4,15 @@ ], "docs": "", "features": [ - "Ethernet", - "SDRAM", - "MicroSD", - "MicroUSB", - "Microphone", - "AudioCodec", - "SPDIF", + "Audio Codec", "CAN", "Camera", - "SIM Socket", - "OpenSDA", - "JLink" + "Ethernet", + "External Flash", + "External RAM", + "Microphone", + "USB", + "microSD" ], "images": [ "IMX-RT1170-EVK-TOP.jpg" diff --git a/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.h index d37050eb56..8ce91adbaf 100644 --- a/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.h @@ -43,6 +43,20 @@ { IOMUXC_GPIO_LPSR_04_LPUART11_TXD }, { IOMUXC_GPIO_LPSR_05_LPUART11_RXD }, \ { IOMUXC_GPIO_LPSR_10_LPUART12_TXD }, { IOMUXC_GPIO_LPSR_11_LPUART12_RXD }, +#define IOMUX_TABLE_UART_CTS_RTS \ + { IOMUXC_GPIO_AD_26_LPUART1_CTS_B }, { IOMUXC_GPIO_AD_27_LPUART1_RTS_B }, \ + { IOMUXC_GPIO_DISP_B2_12_LPUART2_CTS_B }, { IOMUXC_GPIO_DISP_B2_13_LPUART2_RTS_B }, \ + { IOMUXC_GPIO_SD_B2_07_LPUART3_CTS_B }, { IOMUXC_GPIO_SD_B2_08_LPUART3_RTS_B }, \ + { 0 }, { 0 }, \ + { IOMUXC_GPIO_SD_B2_09_LPUART5_CTS_B }, { IOMUXC_GPIO_SD_B2_10_LPUART5_RTS_B }, \ + { 0 }, { 0 }, \ + { IOMUXC_GPIO_AD_02_LPUART7_CTS_B }, { IOMUXC_GPIO_AD_03_LPUART7_RTS_B }, \ + { IOMUXC_GPIO_AD_04_LPUART8_CTS_B }, { IOMUXC_GPIO_AD_05_LPUART8_RTS_B }, \ + { 0 }, { 0 }, \ + { 0 }, { 0 }, \ + { IOMUXC_GPIO_LPSR_10_LPUART11_CTS_B }, { IOMUXC_GPIO_LPSR_11_LPUART11_RTS_B }, \ + { IOMUXC_GPIO_LPSR_05_LPUART12_CTS_B }, { IOMUXC_GPIO_LPSR_04_LPUART12_RTS_B }, + // Define the mapping hardware SPI # to logical SPI # // SCK/CS/SDO/SDI HW-SPI Logical SPI // D13/D10/D11/D12 LPSPI1 -> 0 diff --git a/ports/mimxrt/boards/MIMXRT1176.ld b/ports/mimxrt/boards/MIMXRT1176.ld index 2408977b94..d66c86a046 100644 --- a/ports/mimxrt/boards/MIMXRT1176.ld +++ b/ports/mimxrt/boards/MIMXRT1176.ld @@ -39,7 +39,7 @@ dtcm_size = 0x00020000; ocrm_start = 0x20240000; ocrm_size = 0x00100000; -#ifdef MICROPY_HW_SDRAM_AVAIL +#if MICROPY_HW_SDRAM_AVAIL sdram_start = 0x80000000; sdram_size = MICROPY_HW_SDRAM_SIZE; #endif @@ -49,7 +49,7 @@ __stack_size__ = 0x8000; _estack = __StackTop; _sstack = __StackLimit; -#ifdef MICROPY_HW_SDRAM_AVAIL +#if MICROPY_HW_SDRAM_AVAIL _gc_heap_start = ORIGIN(m_sdram); _gc_heap_end = ORIGIN(m_sdram) + LENGTH(m_sdram); #else diff --git a/ports/mimxrt/boards/MIMXRT1176_af.csv b/ports/mimxrt/boards/MIMXRT1176_af.csv index fe31f502e4..21fd2a2417 100644 --- a/ports/mimxrt/boards/MIMXRT1176_af.csv +++ b/ports/mimxrt/boards/MIMXRT1176_af.csv @@ -80,16 +80,16 @@ GPIO_EMC_B2_17,SEMC_DM03,XBAR1_INOUT15,ENET_1G_RX_EN,SAI3_MCLK,FLEXSPI2_A_DATA04 GPIO_EMC_B2_18,SEMC_DQS4,XBAR1_INOUT16,ENET_1G_RX_ER,EWM_OUT_B,FLEXSPI2_A_DATA05,GPIO2_IO28,FLEXSPI1_A_DQS,,WDOG1_B,TMR3_TIMER1,GPIO8_IO28,,, GPIO_EMC_B2_19,SEMC_CLKX00,ENET_MDC,ENET_1G_MDC,ENET_1G_REF_CLK,FLEXSPI2_A_DATA06,GPIO2_IO29,,,ENET_QOS_MDC,TMR3_TIMER2,GPIO8_IO29,,, GPIO_EMC_B2_20,SEMC_CLKX01,ENET_MDIO,ENET_1G_MDIO,ENET_QOS_REF_CLK,FLEXSPI2_A_DATA07,GPIO2_IO30,,,ENET_QOS_MDIO,TMR3_TIMER3,GPIO8_IO30,,, -GPIO_SNVS_00,SNVS_TAMPER0,,,,,GPIO13_IO03,,,,,,,, -GPIO_SNVS_01,SNVS_TAMPER1,,,,,GPIO13_IO04,,,,,,,, -GPIO_SNVS_02,SNVS_TAMPER2,,,,,GPIO13_IO05,,,,,,,, -GPIO_SNVS_03,SNVS_TAMPER3,,,,,GPIO13_IO06,,,,,,,, -GPIO_SNVS_04,SNVS_TAMPER4,,,,,GPIO13_IO07,,,,,,,, -GPIO_SNVS_05,SNVS_TAMPER5,,,,,GPIO13_IO08,,,,,,,, -GPIO_SNVS_06,SNVS_TAMPER6,,,,,GPIO13_IO09,,,,,,,, -GPIO_SNVS_07,SNVS_TAMPER7,,,,,GPIO13_IO10,,,,,,,, -GPIO_SNVS_08,SNVS_TAMPER8,,,,,GPIO13_IO11,,,,,,,, -GPIO_SNVS_09,SNVS_TAMPER9,,,,,GPIO13_IO12,,,,,,,, +GPIO_SNVS_00_DIG,SNVS_TAMPER0,,,,,GPIO13_IO03,,,,,,,, +GPIO_SNVS_01_DIG,SNVS_TAMPER1,,,,,GPIO13_IO04,,,,,,,, +GPIO_SNVS_02_DIG,SNVS_TAMPER2,,,,,GPIO13_IO05,,,,,,,, +GPIO_SNVS_03_DIG,SNVS_TAMPER3,,,,,GPIO13_IO06,,,,,,,, +GPIO_SNVS_04_DIG,SNVS_TAMPER4,,,,,GPIO13_IO07,,,,,,,, +GPIO_SNVS_05_DIG,SNVS_TAMPER5,,,,,GPIO13_IO08,,,,,,,, +GPIO_SNVS_06_DIG,SNVS_TAMPER6,,,,,GPIO13_IO09,,,,,,,, +GPIO_SNVS_07_DIG,SNVS_TAMPER7,,,,,GPIO13_IO10,,,,,,,, +GPIO_SNVS_08_DIG,SNVS_TAMPER8,,,,,GPIO13_IO11,,,,,,,, +GPIO_SNVS_09_DIG,SNVS_TAMPER9,,,,,GPIO13_IO12,,,,,,,, GPIO_LPSR_00,FLEXCAN3_TX,MIC_CLK,MQS_RIGHT,ARM_CM4_EVENTO,,GPIO6_IO00,LPUART12_TXD,SAI4_MCLK,,,GPIO12_IO00,,, GPIO_LPSR_01,FLEXCAN3_RX,MIC_BITSTREAM0,MQS_LEFT,ARM_CM4_EVENTI,,GPIO6_IO01,LPUART12_RXD,,,,GPIO12_IO01,,, GPIO_LPSR_02,SRC_BOOT_MODE00,LPSPI5_SCK,SAI4_TX_DATA,MQS_RIGHT,,GPIO6_IO02,,,,,GPIO12_IO02,,, diff --git a/ports/mimxrt/boards/OLIMEX_RT1010/board.json b/ports/mimxrt/boards/OLIMEX_RT1010/board.json index 1778725658..882b931f8b 100644 --- a/ports/mimxrt/boards/OLIMEX_RT1010/board.json +++ b/ports/mimxrt/boards/OLIMEX_RT1010/board.json @@ -4,11 +4,9 @@ ], "docs": "", "features": [ - "MicroUSB", - "MicroSD", - "AudioCodec", - "SPDIF", - "JLink" + "External Flash", + "USB", + "microSD" ], "images": [ "OLIMEX_RT1010Py.jpg" diff --git a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h index 3d080ff25f..9443bb3732 100644 --- a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h +++ b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h @@ -25,6 +25,12 @@ { 0 }, { 0 }, \ { IOMUXC_GPIO_06_LPUART4_TXD }, { IOMUXC_GPIO_05_LPUART4_RXD }, +#define IOMUX_TABLE_UART_CTS_RTS \ + { IOMUXC_GPIO_08_LPUART1_CTS_B }, { IOMUXC_GPIO_07_LPUART1_RTS_B }, \ + { 0 }, { 0 }, \ + { 0 }, { 0 }, \ + { IOMUXC_GPIO_AD_14_LPUART4_CTS_B }, { IOMUXC_GPIO_AD_13_LPUART4_RTS_B }, + #define MICROPY_HW_SPI_INDEX { 0, 1, 2 } #define IOMUX_TABLE_SPI \ diff --git a/ports/mimxrt/boards/SEEED_ARCH_MIX/board.json b/ports/mimxrt/boards/SEEED_ARCH_MIX/board.json index 3142f1a814..138d28418c 100644 --- a/ports/mimxrt/boards/SEEED_ARCH_MIX/board.json +++ b/ports/mimxrt/boards/SEEED_ARCH_MIX/board.json @@ -4,10 +4,11 @@ ], "docs": "", "features": [ - "MicroSD", - "MicroUSB", - "SDRAM", - "RGB LED" + "External Flash", + "External RAM", + "RGB LED", + "USB", + "microSD" ], "images": [ "main1.jpg" @@ -16,5 +17,5 @@ "product": "Arch Mix", "thumbnail": "", "url": "https://wiki.seeedstudio.com/Arch_Mix/", - "vendor": "Seeed Technology Co.,Ltd." + "vendor": "Seeed Studio" } diff --git a/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h b/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h index c98cdcb0a7..edda72f266 100644 --- a/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h +++ b/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h @@ -32,6 +32,16 @@ { 0 }, { 0 }, \ { IOMUXC_GPIO_AD_B1_10_LPUART8_TX }, { IOMUXC_GPIO_AD_B1_11_LPUART8_RX }, +#define IOMUX_TABLE_UART_CTS_RTS \ + { IOMUXC_GPIO_AD_B0_14_LPUART1_CTS_B }, { IOMUXC_GPIO_AD_B0_15_LPUART1_RTS_B }, \ + { IOMUXC_GPIO_AD_B1_00_LPUART2_CTS_B }, { IOMUXC_GPIO_AD_B1_01_LPUART2_RTS_B }, \ + { IOMUXC_GPIO_AD_B1_04_LPUART3_CTS_B }, { IOMUXC_GPIO_AD_B1_05_LPUART3_RTS_B }, \ + { IOMUXC_GPIO_EMC_17_LPUART4_CTS_B }, { IOMUXC_GPIO_EMC_18_LPUART4_RTS_B }, \ + { 0 }, { 0 }, \ + { 0 }, { 0 }, \ + { 0 }, { 0 }, \ + { IOMUXC_GPIO_SD_B0_02_LPUART8_CTS_B }, { IOMUXC_GPIO_SD_B0_03_LPUART8_RTS_B }, + #define MICROPY_HW_SPI_INDEX { 3, 4 } #define IOMUX_TABLE_SPI \ diff --git a/ports/mimxrt/boards/TEENSY40/board.json b/ports/mimxrt/boards/TEENSY40/board.json index daa6dbf99e..599fb2f729 100644 --- a/ports/mimxrt/boards/TEENSY40/board.json +++ b/ports/mimxrt/boards/TEENSY40/board.json @@ -4,7 +4,8 @@ ], "docs": "", "features": [ - "Breadboard Friendly" + "External Flash", + "USB" ], "images": [ "teensy40_front.jpg" diff --git a/ports/mimxrt/boards/TEENSY40/mpconfigboard.h b/ports/mimxrt/boards/TEENSY40/mpconfigboard.h index 07da87db10..1a6227a60e 100644 --- a/ports/mimxrt/boards/TEENSY40/mpconfigboard.h +++ b/ports/mimxrt/boards/TEENSY40/mpconfigboard.h @@ -22,6 +22,16 @@ { IOMUXC_GPIO_EMC_31_LPUART7_TX }, { IOMUXC_GPIO_EMC_32_LPUART7_RX }, \ { IOMUXC_GPIO_AD_B1_10_LPUART8_TX }, { IOMUXC_GPIO_AD_B1_11_LPUART8_RX }, +#define IOMUX_TABLE_UART_CTS_RTS \ + { IOMUXC_GPIO_AD_B0_14_LPUART1_CTS_B }, { IOMUXC_GPIO_AD_B0_15_LPUART1_RTS_B }, \ + { IOMUXC_GPIO_AD_B1_00_LPUART2_CTS_B }, { IOMUXC_GPIO_AD_B1_01_LPUART2_RTS_B }, \ + { IOMUXC_GPIO_AD_B1_04_LPUART3_CTS_B }, { IOMUXC_GPIO_AD_B1_05_LPUART3_RTS_B }, \ + { IOMUXC_GPIO_EMC_17_LPUART4_CTS_B }, { IOMUXC_GPIO_EMC_18_LPUART4_RTS_B }, \ + { 0 }, { 0 }, \ + { IOMUXC_GPIO_EMC_30_LPUART6_CTS_B }, { IOMUXC_GPIO_EMC_29_LPUART6_RTS_B }, \ + { IOMUXC_GPIO_SD_B1_06_LPUART7_CTS_B }, { IOMUXC_GPIO_SD_B1_07_LPUART7_RTS_B }, \ + { IOMUXC_GPIO_SD_B0_02_LPUART8_CTS_B }, { IOMUXC_GPIO_SD_B0_03_LPUART8_RTS_B }, + #define MICROPY_HW_SPI_INDEX { 4, 3} #define IOMUX_TABLE_SPI \ diff --git a/ports/mimxrt/boards/TEENSY41/board.json b/ports/mimxrt/boards/TEENSY41/board.json index 1f8fe37a99..08235d4dae 100644 --- a/ports/mimxrt/boards/TEENSY41/board.json +++ b/ports/mimxrt/boards/TEENSY41/board.json @@ -4,9 +4,10 @@ ], "docs": "", "features": [ - "MicroSD", "Ethernet", - "Breadboard Friendly" + "External Flash", + "USB", + "microSD" ], "images": [ "teensy41_4.jpg" diff --git a/ports/mimxrt/boards/TEENSY41/mpconfigboard.h b/ports/mimxrt/boards/TEENSY41/mpconfigboard.h index 56740f48ea..09addbe52c 100644 --- a/ports/mimxrt/boards/TEENSY41/mpconfigboard.h +++ b/ports/mimxrt/boards/TEENSY41/mpconfigboard.h @@ -24,6 +24,16 @@ { IOMUXC_GPIO_EMC_31_LPUART7_TX }, { IOMUXC_GPIO_EMC_32_LPUART7_RX }, \ { IOMUXC_GPIO_AD_B1_10_LPUART8_TX }, { IOMUXC_GPIO_AD_B1_11_LPUART8_RX }, +#define IOMUX_TABLE_UART_CTS_RTS \ + { IOMUXC_GPIO_AD_B0_14_LPUART1_CTS_B }, { IOMUXC_GPIO_AD_B0_15_LPUART1_RTS_B }, \ + { IOMUXC_GPIO_AD_B1_00_LPUART2_CTS_B }, { IOMUXC_GPIO_AD_B1_01_LPUART2_RTS_B }, \ + { IOMUXC_GPIO_AD_B1_04_LPUART3_CTS_B }, { IOMUXC_GPIO_AD_B1_05_LPUART3_RTS_B }, \ + { IOMUXC_GPIO_EMC_17_LPUART4_CTS_B }, { IOMUXC_GPIO_EMC_18_LPUART4_RTS_B }, \ + { IOMUXC_GPIO_EMC_28_LPUART5_CTS_B }, { IOMUXC_GPIO_EMC_27_LPUART5_RTS_B }, \ + { IOMUXC_GPIO_EMC_30_LPUART6_CTS_B }, { IOMUXC_GPIO_EMC_29_LPUART6_RTS_B }, \ + { IOMUXC_GPIO_SD_B1_06_LPUART7_CTS_B }, { IOMUXC_GPIO_SD_B1_07_LPUART7_RTS_B }, \ + { IOMUXC_GPIO_SD_B0_02_LPUART8_CTS_B }, { IOMUXC_GPIO_SD_B0_03_LPUART8_RTS_B }, + #define MICROPY_HW_SPI_INDEX { 4, 3, 1 } #define IOMUX_TABLE_SPI \ diff --git a/ports/mimxrt/boards/make-pins.py b/ports/mimxrt/boards/make-pins.py index 429d648696..51ae9eb717 100644 --- a/ports/mimxrt/boards/make-pins.py +++ b/ports/mimxrt/boards/make-pins.py @@ -24,6 +24,10 @@ regexes = [ r"IOMUXC_(?PGPIO_EMC_B\d_\d\d)_(?P\w+) (?P\w+), (?P\w+), (?P\w+), (?P\w+), (?P\w+)", r"IOMUXC_(?PGPIO_DISP_B\d_\d\d)_(?P\w+) (?P\w+), (?P\w+), (?P\w+), (?P\w+), (?P\w+)", r"IOMUXC_(?PGPIO_LPSR_\d\d)_(?P\w+) (?P\w+), (?P\w+), (?P\w+), (?P\w+), (?P\w+)", + r"IOMUXC_[SNVS_]*(?PWAKEUP[_DIG]*)_(?P\w+) (?P\w+), (?P\w+), (?P\w+), (?P\w+), (?P\w+)", + r"IOMUXC_SNVS_(?PPMIC_ON_REQ)_(?P\w+) (?P\w+), (?P\w+), (?P\w+), (?P\w+), (?P\w+)", + r"IOMUXC_SNVS_(?PPMIC_STBY_REQ)_(?P\w+) (?P\w+), (?P\w+), (?P\w+), (?P\w+), (?P\w+)", + r"IOMUXC_(?PGPIO_SNVS_\d\d_DIG)_(?P\w+) (?P\w+), (?P\w+), (?P\w+), (?P\w+), (?P\w+)", ] @@ -118,10 +122,43 @@ class Pin(object): self.print_pin_af() self.print_pin_adc() + options = { + "GPIO_LPSR_00": "PIN_LPSR", + "GPIO_LPSR_01": "PIN_LPSR", + "GPIO_LPSR_02": "PIN_LPSR", + "GPIO_LPSR_03": "PIN_LPSR", + "GPIO_LPSR_04": "PIN_LPSR", + "GPIO_LPSR_05": "PIN_LPSR", + "GPIO_LPSR_06": "PIN_LPSR", + "GPIO_LPSR_07": "PIN_LPSR", + "GPIO_LPSR_08": "PIN_LPSR", + "GPIO_LPSR_09": "PIN_LPSR", + "GPIO_LPSR_10": "PIN_LPSR", + "GPIO_LPSR_11": "PIN_LPSR", + "GPIO_LPSR_12": "PIN_LPSR", + "GPIO_LPSR_13": "PIN_LPSR", + "GPIO_LPSR_14": "PIN_LPSR", + "GPIO_LPSR_15": "PIN_LPSR", + "GPIO_SNVS_00_DIG": "PIN_SNVS", + "GPIO_SNVS_01_DIG": "PIN_SNVS", + "GPIO_SNVS_02_DIG": "PIN_SNVS", + "GPIO_SNVS_03_DIG": "PIN_SNVS", + "GPIO_SNVS_04_DIG": "PIN_SNVS", + "GPIO_SNVS_05_DIG": "PIN_SNVS", + "GPIO_SNVS_06_DIG": "PIN_SNVS", + "GPIO_SNVS_07_DIG": "PIN_SNVS", + "GPIO_SNVS_08_DIG": "PIN_SNVS", + "GPIO_SNVS_09_DIG": "PIN_SNVS", + "WAKEUP": "PIN_SNVS", + "WAKEUP_DIG": "PIN_SNVS", + "PMIC_ON_REQ": "PIN_SNVS", + "PMIC_STBY_REQ": "PIN_SNVS", + } + print( "const machine_pin_obj_t pin_{0} = {1}({0}, {2}, {3}, pin_{0}_af, {4}, {5});\n".format( self.name, - "PIN_LPSR" if "LPSR" in self.name else "PIN", + options.get(self.name, "PIN"), self.gpio, int(self.pin), len(self.adc_fns), @@ -233,9 +270,6 @@ class Pins(object): pin_number = pin.lstrip("IO") pin = Pin(pad, gpio, pin_number, idx=idx) - if any(s in pad for s in ("SNVS", "WAKEUP")): - continue - # Parse alternate functions af_idx = 0 for af_idx, af in enumerate(row[(pad_col + 1) : adc_col]): diff --git a/ports/mimxrt/boards/mimxrt_prefix.c b/ports/mimxrt/boards/mimxrt_prefix.c index 09c0aa109e..d7a2bcfc80 100644 --- a/ports/mimxrt/boards/mimxrt_prefix.c +++ b/ports/mimxrt/boards/mimxrt_prefix.c @@ -49,3 +49,17 @@ .adc_list = (_adc_list), \ } \ +#define PIN_SNVS(_name, _gpio, _pin, _af_list, _adc_list_len, _adc_list) \ + { \ + .base = { &machine_pin_type }, \ + .name = MP_QSTR_##_name, \ + .gpio = (_gpio), \ + .pin = (uint32_t)(_pin), \ + .muxRegister = (uint32_t)&(IOMUXC_SNVS->SW_MUX_CTL_PAD_##_name), \ + .configRegister = (uint32_t)&(IOMUXC_SNVS->SW_PAD_CTL_PAD_##_name), \ + .af_list_len = (uint8_t)(sizeof((_af_list)) / sizeof(machine_pin_af_obj_t)), \ + .adc_list_len = (_adc_list_len), \ + .af_list = (_af_list), \ + .adc_list = (_adc_list), \ + } \ + diff --git a/ports/mimxrt/cyw43_configport.h b/ports/mimxrt/cyw43_configport.h new file mode 100644 index 0000000000..5f96856474 --- /dev/null +++ b/ports/mimxrt/cyw43_configport.h @@ -0,0 +1,155 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Damien P. George + * Copyright (c) 2022 Jim Mussared + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32_CYW43_CONFIGPORT_H +#define MICROPY_INCLUDED_STM32_CYW43_CONFIGPORT_H + +// The board-level config will be included here, so it can set some CYW43 values. +#include "py/mpconfig.h" +#include "py/mperrno.h" +#include "py/mphal.h" +#include "extmod/modnetwork.h" +#include "pendsv.h" +#include "sdio.h" + +#define CYW43_USE_SPI (0) +#define CYW43_LWIP (1) +#define CYW43_USE_STATS (0) + +#ifndef CYW43_CHIPSET_FIRMWARE_INCLUDE_FILE +#define CYW43_CHIPSET_FIRMWARE_INCLUDE_FILE "lib/cyw43-driver/firmware/w4343WA1_7_45_98_50_combined.h" +#endif + +#ifndef CYW43_WIFI_NVRAM_INCLUDE_FILE +#define CYW43_WIFI_NVRAM_INCLUDE_FILE "lib/cyw43-driver/firmware/wifi_nvram_1dx.h" +#endif + +#define CYW43_IOCTL_TIMEOUT_US (1000000) +#define CYW43_SLEEP_MAX (50) +#define CYW43_NETUTILS (1) +#define CYW43_CLEAR_SDIO_INT (1) + +#define CYW43_EPERM MP_EPERM // Operation not permitted +#define CYW43_EIO MP_EIO // I/O error +#define CYW43_EINVAL MP_EINVAL // Invalid argument +#define CYW43_ETIMEDOUT MP_ETIMEDOUT // Connection timed out + +#define CYW43_THREAD_ENTER MICROPY_PY_LWIP_ENTER +#define CYW43_THREAD_EXIT MICROPY_PY_LWIP_EXIT +#define CYW43_THREAD_LOCK_CHECK + +#define CYW43_HOST_NAME mod_network_hostname + +#define CYW43_SDPCM_SEND_COMMON_WAIT __WFI(); +#define CYW43_DO_IOCTL_WAIT __WFI(); + +#define CYW43_ARRAY_SIZE(a) MP_ARRAY_SIZE(a) + +#define CYW43_HAL_PIN_MODE_INPUT MP_HAL_PIN_MODE_INPUT +#define CYW43_HAL_PIN_MODE_OUTPUT MP_HAL_PIN_MODE_OUTPUT +#define CYW43_HAL_PIN_PULL_NONE MP_HAL_PIN_PULL_NONE +#define CYW43_HAL_PIN_PULL_UP MP_HAL_PIN_PULL_UP +#define CYW43_HAL_PIN_PULL_DOWN MP_HAL_PIN_PULL_DOWN + +#define CYW43_HAL_MAC_WLAN0 MP_HAL_MAC_WLAN0 + +#define cyw43_hal_ticks_us mp_hal_ticks_us +#define cyw43_hal_ticks_ms mp_hal_ticks_ms + +#define cyw43_hal_pin_obj_t mp_hal_pin_obj_t +#define cyw43_hal_pin_read mp_hal_pin_read +#define cyw43_hal_pin_low mp_hal_pin_low +#define cyw43_hal_pin_high mp_hal_pin_high + +#define cyw43_hal_get_mac mp_hal_get_mac +#define cyw43_hal_get_mac_ascii mp_hal_get_mac_ascii +#define cyw43_hal_generate_laa_mac mp_hal_generate_laa_mac + +#define cyw43_delay_us mp_hal_delay_us +#define cyw43_delay_ms mp_hal_delay_ms + +#define CYW43_PIN_WL_REG_ON MICROPY_HW_WL_REG_ON +#define CYW43_PIN_WL_HOST_WAKE MICROPY_HW_WL_HOST_WAKE +#define CYW43_PIN_WL_SDIO_1 MICROPY_HW_SDIO_D1 + +#define CYW43_PIN_BT_REG_ON MICROPY_HW_BT_REG_ON +#ifdef MICROPY_HW_BT_HOST_WAKE +#define CYW43_PIN_BT_HOST_WAKE MICROPY_HW_BT_HOST_WAKE +#endif +#ifdef MICROPY_HW_BT_DEV_WAKE +#define CYW43_PIN_BT_DEV_WAKE MICROPY_HW_BT_DEV_WAKE +#endif +#ifdef MICROPY_HW_BT_CTS +#define CYW43_PIN_BT_CTS MICROPY_HW_BT_CTS +#endif + +#if MICROPY_HW_ENABLE_RF_SWITCH +#define CYW43_PIN_WL_RFSW_VDD pin_WL_RFSW_VDD +#endif + +#define cyw43_schedule_internal_poll_dispatch(func) pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, func) + +static inline void cyw43_hal_pin_config(cyw43_hal_pin_obj_t pin, uint8_t mode, uint8_t pull, uint8_t alt) { + machine_pin_set_mode(pin, mode); +} + +static inline void cyw43_hal_pin_config_irq_falling(cyw43_hal_pin_obj_t pin, int enable) { + if (enable) { + machine_pin_config(pin, PIN_MODE_IT_FALLING, PIN_PULL_UP_100K, 0, 0, PIN_AF_MODE_ALT5); + } +} + +static inline void cyw43_sdio_init(void) { + sdio_init(NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 14, 0)); +} + +static inline void cyw43_sdio_reinit(void) { + sdio_reenable(); +} + +static inline void cyw43_sdio_deinit(void) { + sdio_deinit(); +} + +static inline void cyw43_sdio_set_irq(bool enable) { + sdio_enable_irq(enable); +} + +static inline void cyw43_sdio_enable_high_speed_4bit(void) { + sdio_enable_high_speed_4bit(); +} + +static inline int cyw43_sdio_transfer(uint32_t cmd, uint32_t arg, uint32_t *resp) { + return sdio_transfer(cmd, arg, resp); +} + +static inline int cyw43_sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t len, uint8_t *buf) { + return sdio_transfer_cmd53(write, block_size, arg, len, buf); +} + +#define CYW43_EVENT_POLL_HOOK MICROPY_EVENT_POLL_HOOK + +#endif // MICROPY_INCLUDED_STM32_CYW43_CONFIGPORT_H diff --git a/ports/mimxrt/hal/pwm_backport.c b/ports/mimxrt/hal/pwm_backport.c index 018f8f6279..7732e0e816 100644 --- a/ports/mimxrt/hal/pwm_backport.c +++ b/ports/mimxrt/hal/pwm_backport.c @@ -18,10 +18,10 @@ #include "hal/pwm_backport.h" void PWM_UpdatePwmDutycycle_u16( - PWM_Type *base, pwm_submodule_t subModule, pwm_channels_t pwmSignal, uint16_t dutyCycle, uint16_t Center_u16) { + PWM_Type *base, pwm_submodule_t subModule, pwm_channels_t pwmSignal, uint32_t dutyCycle, uint16_t Center_u16) { assert((uint16_t)pwmSignal < 2U); - uint16_t pulseCnt = 0, pwmHighPulse = 0; - uint16_t center; + uint32_t pulseCnt = 0, pwmHighPulse = 0; + uint32_t center; // check and confine bounds for Center_u16 if ((Center_u16 + dutyCycle / 2) >= PWM_FULL_SCALE) { @@ -36,11 +36,21 @@ void PWM_UpdatePwmDutycycle_u16( // Setup the PWM dutycycle of channel A or B if (pwmSignal == kPWM_PwmA) { - base->SM[subModule].VAL2 = center - pwmHighPulse / 2; - base->SM[subModule].VAL3 = base->SM[subModule].VAL2 + pwmHighPulse; + if (dutyCycle >= 65536) { + base->SM[subModule].VAL2 = 0; + base->SM[subModule].VAL3 = pulseCnt; + } else { + base->SM[subModule].VAL2 = center - pwmHighPulse / 2; + base->SM[subModule].VAL3 = base->SM[subModule].VAL2 + pwmHighPulse; + } } else { - base->SM[subModule].VAL4 = center - pwmHighPulse / 2; - base->SM[subModule].VAL5 = base->SM[subModule].VAL4 + pwmHighPulse; + if (dutyCycle >= 65536) { + base->SM[subModule].VAL4 = 0; + base->SM[subModule].VAL5 = pulseCnt; + } else { + base->SM[subModule].VAL4 = center - pwmHighPulse / 2; + base->SM[subModule].VAL5 = base->SM[subModule].VAL4 + pwmHighPulse; + } } } @@ -86,33 +96,33 @@ void PWM_SetupPwm_u16(PWM_Type *base, pwm_submodule_t subModule, pwm_signal_para } void PWM_SetupPwmx_u16(PWM_Type *base, pwm_submodule_t subModule, - uint32_t pwmFreq_Hz, uint16_t duty_cycle, uint8_t invert, uint32_t srcClock_Hz) { + uint32_t pwmFreq_Hz, uint32_t duty_cycle, uint8_t invert, uint32_t srcClock_Hz) { uint32_t pulseCnt; uint32_t pwmClock; // Divide the clock by the prescale value pwmClock = (srcClock_Hz / (1U << ((base->SM[subModule].CTRL & PWM_CTRL_PRSC_MASK) >> PWM_CTRL_PRSC_SHIFT))); - pulseCnt = (pwmClock + (pwmFreq_Hz - 1) / 2) / pwmFreq_Hz; + pulseCnt = (pwmClock + (pwmFreq_Hz - 1) / 2) / pwmFreq_Hz - 1; base->SM[subModule].INIT = 0; - base->SM[subModule].VAL0 = ((uint32_t)duty_cycle * pulseCnt) / PWM_FULL_SCALE - 1; - base->SM[subModule].VAL1 = pulseCnt - 1; + base->SM[subModule].VAL0 = ((uint32_t)duty_cycle * pulseCnt) / PWM_FULL_SCALE; + base->SM[subModule].VAL1 = pulseCnt; base->SM[subModule].OCTRL = (base->SM[subModule].OCTRL & ~PWM_OCTRL_POLX_MASK) | PWM_OCTRL_POLX(!invert); - base->OUTEN |= (1U << subModule); + // Switch the output on or off. + if (duty_cycle == 0) { + base->OUTEN &= ~(1U << subModule); + } else { + base->OUTEN |= (1U << subModule); + } } #ifdef FSL_FEATURE_SOC_TMR_COUNT status_t QTMR_SetupPwm_u16(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t pwmFreqHz, - uint16_t dutyCycleU16, bool outputPolarity, uint32_t srcClock_Hz, bool is_init) { + uint32_t dutyCycleU16, bool outputPolarity, uint32_t srcClock_Hz, bool is_init) { uint32_t periodCount, highCount, lowCount, reg; - if (dutyCycleU16 >= PWM_FULL_SCALE) { - // Invalid dutycycle - return kStatus_Fail; - } - // Counter values to generate a PWM signal periodCount = ((srcClock_Hz + (pwmFreqHz - 1) / 2) / pwmFreqHz) - 2; highCount = (periodCount * dutyCycleU16) / PWM_FULL_SCALE; @@ -147,11 +157,18 @@ status_t QTMR_SetupPwm_u16(TMR_Type *base, qtmr_channel_selection_t channel, uin reg = base->CHANNEL[channel].CTRL; reg &= ~(TMR_CTRL_OUTMODE_MASK); - // Count until compare value is reached and re-initialize the counter, toggle OFLAG output - // using alternating compare register - reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ToggleOnAltCompareReg)); + if (dutyCycleU16 == 0) { + // Clear the output at the next compare + reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ClearOnCompare)); + } else if (dutyCycleU16 >= 65536) { + // Set the output at the next compare + reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_SetOnCompare)); + } else { + // Count until compare value is reached and re-initialize the counter, toggle OFLAG output + // using alternating compare register + reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ToggleOnAltCompareReg)); + } base->CHANNEL[channel].CTRL = reg; - return kStatus_Success; } #endif // FSL_FEATURE_SOC_TMR_COUNT diff --git a/ports/mimxrt/hal/pwm_backport.h b/ports/mimxrt/hal/pwm_backport.h index 516726961c..04899173e2 100644 --- a/ports/mimxrt/hal/pwm_backport.h +++ b/ports/mimxrt/hal/pwm_backport.h @@ -18,7 +18,7 @@ typedef struct _pwm_signal_param_u16 { pwm_channels_t pwmChannel; // PWM channel being configured; PWM A or PWM B - uint16_t dutyCycle_u16; // PWM pulse width, value should be between 0 to 65536 + uint32_t dutyCycle_u16; // PWM pulse width, value should be between 0 to 65536 uint16_t Center_u16; // Center of the pulse, value should be between 0 to 65536 pwm_level_select_t level; // PWM output active level select */ uint16_t deadtimeValue; // The deadtime value; only used if channel pair is operating in complementary mode @@ -27,17 +27,17 @@ typedef struct _pwm_signal_param_u16 #define PWM_FULL_SCALE (65536UL) void PWM_UpdatePwmDutycycle_u16(PWM_Type *base, pwm_submodule_t subModule, - pwm_channels_t pwmSignal, uint16_t dutyCycle, uint16_t center); + pwm_channels_t pwmSignal, uint32_t dutyCycle, uint16_t center); void PWM_SetupPwm_u16(PWM_Type *base, pwm_submodule_t subModule, pwm_signal_param_u16_t *chnlParams, uint32_t pwmFreq_Hz, uint32_t srcClock_Hz, bool output_enable); void PWM_SetupPwmx_u16(PWM_Type *base, pwm_submodule_t subModule, - uint32_t pwmFreq_Hz, uint16_t duty_cycle, uint8_t invert, uint32_t srcClock_Hz); + uint32_t pwmFreq_Hz, uint32_t duty_cycle, uint8_t invert, uint32_t srcClock_Hz); #ifdef FSL_FEATURE_SOC_TMR_COUNT status_t QTMR_SetupPwm_u16(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t pwmFreqHz, - uint16_t dutyCycleU16, bool outputPolarity, uint32_t srcClock_Hz, bool is_init); + uint32_t dutyCycleU16, bool outputPolarity, uint32_t srcClock_Hz, bool is_init); #endif // FSL_FEATURE_SOC_TMR_COUNT #endif // PWM_BACKPORT_H diff --git a/ports/mimxrt/hal/qspi_hyper_flash_config.c b/ports/mimxrt/hal/qspi_hyper_flash_config.c index f5ffbe8413..aaf2e923c1 100644 --- a/ports/mimxrt/hal/qspi_hyper_flash_config.c +++ b/ports/mimxrt/hal/qspi_hyper_flash_config.c @@ -22,6 +22,10 @@ __attribute__((section(".boot_hdr.conf"))) #pragma location = ".boot_hdr.conf" #endif +#ifndef MICROPY_HW_FLASH_CLK +#define MICROPY_HW_FLASH_CLK kFlexSpiSerialClk_133MHz +#endif + const flexspi_nor_config_t qspiflash_config = { .memConfig = { @@ -36,7 +40,7 @@ const flexspi_nor_config_t qspiflash_config = { (1u << kFlexSpiMiscOffset_DdrModeEnable) | (1u << kFlexSpiMiscOffset_WordAddressableEnable) | (1u << kFlexSpiMiscOffset_SafeConfigFreqEnable) | (1u << kFlexSpiMiscOffset_DiffClkEnable), .sflashPadType = kSerialFlash_8Pads, - .serialClkFreq = kFlexSpiSerialClk_133MHz, + .serialClkFreq = MICROPY_HW_FLASH_CLK, .sflashA1Size = MICROPY_HW_FLASH_SIZE, .dataValidTime = {16u, 16u}, .lookupTable = diff --git a/ports/mimxrt/hal/qspi_nor_flash_config.c b/ports/mimxrt/hal/qspi_nor_flash_config.c index a6bbd624ed..a8040737e5 100644 --- a/ports/mimxrt/hal/qspi_nor_flash_config.c +++ b/ports/mimxrt/hal/qspi_nor_flash_config.c @@ -28,6 +28,10 @@ __attribute__((section(".boot_hdr.conf"))) #define MICROPY_HW_FLASH_DQS kFlexSPIReadSampleClk_LoopbackFromDqsPad #endif +#ifndef MICROPY_HW_FLASH_CLK +#define MICROPY_HW_FLASH_CLK kFlexSpiSerialClk_100MHz +#endif + const flexspi_nor_config_t qspiflash_config = { .memConfig = { @@ -48,7 +52,7 @@ const flexspi_nor_config_t qspiflash_config = { // Enable DDR mode, Wordaddassable, Safe configuration, Differential clock .deviceType = kFlexSpiDeviceType_SerialNOR, .sflashPadType = kSerialFlash_4Pads, - .serialClkFreq = kFlexSpiSerialClk_100MHz, + .serialClkFreq = MICROPY_HW_FLASH_CLK, .sflashA1Size = MICROPY_HW_FLASH_SIZE, .lookupTable = { diff --git a/ports/mimxrt/irq.h b/ports/mimxrt/irq.h new file mode 100644 index 0000000000..b83eb49ffa --- /dev/null +++ b/ports/mimxrt/irq.h @@ -0,0 +1,80 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_MIMXRT_IRQ_H +#define MICROPY_INCLUDED_MIMXRT_IRQ_H + +#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003) + +static inline uint32_t query_irq(void) { + return __get_PRIMASK(); +} + +static inline uint32_t raise_irq_pri(uint32_t pri) { + uint32_t basepri = __get_BASEPRI(); + // If non-zero, the processor does not process any exception with a + // priority value greater than or equal to BASEPRI. + // When writing to BASEPRI_MAX the write goes to BASEPRI only if either: + // - Rn is non-zero and the current BASEPRI value is 0 + // - Rn is non-zero and less than the current BASEPRI value + pri <<= (8 - __NVIC_PRIO_BITS); + __ASM volatile ("msr basepri_max, %0" : : "r" (pri) : "memory"); + return basepri; +} + +// "basepri" should be the value returned from raise_irq_pri +static inline void restore_irq_pri(uint32_t basepri) { + __set_BASEPRI(basepri); +} + +// IRQ priority definitions. +// +// Lower number implies higher interrupt priority. +// +// The default priority grouping used in this port is NVIC_PRIORITYGROUP_4. +// This corresponds to 4 bits for the priority field and 0 bits for the +// sub-priority field (which means that for all intents and purposes the +// sub-priorities below are ignored). +// +// While a given interrupt is being processed, only higher priority (lower number) +// interrupts will preempt a given interrupt. If sub-priorities are active +// then the sub-priority determines the order that pending interrupts of +// a given priority are executed. This is only meaningful if 2 or more +// interrupts of the same priority are pending at the same time. +// +// The following interrupts are arranged from highest priority to lowest +// priority to make it a bit easier to figure out. + +#define IRQ_PRI_SYSTICK NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 0, 0) + +#define IRQ_PRI_OTG_HS NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 6, 0) + +#define IRQ_PRI_EXTINT NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 14, 0) + +// PENDSV should be at the lowst priority so that other interrupts complete +// before exception is raised. +#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0) + +#endif // MICROPY_INCLUDED_MIMXRT_IRQ_H diff --git a/ports/mimxrt/machine_pin.c b/ports/mimxrt/machine_pin.c index f005e38d69..3ebccb1755 100644 --- a/ports/mimxrt/machine_pin.c +++ b/ports/mimxrt/machine_pin.c @@ -34,6 +34,9 @@ #include "shared/runtime/mpirq.h" #include "extmod/virtpin.h" #include "pin.h" +#if MICROPY_PY_NETWORK_CYW43 +#include "pendsv.h" +#endif // Local functions STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); @@ -98,6 +101,16 @@ void call_handler(GPIO_Type *gpio, int gpio_nr, int pin) { if (isr & mask) { gpio->ISR = mask; // clear the ISR flag int index = GET_PIN_IRQ_INDEX(gpio_nr, pin); + #if MICROPY_PY_NETWORK_CYW43 + extern void (*cyw43_poll)(void); + const machine_pin_obj_t *pin = MICROPY_HW_WL_HOST_WAKE; + if (pin->gpio == gpio && pin->pin == (index % 32)) { + if (cyw43_poll) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll); + } + return; + } + #endif machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[index]); if (irq != NULL) { irq->flags = irq->trigger; @@ -187,6 +200,60 @@ void machine_pin_set_mode(const machine_pin_obj_t *self, uint8_t mode) { GPIO_PinInit(self->gpio, self->pin, &pin_config); } +void machine_pin_config(const machine_pin_obj_t *self, uint8_t mode, + uint8_t pull, uint8_t drive, uint8_t speed, uint8_t alt) { + (void)speed; + gpio_pin_config_t pin_config = {0}; + + if (IS_GPIO_IT_MODE(mode)) { + if (mode == PIN_MODE_IT_FALLING) { + pin_config.interruptMode = kGPIO_IntFallingEdge; + } else if (mode == PIN_MODE_IT_RISING) { + pin_config.interruptMode = kGPIO_IntRisingEdge; + } else if (mode == PIN_MODE_IT_BOTH) { + pin_config.interruptMode = kGPIO_IntRisingOrFallingEdge; + } + // Set pad config mode to input. + mode = PIN_MODE_IN; + } + + if (mode == PIN_MODE_IN) { + pin_config.direction = kGPIO_DigitalInput; + } else { + pin_config.direction = kGPIO_DigitalOutput; + } + + if (mode != PIN_MODE_ALT) { + // GPIO is always ALT5 + alt = PIN_AF_MODE_ALT5; + } + + const machine_pin_af_obj_t *af = pin_find_af(self, alt); + if (af == NULL) { + return; + } + + // Configure the pad. + uint32_t pad_config = pin_generate_config(pull, mode, drive, self->configRegister); + IOMUXC_SetPinMux(self->muxRegister, alt, af->input_register, af->input_daisy, self->configRegister, 0U); + IOMUXC_SetPinConfig(self->muxRegister, alt, af->input_register, af->input_daisy, self->configRegister, pad_config); + + // Initialize the pin. + GPIO_PinInit(self->gpio, self->pin, &pin_config); + + // Configure interrupt (if enabled). + if (pin_config.interruptMode != kGPIO_NoIntmode) { + uint32_t gpio_nr = GPIO_get_instance(self->gpio); + uint32_t irq_num = self->pin < 16 ? GPIO_combined_low_irqs[gpio_nr] : GPIO_combined_high_irqs[gpio_nr]; + + GPIO_PortEnableInterrupts(self->gpio, 1U << self->pin); + GPIO_PortClearInterruptFlags(self->gpio, ~0); + + NVIC_SetPriority(irq_num, IRQ_PRI_EXTINT); + EnableIRQ(irq_num); + } +} + STATIC mp_obj_t machine_pin_obj_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); machine_pin_obj_t *self = self_in; @@ -337,6 +404,13 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_ } machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[index]); + if (args[ARG_handler].u_obj == mp_const_none) { + // remove the IRQ from the table, leave it to gc to free it. + GPIO_PortDisableInterrupts(self->gpio, 1U << self->pin); + MP_STATE_PORT(machine_pin_irq_objects[index]) = NULL; + return mp_const_none; + } + // Allocate the IRQ object if it doesn't already exist. if (irq == NULL) { irq = m_new_obj(machine_pin_irq_obj_t); @@ -371,9 +445,9 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_ GPIO_PinSetInterruptConfig(self->gpio, self->pin, irq->trigger); // Enable the specific Pin interrupt GPIO_PortEnableInterrupts(self->gpio, 1U << self->pin); + // Enable LEVEL1 interrupt again + EnableIRQ(irq_num); } - // Enable LEVEL1 interrupt again - EnableIRQ(irq_num); } return MP_OBJ_FROM_PTR(irq); diff --git a/ports/mimxrt/machine_uart.c b/ports/mimxrt/machine_uart.c index ac9351da8a..fba2b7fe30 100644 --- a/ports/mimxrt/machine_uart.c +++ b/ports/mimxrt/machine_uart.c @@ -33,6 +33,7 @@ #include "fsl_lpuart.h" #include "fsl_iomuxc.h" #include CLOCK_CONFIG_H +#include "modmachine.h" #include "pin.h" #define DEFAULT_UART_BAUDRATE (115200) @@ -40,6 +41,10 @@ #define MIN_BUFFER_SIZE (32) #define MAX_BUFFER_SIZE (32766) +#define UART_HWCONTROL_RTS (1) +#define UART_HWCONTROL_CTS (2) +#define UART_HWCONTROL_MASK (UART_HWCONTROL_RTS | UART_HWCONTROL_CTS) + #define UART_INVERT_TX (1) #define UART_INVERT_RX (2) #define UART_INVERT_MASK (UART_INVERT_TX | UART_INVERT_RX) @@ -74,12 +79,18 @@ STATIC LPUART_Type *uart_base_ptr_table[] = LPUART_BASE_PTRS; static const iomux_table_t iomux_table_uart[] = { IOMUX_TABLE_UART }; +static const iomux_table_t iomux_table_uart_cts_rts[] = { + IOMUX_TABLE_UART_CTS_RTS +}; STATIC const char *_parity_name[] = {"None", "", "0", "1"}; // Is defined as 0, 2, 3 STATIC const char *_invert_name[] = {"None", "INV_TX", "INV_RX", "INV_TX|INV_RX"}; +STATIC const char *_flow_name[] = {"None", "RTS", "CTS", "RTS|CTS"}; #define RX (iomux_table_uart[index + 1]) #define TX (iomux_table_uart[index]) +#define RTS (iomux_table_uart_cts_rts[index + 1]) +#define CTS (iomux_table_uart_cts_rts[index]) bool lpuart_set_iomux(int8_t uart) { int index = (uart - 1) * 2; @@ -98,6 +109,33 @@ bool lpuart_set_iomux(int8_t uart) { } } +bool lpuart_set_iomux_rts(int8_t uart) { + MP_STATIC_ASSERT(MP_ARRAY_SIZE(iomux_table_uart) == MP_ARRAY_SIZE(iomux_table_uart_cts_rts)); + int index = (uart - 1) * 2; + + if (RTS.muxRegister != 0) { + IOMUXC_SetPinMux(RTS.muxRegister, RTS.muxMode, RTS.inputRegister, RTS.inputDaisy, RTS.configRegister, 0U); + IOMUXC_SetPinConfig(RTS.muxRegister, RTS.muxMode, RTS.inputRegister, RTS.inputDaisy, RTS.configRegister, + pin_generate_config(PIN_PULL_UP_100K, PIN_MODE_OUT, PIN_DRIVE_6, RTS.configRegister)); + return true; + } else { + return false; + } +} + +bool lpuart_set_iomux_cts(int8_t uart) { + int index = (uart - 1) * 2; + + if (CTS.muxRegister != 0) { + IOMUXC_SetPinMux(CTS.muxRegister, CTS.muxMode, CTS.inputRegister, CTS.inputDaisy, CTS.configRegister, 0U); + IOMUXC_SetPinConfig(CTS.muxRegister, CTS.muxMode, CTS.inputRegister, CTS.inputDaisy, CTS.configRegister, + pin_generate_config(PIN_PULL_UP_100K, PIN_MODE_IN, PIN_DRIVE_6, CTS.configRegister)); + return true; + } else { + return false; + } +} + void LPUART_UserCallback(LPUART_Type *base, lpuart_handle_t *handle, status_t status, void *userData) { machine_uart_obj_t *self = userData; if (kStatus_LPUART_TxIdle == status) { @@ -109,24 +147,54 @@ void LPUART_UserCallback(LPUART_Type *base, lpuart_handle_t *handle, status_t st } } +static void machine_uart_ensure_active(machine_uart_obj_t *uart) { + if (uart->lpuart->CTRL == 0) { + mp_raise_OSError(EIO); + } +} + +#if !defined(MIMXRT117x_SERIES) +static inline void uart_set_clock_divider(uint32_t baudrate) { + // For baud rates < 460800 divide the clock by 10, supporting baud rates down to 50 baud. + if (baudrate >= 460800) { + CLOCK_SetDiv(kCLOCK_UartDiv, 0); + } else { + CLOCK_SetDiv(kCLOCK_UartDiv, 9); + } +} +#endif + +void machine_uart_set_baudrate(mp_obj_t uart_in, uint32_t baudrate) { + machine_uart_obj_t *uart = MP_OBJ_TO_PTR(uart_in); + #if defined(MIMXRT117x_SERIES) + // Use the Lpuart1 clock value, which is set for All UART devices. + LPUART_SetBaudRate(uart->lpuart, baudrate, CLOCK_GetRootClockFreq(kCLOCK_Root_Lpuart1)); + #else + uart_set_clock_divider(baudrate); + LPUART_SetBaudRate(uart->lpuart, baudrate, CLOCK_GetClockRootFreq(kCLOCK_UartClkRoot)); + #endif +} + STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, " + mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, flow=%s, " "rxbuf=%d, txbuf=%d, timeout=%u, timeout_char=%u, invert=%s)", self->id, self->config.baudRate_Bps, 8 - self->config.dataBitsCount, _parity_name[self->config.parityMode], self->config.stopBitCount + 1, + _flow_name[(self->config.enableTxCTS << 1) | self->config.enableRxRTS], self->handle.rxRingBufferSize, self->txbuf_len, self->timeout, self->timeout_char, _invert_name[self->invert]); } STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, + enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_flow, ARG_timeout, ARG_timeout_char, ARG_invert, ARG_rxbuf, ARG_txbuf}; static const mp_arg_t allowed_args[] = { { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_bits, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_parity, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_INT(-1)} }, { MP_QSTR_stop, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 } }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, @@ -164,6 +232,27 @@ STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args self->config.stopBitCount = args[ARG_stop].u_int - 1; } + // Set flow if configured. + if (args[ARG_flow].u_int >= 0) { + if (args[ARG_flow].u_int & ~UART_HWCONTROL_MASK) { + mp_raise_ValueError(MP_ERROR_TEXT("bad flow mask")); + } + + if (args[ARG_flow].u_int & UART_HWCONTROL_RTS) { + if (!lpuart_set_iomux_rts(uart_index_table[self->id])) { + mp_raise_ValueError(MP_ERROR_TEXT("rts not available")); + } + self->config.enableRxRTS = true; + } + + if (args[ARG_flow].u_int & UART_HWCONTROL_CTS) { + if (!lpuart_set_iomux_cts(uart_index_table[self->id])) { + mp_raise_ValueError(MP_ERROR_TEXT("cts not available")); + } + self->config.enableTxCTS = true; + } + } + // Set timeout if configured. if (args[ARG_timeout].u_int >= 0) { self->timeout = args[ARG_timeout].u_int; @@ -222,7 +311,13 @@ STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args self->timeout_char = min_timeout_char; } - LPUART_Init(self->lpuart, &self->config, BOARD_BOOTCLOCKRUN_UART_CLK_ROOT); + #if defined(MIMXRT117x_SERIES) + // Use the Lpuart1 clock value, which is set for All UART devices. + LPUART_Init(self->lpuart, &self->config, CLOCK_GetRootClockFreq(kCLOCK_Root_Lpuart1)); + #else + uart_set_clock_divider(self->config.baudRate_Bps); + LPUART_Init(self->lpuart, &self->config, CLOCK_GetClockRootFreq(kCLOCK_UartClkRoot)); + #endif LPUART_TransferCreateHandle(self->lpuart, &self->handle, LPUART_UserCallback, self); uint8_t *buffer = m_new(uint8_t, rxbuf_len + 1); LPUART_TransferStartRingBuffer(self->lpuart, &self->handle, buffer, rxbuf_len); @@ -288,8 +383,17 @@ STATIC mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t } MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init); +// uart.deinit() +STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + LPUART_SoftwareReset(self->lpuart); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit); + STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + machine_uart_ensure_active(self); size_t count = LPUART_TransferGetRxRingBufferLength(self->lpuart, &self->handle); return MP_OBJ_NEW_SMALL_INT(count); } @@ -297,6 +401,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any); STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + machine_uart_ensure_active(self); self->lpuart->CTRL |= 1 << LPUART_CTRL_SBK_SHIFT; // Set SBK bit self->lpuart->CTRL &= ~LPUART_CTRL_SBK_MASK; // Clear SBK bit return mp_const_none; @@ -314,8 +419,18 @@ STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone); +// Reset all defined UARTs +void machine_uart_deinit_all(void) { + for (int i = 0; i < MICROPY_HW_UART_NUM; i++) { + if (uart_index_table[i] != 0) { + LPUART_SoftwareReset(uart_base_ptr_table[uart_index_table[i]]); + } + } +} + STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) }, @@ -328,6 +443,9 @@ STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) }, { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) }, + { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) }, + { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HWCONTROL_CTS) }, + { MP_ROM_QSTR(MP_QSTR_INV_TX), MP_ROM_INT(UART_INVERT_TX) }, { MP_ROM_QSTR(MP_QSTR_INV_RX), MP_ROM_INT(UART_INVERT_RX) }, @@ -343,6 +461,8 @@ STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t siz size_t avail; size_t nget; + machine_uart_ensure_active(self); + for (size_t received = 0; received < size;) { // Wait for the first/next character. while ((avail = LPUART_TransferGetRxRingBufferLength(self->lpuart, &self->handle)) <= 0) { @@ -375,6 +495,8 @@ STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uin size_t offset = 0; uint8_t fifo_size = FSL_FEATURE_LPUART_FIFO_SIZEn(0); + machine_uart_ensure_active(self); + // First check if a previous transfer is still ongoing, // then wait at least the number of remaining character times. t = ticks_us64() + (uint64_t)(self->handle.txDataSize + fifo_size) * (13000000 / self->config.baudRate_Bps + 1000); @@ -429,6 +551,7 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint machine_uart_obj_t *self = self_in; mp_uint_t ret; if (request == MP_STREAM_POLL) { + machine_uart_ensure_active(self); uintptr_t flags = arg; ret = 0; if (flags & MP_STREAM_POLL_RD) { diff --git a/ports/mimxrt/main.c b/ports/mimxrt/main.c index 9ac46e4814..993e598185 100644 --- a/ports/mimxrt/main.c +++ b/ports/mimxrt/main.c @@ -43,7 +43,16 @@ #if MICROPY_PY_LWIP #include "lwip/init.h" #include "lwip/apps/mdns.h" +#if MICROPY_PY_NETWORK_CYW43 +#include "lib/cyw43-driver/src/cyw43.h" #endif +#endif + +#if MICROPY_PY_BLUETOOTH +#include "mpbthciport.h" +#include "extmod/modbluetooth.h" +#endif + #include "systick.h" #include "extmod/modnetwork.h" @@ -68,6 +77,20 @@ int main(void) { systick_enable_dispatch(SYSTICK_DISPATCH_LWIP, mod_network_lwip_poll_wrapper); #endif + #if MICROPY_PY_BLUETOOTH + mp_bluetooth_hci_init(); + #endif + + #if MICROPY_PY_NETWORK_CYW43 + { + cyw43_init(&cyw43_state); + uint8_t buf[8]; + memcpy(&buf[0], "PYBD", 4); + mp_hal_get_mac_ascii(MP_HAL_MAC_WLAN0, 8, 4, (char *)&buf[4]); + cyw43_wifi_ap_set_ssid(&cyw43_state, 8, buf); + cyw43_wifi_ap_set_password(&cyw43_state, 8, (const uint8_t *)"pybd0123"); + } + #endif for (;;) { #if defined(MICROPY_HW_LED1) @@ -121,9 +144,13 @@ int main(void) { #if MICROPY_PY_MACHINE_I2S machine_i2s_deinit_all(); #endif + #if MICROPY_PY_BLUETOOTH + mp_bluetooth_deinit(); + #endif #if MICROPY_PY_NETWORK mod_network_deinit(); #endif + machine_uart_deinit_all(); machine_pwm_deinit_all(); soft_timer_deinit(); gc_sweep_all(); diff --git a/ports/mimxrt/modmachine.h b/ports/mimxrt/modmachine.h index ed1c4e34a0..904419df2c 100644 --- a/ports/mimxrt/modmachine.h +++ b/ports/mimxrt/modmachine.h @@ -43,6 +43,7 @@ extern const mp_obj_type_t machine_wdt_type; void machine_adc_init(void); void machine_pin_irq_deinit(void); void machine_pwm_deinit_all(void); +void machine_uart_deinit_all(void); void machine_timer_init_PIT(void); void machine_sdcard_init0(void); void mimxrt_sdram_init(void); @@ -50,4 +51,6 @@ void machine_i2s_init0(); void machine_i2s_deinit_all(void); void machine_rtc_start(void); +void machine_uart_set_baudrate(mp_obj_t uart, uint32_t baudrate); + #endif // MICROPY_INCLUDED_MIMXRT_MODMACHINE_H diff --git a/ports/mimxrt/mpbthciport.c b/ports/mimxrt/mpbthciport.c new file mode 100644 index 0000000000..d8b3841364 --- /dev/null +++ b/ports/mimxrt/mpbthciport.c @@ -0,0 +1,191 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2021 Damien P. George + * Copyright (c) 2023 Ibrahim Abdelkader + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/stream.h" +#include "py/mphal.h" +#include "extmod/modbluetooth.h" +#include "extmod/mpbthci.h" +#include "shared/runtime/softtimer.h" +#include "modmachine.h" +#include "mpbthciport.h" + +#if MICROPY_PY_BLUETOOTH + +#define DEBUG_printf(...) // mp_printf(&mp_plat_print, "mpbthciport.c: " __VA_ARGS__) +#define ERROR_printf(...) mp_printf(&mp_plat_print, "mpbthciport.c: " __VA_ARGS__) + +uint8_t mp_bluetooth_hci_cmd_buf[4 + 256]; + +STATIC mp_sched_node_t mp_bluetooth_hci_sched_node; +STATIC soft_timer_entry_t mp_bluetooth_hci_soft_timer; + +STATIC void mp_bluetooth_hci_soft_timer_callback(soft_timer_entry_t *self) { + mp_bluetooth_hci_poll_now(); +} + +void mp_bluetooth_hci_init(void) { + soft_timer_static_init( + &mp_bluetooth_hci_soft_timer, + SOFT_TIMER_MODE_ONE_SHOT, + 0, + mp_bluetooth_hci_soft_timer_callback + ); +} + +STATIC void mp_bluetooth_hci_start_polling(void) { + mp_bluetooth_hci_poll_now(); +} + +void mp_bluetooth_hci_poll_in_ms(uint32_t ms) { + soft_timer_reinsert(&mp_bluetooth_hci_soft_timer, ms); +} + +// For synchronous mode, we run all BLE stack code inside a scheduled task. +STATIC void run_events_scheduled_task(mp_sched_node_t *node) { + // This will process all buffered HCI UART data, and run any callouts or events. + mp_bluetooth_hci_poll(); +} + +// Called periodically (systick) or directly (e.g. UART RX IRQ) in order to +// request that processing happens ASAP in the scheduler. +void mp_bluetooth_hci_poll_now(void) { + mp_sched_schedule_node(&mp_bluetooth_hci_sched_node, run_events_scheduled_task); +} + +mp_obj_t mp_bthci_uart; + +int mp_bluetooth_hci_uart_init(uint32_t port, uint32_t baudrate) { + DEBUG_printf("mp_bluetooth_hci_uart_init\n"); + + mp_obj_t args[] = { + MP_OBJ_NEW_SMALL_INT(port), + MP_OBJ_NEW_QSTR(MP_QSTR_baudrate), MP_OBJ_NEW_SMALL_INT(baudrate), + MP_OBJ_NEW_QSTR(MP_QSTR_timeout), MP_OBJ_NEW_SMALL_INT(200), + MP_OBJ_NEW_QSTR(MP_QSTR_timeout_char), MP_OBJ_NEW_SMALL_INT(200), + MP_OBJ_NEW_QSTR(MP_QSTR_txbuf), MP_OBJ_NEW_SMALL_INT(768), + MP_OBJ_NEW_QSTR(MP_QSTR_rxbuf), MP_OBJ_NEW_SMALL_INT(768), + }; + + mp_bthci_uart = MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, make_new)((mp_obj_t)&machine_uart_type, 1, 5, args); + MP_STATE_PORT(mp_bthci_uart) = mp_bthci_uart; + + // Start the HCI polling to process any initial events/packets. + mp_bluetooth_hci_start_polling(); + return 0; +} + +int mp_bluetooth_hci_uart_deinit(void) { + DEBUG_printf("mp_bluetooth_hci_uart_deinit\n"); + mp_bthci_uart = MP_OBJ_NULL; + return 0; +} + +int mp_bluetooth_hci_uart_set_baudrate(uint32_t baudrate) { + DEBUG_printf("mp_bluetooth_hci_uart_set_baudrate(%lu)\n", baudrate); + if (mp_bthci_uart != MP_OBJ_NULL) { + machine_uart_set_baudrate(mp_bthci_uart, baudrate); + } + return 0; +} + +int mp_bluetooth_hci_uart_any(void) { + int errcode = 0; + const mp_stream_p_t *proto = (mp_stream_p_t *)MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, protocol); + + mp_uint_t ret = proto->ioctl(mp_bthci_uart, MP_STREAM_POLL, MP_STREAM_POLL_RD, &errcode); + if (errcode != 0) { + ERROR_printf("Uart ioctl failed to poll UART %d\n", errcode); + return -1; + } + return ret & MP_STREAM_POLL_RD; +} + +int mp_bluetooth_hci_uart_write(const uint8_t *buf, size_t len) { + DEBUG_printf("mp_bluetooth_hci_uart_write\n"); + + int errcode = 0; + const mp_stream_p_t *proto = (mp_stream_p_t *)MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, protocol); + + mp_bluetooth_hci_controller_wakeup(); + + if (proto->write(mp_bthci_uart, (void *)buf, len, &errcode) < 0) { + ERROR_printf("mp_bluetooth_hci_uart_write: failed to write to UART %d\n", errcode); + } + return 0; +} + +// This function expects the controller to be in the wake state via a previous call +// to mp_bluetooth_hci_controller_woken. +int mp_bluetooth_hci_uart_readchar(void) { + DEBUG_printf("mp_bluetooth_hci_uart_readchar\n"); + if (mp_bluetooth_hci_uart_any()) { + int errcode = 0; + uint8_t buf = 0; + const mp_stream_p_t *proto = (mp_stream_p_t *)MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, protocol); + if (proto->read(mp_bthci_uart, (void *)&buf, 1, &errcode) < 0) { + ERROR_printf("mp_bluetooth_hci_uart_readchar: failed to read UART %d\n", errcode); + return -1; + } + return buf; + } else { + DEBUG_printf("mp_bluetooth_hci_uart_readchar: not ready\n"); + return -1; + } +} + +// Default (weak) implementation of the HCI controller interface. +// A driver (e.g. cywbt43.c) can override these for controller-specific +// functionality (i.e. power management). +MP_WEAK int mp_bluetooth_hci_controller_init(void) { + DEBUG_printf("mp_bluetooth_hci_controller_init (default)\n"); + return 0; +} + +MP_WEAK int mp_bluetooth_hci_controller_deinit(void) { + DEBUG_printf("mp_bluetooth_hci_controller_deinit (default)\n"); + return 0; +} + +MP_WEAK int mp_bluetooth_hci_controller_sleep_maybe(void) { + DEBUG_printf("mp_bluetooth_hci_controller_sleep_maybe (default)\n"); + return 0; +} + +MP_WEAK bool mp_bluetooth_hci_controller_woken(void) { + DEBUG_printf("mp_bluetooth_hci_controller_woken (default)\n"); + return true; +} + +MP_WEAK int mp_bluetooth_hci_controller_wakeup(void) { + DEBUG_printf("mp_bluetooth_hci_controller_wakeup (default)\n"); + return 0; +} + +MP_REGISTER_ROOT_POINTER(mp_obj_t mp_bthci_uart); + +#endif // MICROPY_PY_BLUETOOTH diff --git a/ports/mimxrt/mpbthciport.h b/ports/mimxrt/mpbthciport.h new file mode 100644 index 0000000000..124c85dae5 --- /dev/null +++ b/ports/mimxrt/mpbthciport.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2021 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_MIMXRT_MPBTHCIPORT_H +#define MICROPY_INCLUDED_MIMXRT_MPBTHCIPORT_H + +// Initialise the HCI subsystem (should be called once, early on). +void mp_bluetooth_hci_init(void); + +// Poll the HCI now, or after a certain timeout. +void mp_bluetooth_hci_poll_now(void); +void mp_bluetooth_hci_poll_in_ms(uint32_t ms); + +// Must be provided by the stack bindings (e.g. mpnimbleport.c or mpbtstackport.c). +// Request new data from the uart and pass to the stack, and run pending events/callouts. +// This is a low-level function and should not be called directly, use +// mp_bluetooth_hci_poll_now/mp_bluetooth_hci_poll_in_ms instead. +void mp_bluetooth_hci_poll(void); + +#endif // MICROPY_INCLUDED_MIMXRT_MPBTHCIPORT_H diff --git a/ports/mimxrt/mpconfigport.h b/ports/mimxrt/mpconfigport.h index 52054c5d4d..fb4acede59 100644 --- a/ports/mimxrt/mpconfigport.h +++ b/ports/mimxrt/mpconfigport.h @@ -59,6 +59,7 @@ uint32_t trng_random_u32(void); #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_SCHEDULER_DEPTH (8) +#define MICROPY_SCHEDULER_STATIC_NODES (1) #define MICROPY_VFS (1) // Control over Python builtins @@ -67,7 +68,6 @@ uint32_t trng_random_u32(void); // Extended modules #define MICROPY_EPOCH_IS_1970 (1) -#define MICROPY_PY_SSL_FINALISER (MICROPY_PY_SSL) #define MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME (1) #define MICROPY_PY_TIME_TIME_TIME_NS (1) #define MICROPY_PY_TIME_INCLUDEFILE "ports/mimxrt/modtime.c" @@ -110,7 +110,6 @@ uint32_t trng_random_u32(void); #define MICROPY_PY_WEBSOCKET (MICROPY_PY_LWIP) #define MICROPY_PY_WEBREPL (MICROPY_PY_LWIP) #define MICROPY_PY_LWIP_SOCK_RAW (MICROPY_PY_LWIP) -#define MICROPY_PY_SSL_FINALISER (MICROPY_PY_SSL) // #define MICROPY_PY_HASHLIB_MD5 (MICROPY_PY_SSL) #define MICROPY_PY_HASHLIB_SHA1 (MICROPY_PY_SSL) // #define MICROPY_PY_CRYPTOLIB (MICROPY_PY_SSL) @@ -120,6 +119,14 @@ uint32_t trng_random_u32(void); #define MICROPY_PY_LWIP_REENTER MICROPY_PY_PENDSV_REENTER #define MICROPY_PY_LWIP_EXIT MICROPY_PY_PENDSV_EXIT +#ifndef MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE +#define MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE (1) +#endif + +#ifndef MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS +#define MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS (MICROPY_BLUETOOTH_NIMBLE) +#endif + #ifndef MICROPY_PY_NETWORK_HOSTNAME_DEFAULT #define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-mimxrt" #endif @@ -145,23 +152,6 @@ __attribute__((always_inline)) static inline uint32_t disable_irq(void) { return state; } -static inline uint32_t raise_irq_pri(uint32_t pri) { - uint32_t basepri = __get_BASEPRI(); - // If non-zero, the processor does not process any exception with a - // priority value greater than or equal to BASEPRI. - // When writing to BASEPRI_MAX the write goes to BASEPRI only if either: - // - Rn is non-zero and the current BASEPRI value is 0 - // - Rn is non-zero and less than the current BASEPRI value - pri <<= (8 - __NVIC_PRIO_BITS); - __ASM volatile ("msr basepri_max, %0" : : "r" (pri) : "memory"); - return basepri; -} - -// "basepri" should be the value returned from raise_irq_pri -static inline void restore_irq_pri(uint32_t basepri) { - __set_BASEPRI(basepri); -} - #define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() #define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state) @@ -172,12 +162,20 @@ extern const struct _mp_obj_type_t network_lan_type; #define MICROPY_HW_NIC_ETH #endif +#if MICROPY_PY_NETWORK_CYW43 +extern const struct _mp_obj_type_t mp_network_cyw43_type; +#define MICROPY_HW_NIC_CYW43 { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mp_network_cyw43_type) }, +#else +#define MICROPY_HW_NIC_CYW43 +#endif + #ifndef MICROPY_BOARD_NETWORK_INTERFACES #define MICROPY_BOARD_NETWORK_INTERFACES #endif #define MICROPY_PORT_NETWORK_INTERFACES \ MICROPY_HW_NIC_ETH \ + MICROPY_HW_NIC_CYW43 \ MICROPY_BOARD_NETWORK_INTERFACES \ #ifndef MICROPY_BOARD_ROOT_POINTERS diff --git a/ports/mimxrt/mphalport.h b/ports/mimxrt/mphalport.h index ba7e1cfa94..36eb387798 100644 --- a/ports/mimxrt/mphalport.h +++ b/ports/mimxrt/mphalport.h @@ -31,6 +31,7 @@ #include "ticks.h" #include "py/ringbuf.h" #include "pin.h" +#include "irq.h" #include "fsl_clock.h" #define MICROPY_HAL_VERSION "2.8.0" @@ -38,6 +39,25 @@ #define MICROPY_HW_USB_CDC_TX_TIMEOUT (500) #define MP_HAL_PIN_FMT "%q" +#define MP_HAL_PIN_MODE_INPUT PIN_MODE_IN +#define MP_HAL_PIN_MODE_OUTPUT PIN_MODE_OUT +#define MP_HAL_PIN_MODE_ALT PIN_MODE_ALT +#define MP_HAL_PIN_MODE_OPEN_DRAIN PIN_MODE_OPEN_DRAIN + +#define MP_HAL_PIN_PULL_NONE PIN_PULL_DISABLED +#define MP_HAL_PIN_PULL_UP PIN_PULL_UP_100K +#define MP_HAL_PIN_PULL_DOWN PIN_PULL_DOWN_100K + +#define MP_HAL_PIN_SPEED_LOW (0) +#define MP_HAL_PIN_SPEED_MEDIUM (1) +#define MP_HAL_PIN_SPEED_HIGH (2) +#define MP_HAL_PIN_SPEED_VERY_HIGH (3) + +#define MP_HAL_PIN_TRIGGER_NONE kGPIO_NoIntmode +#define MP_HAL_PIN_TRIGGER_FALL kGPIO_IntFallingEdge +#define MP_HAL_PIN_TRIGGER_RISE kGPIO_IntRisingEdge +#define MP_HAL_PIN_TRIGGER_RISE_FALL kGPIO_IntRisingOrFallingEdge + extern ringbuf_t stdin_ringbuf; // Define an alias for systick_ms, because the shared softtimer.c uses diff --git a/ports/mimxrt/mpnetworkport.c b/ports/mimxrt/mpnetworkport.c index 2e6a49b90e..2ca3426197 100644 --- a/ports/mimxrt/mpnetworkport.c +++ b/ports/mimxrt/mpnetworkport.c @@ -43,6 +43,11 @@ #include "lwip/dhcp.h" #include "lwip/apps/mdns.h" +#if MICROPY_PY_NETWORK_CYW43 +#include "extmod/network_cyw43.h" +#include "lib/cyw43-driver/src/cyw43.h" +#endif + // Poll lwIP every 128ms #define LWIP_TICK(tick) (((tick) & ~(SYSTICK_DISPATCH_NUM_SLOTS - 1) & 0x7f) == 0) @@ -59,6 +64,16 @@ void mod_network_lwip_poll_wrapper(uint32_t ticks_ms) { if (LWIP_TICK(ticks_ms)) { pendsv_schedule_dispatch(PENDSV_DISPATCH_LWIP, pyb_lwip_poll); } + + #if MICROPY_PY_NETWORK_CYW43 + if (cyw43_poll) { + if (cyw43_sleep != 0) { + if (--cyw43_sleep == 0) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll); + } + } + } + #endif } #endif // MICROPY_PY_LWIP diff --git a/ports/mimxrt/mpnimbleport.c b/ports/mimxrt/mpnimbleport.c new file mode 100644 index 0000000000..e2d39e271c --- /dev/null +++ b/ports/mimxrt/mpnimbleport.c @@ -0,0 +1,78 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Jim Mussared + * Copyright (c) 2020 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/mperrno.h" +#include "py/mphal.h" + +#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE + +#define DEBUG_printf(...) // printf("mpnimbleport.c: " __VA_ARGS__) + +#include "host/ble_hs.h" +#include "nimble/nimble_npl.h" + +#include "extmod/mpbthci.h" +#include "extmod/modbluetooth.h" +#include "extmod/nimble/modbluetooth_nimble.h" +#include "extmod/nimble/hal/hal_uart.h" +#include "mpbthciport.h" + +// Get any pending data from the UART and send it to NimBLE's HCI buffers. +// Any further processing by NimBLE will be run via its event queue. +void mp_bluetooth_hci_poll(void) { + if (mp_bluetooth_nimble_ble_state >= MP_BLUETOOTH_NIMBLE_BLE_STATE_WAITING_FOR_SYNC) { + // DEBUG_printf("mp_bluetooth_hci_poll_uart %d\n", mp_bluetooth_nimble_ble_state); + + // Run any timers. + mp_bluetooth_nimble_os_callout_process(); + + // Process incoming UART data, and run events as they are generated. + mp_bluetooth_nimble_hci_uart_process(true); + + // Run any remaining events (e.g. if there was no UART data). + mp_bluetooth_nimble_os_eventq_run_all(); + } + + if (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) { + // Call this function again in 128ms to check for new events. + // TODO: improve this by only calling back when needed. + mp_bluetooth_hci_poll_in_ms(128); + } +} + +// --- Port-specific helpers for the generic NimBLE bindings. ----------------- + +void mp_bluetooth_nimble_hci_uart_wfi(void) { + __WFI(); + + // This is called while NimBLE is waiting in ble_npl_sem_pend, i.e. waiting for an HCI ACK. + // Do not need to run events here (it must not invoke Python code), only processing incoming HCI data. + mp_bluetooth_nimble_hci_uart_process(false); +} + +#endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE diff --git a/ports/mimxrt/mpnimbleport.h b/ports/mimxrt/mpnimbleport.h new file mode 100644 index 0000000000..78f4fc9b00 --- /dev/null +++ b/ports/mimxrt/mpnimbleport.h @@ -0,0 +1,30 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Jim Mussared + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_MIMXRT_NIMBLE_PORT_H +#define MICROPY_INCLUDED_MIMXRT_NIMBLE_PORT_H + +#endif // MICROPY_INCLUDED_MIMXRT_NIMBLE_PORT_H diff --git a/ports/mimxrt/pendsv.c b/ports/mimxrt/pendsv.c index 11f2ef5e1c..46d13a5aca 100644 --- a/ports/mimxrt/pendsv.c +++ b/ports/mimxrt/pendsv.c @@ -28,9 +28,7 @@ #include "py/runtime.h" #include "pendsv.h" - -#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003) -#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0) +#include "irq.h" #if defined(PENDSV_DISPATCH_NUM_SLOTS) pendsv_dispatch_t pendsv_dispatch_table[PENDSV_DISPATCH_NUM_SLOTS]; diff --git a/ports/mimxrt/pendsv.h b/ports/mimxrt/pendsv.h index e68f487fb4..f3369b07fe 100644 --- a/ports/mimxrt/pendsv.h +++ b/ports/mimxrt/pendsv.h @@ -31,6 +31,9 @@ enum { #if MICROPY_PY_NETWORK && MICROPY_PY_LWIP PENDSV_DISPATCH_LWIP, #endif + #if MICROPY_PY_NETWORK_CYW43 + PENDSV_DISPATCH_CYW43, + #endif MICROPY_BOARD_PENDSV_ENTRIES PENDSV_DISPATCH_MAX }; diff --git a/ports/mimxrt/pin.h b/ports/mimxrt/pin.h index 63db55f8a7..aa86f05e82 100644 --- a/ports/mimxrt/pin.h +++ b/ports/mimxrt/pin.h @@ -39,6 +39,10 @@ ((MODE) == PIN_MODE_OPEN_DRAIN) || \ ((MODE) == PIN_MODE_ALT)) +#define IS_GPIO_IT_MODE(MODE) (((MODE) == PIN_MODE_IT_RISING) || \ + ((MODE) == PIN_MODE_IT_FALLING) || \ + ((MODE) == PIN_MODE_IT_BOTH)) + #define IS_GPIO_DRIVE(DRIVE) (((DRIVE) == PIN_DRIVE_OFF) || \ ((DRIVE) == PIN_DRIVE_0) || \ ((DRIVE) == PIN_DRIVE_1) || \ @@ -56,6 +60,9 @@ enum { PIN_MODE_OPEN_DRAIN, PIN_MODE_ALT, PIN_MODE_SKIP, + PIN_MODE_IT_RISING, + PIN_MODE_IT_FALLING, + PIN_MODE_IT_BOTH, }; enum { @@ -161,6 +168,8 @@ const machine_pin_af_obj_t *pin_find_af(const machine_pin_obj_t *pin, uint8_t fn const machine_pin_af_obj_t *pin_find_af_by_index(const machine_pin_obj_t *pin, mp_uint_t af_idx); const machine_pin_af_obj_t *pin_find_af_by_name(const machine_pin_obj_t *pin, const char *name); void machine_pin_set_mode(const machine_pin_obj_t *pin, uint8_t mode); +void machine_pin_config(const machine_pin_obj_t *self, uint8_t mode, + uint8_t pull, uint8_t drive, uint8_t speed, uint8_t alt); uint32_t pin_generate_config(const uint32_t pull, const uint32_t mode, const uint32_t drive, uint32_t config_register); #endif // MICROPY_INCLUDED_MIMXRT_PIN_H diff --git a/ports/mimxrt/sdio.c b/ports/mimxrt/sdio.c new file mode 100644 index 0000000000..d97fef9e51 --- /dev/null +++ b/ports/mimxrt/sdio.c @@ -0,0 +1,334 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Ibrahim Abdelkader + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include "py/mperrno.h" +#include "py/mphal.h" +#include "pin.h" +#include "pendsv.h" + +#if MICROPY_PY_NETWORK_CYW43 + +#include "fsl_usdhc.h" +#include "fsl_iomuxc.h" + +#if MICROPY_HW_SDIO_SDMMC == 1 +#define SDMMC USDHC1 +#define SDMMC_IRQn USDHC1_IRQn +#define SDMMC_CLOCK_DIV kCLOCK_Usdhc1Div +#define SDMMC_CLOCK_MUX kCLOCK_Usdhc1Mux +#ifndef MICROPY_HW_SDIO_CLK_ALT +#define MICROPY_HW_SDIO_CMD_ALT (0) +#define MICROPY_HW_SDIO_CLK_ALT (0) +#define MICROPY_HW_SDIO_D0_ALT (0) +#define MICROPY_HW_SDIO_D1_ALT (0) +#define MICROPY_HW_SDIO_D2_ALT (0) +#define MICROPY_HW_SDIO_D3_ALT (0) +#endif +#else +#define SDMMC USDHC2 +#define SDMMC_IRQn USDHC2_IRQn +#define SDMMC_CLOCK_DIV kCLOCK_Usdhc2Div +#define SDMMC_CLOCK_MUX kCLOCK_Usdhc2Mux +#ifndef MICROPY_HW_SDIO_CLK_ALT +#define MICROPY_HW_SDIO_CMD_ALT (6) +#define MICROPY_HW_SDIO_CLK_ALT (6) +#define MICROPY_HW_SDIO_D0_ALT (6) +#define MICROPY_HW_SDIO_D1_ALT (6) +#define MICROPY_HW_SDIO_D2_ALT (6) +#define MICROPY_HW_SDIO_D3_ALT (6) +#endif +#endif + +#define SDMMC_CLOCK_400KHZ (400000U) +#define SDMMC_CLOCK_25MHZ (25000000U) +#define SDMMC_CLOCK_50MHZ (50000000U) + +#if SDIO_DEBUG +#define debug_printf(...) mp_printf(&mp_plat_print, __VA_ARGS__) +#else +#define debug_printf(...) +#endif + +#define DMA_DESCRIPTOR_BUFFER_SIZE (32U) +AT_NONCACHEABLE_SECTION_ALIGN( + static uint32_t sdio_adma_descriptor_table[DMA_DESCRIPTOR_BUFFER_SIZE], USDHC_ADMA2_ADDRESS_ALIGN); + +typedef struct _mimxrt_sdmmc_t { + USDHC_Type *inst; + usdhc_handle_t handle; + volatile uint32_t xfer_flags; + volatile uint32_t xfer_error; +} mimxrt_sdmmc_t; + +static mimxrt_sdmmc_t sdmmc = { + .inst = SDMMC, +}; + +typedef enum { + SDIO_TRANSFER_DATA_COMPLETE = (1 << 0), + SDIO_TRANSFER_CMD_COMPLETE = (1 << 1), + SDIO_TRANSFER_ERROR = (1 << 2), +} sdio_xfer_flags_t; + +static uint32_t sdio_base_clk(void) { + return CLOCK_GetSysPfdFreq(kCLOCK_Pfd0) / (CLOCK_GetDiv(kCLOCK_Usdhc1Div) + 1U); +} + +static uint32_t sdio_response_type(uint32_t cmd) { + switch (cmd) { + case 3: + return kCARD_ResponseTypeR6; + case 5: + return kCARD_ResponseTypeR4; + case 7: + return kCARD_ResponseTypeR1; + case 52: + return kCARD_ResponseTypeR5; + default: + return kCARD_ResponseTypeNone; + } +} + +static void sdio_transfer_callback(USDHC_Type *base, + usdhc_handle_t *handle, status_t status, void *userData) { + if (status == kStatus_USDHC_TransferDataComplete) { + sdmmc.xfer_flags |= SDIO_TRANSFER_DATA_COMPLETE; + } else if (status == kStatus_USDHC_SendCommandSuccess) { + sdmmc.xfer_flags |= SDIO_TRANSFER_CMD_COMPLETE; + } else if (status != kStatus_USDHC_BusyTransferring) { + sdmmc.xfer_error = status; + sdmmc.xfer_flags |= SDIO_TRANSFER_ERROR; + } +} + +static void sdio_interrupt_callback(USDHC_Type *base, void *userData) { + extern void (*cyw43_poll)(void); + + USDHC_DisableInterruptSignal(base, kUSDHC_CardInterruptFlag); + USDHC_ClearInterruptStatusFlags(base, kUSDHC_CardInterruptFlag); + + if (cyw43_poll) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll); + } +} + +void sdio_init(uint32_t irq_pri) { + machine_pin_config(MICROPY_HW_SDIO_CMD, PIN_MODE_ALT, PIN_PULL_UP_100K, PIN_DRIVE_6, 0, MICROPY_HW_SDIO_CMD_ALT); + machine_pin_config(MICROPY_HW_SDIO_CLK, PIN_MODE_ALT, PIN_PULL_DISABLED, PIN_DRIVE_6, 0, MICROPY_HW_SDIO_CLK_ALT); + machine_pin_config(MICROPY_HW_SDIO_D0, PIN_MODE_ALT, PIN_PULL_UP_100K, PIN_DRIVE_6, 0, MICROPY_HW_SDIO_D0_ALT); + machine_pin_config(MICROPY_HW_SDIO_D1, PIN_MODE_ALT, PIN_PULL_UP_100K, PIN_DRIVE_6, 0, MICROPY_HW_SDIO_D1_ALT); + machine_pin_config(MICROPY_HW_SDIO_D2, PIN_MODE_ALT, PIN_PULL_UP_100K, PIN_DRIVE_6, 0, MICROPY_HW_SDIO_D2_ALT); + machine_pin_config(MICROPY_HW_SDIO_D3, PIN_MODE_ALT, PIN_PULL_UP_100K, PIN_DRIVE_6, 0, MICROPY_HW_SDIO_D3_ALT); + + // Configure PFD0 of PLL2 (system PLL) fractional divider to 24 resulting in: + // with PFD0_clk = PLL2_clk * 18 / N + // PFD0_clk = 528MHz * 18 / 24 = 396MHz + CLOCK_InitSysPfd(kCLOCK_Pfd0, 24U); + CLOCK_SetDiv(SDMMC_CLOCK_DIV, 1U); // USDHC_input_clk = PFD0_clk / 2 + CLOCK_SetMux(SDMMC_CLOCK_MUX, 1U); // Select PFD0 as clock input for USDHC + + // Initialize USDHC + const usdhc_config_t config = { + .endianMode = kUSDHC_EndianModeLittle, + .dataTimeout = 0xFU, + .readBurstLen = 0, + .writeBurstLen = 0, + .readWatermarkLevel = 128U, + .writeWatermarkLevel = 128U, + }; + + USDHC_Init(sdmmc.inst, &config); + USDHC_Reset(SDMMC, kUSDHC_ResetAll, 1000U); + USDHC_DisableInterruptSignal(SDMMC, kUSDHC_AllInterruptFlags); + USDHC_SetSdClock(sdmmc.inst, sdio_base_clk(), SDMMC_CLOCK_25MHZ); + USDHC_SetDataBusWidth(sdmmc.inst, kUSDHC_DataBusWidth1Bit); + + mp_hal_delay_ms(10); + + NVIC_SetPriority(SDMMC_IRQn, irq_pri); + EnableIRQ(SDMMC_IRQn); + + usdhc_transfer_callback_t callbacks = { + .SdioInterrupt = sdio_interrupt_callback, + .TransferComplete = sdio_transfer_callback, + }; + USDHC_TransferCreateHandle(sdmmc.inst, &sdmmc.handle, &callbacks, NULL); +} + +void sdio_deinit(void) { +} + +void sdio_reenable(void) { +} + +void sdio_enable_irq(bool enable) { + if (enable) { + USDHC_ClearInterruptStatusFlags(sdmmc.inst, kUSDHC_CardInterruptFlag); + USDHC_EnableInterruptStatus(sdmmc.inst, kUSDHC_CardInterruptFlag); + USDHC_EnableInterruptSignal(sdmmc.inst, kUSDHC_CardInterruptFlag); + } else { + USDHC_DisableInterruptStatus(sdmmc.inst, kUSDHC_CardInterruptFlag); + USDHC_ClearInterruptStatusFlags(sdmmc.inst, kUSDHC_CardInterruptFlag); + USDHC_DisableInterruptSignal(sdmmc.inst, kUSDHC_CardInterruptFlag); + } +} + +void sdio_enable_high_speed_4bit(void) { + USDHC_SetSdClock(sdmmc.inst, sdio_base_clk(), SDMMC_CLOCK_50MHZ); + USDHC_SetDataBusWidth(sdmmc.inst, kUSDHC_DataBusWidth4Bit); +} + +static status_t sdio_transfer_dma(USDHC_Type *base, + usdhc_handle_t *handle, usdhc_transfer_t *transfer, uint32_t timeout_ms) { + status_t status; + usdhc_adma_config_t dma_config = { + .dmaMode = kUSDHC_DmaModeAdma2, + #if !FSL_FEATURE_USDHC_HAS_NO_RW_BURST_LEN + .burstLen = kUSDHC_EnBurstLenForINCR, + #endif + .admaTable = sdio_adma_descriptor_table, + .admaTableWords = DMA_DESCRIPTOR_BUFFER_SIZE, + }; + + sdmmc.xfer_flags = 0; + sdmmc.xfer_error = 0; + + uint32_t xfer_flags = SDIO_TRANSFER_CMD_COMPLETE; + if (transfer->data != NULL) { + xfer_flags |= SDIO_TRANSFER_DATA_COMPLETE; + } + + status = USDHC_TransferNonBlocking(base, handle, &dma_config, transfer); + if (status != kStatus_Success) { + debug_printf("sdio_transfer_dma failed to start transfer error: %lu\n", status); + return status; + } + + uint32_t start = mp_hal_ticks_ms(); + while ((sdmmc.xfer_flags != xfer_flags) && + !(sdmmc.xfer_flags & SDIO_TRANSFER_ERROR) && + (mp_hal_ticks_ms() - start) < timeout_ms) { + MICROPY_EVENT_POLL_HOOK; + } + + if (sdmmc.xfer_flags == 0) { + debug_printf("sdio_transfer_dma transfer timeout.\n"); + return kStatus_Timeout; + } else if (sdmmc.xfer_flags != xfer_flags) { + debug_printf("sdio_transfer_dma transfer failed: %lu\n", sdmmc.xfer_error); + USDHC_Reset(base, kUSDHC_ResetCommand, 100); + if (xfer_flags & SDIO_TRANSFER_DATA_COMPLETE) { + USDHC_Reset(base, kUSDHC_ResetData, 100); + } + return sdmmc.xfer_error; + } + + return kStatus_Success; +} + +int sdio_transfer(uint32_t cmd, uint32_t arg, uint32_t *resp) { + status_t status; + usdhc_command_t command = { + .index = cmd, + .argument = arg, + .type = kCARD_CommandTypeNormal, + .responseType = sdio_response_type(cmd), + .responseErrorFlags = 0 + }; + + usdhc_transfer_t transfer = { + .data = NULL, + .command = &command, + }; + + status = sdio_transfer_dma(sdmmc.inst, &sdmmc.handle, &transfer, 5000); + + if (status != kStatus_Success) { + debug_printf("sdio_transfer failed!\n"); + return -MP_EIO; + } + + if (resp != NULL) { + *resp = command.response[0]; + } + + return 0; +} + +int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t len, uint8_t *buf) { + usdhc_data_t data = { + .enableAutoCommand12 = false, + .enableAutoCommand23 = false, + .enableIgnoreError = false, + .dataType = kUSDHC_TransferDataNormal, + }; + + usdhc_command_t command = { + .index = 53, + .argument = arg, + .type = kCARD_CommandTypeNormal, + .responseType = kCARD_ResponseTypeR5, + .responseErrorFlags = 0 + }; + + usdhc_transfer_t transfer = { + .data = &data, + .command = &command, + }; + + if (write) { + data.rxData = NULL; + data.txData = (uint32_t *)buf; + } else { + data.txData = NULL; + data.rxData = (uint32_t *)buf; + } + + if (arg & (1 << 27)) { + // SDIO_BLOCK_MODE + data.blockSize = block_size; + data.blockCount = len / block_size; + } else { + // SDIO_BYTE_MODE + data.blockSize = block_size; + data.blockCount = 1; + } + + debug_printf("cmd53 rw: %d addr 0x%p blocksize %u blockcount %lu total %lu len %d\n", + write, buf, data.blockSize, data.blockCount, data.blockSize * data.blockCount, len); + + status_t status = sdio_transfer_dma(sdmmc.inst, &sdmmc.handle, &transfer, 5000); + + if (status != kStatus_Success) { + debug_printf("sdio_transfer_cmd53 failed!\n"); + return -1; + } + + return 0; +} + +#endif diff --git a/ports/mimxrt/sdio.h b/ports/mimxrt/sdio.h new file mode 100644 index 0000000000..f8d6f498b6 --- /dev/null +++ b/ports/mimxrt/sdio.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Ibrahim Abdelkader + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_MIMXRT_SDIO_H +#define MICROPY_INCLUDED_MIMXRT_SDIO_H + +#include +#include + +void sdio_init(uint32_t irq_pri); +void sdio_deinit(void); +void sdio_reenable(void); +void sdio_enable_irq(bool enable); +void sdio_enable_high_speed_4bit(void); +int sdio_transfer(uint32_t cmd, uint32_t arg, uint32_t *resp); +int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t len, uint8_t *buf); + +#endif // MICROPY_INCLUDED_MIMXRT_SDIO_H diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 3a4b0ef23d..5e9e31ad01 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -4,8 +4,8 @@ ifdef BOARD_DIR # the path as the board name. BOARD ?= $(notdir $(BOARD_DIR:/=)) else -# If not given on the command line, then default to pca10040. -BOARD ?= pca10040 +# If not given on the command line, then default to PCA10040. +BOARD ?= PCA10040 BOARD_DIR ?= boards/$(BOARD) endif diff --git a/ports/nrf/README.md b/ports/nrf/README.md index fde04e61f1..889ead5d4d 100644 --- a/ports/nrf/README.md +++ b/ports/nrf/README.md @@ -41,7 +41,7 @@ This is a port of MicroPython to the Nordic Semiconductor nRF series of chips. * [PCA10056](http://www.nordicsemi.com/eng/Products/nRF52840-Preview-DK) * [PCA10059](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle) * [Particle Xenon](https://docs.particle.io/xenon/) - * [nRF52840 MDK USB Dongle](boards/nrf52840-mdk-usb-dongle/README.md) + * [nRF52840 MDK USB Dongle](boards/NRF52840_MDK_USB_DONGLE/README.md) * nRF9160 * [PCA10090](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF9160-DK) * [Actinius Icarus](https://www.actinius.com/icarus) @@ -63,8 +63,8 @@ By default, the PCA10040 (nrf52832) is used as compile target. To build and flas Alternatively the target board could be defined: make submodules - make BOARD=pca10040 - make BOARD=pca10040 deploy + make BOARD=PCA10040 + make BOARD=PCA10040 deploy ## Compile without LTO enabled @@ -73,7 +73,7 @@ targets in the nrf-port. The `-flto` linker flag can be toggled easily by using the argument LTO when building. The example below shows how to disable LTO for the compilation: - make BOARD=pca10040 LTO=0 + make BOARD=PCA10040 LTO=0 **Note**: There have been several issues with use of LTO in conjunction with GNU ARM Embedded Toolchain 7.2.1/4Q17. It's recommended to use a toolchain after @@ -88,11 +88,11 @@ First prepare the bluetooth folder by downloading Bluetooth LE stacks and header If the Bluetooth stacks has been downloaded, compile the target with the following command: - make BOARD=pca10040 SD=s132 + make BOARD=PCA10040 SD=s132 The **make sd** will trigger a flash of the bluetooth stack before that application is flashed. Note that **make sd** will perform a full erase of the chip, which could cause 3rd party bootloaders to also be wiped. - make BOARD=pca10040 SD=s132 sd + make BOARD=PCA10040 SD=s132 sd Note: further tuning of features to include in bluetooth or even setting up the device to use REPL over Bluetooth can be configured in the `bluetooth_conf.h`. @@ -104,7 +104,7 @@ it in the specific target board's `mpconfigboard.mk`. For example: - make BOARD=pca10040 FROZEN_MANIFEST=path/to/manifest.py + make BOARD=PCA10040 FROZEN_MANIFEST=path/to/manifest.py In case of using the target board's makefile, add a line similar to this: @@ -117,7 +117,7 @@ As the `oofatfs` module is not having header guards that can exclude the impleme For example: - make BOARD=pca10040 MICROPY_VFS_FAT=1 + make BOARD=PCA10040 MICROPY_VFS_FAT=1 ## Enable MICROPY_VFS_LFS1 or MICROPY_VFS_LFS2 @@ -127,7 +127,7 @@ or `MICROPY_VFS_LFS2` can be set. This will be in addition of setting For example: - make BOARD=pca10056 MICROPY_VFS_LFS2=1 + make BOARD=PCA10056 MICROPY_VFS_LFS2=1 ## Set file system size @@ -141,7 +141,7 @@ linker script syntax as it is passed directly. For example, if we want to override the default file system size set by the linker scripts to use 256K: - make BOARD=pca10056 MICROPY_VFS_LFS2=1 FS_SIZE=256K + make BOARD=PCA10056 MICROPY_VFS_LFS2=1 FS_SIZE=256K Also note that changing this size between builds might cause loss of files present from a previous firmware as it will format the file system due to a new @@ -151,25 +151,25 @@ location. Target Board (BOARD) | Bluetooth Stack (SD) | Bluetooth Support | Bootloader | Default Flash Util ---------------------|-------------------------|------------------------|----------------|------------------- -microbit | s110 | Peripheral | | [PyOCD](#pyocdopenocd-targets) -pca10000 | s110 | Peripheral | | [Segger](#segger-targets) -pca10001 | s110 | Peripheral | | [Segger](#segger-targets) -pca10028 | s110 | Peripheral | | [Segger](#segger-targets) -pca10031 | s110 | Peripheral | | [Segger](#segger-targets) -wt51822_s4at | s110 | Peripheral | | Manual, see [datasheet](https://4tronix.co.uk/picobot2/WT51822-S4AT.pdf) for pinout -pca10040 | s132 | Peripheral and Central | | [Segger](#segger-targets) -feather52 | s132 | Peripheral and Central | | Manual, SWDIO and SWCLK solder points on the bottom side of the board -arduino_primo | s132 | Peripheral and Central | | [PyOCD](#pyocdopenocd-targets) -ibk_blyst_nano | s132 | Peripheral and Central | | [IDAP](#idap-midap-link-targets) -idk_blyst_nano | s132 | Peripheral and Central | | [IDAP](#idap-midap-link-targets) -blueio_tag_evim | s132 | Peripheral and Central | | [IDAP](#idap-midap-link-targets) -evk_nina_b1 | s132 | Peripheral and Central | | [Segger](#segger-targets) -pca10056 | s140 | Peripheral and Central | | [Segger](#segger-targets) -pca10059 | s140 | Peripheral and Central | OpenBootloader | [nrfutil](#nrfutil-targets) -particle_xenon | s140 | Peripheral and Central | | [Black Magic Probe](#black-magic-probe-targets) -nrf52840-mdk-usb-dongle | s140 | Peripheral and Central | OpenBootloader | [nrfutil](#nrfutil-targets) -pca10090 | None (bsdlib.a) | None (LTE/GNSS) | | [Segger](#segger-targets) -actinius_icarus | None (bsdlib.a) | None (LTE/GNSS) | | [Segger](#segger-targets) +MICROBIT | s110 | Peripheral | | [PyOCD](#pyocdopenocd-targets) +PCA10000 | s110 | Peripheral | | [Segger](#segger-targets) +PCA10001 | s110 | Peripheral | | [Segger](#segger-targets) +PCA10028 | s110 | Peripheral | | [Segger](#segger-targets) +PCA10031 | s110 | Peripheral | | [Segger](#segger-targets) +WT51822_S4AT | s110 | Peripheral | | Manual, see [datasheet](https://4tronix.co.uk/picobot2/WT51822-S4AT.pdf) for pinout +PCA10040 | s132 | Peripheral and Central | | [Segger](#segger-targets) +FEATHER52 | s132 | Peripheral and Central | | Manual, SWDIO and SWCLK solder points on the bottom side of the board +ARDUINO_PRIMO | s132 | Peripheral and Central | | [PyOCD](#pyocdopenocd-targets) +IBK_BLYST_NANO | s132 | Peripheral and Central | | [IDAP](#idap-midap-link-targets) +IDK_BLYST_NANO | s132 | Peripheral and Central | | [IDAP](#idap-midap-link-targets) +BLUEIO_TAG_EVIM | s132 | Peripheral and Central | | [IDAP](#idap-midap-link-targets) +EVK_NINA_B1 | s132 | Peripheral and Central | | [Segger](#segger-targets) +PCA10056 | s140 | Peripheral and Central | | [Segger](#segger-targets) +PCA10059 | s140 | Peripheral and Central | OpenBootloader | [nrfutil](#nrfutil-targets) +PARTICLE_XENON | s140 | Peripheral and Central | | [Black Magic Probe](#black-magic-probe-targets) +NRF52840_MDK_USB_DONGLE | s140 | Peripheral and Central | OpenBootloader | [nrfutil](#nrfutil-targets) +PCA10090 | None (bsdlib.a) | None (LTE/GNSS) | | [Segger](#segger-targets) +ACTINIUS_ICARUS | None (bsdlib.a) | None (LTE/GNSS) | | [Segger](#segger-targets) ## IDAP-M/IDAP-Link Targets @@ -218,7 +218,7 @@ to trim of the MBR in case SoftDevice flashing is requested. `nrfutil` as flashing backend also requires a serial port parameter to be defined in addition to the `deploy` target of make. For example: - make BOARD=nrf52840-mdk-usb-dongle NRFUTIL_PORT=/dev/ttyACM0 deploy + make BOARD=NRF52840_MDK_USB_DONGLE NRFUTIL_PORT=/dev/ttyACM0 deploy If the target device is connected to `/dev/ttyACM0` serial port, the `NRFUTIL_PORT` parameter to make can be elided as it is the default serial @@ -228,7 +228,7 @@ When enabling Bluetooth LE, as with the other flash utils, the SoftDevice needs to be flashed in the first firmware update. This can be done by issuing the `sd` target instead of `deploy`. For example: - make BOARD=nrf52840-mdk-usb-dongle SD=s140 NRFUTIL_PORT=/dev/ttyACM0 sd + make BOARD=NRF52840_MDK_USB_DONGLE SD=s140 NRFUTIL_PORT=/dev/ttyACM0 sd ## Bluetooth LE REPL diff --git a/ports/nrf/boards/actinius_icarus/board.json b/ports/nrf/boards/ACTINIUS_ICARUS/board.json similarity index 100% rename from ports/nrf/boards/actinius_icarus/board.json rename to ports/nrf/boards/ACTINIUS_ICARUS/board.json diff --git a/ports/nrf/boards/actinius_icarus/mpconfigboard.h b/ports/nrf/boards/ACTINIUS_ICARUS/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/actinius_icarus/mpconfigboard.h rename to ports/nrf/boards/ACTINIUS_ICARUS/mpconfigboard.h diff --git a/ports/nrf/boards/actinius_icarus/mpconfigboard.mk b/ports/nrf/boards/ACTINIUS_ICARUS/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/actinius_icarus/mpconfigboard.mk rename to ports/nrf/boards/ACTINIUS_ICARUS/mpconfigboard.mk diff --git a/ports/nrf/boards/actinius_icarus/pins.csv b/ports/nrf/boards/ACTINIUS_ICARUS/pins.csv similarity index 100% rename from ports/nrf/boards/actinius_icarus/pins.csv rename to ports/nrf/boards/ACTINIUS_ICARUS/pins.csv diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/board.c b/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/board.c similarity index 100% rename from ports/nrf/boards/arduino_nano_33_ble_sense/board.c rename to ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/board.c diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/board.json b/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/board.json similarity index 54% rename from ports/nrf/boards/arduino_nano_33_ble_sense/board.json rename to ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/board.json index 65a8e24350..9079fbd666 100644 --- a/ports/nrf/boards/arduino_nano_33_ble_sense/board.json +++ b/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/board.json @@ -4,15 +4,12 @@ ], "docs": "", "features": [ - "Bluetooth 5.0", - "IMU LSM9DS1", - "Humidity sensor HTS221", - "Pressure sensor LPS22H", - "Proximity, Light, RGB sensor APDS-9960", - "Microphone MPM3610", - "Crypto IC ARM CC310", - "USB-MICRO", - "Breadboard Friendly" + "BLE", + "Environment Sensor", + "IMU", + "Microphone", + "Secure Element", + "USB" ], "images": [ "ABX00031_01.iso_998x749.jpg" diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/deploy.md b/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/deploy.md similarity index 100% rename from ports/nrf/boards/arduino_nano_33_ble_sense/deploy.md rename to ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/deploy.md diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py b/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/manifest.py similarity index 100% rename from ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py rename to ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/manifest.py diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/modules/imu.py b/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/modules/imu.py similarity index 100% rename from ports/nrf/boards/arduino_nano_33_ble_sense/modules/imu.py rename to ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/modules/imu.py diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.h b/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.h rename to ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/mpconfigboard.h diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.mk b/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/mpconfigboard.mk similarity index 77% rename from ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.mk rename to ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/mpconfigboard.mk index cb2ff5c6b8..148a9f1017 100644 --- a/ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.mk +++ b/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/mpconfigboard.mk @@ -4,7 +4,7 @@ MCU_SUB_VARIANT = nrf52840 SOFTDEV_VERSION = 6.1.1 SD=s140 -LD_FILES += boards/arduino_nano_33_ble_sense/nano_bootloader.ld boards/nrf52840_1M_256k.ld +LD_FILES += boards/ARDUINO_NANO_33_BLE_SENSE/nano_bootloader.ld boards/nrf52840_1M_256k.ld NRF_DEFINES += -DNRF52840_XXAA diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/nano_bootloader.ld b/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/nano_bootloader.ld similarity index 100% rename from ports/nrf/boards/arduino_nano_33_ble_sense/nano_bootloader.ld rename to ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/nano_bootloader.ld diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/pins.csv b/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/pins.csv similarity index 100% rename from ports/nrf/boards/arduino_nano_33_ble_sense/pins.csv rename to ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/pins.csv diff --git a/ports/nrf/boards/arduino_primo/board.json b/ports/nrf/boards/ARDUINO_PRIMO/board.json similarity index 90% rename from ports/nrf/boards/arduino_primo/board.json rename to ports/nrf/boards/ARDUINO_PRIMO/board.json index d16ce1c346..f7afed0ced 100644 --- a/ports/nrf/boards/arduino_primo/board.json +++ b/ports/nrf/boards/ARDUINO_PRIMO/board.json @@ -11,5 +11,5 @@ "product": "arduino_primo", "thumbnail": "", "url": "", - "vendor": "" + "vendor": "Arduino" } diff --git a/ports/nrf/boards/arduino_primo/mpconfigboard.h b/ports/nrf/boards/ARDUINO_PRIMO/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/arduino_primo/mpconfigboard.h rename to ports/nrf/boards/ARDUINO_PRIMO/mpconfigboard.h diff --git a/ports/nrf/boards/arduino_primo/mpconfigboard.mk b/ports/nrf/boards/ARDUINO_PRIMO/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/arduino_primo/mpconfigboard.mk rename to ports/nrf/boards/ARDUINO_PRIMO/mpconfigboard.mk diff --git a/ports/nrf/boards/pca10040/pins.csv b/ports/nrf/boards/ARDUINO_PRIMO/pins.csv similarity index 100% rename from ports/nrf/boards/pca10040/pins.csv rename to ports/nrf/boards/ARDUINO_PRIMO/pins.csv diff --git a/ports/nrf/boards/blueio_tag_evim/board.json b/ports/nrf/boards/BLUEIO_TAG_EVIM/board.json similarity index 100% rename from ports/nrf/boards/blueio_tag_evim/board.json rename to ports/nrf/boards/BLUEIO_TAG_EVIM/board.json diff --git a/ports/nrf/boards/blueio_tag_evim/mpconfigboard.h b/ports/nrf/boards/BLUEIO_TAG_EVIM/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/blueio_tag_evim/mpconfigboard.h rename to ports/nrf/boards/BLUEIO_TAG_EVIM/mpconfigboard.h diff --git a/ports/nrf/boards/idk_blyst_nano/mpconfigboard.mk b/ports/nrf/boards/BLUEIO_TAG_EVIM/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/idk_blyst_nano/mpconfigboard.mk rename to ports/nrf/boards/BLUEIO_TAG_EVIM/mpconfigboard.mk diff --git a/ports/nrf/boards/idk_blyst_nano/pins.csv b/ports/nrf/boards/BLUEIO_TAG_EVIM/pins.csv similarity index 100% rename from ports/nrf/boards/idk_blyst_nano/pins.csv rename to ports/nrf/boards/BLUEIO_TAG_EVIM/pins.csv diff --git a/ports/nrf/boards/dvk_bl652/board.json b/ports/nrf/boards/DVK_BL652/board.json similarity index 100% rename from ports/nrf/boards/dvk_bl652/board.json rename to ports/nrf/boards/DVK_BL652/board.json diff --git a/ports/nrf/boards/dvk_bl652/mpconfigboard.h b/ports/nrf/boards/DVK_BL652/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/dvk_bl652/mpconfigboard.h rename to ports/nrf/boards/DVK_BL652/mpconfigboard.h diff --git a/ports/nrf/boards/dvk_bl652/mpconfigboard.mk b/ports/nrf/boards/DVK_BL652/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/dvk_bl652/mpconfigboard.mk rename to ports/nrf/boards/DVK_BL652/mpconfigboard.mk diff --git a/ports/nrf/boards/dvk_bl652/pins.csv b/ports/nrf/boards/DVK_BL652/pins.csv similarity index 100% rename from ports/nrf/boards/dvk_bl652/pins.csv rename to ports/nrf/boards/DVK_BL652/pins.csv diff --git a/ports/nrf/boards/evk_nina_b1/board.json b/ports/nrf/boards/EVK_NINA_B1/board.json similarity index 100% rename from ports/nrf/boards/evk_nina_b1/board.json rename to ports/nrf/boards/EVK_NINA_B1/board.json diff --git a/ports/nrf/boards/evk_nina_b1/mpconfigboard.h b/ports/nrf/boards/EVK_NINA_B1/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/evk_nina_b1/mpconfigboard.h rename to ports/nrf/boards/EVK_NINA_B1/mpconfigboard.h diff --git a/ports/nrf/boards/pca10040/mpconfigboard.mk b/ports/nrf/boards/EVK_NINA_B1/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/pca10040/mpconfigboard.mk rename to ports/nrf/boards/EVK_NINA_B1/mpconfigboard.mk diff --git a/ports/nrf/boards/evk_nina_b1/pins.csv b/ports/nrf/boards/EVK_NINA_B1/pins.csv similarity index 100% rename from ports/nrf/boards/evk_nina_b1/pins.csv rename to ports/nrf/boards/EVK_NINA_B1/pins.csv diff --git a/ports/nrf/boards/evk_nina_b3/board.json b/ports/nrf/boards/EVK_NINA_B3/board.json similarity index 100% rename from ports/nrf/boards/evk_nina_b3/board.json rename to ports/nrf/boards/EVK_NINA_B3/board.json diff --git a/ports/nrf/boards/evk_nina_b3/mpconfigboard.h b/ports/nrf/boards/EVK_NINA_B3/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/evk_nina_b3/mpconfigboard.h rename to ports/nrf/boards/EVK_NINA_B3/mpconfigboard.h diff --git a/ports/nrf/boards/evk_nina_b3/mpconfigboard.mk b/ports/nrf/boards/EVK_NINA_B3/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/evk_nina_b3/mpconfigboard.mk rename to ports/nrf/boards/EVK_NINA_B3/mpconfigboard.mk diff --git a/ports/nrf/boards/pca10056/pins.csv b/ports/nrf/boards/EVK_NINA_B3/pins.csv similarity index 100% rename from ports/nrf/boards/pca10056/pins.csv rename to ports/nrf/boards/EVK_NINA_B3/pins.csv diff --git a/ports/nrf/boards/feather52/board.json b/ports/nrf/boards/FEATHER52/board.json similarity index 100% rename from ports/nrf/boards/feather52/board.json rename to ports/nrf/boards/FEATHER52/board.json diff --git a/ports/nrf/boards/feather52/mpconfigboard.h b/ports/nrf/boards/FEATHER52/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/feather52/mpconfigboard.h rename to ports/nrf/boards/FEATHER52/mpconfigboard.h diff --git a/ports/nrf/boards/feather52/mpconfigboard.mk b/ports/nrf/boards/FEATHER52/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/feather52/mpconfigboard.mk rename to ports/nrf/boards/FEATHER52/mpconfigboard.mk diff --git a/ports/nrf/boards/feather52/pins.csv b/ports/nrf/boards/FEATHER52/pins.csv similarity index 100% rename from ports/nrf/boards/feather52/pins.csv rename to ports/nrf/boards/FEATHER52/pins.csv diff --git a/ports/nrf/boards/ibk_blyst_nano/board.json b/ports/nrf/boards/IBK_BLYST_NANO/board.json similarity index 100% rename from ports/nrf/boards/ibk_blyst_nano/board.json rename to ports/nrf/boards/IBK_BLYST_NANO/board.json diff --git a/ports/nrf/boards/ibk_blyst_nano/mpconfigboard.h b/ports/nrf/boards/IBK_BLYST_NANO/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/ibk_blyst_nano/mpconfigboard.h rename to ports/nrf/boards/IBK_BLYST_NANO/mpconfigboard.h diff --git a/ports/nrf/boards/ibk_blyst_nano/mpconfigboard.mk b/ports/nrf/boards/IBK_BLYST_NANO/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/ibk_blyst_nano/mpconfigboard.mk rename to ports/nrf/boards/IBK_BLYST_NANO/mpconfigboard.mk diff --git a/ports/nrf/boards/ibk_blyst_nano/pins.csv b/ports/nrf/boards/IBK_BLYST_NANO/pins.csv similarity index 100% rename from ports/nrf/boards/ibk_blyst_nano/pins.csv rename to ports/nrf/boards/IBK_BLYST_NANO/pins.csv diff --git a/ports/nrf/boards/idk_blyst_nano/board.json b/ports/nrf/boards/IDK_BLYST_NANO/board.json similarity index 100% rename from ports/nrf/boards/idk_blyst_nano/board.json rename to ports/nrf/boards/IDK_BLYST_NANO/board.json diff --git a/ports/nrf/boards/idk_blyst_nano/mpconfigboard.h b/ports/nrf/boards/IDK_BLYST_NANO/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/idk_blyst_nano/mpconfigboard.h rename to ports/nrf/boards/IDK_BLYST_NANO/mpconfigboard.h diff --git a/ports/nrf/boards/blueio_tag_evim/mpconfigboard.mk b/ports/nrf/boards/IDK_BLYST_NANO/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/blueio_tag_evim/mpconfigboard.mk rename to ports/nrf/boards/IDK_BLYST_NANO/mpconfigboard.mk diff --git a/ports/nrf/boards/blueio_tag_evim/pins.csv b/ports/nrf/boards/IDK_BLYST_NANO/pins.csv similarity index 100% rename from ports/nrf/boards/blueio_tag_evim/pins.csv rename to ports/nrf/boards/IDK_BLYST_NANO/pins.csv diff --git a/ports/nrf/boards/microbit/board.json b/ports/nrf/boards/MICROBIT/board.json similarity index 100% rename from ports/nrf/boards/microbit/board.json rename to ports/nrf/boards/MICROBIT/board.json diff --git a/ports/nrf/boards/microbit/custom_nrf51822_s110_microbit.ld b/ports/nrf/boards/MICROBIT/custom_nrf51822_s110_microbit.ld similarity index 100% rename from ports/nrf/boards/microbit/custom_nrf51822_s110_microbit.ld rename to ports/nrf/boards/MICROBIT/custom_nrf51822_s110_microbit.ld diff --git a/ports/nrf/boards/microbit/modules/AUTHORS b/ports/nrf/boards/MICROBIT/modules/AUTHORS similarity index 100% rename from ports/nrf/boards/microbit/modules/AUTHORS rename to ports/nrf/boards/MICROBIT/modules/AUTHORS diff --git a/ports/nrf/boards/microbit/modules/LICENSE b/ports/nrf/boards/MICROBIT/modules/LICENSE similarity index 100% rename from ports/nrf/boards/microbit/modules/LICENSE rename to ports/nrf/boards/MICROBIT/modules/LICENSE diff --git a/ports/nrf/boards/microbit/modules/boardmodules.h b/ports/nrf/boards/MICROBIT/modules/boardmodules.h similarity index 100% rename from ports/nrf/boards/microbit/modules/boardmodules.h rename to ports/nrf/boards/MICROBIT/modules/boardmodules.h diff --git a/ports/nrf/boards/microbit/modules/boardmodules.mk b/ports/nrf/boards/MICROBIT/modules/boardmodules.mk similarity index 91% rename from ports/nrf/boards/microbit/modules/boardmodules.mk rename to ports/nrf/boards/MICROBIT/modules/boardmodules.mk index eb8f108615..84a606c448 100644 --- a/ports/nrf/boards/microbit/modules/boardmodules.mk +++ b/ports/nrf/boards/MICROBIT/modules/boardmodules.mk @@ -1,4 +1,4 @@ -BOARD_MICROBIT_DIR = boards/microbit/modules +BOARD_MICROBIT_DIR = boards/MICROBIT/modules INC += -I./$(BOARD_MICROBIT_DIR) CFLAGS += -DBOARD_SPECIFIC_MODULES diff --git a/ports/nrf/boards/microbit/modules/iters.c b/ports/nrf/boards/MICROBIT/modules/iters.c similarity index 100% rename from ports/nrf/boards/microbit/modules/iters.c rename to ports/nrf/boards/MICROBIT/modules/iters.c diff --git a/ports/nrf/boards/microbit/modules/iters.h b/ports/nrf/boards/MICROBIT/modules/iters.h similarity index 100% rename from ports/nrf/boards/microbit/modules/iters.h rename to ports/nrf/boards/MICROBIT/modules/iters.h diff --git a/ports/nrf/boards/microbit/modules/microbitconstimage.c b/ports/nrf/boards/MICROBIT/modules/microbitconstimage.c similarity index 100% rename from ports/nrf/boards/microbit/modules/microbitconstimage.c rename to ports/nrf/boards/MICROBIT/modules/microbitconstimage.c diff --git a/ports/nrf/boards/microbit/modules/microbitconstimage.h b/ports/nrf/boards/MICROBIT/modules/microbitconstimage.h similarity index 100% rename from ports/nrf/boards/microbit/modules/microbitconstimage.h rename to ports/nrf/boards/MICROBIT/modules/microbitconstimage.h diff --git a/ports/nrf/boards/microbit/modules/microbitconstimagetuples.c b/ports/nrf/boards/MICROBIT/modules/microbitconstimagetuples.c similarity index 100% rename from ports/nrf/boards/microbit/modules/microbitconstimagetuples.c rename to ports/nrf/boards/MICROBIT/modules/microbitconstimagetuples.c diff --git a/ports/nrf/boards/microbit/modules/microbitdisplay.c b/ports/nrf/boards/MICROBIT/modules/microbitdisplay.c similarity index 100% rename from ports/nrf/boards/microbit/modules/microbitdisplay.c rename to ports/nrf/boards/MICROBIT/modules/microbitdisplay.c diff --git a/ports/nrf/boards/microbit/modules/microbitdisplay.h b/ports/nrf/boards/MICROBIT/modules/microbitdisplay.h similarity index 100% rename from ports/nrf/boards/microbit/modules/microbitdisplay.h rename to ports/nrf/boards/MICROBIT/modules/microbitdisplay.h diff --git a/ports/nrf/boards/microbit/modules/microbitfont.h b/ports/nrf/boards/MICROBIT/modules/microbitfont.h similarity index 100% rename from ports/nrf/boards/microbit/modules/microbitfont.h rename to ports/nrf/boards/MICROBIT/modules/microbitfont.h diff --git a/ports/nrf/boards/microbit/modules/microbitimage.c b/ports/nrf/boards/MICROBIT/modules/microbitimage.c similarity index 100% rename from ports/nrf/boards/microbit/modules/microbitimage.c rename to ports/nrf/boards/MICROBIT/modules/microbitimage.c diff --git a/ports/nrf/boards/microbit/modules/microbitimage.h b/ports/nrf/boards/MICROBIT/modules/microbitimage.h similarity index 100% rename from ports/nrf/boards/microbit/modules/microbitimage.h rename to ports/nrf/boards/MICROBIT/modules/microbitimage.h diff --git a/ports/nrf/boards/microbit/modules/modmicrobit.c b/ports/nrf/boards/MICROBIT/modules/modmicrobit.c similarity index 100% rename from ports/nrf/boards/microbit/modules/modmicrobit.c rename to ports/nrf/boards/MICROBIT/modules/modmicrobit.c diff --git a/ports/nrf/boards/microbit/modules/modmicrobit.h b/ports/nrf/boards/MICROBIT/modules/modmicrobit.h similarity index 100% rename from ports/nrf/boards/microbit/modules/modmicrobit.h rename to ports/nrf/boards/MICROBIT/modules/modmicrobit.h diff --git a/ports/nrf/boards/microbit/mpconfigboard.h b/ports/nrf/boards/MICROBIT/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/microbit/mpconfigboard.h rename to ports/nrf/boards/MICROBIT/mpconfigboard.h diff --git a/ports/nrf/boards/microbit/mpconfigboard.mk b/ports/nrf/boards/MICROBIT/mpconfigboard.mk similarity index 79% rename from ports/nrf/boards/microbit/mpconfigboard.mk rename to ports/nrf/boards/MICROBIT/mpconfigboard.mk index 6fdd2bc500..6c7e1b46b9 100644 --- a/ports/nrf/boards/microbit/mpconfigboard.mk +++ b/ports/nrf/boards/MICROBIT/mpconfigboard.mk @@ -4,7 +4,7 @@ MCU_SUB_VARIANT = nrf51822 SOFTDEV_VERSION = 8.0.0 ifneq ($(SD),) -LD_FILES += boards/microbit/custom_nrf51822_s110_microbit.ld +LD_FILES += boards/MICROBIT/custom_nrf51822_s110_microbit.ld FROZEN_MANIFEST ?= else MICROPY_VFS_LFS2 = 1 diff --git a/ports/nrf/boards/microbit/pins.csv b/ports/nrf/boards/MICROBIT/pins.csv similarity index 100% rename from ports/nrf/boards/microbit/pins.csv rename to ports/nrf/boards/MICROBIT/pins.csv diff --git a/ports/nrf/boards/nrf52840-mdk-usb-dongle/README.md b/ports/nrf/boards/NRF52840_MDK_USB_DONGLE/README.md similarity index 100% rename from ports/nrf/boards/nrf52840-mdk-usb-dongle/README.md rename to ports/nrf/boards/NRF52840_MDK_USB_DONGLE/README.md diff --git a/ports/nrf/boards/nrf52840-mdk-usb-dongle/board.json b/ports/nrf/boards/NRF52840_MDK_USB_DONGLE/board.json similarity index 91% rename from ports/nrf/boards/nrf52840-mdk-usb-dongle/board.json rename to ports/nrf/boards/NRF52840_MDK_USB_DONGLE/board.json index 853c375710..99d0caad23 100644 --- a/ports/nrf/boards/nrf52840-mdk-usb-dongle/board.json +++ b/ports/nrf/boards/NRF52840_MDK_USB_DONGLE/board.json @@ -11,5 +11,5 @@ "product": "nrf52840-mdk-usb-dongle", "thumbnail": "", "url": "https://wiki.makerdiary.com/nrf52840-mdk-usb-dongle", - "vendor": "" + "vendor": "Makerdiary" } diff --git a/ports/nrf/boards/nrf52840-mdk-usb-dongle/mpconfigboard.h b/ports/nrf/boards/NRF52840_MDK_USB_DONGLE/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/nrf52840-mdk-usb-dongle/mpconfigboard.h rename to ports/nrf/boards/NRF52840_MDK_USB_DONGLE/mpconfigboard.h diff --git a/ports/nrf/boards/pca10059/mpconfigboard.mk b/ports/nrf/boards/NRF52840_MDK_USB_DONGLE/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/pca10059/mpconfigboard.mk rename to ports/nrf/boards/NRF52840_MDK_USB_DONGLE/mpconfigboard.mk diff --git a/ports/nrf/boards/nrf52840-mdk-usb-dongle/pins.csv b/ports/nrf/boards/NRF52840_MDK_USB_DONGLE/pins.csv similarity index 100% rename from ports/nrf/boards/nrf52840-mdk-usb-dongle/pins.csv rename to ports/nrf/boards/NRF52840_MDK_USB_DONGLE/pins.csv diff --git a/ports/nrf/boards/particle_xenon/board.json b/ports/nrf/boards/PARTICLE_XENON/board.json similarity index 100% rename from ports/nrf/boards/particle_xenon/board.json rename to ports/nrf/boards/PARTICLE_XENON/board.json diff --git a/ports/nrf/boards/particle_xenon/mpconfigboard.h b/ports/nrf/boards/PARTICLE_XENON/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/particle_xenon/mpconfigboard.h rename to ports/nrf/boards/PARTICLE_XENON/mpconfigboard.h diff --git a/ports/nrf/boards/particle_xenon/mpconfigboard.mk b/ports/nrf/boards/PARTICLE_XENON/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/particle_xenon/mpconfigboard.mk rename to ports/nrf/boards/PARTICLE_XENON/mpconfigboard.mk diff --git a/ports/nrf/boards/particle_xenon/pins.csv b/ports/nrf/boards/PARTICLE_XENON/pins.csv similarity index 100% rename from ports/nrf/boards/particle_xenon/pins.csv rename to ports/nrf/boards/PARTICLE_XENON/pins.csv diff --git a/ports/nrf/boards/pca10000/board.json b/ports/nrf/boards/PCA10000/board.json similarity index 100% rename from ports/nrf/boards/pca10000/board.json rename to ports/nrf/boards/PCA10000/board.json diff --git a/ports/nrf/boards/pca10000/mpconfigboard.h b/ports/nrf/boards/PCA10000/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/pca10000/mpconfigboard.h rename to ports/nrf/boards/PCA10000/mpconfigboard.h diff --git a/ports/nrf/boards/pca10001/mpconfigboard.mk b/ports/nrf/boards/PCA10000/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/pca10001/mpconfigboard.mk rename to ports/nrf/boards/PCA10000/mpconfigboard.mk diff --git a/ports/nrf/boards/pca10000/pins.csv b/ports/nrf/boards/PCA10000/pins.csv similarity index 100% rename from ports/nrf/boards/pca10000/pins.csv rename to ports/nrf/boards/PCA10000/pins.csv diff --git a/ports/nrf/boards/pca10001/board.json b/ports/nrf/boards/PCA10001/board.json similarity index 100% rename from ports/nrf/boards/pca10001/board.json rename to ports/nrf/boards/PCA10001/board.json diff --git a/ports/nrf/boards/pca10001/mpconfigboard.h b/ports/nrf/boards/PCA10001/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/pca10001/mpconfigboard.h rename to ports/nrf/boards/PCA10001/mpconfigboard.h diff --git a/ports/nrf/boards/pca10000/mpconfigboard.mk b/ports/nrf/boards/PCA10001/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/pca10000/mpconfigboard.mk rename to ports/nrf/boards/PCA10001/mpconfigboard.mk diff --git a/ports/nrf/boards/pca10001/pins.csv b/ports/nrf/boards/PCA10001/pins.csv similarity index 100% rename from ports/nrf/boards/pca10001/pins.csv rename to ports/nrf/boards/PCA10001/pins.csv diff --git a/ports/nrf/boards/pca10028/board.json b/ports/nrf/boards/PCA10028/board.json similarity index 100% rename from ports/nrf/boards/pca10028/board.json rename to ports/nrf/boards/PCA10028/board.json diff --git a/ports/nrf/boards/pca10028/mpconfigboard.h b/ports/nrf/boards/PCA10028/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/pca10028/mpconfigboard.h rename to ports/nrf/boards/PCA10028/mpconfigboard.h diff --git a/ports/nrf/boards/pca10031/mpconfigboard.mk b/ports/nrf/boards/PCA10028/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/pca10031/mpconfigboard.mk rename to ports/nrf/boards/PCA10028/mpconfigboard.mk diff --git a/ports/nrf/boards/pca10028/pins.csv b/ports/nrf/boards/PCA10028/pins.csv similarity index 100% rename from ports/nrf/boards/pca10028/pins.csv rename to ports/nrf/boards/PCA10028/pins.csv diff --git a/ports/nrf/boards/pca10031/board.json b/ports/nrf/boards/PCA10031/board.json similarity index 100% rename from ports/nrf/boards/pca10031/board.json rename to ports/nrf/boards/PCA10031/board.json diff --git a/ports/nrf/boards/pca10031/mpconfigboard.h b/ports/nrf/boards/PCA10031/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/pca10031/mpconfigboard.h rename to ports/nrf/boards/PCA10031/mpconfigboard.h diff --git a/ports/nrf/boards/pca10028/mpconfigboard.mk b/ports/nrf/boards/PCA10031/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/pca10028/mpconfigboard.mk rename to ports/nrf/boards/PCA10031/mpconfigboard.mk diff --git a/ports/nrf/boards/pca10031/pins.csv b/ports/nrf/boards/PCA10031/pins.csv similarity index 100% rename from ports/nrf/boards/pca10031/pins.csv rename to ports/nrf/boards/PCA10031/pins.csv diff --git a/ports/nrf/boards/pca10040/board.json b/ports/nrf/boards/PCA10040/board.json similarity index 100% rename from ports/nrf/boards/pca10040/board.json rename to ports/nrf/boards/PCA10040/board.json diff --git a/ports/nrf/boards/pca10040/mpconfigboard.h b/ports/nrf/boards/PCA10040/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/pca10040/mpconfigboard.h rename to ports/nrf/boards/PCA10040/mpconfigboard.h diff --git a/ports/nrf/boards/evk_nina_b1/mpconfigboard.mk b/ports/nrf/boards/PCA10040/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/evk_nina_b1/mpconfigboard.mk rename to ports/nrf/boards/PCA10040/mpconfigboard.mk diff --git a/ports/nrf/boards/arduino_primo/pins.csv b/ports/nrf/boards/PCA10040/pins.csv similarity index 100% rename from ports/nrf/boards/arduino_primo/pins.csv rename to ports/nrf/boards/PCA10040/pins.csv diff --git a/ports/nrf/boards/pca10056/board.json b/ports/nrf/boards/PCA10056/board.json similarity index 100% rename from ports/nrf/boards/pca10056/board.json rename to ports/nrf/boards/PCA10056/board.json diff --git a/ports/nrf/boards/pca10056/mpconfigboard.h b/ports/nrf/boards/PCA10056/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/pca10056/mpconfigboard.h rename to ports/nrf/boards/PCA10056/mpconfigboard.h diff --git a/ports/nrf/boards/pca10056/mpconfigboard.mk b/ports/nrf/boards/PCA10056/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/pca10056/mpconfigboard.mk rename to ports/nrf/boards/PCA10056/mpconfigboard.mk diff --git a/ports/nrf/boards/evk_nina_b3/pins.csv b/ports/nrf/boards/PCA10056/pins.csv similarity index 100% rename from ports/nrf/boards/evk_nina_b3/pins.csv rename to ports/nrf/boards/PCA10056/pins.csv diff --git a/ports/nrf/boards/pca10059/board.json b/ports/nrf/boards/PCA10059/board.json similarity index 100% rename from ports/nrf/boards/pca10059/board.json rename to ports/nrf/boards/PCA10059/board.json diff --git a/ports/nrf/boards/pca10059/modules/boardmodules.h b/ports/nrf/boards/PCA10059/modules/boardmodules.h similarity index 100% rename from ports/nrf/boards/pca10059/modules/boardmodules.h rename to ports/nrf/boards/PCA10059/modules/boardmodules.h diff --git a/ports/nrf/boards/pca10059/modules/boardmodules.mk b/ports/nrf/boards/PCA10059/modules/boardmodules.mk similarity index 85% rename from ports/nrf/boards/pca10059/modules/boardmodules.mk rename to ports/nrf/boards/PCA10059/modules/boardmodules.mk index 413790fbea..d1457cde7c 100644 --- a/ports/nrf/boards/pca10059/modules/boardmodules.mk +++ b/ports/nrf/boards/PCA10059/modules/boardmodules.mk @@ -1,4 +1,4 @@ -BOARD_PCA10059_DIR = boards/pca10059/modules +BOARD_PCA10059_DIR = boards/PCA10059/modules INC += -I./$(BOARD_PCA10059_DIR) CFLAGS += -DBOARD_SPECIFIC_MODULES diff --git a/ports/nrf/boards/pca10059/modules/recover_uicr_regout0.c b/ports/nrf/boards/PCA10059/modules/recover_uicr_regout0.c similarity index 100% rename from ports/nrf/boards/pca10059/modules/recover_uicr_regout0.c rename to ports/nrf/boards/PCA10059/modules/recover_uicr_regout0.c diff --git a/ports/nrf/boards/pca10059/mpconfigboard.h b/ports/nrf/boards/PCA10059/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/pca10059/mpconfigboard.h rename to ports/nrf/boards/PCA10059/mpconfigboard.h diff --git a/ports/nrf/boards/nrf52840-mdk-usb-dongle/mpconfigboard.mk b/ports/nrf/boards/PCA10059/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/nrf52840-mdk-usb-dongle/mpconfigboard.mk rename to ports/nrf/boards/PCA10059/mpconfigboard.mk diff --git a/ports/nrf/boards/pca10059/pins.csv b/ports/nrf/boards/PCA10059/pins.csv similarity index 100% rename from ports/nrf/boards/pca10059/pins.csv rename to ports/nrf/boards/PCA10059/pins.csv diff --git a/ports/nrf/boards/pca10090/board.json b/ports/nrf/boards/PCA10090/board.json similarity index 100% rename from ports/nrf/boards/pca10090/board.json rename to ports/nrf/boards/PCA10090/board.json diff --git a/ports/nrf/boards/pca10090/mpconfigboard.h b/ports/nrf/boards/PCA10090/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/pca10090/mpconfigboard.h rename to ports/nrf/boards/PCA10090/mpconfigboard.h diff --git a/ports/nrf/boards/pca10090/mpconfigboard.mk b/ports/nrf/boards/PCA10090/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/pca10090/mpconfigboard.mk rename to ports/nrf/boards/PCA10090/mpconfigboard.mk diff --git a/ports/nrf/boards/pca10090/pins.csv b/ports/nrf/boards/PCA10090/pins.csv similarity index 100% rename from ports/nrf/boards/pca10090/pins.csv rename to ports/nrf/boards/PCA10090/pins.csv diff --git a/ports/nrf/boards/seeed_xiao_nrf52/XIAO_bootloader.ld b/ports/nrf/boards/SEEED_XIAO_NRF52/XIAO_bootloader.ld similarity index 100% rename from ports/nrf/boards/seeed_xiao_nrf52/XIAO_bootloader.ld rename to ports/nrf/boards/SEEED_XIAO_NRF52/XIAO_bootloader.ld diff --git a/ports/nrf/boards/seeed_xiao_nrf52/board.c b/ports/nrf/boards/SEEED_XIAO_NRF52/board.c similarity index 100% rename from ports/nrf/boards/seeed_xiao_nrf52/board.c rename to ports/nrf/boards/SEEED_XIAO_NRF52/board.c diff --git a/ports/nrf/boards/seeed_xiao_nrf52/board.json b/ports/nrf/boards/SEEED_XIAO_NRF52/board.json similarity index 62% rename from ports/nrf/boards/seeed_xiao_nrf52/board.json rename to ports/nrf/boards/SEEED_XIAO_NRF52/board.json index 619a7c23b9..d40355bb2e 100644 --- a/ports/nrf/boards/seeed_xiao_nrf52/board.json +++ b/ports/nrf/boards/SEEED_XIAO_NRF52/board.json @@ -4,14 +4,13 @@ ], "docs": "", "features": [ - "Bluetooth 5.0", - "IMU LSM6DS3TR", - "Microphone MSM261D3526H1CPM", - "USB-C", - "Breadboard Friendly", - "Battery Management", + "BLE", + "Battery Charging", + "External Flash", + "IMU", + "Microphone", "RGB LED", - "QSPI Flash" + "USB-C" ], "images": [ "XIAO_nrf52840_front.jpg" diff --git a/ports/nrf/boards/seeed_xiao_nrf52/deploy.md b/ports/nrf/boards/SEEED_XIAO_NRF52/deploy.md similarity index 100% rename from ports/nrf/boards/seeed_xiao_nrf52/deploy.md rename to ports/nrf/boards/SEEED_XIAO_NRF52/deploy.md diff --git a/ports/nrf/boards/seeed_xiao_nrf52/mpconfigboard.h b/ports/nrf/boards/SEEED_XIAO_NRF52/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/seeed_xiao_nrf52/mpconfigboard.h rename to ports/nrf/boards/SEEED_XIAO_NRF52/mpconfigboard.h diff --git a/ports/nrf/boards/seeed_xiao_nrf52/mpconfigboard.mk b/ports/nrf/boards/SEEED_XIAO_NRF52/mpconfigboard.mk similarity index 82% rename from ports/nrf/boards/seeed_xiao_nrf52/mpconfigboard.mk rename to ports/nrf/boards/SEEED_XIAO_NRF52/mpconfigboard.mk index c2fc219187..1f495a9c64 100644 --- a/ports/nrf/boards/seeed_xiao_nrf52/mpconfigboard.mk +++ b/ports/nrf/boards/SEEED_XIAO_NRF52/mpconfigboard.mk @@ -3,7 +3,7 @@ MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52840 SOFTDEV_VERSION = 7.3.0 SD=s140 -LD_FILES += boards/seeed_xiao_nrf52/XIAO_bootloader.ld boards/nrf52840_1M_256k.ld +LD_FILES += boards/SEEED_XIAO_NRF52/XIAO_bootloader.ld boards/nrf52840_1M_256k.ld NRF_DEFINES += -DNRF52840_XXAA diff --git a/ports/nrf/boards/seeed_xiao_nrf52/pins.csv b/ports/nrf/boards/SEEED_XIAO_NRF52/pins.csv similarity index 100% rename from ports/nrf/boards/seeed_xiao_nrf52/pins.csv rename to ports/nrf/boards/SEEED_XIAO_NRF52/pins.csv diff --git a/ports/nrf/boards/wt51822_s4at/board.json b/ports/nrf/boards/WT51822_S4AT/board.json similarity index 100% rename from ports/nrf/boards/wt51822_s4at/board.json rename to ports/nrf/boards/WT51822_S4AT/board.json diff --git a/ports/nrf/boards/wt51822_s4at/mpconfigboard.h b/ports/nrf/boards/WT51822_S4AT/mpconfigboard.h similarity index 100% rename from ports/nrf/boards/wt51822_s4at/mpconfigboard.h rename to ports/nrf/boards/WT51822_S4AT/mpconfigboard.h diff --git a/ports/nrf/boards/wt51822_s4at/mpconfigboard.mk b/ports/nrf/boards/WT51822_S4AT/mpconfigboard.mk similarity index 100% rename from ports/nrf/boards/wt51822_s4at/mpconfigboard.mk rename to ports/nrf/boards/WT51822_S4AT/mpconfigboard.mk diff --git a/ports/nrf/boards/wt51822_s4at/pins.csv b/ports/nrf/boards/WT51822_S4AT/pins.csv similarity index 100% rename from ports/nrf/boards/wt51822_s4at/pins.csv rename to ports/nrf/boards/WT51822_S4AT/pins.csv diff --git a/ports/nrf/examples/ssd1306_mod.py b/ports/nrf/examples/ssd1306_mod.py index b083a3aa7e..d42d165fa8 100644 --- a/ports/nrf/examples/ssd1306_mod.py +++ b/ports/nrf/examples/ssd1306_mod.py @@ -19,6 +19,7 @@ # disp = SSD1306_I2C_Mod(128, 64, i2c) from ssd1306 import SSD1306_I2C +from micropython import const SET_COL_ADDR = const(0x21) SET_PAGE_ADDR = const(0x22) diff --git a/ports/nrf/examples/ubluepy_eddystone.py b/ports/nrf/examples/ubluepy_eddystone.py index 96818d01c2..c98a2266f5 100644 --- a/ports/nrf/examples/ubluepy_eddystone.py +++ b/ports/nrf/examples/ubluepy_eddystone.py @@ -1,3 +1,4 @@ +from micropython import const from ubluepy import Peripheral, constants BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE = const(0x02) diff --git a/ports/qemu-arm/test-frzmpy/frozen_asm.py b/ports/qemu-arm/test-frzmpy/frozen_asm.py index 2c7f5c92cd..ba43264b38 100644 --- a/ports/qemu-arm/test-frzmpy/frozen_asm.py +++ b/ports/qemu-arm/test-frzmpy/frozen_asm.py @@ -1,5 +1,7 @@ # Test freezing inline-asm code. +# ruff: noqa: F821 - @asm_thumb decorator adds names to function scope + import micropython diff --git a/ports/renesas-ra/boards/EK_RA4M1/board.json b/ports/renesas-ra/boards/EK_RA4M1/board.json index bab3bcacee..4d8dcd5e6d 100644 --- a/ports/renesas-ra/boards/EK_RA4M1/board.json +++ b/ports/renesas-ra/boards/EK_RA4M1/board.json @@ -3,17 +3,11 @@ "../deploy.md" ], "docs": "", - "features": [ - "UART", - "SPI", - "I2C", - "ADC" - ], - "id": "EK-RA4M1", + "features": [], "images": [ "ek_ra4m1_board.jpg" ], - "mcu": "RA4M1", + "mcu": "ra4m1", "product": "EK-RA4M1", "thumbnail": "", "url": "https://www.renesas.com/products/microcontrollers-microprocessors/ra-cortex-m-mcus/ek-ra4m1-evaluation-kit-ra4m1-mcu-group", diff --git a/ports/renesas-ra/boards/EK_RA4W1/board.json b/ports/renesas-ra/boards/EK_RA4W1/board.json index db06b6751d..edc4fcbfe0 100644 --- a/ports/renesas-ra/boards/EK_RA4W1/board.json +++ b/ports/renesas-ra/boards/EK_RA4W1/board.json @@ -3,17 +3,11 @@ "../deploy.md" ], "docs": "", - "features": [ - "UART", - "SPI", - "I2C", - "ADC" - ], - "id": "EK-RA4W1", + "features": [], "images": [ "ek_ra4w1_board.jpg" ], - "mcu": "RA4W1", + "mcu": "ra4w1", "product": "EK-RA4W1", "thumbnail": "", "url": "https://www.renesas.com/products/microcontrollers-microprocessors/ra-cortex-m-mcus/ek-ra4w1-evaluation-kit-ra4w1-mcu-group", diff --git a/ports/renesas-ra/boards/EK_RA6M1/board.json b/ports/renesas-ra/boards/EK_RA6M1/board.json index babcc5c166..3bdb08b92f 100644 --- a/ports/renesas-ra/boards/EK_RA6M1/board.json +++ b/ports/renesas-ra/boards/EK_RA6M1/board.json @@ -3,17 +3,11 @@ "../deploy.md" ], "docs": "", - "features": [ - "UART", - "SPI", - "I2C", - "ADC" - ], - "id": "EK-RA6M1", + "features": [], "images": [ "ek_ra6m1_board.jpg" ], - "mcu": "RA6M1", + "mcu": "ra6m1", "product": "EK-RA6M1", "thumbnail": "", "url": "https://www.renesas.com/products/microcontrollers-microprocessors/ra-cortex-m-mcus/ek-ra6m1-evaluation-kit-ra6m1-mcu-group", diff --git a/ports/renesas-ra/boards/EK_RA6M2/board.json b/ports/renesas-ra/boards/EK_RA6M2/board.json index 63547d8807..5760b19736 100644 --- a/ports/renesas-ra/boards/EK_RA6M2/board.json +++ b/ports/renesas-ra/boards/EK_RA6M2/board.json @@ -3,13 +3,7 @@ "../deploy.md" ], "docs": "", - "features": [ - "UART", - "SPI", - "I2C", - "ADC" - ], - "id": "EK-RA6M2", + "features": [], "images": [ "ek_ra6m2_board.jpg", "ek_ra6m2_j1_pins.jpg", @@ -17,7 +11,7 @@ "ek_ra6m2_j3_pins.jpg", "ek_ra6m2_j4_pins.jpg" ], - "mcu": "RA6M2", + "mcu": "ra6m2", "product": "EK-RA6M2", "thumbnail": "", "url": "https://www.renesas.com/products/microcontrollers-microprocessors/ra-cortex-m-mcus/ek-ra6m2-evaluation-kit-ra6m2-mcu-group", diff --git a/ports/renesas-ra/boards/RA4M1_CLICKER/board.json b/ports/renesas-ra/boards/RA4M1_CLICKER/board.json index 1c3c4c8e91..be1dd977c3 100644 --- a/ports/renesas-ra/boards/RA4M1_CLICKER/board.json +++ b/ports/renesas-ra/boards/RA4M1_CLICKER/board.json @@ -3,18 +3,12 @@ "../deploy.md" ], "docs": "", - "features": [ - "UART", - "SPI", - "I2C", - "ADC" - ], - "id": "RA4M1-CLICKER", + "features": [], "images": [ "ra4m1_clicker_board.jpg", "ra4m1_clicker_pins.jpg" ], - "mcu": "RA4M1", + "mcu": "ra4m1", "product": "Mikroe RA4M1 Clicker", "thumbnail": "", "url": "https://www.mikroe.com/ra4m1-clicker", diff --git a/ports/renesas-ra/boards/VK_RA6M5/board.json b/ports/renesas-ra/boards/VK_RA6M5/board.json index ae11d52213..48371138b1 100644 --- a/ports/renesas-ra/boards/VK_RA6M5/board.json +++ b/ports/renesas-ra/boards/VK_RA6M5/board.json @@ -4,18 +4,12 @@ ], "docs": "", "features": [ - "UART", - "SPI", - "I2C", - "ADC", - "DAC", - "PWM" + "DAC" ], - "id": "VK-RA6M5", "images": [ "VK-RA6M5.jpg" ], - "mcu": "RA6M5", + "mcu": "ra6m5", "product": "VK-RA6M5", "thumbnail": "", "url": "https://vekatech.com/VK-RA6M5_docs/brochures/VK-RA6M5%20Flyer%20R2.pdf", diff --git a/ports/renesas-ra/boards/make-pins.py b/ports/renesas-ra/boards/make-pins.py index 1b4588f02f..5147d27940 100644 --- a/ports/renesas-ra/boards/make-pins.py +++ b/ports/renesas-ra/boards/make-pins.py @@ -220,13 +220,7 @@ class Pins(object): for named_pin in self.board_pins: qstr_set |= set([named_pin.name()]) for qstr in sorted(qstr_set): - cond_var = None - if qstr.startswith("AF"): - af_words = qstr.split("_") - cond_var = conditional_var(af_words[1]) - print_conditional_if(cond_var, file=qstr_file) print("Q({})".format(qstr), file=qstr_file) - # print_conditional_endif(cond_var, file=qstr_file) def print_ad_hdr(self, ad_const_filename): with open(ad_const_filename, "wt") as ad_const_file: diff --git a/ports/renesas-ra/mpthreadport.c b/ports/renesas-ra/mpthreadport.c index ecdb268468..a7d85cfe32 100644 --- a/ports/renesas-ra/mpthreadport.c +++ b/ports/renesas-ra/mpthreadport.c @@ -54,7 +54,11 @@ void mp_thread_gc_others(void) { mp_thread_mutex_unlock(&thread_mutex); } -void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { +mp_uint_t mp_thread_get_id(void) { + return (uint32_t)pyb_thread_cur; +} + +mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { if (*stack_size == 0) { *stack_size = 4096; // default stack size } else if (*stack_size < 2048) { @@ -82,6 +86,8 @@ void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { // adjust stack_size to provide room to recover from hitting the limit *stack_size -= 1024; + + return id; } void mp_thread_start(void) { diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 4334a0aba9..7718697b43 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -26,7 +26,7 @@ set(MICROPY_PORT_DIR ${CMAKE_CURRENT_LIST_DIR}) # Set the board if it's not already set. if(NOT MICROPY_BOARD) - set(MICROPY_BOARD PICO) + set(MICROPY_BOARD RPI_PICO) endif() # Set the board directory and check that it exists. diff --git a/ports/rp2/Makefile b/ports/rp2/Makefile index 4f5b4728ec..8399b9e98a 100644 --- a/ports/rp2/Makefile +++ b/ports/rp2/Makefile @@ -8,16 +8,25 @@ ifdef BOARD_DIR # the path as the board name. BOARD ?= $(notdir $(BOARD_DIR:/=)) else -# If not given on the command line, then default to PICO. -BOARD ?= PICO +# If not given on the command line, then default to RPI_PICO. +BOARD ?= RPI_PICO BOARD_DIR ?= boards/$(BOARD) endif ifeq ($(wildcard $(BOARD_DIR)/.),) +ifeq ($(findstring boards/PICO,$(BOARD_DIR)),boards/PICO) +$(warning The PICO* boards have been renamed to RPI_PICO*) +endif $(error Invalid BOARD specified: $(BOARD_DIR)) endif - + +# If the build directory is not given, make it reflect the board name (and +# optionally the board variant). +ifneq ($(BOARD_VARIANT),) +BUILD ?= build-$(BOARD)-$(BOARD_VARIANT) +else BUILD ?= build-$(BOARD) +endif $(VERBOSE)MAKESILENT = -s @@ -36,7 +45,7 @@ CMAKE_ARGS += -DCMAKE_BUILD_TYPE=Debug endif ifdef BOARD_VARIANT -CMAKE_ARGS += -DBOARD_VARIANT=${BOARD_VARIANT} +CMAKE_ARGS += -DMICROPY_BOARD_VARIANT=$(BOARD_VARIANT) endif HELP_BUILD_ERROR ?= "See \033[1;31mhttps://github.com/micropython/micropython/wiki/Build-Troubleshooting\033[0m" @@ -50,13 +59,13 @@ clean: # First ensure that pico-sdk is initialised, then use cmake to pick everything # else (including board-specific dependencies). +# Running the build with ECHO_SUBMODULES set will trigger py/mkrules.cmake to +# print out the value of the GIT_SUBMODULES variable, prefixed with +# "GIT_SUBMODULES", and then abort. This extracts out that line from the cmake +# output and passes the list of submodules to py/mkrules.mk which does the +# `git submodule init` on each. submodules: $(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="lib/pico-sdk" submodules - GIT_SUBMODULES=$$(cmake -B $(BUILD)/submodules -DECHO_SUBMODULES=1 ${CMAKE_ARGS} -S . 2>&1 | \ + @GIT_SUBMODULES=$$(cmake -B $(BUILD)/submodules -DECHO_SUBMODULES=1 ${CMAKE_ARGS} -S . 2>&1 | \ grep '^GIT_SUBMODULES=' | cut -d= -f2); \ $(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="$${GIT_SUBMODULES}" submodules - -query-variants: - @BOARD_VARIANTS=$$(cmake -B $(BUILD)/variants -DECHO_BOARD_VARIANTS=1 ${CMAKE_ARGS} -S . 2>&1 | \ - grep '^BOARD_VARIANTS=' | cut -d= -f2); \ - echo "VARIANTS: $${BOARD_VARIANTS}" diff --git a/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/board.json b/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/board.json index a7db469389..be63f4430b 100644 --- a/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/board.json +++ b/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/board.json @@ -5,11 +5,11 @@ "docs": "", "features": [ "Battery Charging", - "Breadboard Friendly", + "Dual-core", + "External Flash", "Feather", + "JST-SH", "RGB LED", - "SPI Flash", - "STEMMA QT/QWIIC", "USB-C" ], "images": [ diff --git a/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/board.json b/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/board.json index 7ca0db0698..ea9070e13c 100644 --- a/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/board.json +++ b/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/board.json @@ -4,10 +4,10 @@ ], "docs": "", "features": [ - "Breadboard Friendly", - "Micro USB", + "Dual-core", + "External Flash", "RGB LED", - "SPI Flash" + "USB" ], "images": [ "4888-05.jpg" diff --git a/ports/rp2/boards/ADAFRUIT_QTPY_RP2040/board.json b/ports/rp2/boards/ADAFRUIT_QTPY_RP2040/board.json index d63166616f..d5e4394f4e 100644 --- a/ports/rp2/boards/ADAFRUIT_QTPY_RP2040/board.json +++ b/ports/rp2/boards/ADAFRUIT_QTPY_RP2040/board.json @@ -4,11 +4,10 @@ ], "docs": "", "features": [ - "Breadboard Friendly", - "Castellated Pads", + "Dual-core", + "External Flash", + "JST-SH", "RGB LED", - "SPI Flash", - "STEMMA QT/QWIIC", "USB-C" ], "images": [ diff --git a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/board.json b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/board.json index 5bd03e1e0b..5639aaa2a4 100644 --- a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/board.json +++ b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/board.json @@ -4,15 +4,14 @@ ], "docs": "", "features": [ - "Breadboard Friendly", - "Castellated Pads", - "WiFi Nina-W102", - "Bluetooth Nina-W102", - "IMU LSM6DSOXTR", - "Crypto IC ATECC608A-MAHDA-T", - "Microphone MP34DT05", - "SPI Flash 16MB", - "USB-MICRO" + "BLE", + "Dual-core", + "External Flash", + "IMU", + "Microphone", + "Secure Element", + "USB", + "WiFi" ], "images": [ "ABX00052_01.iso_999x750.jpg" diff --git a/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/board.json b/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/board.json index 1b9e113143..df9dd5d0de 100644 --- a/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/board.json +++ b/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/board.json @@ -4,12 +4,10 @@ ], "docs": "", "features": [ - "USB Stick form factor", - "Breadboard Friendly", - "Reset/User button", - "Red/green/orange/blue leds", - "1MB SPI Flash", - "USB-A" + "Dual-core", + "External Flash", + "RGB LED", + "USB" ], "images": [ "pybstick-rp2040-26-broches-micropython-c.jpg" diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/board.json b/ports/rp2/boards/NULLBITS_BIT_C_PRO/board.json index 2aff0580d8..08aa7068ef 100644 --- a/ports/rp2/boards/NULLBITS_BIT_C_PRO/board.json +++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/board.json @@ -4,10 +4,10 @@ ], "docs": "", "features": [ - "Breadboard Friendly", + "Dual-core", + "External Flash", "RGB LED", - "USB-C", - "SPI Flash" + "USB-C" ], "images": [ "nullbits_bit_c_pro.jpg" diff --git a/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/board.json b/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/board.json index 9121154d81..c44ea55514 100644 --- a/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/board.json +++ b/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/board.json @@ -5,10 +5,9 @@ "docs": "", "features": [ "Battery Charging", - "Breadboard Friendly", - "Castellated Pads", - "SPI Flash", - "STEMMA QT/QWIIC", + "Dual-core", + "External Flash", + "JST-SH", "USB-C" ], "images": [ diff --git a/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/board.json b/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/board.json index 69d8532397..cb06c746b6 100644 --- a/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/board.json +++ b/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/board.json @@ -5,10 +5,9 @@ "docs": "", "features": [ "Battery Charging", - "Breadboard Friendly", - "Castellated Pads", - "SPI Flash", - "STEMMA QT/QWIIC", + "Dual-core", + "External Flash", + "JST-SH", "USB-C" ], "images": [ diff --git a/ports/rp2/boards/PIMORONI_TINY2040/board.json b/ports/rp2/boards/PIMORONI_TINY2040/board.json index 753a25beae..207647f6b2 100644 --- a/ports/rp2/boards/PIMORONI_TINY2040/board.json +++ b/ports/rp2/boards/PIMORONI_TINY2040/board.json @@ -4,8 +4,8 @@ ], "docs": "", "features": [ - "Breadboard Friendly", - "Castellated Pads", + "Dual-core", + "External Flash", "RGB LED", "USB-C" ], diff --git a/ports/rp2/boards/PICO/board.json b/ports/rp2/boards/RPI_PICO/board.json similarity index 74% rename from ports/rp2/boards/PICO/board.json rename to ports/rp2/boards/RPI_PICO/board.json index 9abf505e54..07938978f3 100644 --- a/ports/rp2/boards/PICO/board.json +++ b/ports/rp2/boards/RPI_PICO/board.json @@ -4,11 +4,10 @@ ], "docs": "", "features": [ - "Breadboard friendly", - "Castellated Pads", - "Micro USB" + "Dual-core", + "External Flash", + "USB" ], - "id": "rp2-pico", "images": [ "rp2-pico.jpg" ], diff --git a/ports/rp2/boards/PICO/mpconfigboard.cmake b/ports/rp2/boards/RPI_PICO/mpconfigboard.cmake similarity index 60% rename from ports/rp2/boards/PICO/mpconfigboard.cmake rename to ports/rp2/boards/RPI_PICO/mpconfigboard.cmake index 3a40ca2871..13269e81e5 100644 --- a/ports/rp2/boards/PICO/mpconfigboard.cmake +++ b/ports/rp2/boards/RPI_PICO/mpconfigboard.cmake @@ -1 +1,2 @@ # cmake file for Raspberry Pi Pico +set(PICO_BOARD "pico") diff --git a/ports/rp2/boards/PICO/mpconfigboard.h b/ports/rp2/boards/RPI_PICO/mpconfigboard.h similarity index 100% rename from ports/rp2/boards/PICO/mpconfigboard.h rename to ports/rp2/boards/RPI_PICO/mpconfigboard.h diff --git a/ports/rp2/boards/PICO/pins.csv b/ports/rp2/boards/RPI_PICO/pins.csv similarity index 100% rename from ports/rp2/boards/PICO/pins.csv rename to ports/rp2/boards/RPI_PICO/pins.csv diff --git a/ports/rp2/boards/PICO_W/board.json b/ports/rp2/boards/RPI_PICO_W/board.json similarity index 68% rename from ports/rp2/boards/PICO_W/board.json rename to ports/rp2/boards/RPI_PICO_W/board.json index a85d7e0446..6ea326c6cd 100644 --- a/ports/rp2/boards/PICO_W/board.json +++ b/ports/rp2/boards/RPI_PICO_W/board.json @@ -4,13 +4,12 @@ ], "docs": "", "features": [ - "Breadboard friendly", - "Castellated Pads", - "Micro USB", - "WiFi", - "Bluetooth" + "BLE", + "Dual-core", + "External Flash", + "USB", + "WiFi" ], - "id": "rp2-pico-w", "images": [ "rp2-pico-w.jpg" ], diff --git a/ports/rp2/boards/PICO_W/manifest.py b/ports/rp2/boards/RPI_PICO_W/manifest.py similarity index 100% rename from ports/rp2/boards/PICO_W/manifest.py rename to ports/rp2/boards/RPI_PICO_W/manifest.py diff --git a/ports/rp2/boards/PICO_W/mpconfigboard.cmake b/ports/rp2/boards/RPI_PICO_W/mpconfigboard.cmake similarity index 93% rename from ports/rp2/boards/PICO_W/mpconfigboard.cmake rename to ports/rp2/boards/RPI_PICO_W/mpconfigboard.cmake index e6db8dda6a..5610c313e6 100644 --- a/ports/rp2/boards/PICO_W/mpconfigboard.cmake +++ b/ports/rp2/boards/RPI_PICO_W/mpconfigboard.cmake @@ -1,5 +1,7 @@ # cmake file for Raspberry Pi Pico W +set(PICO_BOARD "pico_w") + # The C malloc is needed by cyw43-driver Bluetooth set(MICROPY_C_HEAP_SIZE 4096) diff --git a/ports/rp2/boards/PICO_W/mpconfigboard.h b/ports/rp2/boards/RPI_PICO_W/mpconfigboard.h similarity index 100% rename from ports/rp2/boards/PICO_W/mpconfigboard.h rename to ports/rp2/boards/RPI_PICO_W/mpconfigboard.h diff --git a/ports/rp2/boards/PICO_W/pins.csv b/ports/rp2/boards/RPI_PICO_W/pins.csv similarity index 100% rename from ports/rp2/boards/PICO_W/pins.csv rename to ports/rp2/boards/RPI_PICO_W/pins.csv diff --git a/ports/rp2/boards/SPARKFUN_PROMICRO/board.json b/ports/rp2/boards/SPARKFUN_PROMICRO/board.json index a0d39165af..46878a29cd 100644 --- a/ports/rp2/boards/SPARKFUN_PROMICRO/board.json +++ b/ports/rp2/boards/SPARKFUN_PROMICRO/board.json @@ -4,10 +4,10 @@ ], "docs": "", "features": [ - "Breadboard Friendly", - "Castellated Pads", + "Dual-core", + "External Flash", + "JST-SH", "RGB LED", - "STEMMA QT/QWIIC", "USB-C" ], "images": [ diff --git a/ports/rp2/boards/SPARKFUN_THINGPLUS/board.json b/ports/rp2/boards/SPARKFUN_THINGPLUS/board.json index 871a411b5b..3eeb397265 100644 --- a/ports/rp2/boards/SPARKFUN_THINGPLUS/board.json +++ b/ports/rp2/boards/SPARKFUN_THINGPLUS/board.json @@ -5,13 +5,13 @@ "docs": "", "features": [ "Battery Charging", - "Breadboard Friendly", + "Dual-core", + "External Flash", "Feather", - "MicroSD", + "JST-SH", "RGB LED", - "SPI Flash", - "STEMMA QT/QWIIC", - "USB-C" + "USB-C", + "microSD" ], "images": [ "17745-SparkFun_Thing_Plus_-_RP2040-01a.jpg" diff --git a/ports/rp2/boards/W5100S_EVB_PICO/board.json b/ports/rp2/boards/W5100S_EVB_PICO/board.json index 4091b78433..daaf1cf8ac 100644 --- a/ports/rp2/boards/W5100S_EVB_PICO/board.json +++ b/ports/rp2/boards/W5100S_EVB_PICO/board.json @@ -4,10 +4,10 @@ ], "docs": "", "features": [ - "Breadboard Friendly", - "Castellated Pads", + "Dual-core", "Ethernet", - "Micro USB" + "External Flash", + "USB" ], "images": [ "W5100S-EVB-Pico.jpg" diff --git a/ports/rp2/boards/W5500_EVB_PICO/board.json b/ports/rp2/boards/W5500_EVB_PICO/board.json index 90b3186cd6..9359825559 100644 --- a/ports/rp2/boards/W5500_EVB_PICO/board.json +++ b/ports/rp2/boards/W5500_EVB_PICO/board.json @@ -4,10 +4,10 @@ ], "docs": "", "features": [ - "Breadboard Friendly", - "Castellated Pads", + "Dual-core", "Ethernet", - "Micro USB" + "External Flash", + "USB" ], "images": [ "W5500-EVB-Pico.jpg" diff --git a/ports/rp2/boards/WEACTSTUDIO/README.md b/ports/rp2/boards/WEACTSTUDIO/README.md index ae0acfd2c7..1d55350900 100644 --- a/ports/rp2/boards/WEACTSTUDIO/README.md +++ b/ports/rp2/boards/WEACTSTUDIO/README.md @@ -9,18 +9,15 @@ repository containing information on the board. ## Build notes -Builds can be configured with the `BOARD_VARIANT` parameter. Valid variants -can be displayed with the `query-variant` target. An example: +By default the firmware supports boards with 16MiB flash. This can be +configured using the `BOARD_VARIANT` parameter. The valid options are +`FLASH_2M`, 'FLASH_4M', and 'FLASH_8M'. ```bash > cd ports/rp2 -> make BOARD=WEACTSTUDIO query-variants -VARIANTS: flash_2mb flash_4mb flash_8mb flash_16mb -> make BOARD=WEACTSTUDIO BOARD_VARIANT=flash_8mb submodules all # Build the 8 MiB variant +> make BOARD=WEACTSTUDIO BOARD_VARIANT=FLASH_8M submodules all # Build the 8 MiB variant ``` -`flash_16mb` is the default if `BOARD_VARIANT` is not supplied. - ## Board-specific modules The `board` module contains definitions for the onboard LED and user button. diff --git a/ports/rp2/boards/WEACTSTUDIO/board.json b/ports/rp2/boards/WEACTSTUDIO/board.json index bac5263627..223bbdc07b 100644 --- a/ports/rp2/boards/WEACTSTUDIO/board.json +++ b/ports/rp2/boards/WEACTSTUDIO/board.json @@ -4,8 +4,8 @@ ], "docs": "", "features": [ - "Breadboard Friendly", - "SPI Flash", + "Dual-core", + "External Flash", "USB-C" ], "images": [ @@ -15,9 +15,9 @@ "product": "WeAct Studio RP2040", "url": "https://github.com/WeActTC/WeActStudio.RP2040CoreBoard", "variants": { - "flash_2mb": "2 MiB Flash", - "flash_4mb": "4 MiB Flash", - "flash_8mb": "8 MiB Flash" + "FLASH_2MB": "2 MiB Flash", + "FLASH_4MB": "4 MiB Flash", + "FLASH_8MB": "8 MiB Flash" }, "vendor": "WeAct" } diff --git a/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.cmake b/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.cmake index 5fd3eec897..848b50f604 100644 --- a/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.cmake +++ b/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.cmake @@ -7,20 +7,18 @@ list(APPEND PICO_BOARD_HEADER_DIRS ${MICROPY_BOARD_DIR}) # Freeze board.py set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py) -# Provide different variants for the downloads page -set(BOARD_VARIANTS "flash_2mb flash_4mb flash_8mb flash_16mb") - # Select the 16MB variant as the default -set(PICO_BOARD "weactstudio_16mb") +set(PICO_BOARD "weactstudio_16MiB") -if("${BOARD_VARIANT}" STREQUAL "flash_2mb") - set(PICO_BOARD "weactstudio_2mb") +# Provide different variants for the downloads page +if(MICROPY_BOARD_VARIANT STREQUAL "FLASH_2M") + set(PICO_BOARD "weactstudio_2MiB") endif() -if("${BOARD_VARIANT}" STREQUAL "flash_4mb") -set(PICO_BOARD "weactstudio_4mb") +if(MICROPY_BOARD_VARIANT STREQUAL "FLASH_4M") + set(PICO_BOARD "weactstudio_4MiB") endif() -if("${BOARD_VARIANT}" STREQUAL "flash_8mb") -set(PICO_BOARD "weactstudio_8mb") +if(MICROPY_BOARD_VARIANT STREQUAL "FLASH_8M") + set(PICO_BOARD "weactstudio_8MiB") endif() diff --git a/ports/rp2/boards/WEACTSTUDIO/weactstudio_16mb.h b/ports/rp2/boards/WEACTSTUDIO/weactstudio_16MiB.h similarity index 100% rename from ports/rp2/boards/WEACTSTUDIO/weactstudio_16mb.h rename to ports/rp2/boards/WEACTSTUDIO/weactstudio_16MiB.h diff --git a/ports/rp2/boards/WEACTSTUDIO/weactstudio_2mb.h b/ports/rp2/boards/WEACTSTUDIO/weactstudio_2MiB.h similarity index 100% rename from ports/rp2/boards/WEACTSTUDIO/weactstudio_2mb.h rename to ports/rp2/boards/WEACTSTUDIO/weactstudio_2MiB.h diff --git a/ports/rp2/boards/WEACTSTUDIO/weactstudio_4mb.h b/ports/rp2/boards/WEACTSTUDIO/weactstudio_4MiB.h similarity index 100% rename from ports/rp2/boards/WEACTSTUDIO/weactstudio_4mb.h rename to ports/rp2/boards/WEACTSTUDIO/weactstudio_4MiB.h diff --git a/ports/rp2/boards/WEACTSTUDIO/weactstudio_8mb.h b/ports/rp2/boards/WEACTSTUDIO/weactstudio_8MiB.h similarity index 100% rename from ports/rp2/boards/WEACTSTUDIO/weactstudio_8mb.h rename to ports/rp2/boards/WEACTSTUDIO/weactstudio_8MiB.h diff --git a/ports/rp2/machine_timer.c b/ports/rp2/machine_timer.c index e4fbb03af4..f0df541e6b 100644 --- a/ports/rp2/machine_timer.c +++ b/ports/rp2/machine_timer.c @@ -57,7 +57,12 @@ STATIC int64_t alarm_callback(alarm_id_t id, void *user_data) { STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); qstr mode = self->mode == TIMER_MODE_ONE_SHOT ? MP_QSTR_ONE_SHOT : MP_QSTR_PERIODIC; - mp_printf(print, "Timer(mode=%q, period=%u, tick_hz=1000000)", mode, self->delta_us); + mp_printf(print, "Timer(mode=%q, tick_hz=1000000, period=", mode); + if (self->delta_us <= 0xffffffff) { + mp_printf(print, "%u)", (uint32_t)self->delta_us); + } else { + mp_printf(print, "%u000)", (uint32_t)(self->delta_us / 1000)); + } } STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { diff --git a/ports/rp2/mpthreadport.c b/ports/rp2/mpthreadport.c index 33dc698305..ed9e338da7 100644 --- a/ports/rp2/mpthreadport.c +++ b/ports/rp2/mpthreadport.c @@ -116,7 +116,13 @@ STATIC void core1_entry_wrapper(void) { // returning from here will loop the core forever (WFI) } -void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { +mp_uint_t mp_thread_get_id(void) { + // On RP2, there are only two threads, one for each core, so the thread id + // is the core number. + return get_core_num(); +} + +mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { // Check if core1 is already in use. if (core1_entry != NULL) { mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("core1 in use")); @@ -144,6 +150,8 @@ void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { // Adjust stack_size to provide room to recover from hitting the limit. *stack_size -= 512; + + return 1; } void mp_thread_start(void) { diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/board.json index b0cb02cd4f..22a9ffccba 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/board.json +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/board.json @@ -5,11 +5,10 @@ "docs": "", "features": [ "Battery Charging", - "Breadboard Friendly", + "External Flash", "Feather", - "Micro USB", "RGB LED", - "SPI Flash" + "USB" ], "images": [ "feather_m0_express.jpg" diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json index c8042aa254..06cd9a4fe4 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json @@ -5,11 +5,10 @@ "docs": "", "features": [ "Battery Charging", - "Breadboard Friendly", + "External Flash", "Feather", - "Micro USB", "RGB LED", - "SPI Flash" + "USB" ], "images": [ "feather_m4_express.jpg" diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/board.json index f99d19ca87..0e423b2b8e 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/board.json +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/board.json @@ -4,10 +4,9 @@ ], "docs": "", "features": [ - "Breadboard Friendly", - "Micro USB", + "External Flash", "RGB LED", - "SPI Flash" + "USB" ], "images": [ "itsybitsy_m0_express.jpg" diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json index 83db285b4d..a998529ccd 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json @@ -4,10 +4,9 @@ ], "docs": "", "features": [ - "Breadboard Friendly", - "Micro USB", + "External Flash", "RGB LED", - "SPI Flash" + "USB" ], "images": [ "itsybitsy_m4_express.jpg" diff --git a/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json index e0a256cf88..f830ff223f 100644 --- a/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json +++ b/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json @@ -4,14 +4,12 @@ ], "docs": "", "features": [ - "Micro USB", - "ADC", - "DAC", - "RGB LED", - "QSPI Flash", - "WiFi", "BLE", - "JLink" + "DAC", + "External Flash", + "RGB LED", + "USB", + "WiFi" ], "images": [ "metro_m4_express_airlift.jpg" diff --git a/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk index 1a2635f7af..43ca5a59cc 100644 --- a/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk +++ b/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk @@ -7,5 +7,4 @@ TEXT0 = 0x4000 MICROPY_PY_NETWORK ?= 1 MICROPY_PY_NETWORK_NINAW10 ?= 1 -BOARD_VARIANTS += "wlan" MICROPY_HW_CODESIZE ?= 496K diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/board.json b/ports/samd/boards/ADAFRUIT_TRINKET_M0/board.json index 9112bc06ef..d77282db01 100644 --- a/ports/samd/boards/ADAFRUIT_TRINKET_M0/board.json +++ b/ports/samd/boards/ADAFRUIT_TRINKET_M0/board.json @@ -4,9 +4,8 @@ ], "docs": "", "features": [ - "Breadboard Friendly", - "Micro USB", - "RGB LED" + "RGB LED", + "USB" ], "images": [ "trinket_m0.jpg" diff --git a/ports/samd/boards/MINISAM_M4/board.json b/ports/samd/boards/MINISAM_M4/board.json index 126e036400..6489dae863 100644 --- a/ports/samd/boards/MINISAM_M4/board.json +++ b/ports/samd/boards/MINISAM_M4/board.json @@ -4,9 +4,9 @@ ], "docs": "", "features": [ - "Micro USB", + "External Flash", "RGB LED", - "SPI Flash" + "USB" ], "images": [ "mini_sam_m4.jpg" diff --git a/ports/samd/boards/SAMD21_XPLAINED_PRO/board.json b/ports/samd/boards/SAMD21_XPLAINED_PRO/board.json index 4d22c42bad..c59ebc1b7b 100644 --- a/ports/samd/boards/SAMD21_XPLAINED_PRO/board.json +++ b/ports/samd/boards/SAMD21_XPLAINED_PRO/board.json @@ -4,10 +4,12 @@ ], "docs": "", "features": [ - "Micro USB", - "SPI Flash" + "External Flash", + "USB" + ], + "images": [ + "2033-atsamd21-xpro.jpg" ], - "images": ["2033-atsamd21-xpro.jpg"], "mcu": "samd21", "product": "SAMD21 Xplained Pro", "thumbnail": "", diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/board.json b/ports/samd/boards/SEEED_WIO_TERMINAL/board.json index 350ada4c4a..5300b03808 100644 --- a/ports/samd/boards/SEEED_WIO_TERMINAL/board.json +++ b/ports/samd/boards/SEEED_WIO_TERMINAL/board.json @@ -4,14 +4,17 @@ ], "docs": "", "features": [ - "USB-C", - "Display", - "Grove", - "WiFi", "BLE", - "SDCard" + "Display", + "External Flash", + "JST-PH", + "SDCard", + "USB-C", + "WiFi" + ], + "images": [ + "wio-terminal.jpg" ], - "images": ["wio-terminal.jpg"], "mcu": "samd51", "product": "Wio Terminal D51R", "thumbnail": "", diff --git a/ports/samd/boards/SEEED_XIAO_SAMD21/board.json b/ports/samd/boards/SEEED_XIAO_SAMD21/board.json index 4e6217e19e..4d19f6b945 100644 --- a/ports/samd/boards/SEEED_XIAO_SAMD21/board.json +++ b/ports/samd/boards/SEEED_XIAO_SAMD21/board.json @@ -6,7 +6,9 @@ "features": [ "USB-C" ], - "images": ["seeeduino-xiao.jpg"], + "images": [ + "seeeduino-xiao.jpg" + ], "mcu": "samd21", "product": "Seeeduino XIAO (SAMD21)", "thumbnail": "", diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json index af643f5c5f..ee9ca9d368 100644 --- a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json +++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json @@ -5,10 +5,9 @@ "docs": "", "features": [ "Battery Charging", - "Breadboard Friendly", - "Micro USB", - "QWIIC", - "SPI Flash" + "External Flash", + "JST-SH", + "USB" ], "images": [ "sparkfun_samd51_thing_plus.jpg" diff --git a/ports/samd/modules/_boot.py b/ports/samd/modules/_boot.py index 1ff51de598..93522e2ea3 100644 --- a/ports/samd/modules/_boot.py +++ b/ports/samd/modules/_boot.py @@ -1,6 +1,7 @@ import gc import os import samd +import sys bdev = samd.Flash() @@ -13,7 +14,8 @@ except: fs_type.mkfs(bdev, progsize=256) vfs = fs_type(bdev, progsize=256) os.mount(vfs, "/") +sys.path.append("/lib") -del vfs, fs_type, bdev, os, samd +del vfs, fs_type, bdev, os, samd, sys gc.collect() del gc diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 81a48249e8..475d8f1004 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -13,8 +13,13 @@ ifeq ($(wildcard $(BOARD_DIR)/.),) $(error Invalid BOARD specified: $(BOARD_DIR)) endif -# If the build directory is not given, make it reflect the board name. +# If the build directory is not given, make it reflect the board name (and +# optionally the board variant). +ifneq ($(BOARD_VARIANT),) +BUILD ?= build-$(BOARD)-$(BOARD_VARIANT) +else BUILD ?= build-$(BOARD) +endif include ../../py/mkenv.mk -include mpconfigport.mk @@ -43,9 +48,6 @@ include $(TOP)/extmod/extmod.mk GIT_SUBMODULES += lib/libhydrogen lib/stm32lib -query-variants: - $(ECHO) "VARIANTS:" $(BOARD_VARIANTS) - LD_DIR=boards USBDEV_DIR=usbdev #USBHOST_DIR=usbhost @@ -358,6 +360,7 @@ SRC_C += \ dac.c \ adc.c \ sdio.c \ + subghz.c \ $(wildcard $(BOARD_DIR)/*.c) SRC_O += \ diff --git a/ports/stm32/boards/ARDUINO_GIGA/board.json b/ports/stm32/boards/ARDUINO_GIGA/board.json index f0595d4ad5..53c636c774 100644 --- a/ports/stm32/boards/ARDUINO_GIGA/board.json +++ b/ports/stm32/boards/ARDUINO_GIGA/board.json @@ -4,11 +4,12 @@ ], "docs": "", "features": [ - "8MB SDRAM", - "16MB Flash", - "Dual-core processor", - "USB Full speed", - "CYW43 WiFi/BT Module" + "BLE", + "Dual-core", + "External Flash", + "External RAM", + "USB", + "WiFi" ], "images": [ "ABX00063_01.front_1000x750.jpg" diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/board.json b/ports/stm32/boards/ARDUINO_NICLA_VISION/board.json index 801bc320b5..a4c81d69d4 100644 --- a/ports/stm32/boards/ARDUINO_NICLA_VISION/board.json +++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/board.json @@ -4,11 +4,12 @@ ], "docs": "", "features": [ - "16MB Flash", - "Dual-core processor", - "USB High Speed Phy", - "CYW43 WiFi/BT Module", - "NXP SE050 crypto device" + "BLE", + "Dual-core", + "External Flash", + "Secure Element", + "USB", + "WiFi" ], "images": [ "ABX00051_01.iso_1000x750.jpg" diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/board.json b/ports/stm32/boards/ARDUINO_PORTENTA_H7/board.json index 6467e43bb9..f39d7d4c47 100644 --- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/board.json +++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/board.json @@ -4,14 +4,13 @@ ], "docs": "", "features": [ - "8MB SDRAM", - "16MB Flash", - "Dual-core processor", - "USB High Speed Phy", - "10/100 Ethernet Phy", - "CYW43 WiFi/BT Module", - "DisplayPort over USB-C", - "2x80 pin HD connectors" + "BLE", + "Dual-core", + "Ethernet", + "External Flash", + "External RAM", + "USB", + "WiFi" ], "images": [ "ABX00042_01.iso_1000x750.jpg" diff --git a/ports/stm32/boards/CERB40/board.json b/ports/stm32/boards/CERB40/board.json index f80b3f5cab..e3bd4296ba 100644 --- a/ports/stm32/boards/CERB40/board.json +++ b/ports/stm32/boards/CERB40/board.json @@ -8,8 +8,8 @@ "cerb40.jpg" ], "mcu": "stm32f4", - "product": "CERB40", + "product": "Cerb40", "thumbnail": "", "url": "", - "vendor": "" + "vendor": "Fez" } diff --git a/ports/stm32/boards/HYDRABUS/board.json b/ports/stm32/boards/HYDRABUS/board.json index 32561e6525..20a2ac5eae 100644 --- a/ports/stm32/boards/HYDRABUS/board.json +++ b/ports/stm32/boards/HYDRABUS/board.json @@ -8,8 +8,8 @@ "hydrabus.jpg" ], "mcu": "stm32f4", - "product": "HYDRABUS", + "product": "HydraBus v1.0", "thumbnail": "", "url": "", - "vendor": "" + "vendor": "HydraBus" } diff --git a/ports/stm32/boards/LEGO_HUB_NO6/board.json b/ports/stm32/boards/LEGO_HUB_NO6/board.json index c11b9f1818..3c602abba1 100644 --- a/ports/stm32/boards/LEGO_HUB_NO6/board.json +++ b/ports/stm32/boards/LEGO_HUB_NO6/board.json @@ -9,5 +9,5 @@ "product": "Hub No.6", "thumbnail": "", "url": "", - "vendor": "Lego" + "vendor": "LEGO" } diff --git a/ports/stm32/boards/LIMIFROG/board.json b/ports/stm32/boards/LIMIFROG/board.json index 3137350074..f516963a5b 100644 --- a/ports/stm32/boards/LIMIFROG/board.json +++ b/ports/stm32/boards/LIMIFROG/board.json @@ -8,8 +8,8 @@ "limifrog.jpg" ], "mcu": "stm32l4", - "product": "LIMIFROG", + "product": "LimiFrog", "thumbnail": "", "url": "", - "vendor": "" + "vendor": "LimiFrog" } diff --git a/ports/stm32/boards/MIKROE_QUAIL/board.json b/ports/stm32/boards/MIKROE_QUAIL/board.json index ccd9b4fdc0..689bdb1052 100644 --- a/ports/stm32/boards/MIKROE_QUAIL/board.json +++ b/ports/stm32/boards/MIKROE_QUAIL/board.json @@ -6,9 +6,8 @@ "features": [ "mikroBUS" ], - "id": "MIKROE-QUAIL", "images": [ - "quail_top.jpg" + "quail_top.jpg" ], "mcu": "stm32f4", "product": "MikroE Quail", diff --git a/ports/stm32/boards/NETDUINO_PLUS_2/board.json b/ports/stm32/boards/NETDUINO_PLUS_2/board.json index 044bc2736b..603032ee98 100644 --- a/ports/stm32/boards/NETDUINO_PLUS_2/board.json +++ b/ports/stm32/boards/NETDUINO_PLUS_2/board.json @@ -8,8 +8,8 @@ "netduino_plus_2.jpg" ], "mcu": "stm32f4", - "product": "NETDUINO_PLUS_2", + "product": "Netduino Plus 2", "thumbnail": "", "url": "", - "vendor": "" + "vendor": "Netduino" } diff --git a/ports/stm32/boards/NUCLEO_WB55/rfcore_debug.py b/ports/stm32/boards/NUCLEO_WB55/rfcore_debug.py index 4dbead0acc..db533f18dc 100644 --- a/ports/stm32/boards/NUCLEO_WB55/rfcore_debug.py +++ b/ports/stm32/boards/NUCLEO_WB55/rfcore_debug.py @@ -35,6 +35,7 @@ # See rfcore_firmware.py for more information. from machine import mem8, mem16, mem32 +from micropython import const import stm SRAM2A_BASE = const(0x2003_0000) diff --git a/ports/stm32/boards/NUCLEO_WL55/mpconfigboard.h b/ports/stm32/boards/NUCLEO_WL55/mpconfigboard.h index 51700ba8a5..843e855ce7 100644 --- a/ports/stm32/boards/NUCLEO_WL55/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_WL55/mpconfigboard.h @@ -14,7 +14,8 @@ #define MICROPY_PY_SOCKET (0) #define MICROPY_PY_NETWORK (0) #define MICROPY_PY_ONEWIRE (0) -#define MICROPY_PY_STM (0) +#define MICROPY_PY_STM (1) // for subghz radio functions +#define MICROPY_PY_STM_CONST (0) // saves size, no named registers #define MICROPY_PY_PYB_LEGACY (0) #define MICROPY_PY_HEAPQ (0) @@ -28,6 +29,13 @@ #define MICROPY_HW_RTC_USE_LSE (1) #define MICROPY_HW_RTC_USE_US (1) +// Use external 32MHz TCXO + PLL as system clock source +// (If unset, board will use the internal MSI oscillator instead.) +#define MICROPY_HW_CLK_USE_HSE (1) + +// HSE bypass for STM32WL5x means TCXO is powered from PB0_VDDTCXO pin +#define MICROPY_HW_CLK_USE_BYPASS (1) + // UART buses #define MICROPY_HW_UART1_TX (pin_B6) // Arduino D1, pin 7 on CN9 #define MICROPY_HW_UART1_RX (pin_B7) // Arduino D0, pin 8 on CN9 @@ -48,6 +56,10 @@ #define MICROPY_HW_SPI1_MISO (pin_A6) // Arduino D12, pin 5 on CN5 #define MICROPY_HW_SPI1_MOSI (pin_A7) // Arduino D11, pin 4 on CN5 +// SUBGHZSPI Internal radio SPI BUS +#define MICROPY_HW_SUBGHZSPI_NAME "SUBGHZ" +#define MICROPY_HW_SUBGHZSPI_ID 3 + // User switch; pressing the button makes the input go low #define MICROPY_HW_USRSW_PIN (pin_A0) #define MICROPY_HW_USRSW_PULL (GPIO_PULLUP) diff --git a/ports/stm32/boards/NUCLEO_WL55/pins.csv b/ports/stm32/boards/NUCLEO_WL55/pins.csv index afcf34df11..41e2d725a2 100644 --- a/ports/stm32/boards/NUCLEO_WL55/pins.csv +++ b/ports/stm32/boards/NUCLEO_WL55/pins.csv @@ -14,7 +14,8 @@ ,PA13 ,PA14 ,PA15 -,PB0 +# in the default board configuration, PB0 must stay muxed to analog for HSE VDDTCXO function +,-PB0 ,PB1 ,PB2 ,PB3 @@ -33,9 +34,9 @@ ,PC0 ,PC1 ,PC2 -,PC3 -,PC4 -,PC5 +FE_CTRL3,PC3 +FE_CTRL1,PC4 +FE_CTRL2,PC5 ,PC6 SW,PA0 SW1,PA0 diff --git a/ports/stm32/boards/PYBD_SF2/board.json b/ports/stm32/boards/PYBD_SF2/board.json index 534a048ff0..06a83e4d89 100644 --- a/ports/stm32/boards/PYBD_SF2/board.json +++ b/ports/stm32/boards/PYBD_SF2/board.json @@ -4,7 +4,6 @@ ], "docs": "", "features": [], - "id": "PYBD-SF2", "images": [ "PYBD_SF2_W4F2.jpg", "PYBD_SF2_W4F2_top.jpg", diff --git a/ports/stm32/boards/PYBD_SF3/board.json b/ports/stm32/boards/PYBD_SF3/board.json index 3e4731b3d2..e89f268cff 100644 --- a/ports/stm32/boards/PYBD_SF3/board.json +++ b/ports/stm32/boards/PYBD_SF3/board.json @@ -4,7 +4,6 @@ ], "docs": "", "features": [], - "id": "PYBD-SF3", "images": [ "PYBD_SF3_W4F2.jpg", "PYBD_SF3_W4F2_top.jpg", diff --git a/ports/stm32/boards/PYBD_SF6/board.json b/ports/stm32/boards/PYBD_SF6/board.json index 3e689d69be..b6d85d6fd7 100644 --- a/ports/stm32/boards/PYBD_SF6/board.json +++ b/ports/stm32/boards/PYBD_SF6/board.json @@ -4,10 +4,9 @@ ], "docs": "", "features": [ - "WiFi", - "BLE" + "BLE", + "WiFi" ], - "id": "PYBD-SF6", "images": [ "PYBD_SF6_W4F2.jpg", "PYBD_SF6_W4F2_top.jpg", diff --git a/ports/stm32/boards/PYBLITEV10/board.json b/ports/stm32/boards/PYBLITEV10/board.json index ce98ba7de7..0d2338d3db 100644 --- a/ports/stm32/boards/PYBLITEV10/board.json +++ b/ports/stm32/boards/PYBLITEV10/board.json @@ -4,7 +4,6 @@ ], "docs": "", "features": [], - "id": "pyblitev10", "images": [ "PYBLITEv1_0.jpg", "PYBLITEv1_0-B.jpg", @@ -15,10 +14,10 @@ "thumbnail": "", "url": "https://store.micropython.org/product/PYBLITEv1.0", "variants": { - "dp": "Double-precision float", - "dp-thread": "Double precision float + Threads", - "network": "Wiznet 5200 Driver", - "thread": "Threading" + "DP": "Double-precision float", + "DP_THREAD": "Double precision float + Threads", + "NETWORK": "Wiznet 5200 Driver", + "THREAD": "Threading" }, "vendor": "George Robotics" } diff --git a/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk b/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk index 461886b63c..1fe609cbb5 100644 --- a/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk +++ b/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk @@ -6,22 +6,20 @@ TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 # Provide different variants for the downloads page. -BOARD_VARIANTS += "dp thread dp-thread network" - -ifeq ($(BOARD_VARIANT),dp) +ifeq ($(BOARD_VARIANT),DP) MICROPY_FLOAT_IMPL=double endif -ifeq ($(BOARD_VARIANT),thread) +ifeq ($(BOARD_VARIANT),THREAD) CFLAGS += -DMICROPY_PY_THREAD=1 endif -ifeq ($(BOARD_VARIANT),dp-thread) +ifeq ($(BOARD_VARIANT),DP_THREAD) MICROPY_FLOAT_IMPL=double CFLAGS += -DMICROPY_PY_THREAD=1 endif -ifeq ($(BOARD_VARIANT),network) +ifeq ($(BOARD_VARIANT),NETWORK) MICROPY_PY_NETWORK_WIZNET5K=5200 endif diff --git a/ports/stm32/boards/PYBV10/board.json b/ports/stm32/boards/PYBV10/board.json index 2907b8fc45..0c5fea2eb8 100644 --- a/ports/stm32/boards/PYBV10/board.json +++ b/ports/stm32/boards/PYBV10/board.json @@ -4,7 +4,6 @@ ], "docs": "", "features": [], - "id": "pybv10", "images": [ "PYBv1_0-C.jpg" ], @@ -13,10 +12,10 @@ "thumbnail": "", "url": "", "variants": { - "dp": "Double-precision float", - "dp-thread": "Double precision float + Threads", - "network": "Wiznet 5200 Driver", - "thread": "Threading" + "DP": "Double-precision float", + "DP_THREAD": "Double precision float + Threads", + "NETWORK": "Wiznet 5200 Driver", + "THREAD": "Threading" }, "vendor": "George Robotics" } diff --git a/ports/stm32/boards/PYBV10/mpconfigboard.mk b/ports/stm32/boards/PYBV10/mpconfigboard.mk index 363f6b4806..1a4d676319 100644 --- a/ports/stm32/boards/PYBV10/mpconfigboard.mk +++ b/ports/stm32/boards/PYBV10/mpconfigboard.mk @@ -16,22 +16,20 @@ endif MICROPY_VFS_LFS2 = 1 # Provide different variants for the downloads page. -BOARD_VARIANTS += "dp thread dp-thread network" - -ifeq ($(BOARD_VARIANT),dp) +ifeq ($(BOARD_VARIANT),DP) MICROPY_FLOAT_IMPL=double endif -ifeq ($(BOARD_VARIANT),thread) +ifeq ($(BOARD_VARIANT),THREAD) CFLAGS += -DMICROPY_PY_THREAD=1 endif -ifeq ($(BOARD_VARIANT),dp-thread) +ifeq ($(BOARD_VARIANT),DP_THREAD) MICROPY_FLOAT_IMPL=double CFLAGS += -DMICROPY_PY_THREAD=1 endif -ifeq ($(BOARD_VARIANT),network) +ifeq ($(BOARD_VARIANT),NETWORK) MICROPY_PY_NETWORK_WIZNET5K=5200 endif diff --git a/ports/stm32/boards/PYBV11/board.json b/ports/stm32/boards/PYBV11/board.json index fe59a7b16d..5d7abbaa83 100644 --- a/ports/stm32/boards/PYBV11/board.json +++ b/ports/stm32/boards/PYBV11/board.json @@ -4,7 +4,6 @@ ], "docs": "", "features": [], - "id": "pybv11", "images": [ "PYBv1_1.jpg", "PYBv1_1-C.jpg", @@ -15,10 +14,10 @@ "thumbnail": "", "url": "https://store.micropython.org/product/PYBv1.1", "variants": { - "dp": "Double-precision float", - "dp-thread": "Double precision float + Threads", - "network": "Wiznet 5200 Driver", - "thread": "Threading" + "DP": "Double-precision float", + "DP_THREAD": "Double precision float + Threads", + "NETWORK": "Wiznet 5200 Driver", + "THREAD": "Threading" }, "vendor": "George Robotics" } diff --git a/ports/stm32/boards/PYBV11/mpconfigboard.mk b/ports/stm32/boards/PYBV11/mpconfigboard.mk index 857049f215..6dcb2fd1b4 100644 --- a/ports/stm32/boards/PYBV11/mpconfigboard.mk +++ b/ports/stm32/boards/PYBV11/mpconfigboard.mk @@ -16,22 +16,20 @@ endif MICROPY_VFS_LFS2 = 1 # Provide different variants for the downloads page. -BOARD_VARIANTS += "dp thread dp-thread network" - -ifeq ($(BOARD_VARIANT),dp) +ifeq ($(BOARD_VARIANT),DP) MICROPY_FLOAT_IMPL=double endif -ifeq ($(BOARD_VARIANT),thread) +ifeq ($(BOARD_VARIANT),THREAD) CFLAGS += -DMICROPY_PY_THREAD=1 endif -ifeq ($(BOARD_VARIANT),dp-thread) +ifeq ($(BOARD_VARIANT),DP_THREAD) MICROPY_FLOAT_IMPL=double CFLAGS += -DMICROPY_PY_THREAD=1 endif -ifeq ($(BOARD_VARIANT),network) +ifeq ($(BOARD_VARIANT),NETWORK) MICROPY_PY_NETWORK_WIZNET5K=5200 endif diff --git a/ports/stm32/boards/STM32F439/board.json b/ports/stm32/boards/STM32F439/board.json index 140c3474ca..068a9022d7 100644 --- a/ports/stm32/boards/STM32F439/board.json +++ b/ports/stm32/boards/STM32F439/board.json @@ -11,5 +11,5 @@ "product": "STM32F439", "thumbnail": "", "url": "", - "vendor": "" + "vendor": "ST Microelectronics" } diff --git a/ports/stm32/boards/USBDONGLE_WB55/board.json b/ports/stm32/boards/USBDONGLE_WB55/board.json index 858e94d105..6d61f0c280 100644 --- a/ports/stm32/boards/USBDONGLE_WB55/board.json +++ b/ports/stm32/boards/USBDONGLE_WB55/board.json @@ -11,5 +11,5 @@ "product": "USBDONGLE_WB55", "thumbnail": "", "url": "", - "vendor": "" + "vendor": "ST Microelectronics" } diff --git a/ports/stm32/cyw43_configport.h b/ports/stm32/cyw43_configport.h index 4b6dde3c43..f2a880603a 100644 --- a/ports/stm32/cyw43_configport.h +++ b/ports/stm32/cyw43_configport.h @@ -93,6 +93,13 @@ #define CYW43_PIN_WL_REG_ON pyb_pin_WL_REG_ON #define CYW43_PIN_WL_HOST_WAKE pyb_pin_WL_HOST_WAKE #define CYW43_PIN_WL_SDIO_1 pyb_pin_WL_SDIO_1 +#define CYW43_PIN_WL_GPIO_1 pyb_pin_WL_GPIO_1 +#define CYW43_PIN_WL_GPIO_4 pyb_pin_WL_GPIO_4 + +#define CYW43_PIN_BT_REG_ON pyb_pin_BT_REG_ON +#define CYW43_PIN_BT_HOST_WAKE pyb_pin_BT_HOST_WAKE +#define CYW43_PIN_BT_DEV_WAKE pyb_pin_BT_DEV_WAKE +#define CYW43_PIN_BT_CTS pyb_pin_BT_CTS #if MICROPY_HW_ENABLE_RF_SWITCH #define CYW43_PIN_WL_RFSW_VDD pyb_pin_WL_RFSW_VDD diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index cdbb90e5d8..bfa4fb23ff 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -161,7 +161,7 @@ static const DMA_InitTypeDef dma_init_struct_i2s = { static const DMA_InitTypeDef dma_init_struct_sdio = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, - #elif defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB)) || defined(STM32WL) .Request = 0, #endif .Direction = 0, @@ -171,7 +171,7 @@ static const DMA_InitTypeDef dma_init_struct_sdio = { .MemDataAlignment = DMA_MDATAALIGN_WORD, #if defined(STM32F4) || defined(STM32F7) .Mode = DMA_PFCTRL, - #elif defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) .Mode = DMA_NORMAL, #endif .Priority = DMA_PRIORITY_VERY_HIGH, @@ -189,7 +189,7 @@ static const DMA_InitTypeDef dma_init_struct_sdio = { static const DMA_InitTypeDef dma_init_struct_dac = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, - #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) .Request = 0, #endif .Direction = 0, @@ -558,6 +558,10 @@ const dma_descr_t dma_SPI_1_RX = { DMA1_Channel1, DMA_REQUEST_SPI1_RX, dma_id_0, const dma_descr_t dma_SPI_1_TX = { DMA1_Channel2, DMA_REQUEST_SPI1_TX, dma_id_1, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_2_RX = { DMA1_Channel3, DMA_REQUEST_SPI2_RX, dma_id_2, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_2_TX = { DMA1_Channel4, DMA_REQUEST_SPI2_TX, dma_id_3, &dma_init_struct_spi_i2c }; +#if defined(STM32WL) +const dma_descr_t dma_SPI_SUBGHZ_RX = { DMA1_Channel5, DMA_REQUEST_SUBGHZSPI_RX, dma_id_4, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_SUBGHZ_TX = { DMA1_Channel6, DMA_REQUEST_SUBGHZSPI_TX, dma_id_5, &dma_init_struct_spi_i2c }; +#endif static const uint8_t dma_irqn[NSTREAM] = { DMA1_Channel1_IRQn, @@ -1217,7 +1221,7 @@ void DMA1_Channel4_5_6_7_IRQHandler(void) { IRQ_EXIT(DMA1_Channel4_5_6_7_IRQn); } -#elif defined(STM32L1) || defined(STM32L4) || defined(STM32WB) +#elif defined(STM32L1) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) void DMA1_Channel1_IRQHandler(void) { IRQ_ENTER(DMA1_Channel1_IRQn); @@ -1340,9 +1344,9 @@ static void dma_enable_clock(dma_id_t dma_id) { dma_enable_mask |= (1 << dma_id); MICROPY_END_ATOMIC_SECTION(irq_state); - #if defined(STM32WB) - // This MCU has a DMAMUX peripheral which needs to be enabled to multiplex the channels. + #if defined(STM32G4) || defined(STM32WB) || defined(STM32WL) if (!__HAL_RCC_DMAMUX1_IS_CLK_ENABLED()) { + // MCU has a DMAMUX peripheral which needs to be enabled to multiplex the channels. __HAL_RCC_DMAMUX1_CLK_ENABLE(); } #endif @@ -1350,9 +1354,6 @@ static void dma_enable_clock(dma_id_t dma_id) { if (dma_id < NSTREAMS_PER_CONTROLLER) { if (((old_enable_mask & DMA1_ENABLE_MASK) == 0) && !DMA1_IS_CLK_ENABLED()) { __HAL_RCC_DMA1_CLK_ENABLE(); - #if defined(STM32G4) - __HAL_RCC_DMAMUX1_CLK_ENABLE(); - #endif // We just turned on the clock. This means that anything stored // in dma_last_channel (for DMA1) needs to be invalidated. @@ -1367,9 +1368,6 @@ static void dma_enable_clock(dma_id_t dma_id) { if (((old_enable_mask & DMA2_ENABLE_MASK) == 0) && !DMA2_IS_CLK_ENABLED()) { __HAL_RCC_DMA2_CLK_ENABLE(); - #if defined(STM32G4) - __HAL_RCC_DMAMUX1_CLK_ENABLE(); - #endif // We just turned on the clock. This means that anything stored // in dma_last_channel (for DMA2) needs to be invalidated. diff --git a/ports/stm32/dma.h b/ports/stm32/dma.h index 92d5db6c0a..2afc947541 100644 --- a/ports/stm32/dma.h +++ b/ports/stm32/dma.h @@ -136,6 +136,8 @@ extern const dma_descr_t dma_SPI_3_TX; extern const dma_descr_t dma_SDIO_0; extern const dma_descr_t dma_I2C_4_TX; extern const dma_descr_t dma_I2C_4_RX; +extern const dma_descr_t dma_SPI_SUBGHZ_TX; +extern const dma_descr_t dma_SPI_SUBGHZ_RX; #endif diff --git a/ports/stm32/irq.h b/ports/stm32/irq.h index 8e98b4cc5e..7f10d0d004 100644 --- a/ports/stm32/irq.h +++ b/ports/stm32/irq.h @@ -155,6 +155,8 @@ static inline void restore_irq_pri(uint32_t state) { #define IRQ_PRI_CAN NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 7, 0) +#define IRQ_PRI_SUBGHZ_RADIO NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 8, 0) + #define IRQ_PRI_SPI NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 8, 0) // Interrupt priority for non-special timers. diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 2235e4de35..95b74c621a 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -86,6 +86,7 @@ #include "servo.h" #include "dac.h" #include "can.h" +#include "subghz.h" #if MICROPY_PY_THREAD STATIC pyb_thread_t pyb_thread_main; @@ -403,6 +404,9 @@ void stm32_main(uint32_t reset_mode) { #if defined(STM32WB) rfcore_init(); #endif + #if defined(STM32WL) + subghz_init(); + #endif #if MICROPY_HW_SDRAM_SIZE sdram_init(); bool sdram_valid = true; @@ -650,6 +654,9 @@ soft_reset_exit: #if MICROPY_PY_BLUETOOTH mp_bluetooth_deinit(); #endif + #if defined(STM32WL) + subghz_deinit(); + #endif #if MICROPY_PY_NETWORK mod_network_deinit(); #endif diff --git a/ports/stm32/make-stmconst.py b/ports/stm32/make-stmconst.py index 49b5c1a17b..4e4f2d7155 100644 --- a/ports/stm32/make-stmconst.py +++ b/ports/stm32/make-stmconst.py @@ -319,10 +319,10 @@ def main(): print("") with open(args.qstr_filename, "wt") as qstr_file: - print("#if MICROPY_PY_STM", file=qstr_file) + print("#if MICROPY_PY_STM_CONST", file=qstr_file) for qstr in sorted(needed_qstrs): print("Q({})".format(qstr), file=qstr_file) - print("#endif // MICROPY_PY_STM", file=qstr_file) + print("#endif // MICROPY_PY_STM_CONST", file=qstr_file) with open(args.mpz_filename, "wt") as mpz_file: for mpz in sorted(needed_mpzs): diff --git a/ports/stm32/mboot/fwupdate.py b/ports/stm32/mboot/fwupdate.py index 78a8d73658..47ceb19ba5 100644 --- a/ports/stm32/mboot/fwupdate.py +++ b/ports/stm32/mboot/fwupdate.py @@ -3,7 +3,7 @@ from micropython import const import struct, time -import zlib, machine, stm +import deflate, machine, stm # Constants to be used with update_mpy VFS_FAT = 1 @@ -36,7 +36,7 @@ def dfu_read(filename): if hdr == b"Dfu": pass elif hdr == b"\x1f\x8b\x08": - f = zlib.DecompIO(f, 16 + 15) + f = deflate.DeflateIO(f, deflate.GZIP) else: print("Invalid firmware", filename) return None @@ -231,7 +231,7 @@ def update_app_elements( # Check firmware is of .dfu or .dfu.gz type try: with open(filename, "rb") as f: - hdr = zlib.DecompIO(f, 16 + 15).read(6) + hdr = deflate.DeflateIO(f, deflate.GZIP).read(6) except Exception: with open(filename, "rb") as f: hdr = f.read(6) diff --git a/ports/stm32/modstm.c b/ports/stm32/modstm.c index 94d56d4d08..251360594a 100644 --- a/ports/stm32/modstm.c +++ b/ports/stm32/modstm.c @@ -32,6 +32,7 @@ #include "extmod/machine_mem.h" #include "rfcore.h" #include "portmodules.h" +#include "subghz.h" #if MICROPY_PY_STM @@ -44,13 +45,21 @@ STATIC const mp_rom_map_elem_t stm_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, + #if MICROPY_PY_STM_CONST #include "genhdr/modstm_const.h" + #endif #if defined(STM32WB) { MP_ROM_QSTR(MP_QSTR_rfcore_status), MP_ROM_PTR(&rfcore_status_obj) }, { MP_ROM_QSTR(MP_QSTR_rfcore_fw_version), MP_ROM_PTR(&rfcore_fw_version_obj) }, { MP_ROM_QSTR(MP_QSTR_rfcore_sys_hci), MP_ROM_PTR(&rfcore_sys_hci_obj) }, #endif + + #if defined(STM32WL) + { MP_ROM_QSTR(MP_QSTR_subghz_cs), MP_ROM_PTR(&subghz_cs_obj) }, + { MP_ROM_QSTR(MP_QSTR_subghz_irq), MP_ROM_PTR(&subghz_irq_obj) }, + { MP_ROM_QSTR(MP_QSTR_subghz_is_busy), MP_ROM_PTR(&subghz_is_busy_obj) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(stm_module_globals, stm_module_globals_table); diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 149d2ae73a..611a08252d 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -32,11 +32,16 @@ /*****************************************************************************/ // Feature settings with defaults -// Whether to include the stm module, with peripheral register constants +// Whether to include the stm module #ifndef MICROPY_PY_STM #define MICROPY_PY_STM (1) #endif +// Whether to include named register constants in the stm module +#ifndef MICROPY_PY_STM_CONST +#define MICROPY_PY_STM_CONST (MICROPY_PY_STM) +#endif + // Whether to include the pyb module #ifndef MICROPY_PY_PYB #define MICROPY_PY_PYB (1) @@ -471,8 +476,12 @@ #define MICROPY_HW_RCC_HSI_STATE (RCC_HSI_OFF) #define MICROPY_HW_RCC_FLAG_HSxRDY (RCC_FLAG_HSERDY) #if MICROPY_HW_CLK_USE_BYPASS +#if !defined(STM32WL) #define MICROPY_HW_RCC_HSE_STATE (RCC_HSE_BYPASS) #else +#define MICROPY_HW_RCC_HSE_STATE (RCC_HSE_BYPASS_PWR) +#endif +#else #define MICROPY_HW_RCC_HSE_STATE (RCC_HSE_ON) #endif #endif diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 37165b1589..2d2d81486b 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -92,7 +92,6 @@ #endif // extended modules -#define MICROPY_PY_SSL_FINALISER (MICROPY_PY_SSL) #define MICROPY_PY_HASHLIB_MD5 (MICROPY_PY_SSL) #define MICROPY_PY_HASHLIB_SHA1 (MICROPY_PY_SSL) #define MICROPY_PY_CRYPTOLIB (MICROPY_PY_SSL) diff --git a/ports/stm32/mpthreadport.c b/ports/stm32/mpthreadport.c index ecdb268468..a7d85cfe32 100644 --- a/ports/stm32/mpthreadport.c +++ b/ports/stm32/mpthreadport.c @@ -54,7 +54,11 @@ void mp_thread_gc_others(void) { mp_thread_mutex_unlock(&thread_mutex); } -void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { +mp_uint_t mp_thread_get_id(void) { + return (uint32_t)pyb_thread_cur; +} + +mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { if (*stack_size == 0) { *stack_size = 4096; // default stack size } else if (*stack_size < 2048) { @@ -82,6 +86,8 @@ void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { // adjust stack_size to provide room to recover from hitting the limit *stack_size -= 1024; + + return id; } void mp_thread_start(void) { diff --git a/ports/stm32/powerctrlboot.c b/ports/stm32/powerctrlboot.c index 51b740a809..b075073a5b 100644 --- a/ports/stm32/powerctrlboot.c +++ b/ports/stm32/powerctrlboot.c @@ -460,13 +460,71 @@ void SystemClock_Config(void) { #include "stm32wlxx_ll_utils.h" void SystemClock_Config(void) { - // Set flash latency + // Set flash latency (2 wait states, sysclk > 36MHz) LL_FLASH_SetLatency(LL_FLASH_LATENCY_2); while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2) { } LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + #if MICROPY_HW_CLK_USE_HSE + // Enable the 32MHz external oscillator and 48MHZ SYSCLK via PLL + + #if MICROPY_HW_CLK_USE_BYPASS + // Use "bypass power" option, port PB0_VDDTCXO supplies TCXO + // (STM32WL5x has no other HSE bypass mode.) + + // "PB0 must be configured in analog mode prior enabling the HSE" + // + // Note: PB0 analog mode muxes PB0_VDDTCXO pin to the VDDTCXO regulator, set + // to default voltage of 1.7V. Changing this voltage requires initializing + // the SUBGHZ radio and sending a Set_Tcxo command to it. + // + // For the Nucelo-WL55 board, ST uses the NDK "NT2016SF-32M-END5875A" TCXO + // which has no publicly available datasheet. However, the ST code for this + // board always keeps the pin at the default 1.7V voltage level so changing + // the level would only be needed if a different TCXO is used. + // + // (Note also that setting pin PB0 as a push-pull GPIO output is technically + // possible too, but 3.3V will be too high for many TCXOs.) + mp_hal_pin_config(pin_B0, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); + + LL_RCC_HSE_EnableTcxo(); + + #endif // MICROPY_HW_CLK_USE_BYPASS + + LL_RCC_HSE_Enable(); + while (!LL_RCC_HSE_IsReady()) { + // Wait for HSE Ready signal + } + + // Configure PLL for a 48MHz SYSCLK + #define PLLM (HSE_VALUE / 16000000) // VCO input 16MHz (recommended in ST docs) + #define PLLN (6) // 7*8MHz = 96MHz + #define PLLP (2) // f_P = 48MHz + #define PLLQ (2) // f_Q = 48MHz + #define PLLR (2) // f_R = 48MHz + RCC->PLLCFGR = + (PLLR - 1) << RCC_PLLCFGR_PLLR_Pos | RCC_PLLCFGR_PLLREN + | (PLLQ - 1) << RCC_PLLCFGR_PLLQ_Pos | RCC_PLLCFGR_PLLQEN + | (PLLP - 1) << RCC_PLLCFGR_PLLP_Pos | RCC_PLLCFGR_PLLPEN + | PLLN << RCC_PLLCFGR_PLLN_Pos + | (PLLM - 1) << RCC_PLLCFGR_PLLM_Pos + | LL_RCC_PLLSOURCE_HSE; + + LL_RCC_PLL_Enable(); + LL_RCC_PLL_EnableDomain_SYS(); + while (!LL_RCC_PLL_IsReady()) { + // Wait for PLL to lock + } + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { + // Wait for system clock source to switch + } + + #else // Use MSI as 48MHz source for SYSCLK + // Enable MSI LL_RCC_MSI_Enable(); while (!LL_RCC_MSI_IsReady()) { @@ -482,6 +540,8 @@ void SystemClock_Config(void) { while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) { } + #endif // MICROPY_HW_CLK_USE_HSE + // Set bus dividers LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); LL_RCC_SetAHB3Prescaler(LL_RCC_SYSCLK_DIV_1); diff --git a/ports/stm32/spi.c b/ports/stm32/spi.c index 11a9a74ea3..1f5996165e 100644 --- a/ports/stm32/spi.c +++ b/ports/stm32/spi.c @@ -62,6 +62,9 @@ STATIC SPI_HandleTypeDef SPIHandle5 = {.Instance = NULL}; #if defined(MICROPY_HW_SPI6_SCK) STATIC SPI_HandleTypeDef SPIHandle6 = {.Instance = NULL}; #endif +#if defined(MICROPY_HW_SUBGHZSPI_ID) +static SPI_HandleTypeDef SPIHandleSubGhz = {.Instance = NULL}; +#endif const spi_t spi_obj[6] = { #if defined(MICROPY_HW_SPI1_SCK) @@ -76,6 +79,8 @@ const spi_t spi_obj[6] = { #endif #if defined(MICROPY_HW_SPI3_SCK) {&SPIHandle3, &dma_SPI_3_TX, &dma_SPI_3_RX}, + #elif MICROPY_HW_SUBGHZSPI_ID == 3 + {&SPIHandleSubGhz, &dma_SPI_SUBGHZ_TX, &dma_SPI_SUBGHZ_RX}, #else {NULL, NULL, NULL}, #endif @@ -96,6 +101,10 @@ const spi_t spi_obj[6] = { #endif }; +#if defined(MICROPY_HW_SUBGHZSPI_ID) && MICROPY_HW_SUBGHZSPI_ID != 3 +#error "spi_obj needs updating for new value of MICROPY_HW_SUBGHZSPI_ID" +#endif + #if defined(STM32H5) || defined(STM32H7) // STM32H5/H7 HAL requires SPI IRQs to be enabled and handled. #if defined(MICROPY_HW_SPI1_SCK) @@ -163,6 +172,9 @@ void spi_init0(void) { #if defined(MICROPY_HW_SPI6_SCK) SPIHandle6.Instance = SPI6; #endif + #if defined(MICROPY_HW_SUBGHZSPI_ID) + SPIHandleSubGhz.Instance = SUBGHZSPI; + #endif } int spi_find_index(mp_obj_t id) { @@ -195,6 +207,10 @@ int spi_find_index(mp_obj_t id) { } else if (strcmp(port, MICROPY_HW_SPI6_NAME) == 0) { spi_id = 6; #endif + #ifdef MICROPY_HW_SUBGHZSPI_NAME + } else if (strcmp(port, MICROPY_HW_SUBGHZSPI_NAME) == 0) { + spi_id = MICROPY_HW_SUBGHZSPI_ID; + #endif } else { mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SPI(%s) doesn't exist"), port); } @@ -239,7 +255,7 @@ STATIC uint32_t spi_get_source_freq(SPI_HandleTypeDef *spi) { } else { return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6); } - #else + #else // !STM32F0, !STM32G0, !STM32H #if defined(SPI2) if (spi->Instance == SPI2) { // SPI2 is on APB1 @@ -252,11 +268,20 @@ STATIC uint32_t spi_get_source_freq(SPI_HandleTypeDef *spi) { return HAL_RCC_GetPCLK1Freq(); } else #endif + #if defined(MICROPY_HW_SUBGHZSPI_ID) + if (spi->Instance == SUBGHZSPI) { + // In STM32WL5x, SUBGHZSPI is PCLK3 which is same as HCLK3, no HCLK3->PCLK3 divider exists in clock tree + #if !defined(LL_APB3_GRP1_PERIPH_SUBGHZSPI) + #error "SPI needs updating for new SUBGHZSPI clock configuration" + #endif + return HAL_RCC_GetHCLK3Freq(); + } else + #endif { // SPI1, SPI4, SPI5 and SPI6 are on APB2 return HAL_RCC_GetPCLK2Freq(); } - #endif + #endif // STM32F0, STM32G0, STM32H } // sets the parameters in the SPI_InitTypeDef struct @@ -411,6 +436,12 @@ int spi_init(const spi_t *self, bool enable_nss_pin) { // enable the SPI clock __HAL_RCC_SPI6_CLK_ENABLE(); #endif + #if defined(MICROPY_HW_SUBGHZSPI_ID) + } else if (spi->Instance == SUBGHZSPI) { + irqn = SUBGHZSPI_IRQn; + // pins remain all NULL, internal bus has no GPIO mappings + __HAL_RCC_SUBGHZSPI_CLK_ENABLE(); + #endif } else { // SPI does not exist for this board (shouldn't get here, should be checked by caller) return -MP_EINVAL; @@ -502,6 +533,14 @@ void spi_deinit(const spi_t *spi_obj) { __HAL_RCC_SPI6_CLK_DISABLE(); HAL_NVIC_DisableIRQ(SPI6_IRQn); #endif + #if defined(MICROPY_HW_SUBGHZSPI_ID) + } else if (spi->Instance == SUBGHZSPI) { + __HAL_RCC_SUBGHZSPI_FORCE_RESET(); + __HAL_RCC_SUBGHZSPI_RELEASE_RESET(); + __HAL_RCC_SUBGHZSPI_CLK_DISABLE(); + HAL_NVIC_DisableIRQ(SUBGHZSPI_IRQn); + + #endif } } @@ -661,6 +700,11 @@ void spi_print(const mp_print_t *print, const spi_t *spi_obj, bool legacy) { spi_num = 6; } #endif + #if defined(MICROPY_HW_SUBGHZSPI_ID) + else if (spi->Instance == SUBGHZSPI) { + spi_num = MICROPY_HW_SUBGHZSPI_ID; + } + #endif mp_printf(print, "SPI(%u", spi_num); if (spi->State != HAL_SPI_STATE_RESET) { diff --git a/ports/stm32/subghz.c b/ports/stm32/subghz.c new file mode 100644 index 0000000000..1daed59aaf --- /dev/null +++ b/ports/stm32/subghz.c @@ -0,0 +1,139 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Angus Gratton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/gc.h" +#include "py/runtime.h" +#include "subghz.h" +#include "irq.h" +#include "spi.h" + +#if defined(STM32WL) + +// Interface to the STM32WL series "SUBGHZ Radio" module + +STATIC void handle_radio_irq() { + // Level-triggered interrupts means the interrupt has to be cleared before + // this function returns. + // + // Rather than writing to SUBGHZ SPI in Interrupt Context to clear the + // interrupt, disable the IRQ and rely on Python code to call + // subghz_irq(handler) to re-enable when needed. + HAL_NVIC_DisableIRQ(SUBGHZ_Radio_IRQn); + + mp_obj_t callback = MP_STATE_PORT(subghz_callback); + if (callback != mp_const_none) { + mp_sched_lock(); + gc_lock(); + // Passing dummy 'pin' argument of None, to keep + // compatibility with machine.Pin.isr() handlers + mp_call_function_1_protected(callback, mp_const_none); + gc_unlock(); + mp_sched_unlock(); + } +} + +void SUBGHZ_Radio_IRQHandler(void) { + IRQ_ENTER(SUBGHZ_Radio_IRQn); + handle_radio_irq(); + IRQ_EXIT(SUBGHZ_Radio_IRQn); +} + +void subghz_init(void) { + __HAL_RCC_SUBGHZ_RADIO_FORCE_RESET(); + + #if !MICROPY_HW_CLK_USE_HSE && MICROPY_HW_CLK_USE_BYPASS + // SUBGHZ clock source is HSE oscillator. + // + // If this is not already enabled for the system clock, and we're depending + // on the VDDTCXO pin to power the HSE ("bypass mode"), then enable it. + __HAL_RCC_HSE_CONFIG(RCC_HSE_BYPASS_PWR); + #endif + + NVIC_DisableIRQ(SUBGHZ_Radio_IRQn); + NVIC_SetPriority(SUBGHZ_Radio_IRQn, IRQ_PRI_SUBGHZ_RADIO); + + __HAL_RCC_SUBGHZ_RADIO_RELEASE_RESET(); + + while (__HAL_RCC_GET_FLAG(RCC_FLAG_RFRST) != 0) { + } + + MP_STATE_PORT(subghz_callback) = mp_const_none; +} + +void subghz_deinit(void) { + MP_STATE_PORT(subghz_callback) = mp_const_none; + NVIC_DisableIRQ(SUBGHZ_Radio_IRQn); + __HAL_RCC_SUBGHZ_RADIO_FORCE_RESET(); + __HAL_RCC_SUBGHZ_RADIO_RELEASE_RESET(); +} + +STATIC mp_obj_t subghz_cs(mp_obj_t value) { + // Treat the same as normal SPI - truthy is "unselected", + // falsey is active low "selected", + if (mp_obj_is_true(value)) { + LL_PWR_UnselectSUBGHZSPI_NSS(); + } else { + LL_PWR_SelectSUBGHZSPI_NSS(); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(subghz_cs_obj, subghz_cs); + +STATIC mp_obj_t subghz_irq(mp_obj_t handler) { + MP_STATE_PORT(subghz_callback) = handler; + + if (mp_obj_is_true(handler)) { + HAL_NVIC_ClearPendingIRQ(SUBGHZ_Radio_IRQn); + HAL_NVIC_EnableIRQ(SUBGHZ_Radio_IRQn); + } else { + HAL_NVIC_DisableIRQ(SUBGHZ_Radio_IRQn); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(subghz_irq_obj, subghz_irq); + +STATIC mp_obj_t subghz_is_busy(void) { + // Read the raw unmasked busy signal. This should be checked before driving + // CS low to start a command. + // + // Reads the raw RFBUSYS not the masked RFBUSYMS, in contradiction to EM0453 + // 6.3 "Radio busy management". This is because the RFBUSYMS signal doesn't + // seem to match the reference manual. Observed behaviour matches this bug + // report instead: https://community.st.com/s/question/0D53W000014zFx9SAE + // + // Reading RFBUSYS won't cause any problems here provided a new SPI command + // isn't immediately after the previous command, which shouldn't be possible + // with MicroPython. + return mp_obj_new_bool(LL_PWR_IsActiveFlag_RFBUSYS()); + +} +MP_DEFINE_CONST_FUN_OBJ_0(subghz_is_busy_obj, subghz_is_busy); + +MP_REGISTER_ROOT_POINTER(mp_obj_t subghz_callback); + +#endif // STM32WL diff --git a/ports/stm32/subghz.h b/ports/stm32/subghz.h new file mode 100644 index 0000000000..f8678cd087 --- /dev/null +++ b/ports/stm32/subghz.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Angus Gratton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32_SUBGHZ_H +#define MICROPY_INCLUDED_STM32_SUBGHZ_H + +#include "py/obj.h" + +// Interface to the STM32WL series "SUBGHZ Radio" module + +void subghz_init(void); +void subghz_deinit(void); + +MP_DECLARE_CONST_FUN_OBJ_1(subghz_cs_obj); +MP_DECLARE_CONST_FUN_OBJ_1(subghz_irq_obj); +MP_DECLARE_CONST_FUN_OBJ_0(subghz_is_busy_obj); + +#endif diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index e477c5c16c..7a2a3a9580 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -1052,12 +1052,20 @@ size_t uart_tx_data(pyb_uart_obj_t *self, const void *src_in, size_t num_chars, // the overall timeout rather than the character timeout. timeout = self->timeout; } else { + #if defined(STM32G4) + // With using UART FIFO, the timeout should be long enough that FIFO becomes empty. + // Since previous data transfer may be ongoing, the timeout must be multiplied + // timeout_char by FIFO size + 1. + // STM32G4 has 8 words FIFO. + timeout = (8 + 1) * self->timeout_char; + #else // The timeout specified here is for waiting for the TX data register to // become empty (ie between chars), as well as for the final char to be // completely transferred. The default value for timeout_char is long // enough for 1 char, but we need to double it to wait for the last char // to be transferred to the data register, and then to be transmitted. timeout = 2 * self->timeout_char; + #endif } const uint8_t *src = (const uint8_t *)src_in; diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 188e4be633..eae02bf257 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -201,7 +201,6 @@ SRC_C += \ mpthreadport.c \ input.c \ modmachine.c \ - modselect.c \ alloc.c \ fatfs_port.c \ mpbthciport.c \ diff --git a/ports/unix/modjni.c b/ports/unix/modjni.c index 10622f588f..a1cfca8149 100644 --- a/ports/unix/modjni.c +++ b/ports/unix/modjni.c @@ -329,8 +329,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( unary_op, jobject_unary_op, attr, jobject_attr, subscr, jobject_subscr, - iter, subscr_getiter, - // .locals_dict = &jobject_locals_dict, + iter, subscr_getiter ); STATIC mp_obj_t new_jobject(jobject jo) { @@ -574,9 +573,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_jmethod, MP_TYPE_FLAG_NONE, print, jmethod_print, - call, jmethod_call, - // .attr = jobject_attr, - // .locals_dict = &jobject_locals_dict, + call, jmethod_call ); #ifdef __ANDROID__ @@ -615,26 +612,26 @@ STATIC void create_jvm(void) { jclass Object_class = JJ(FindClass, "java/lang/Object"); Object_toString_mid = JJ(GetMethodID, Object_class, "toString", - MP_ERROR_TEXT("()Ljava/lang/String;")); + MP_COMPRESSED_ROM_TEXT("()Ljava/lang/String;")); Class_getName_mid = (*env)->GetMethodID(env, Class_class, "getName", - MP_ERROR_TEXT("()Ljava/lang/String;")); + MP_COMPRESSED_ROM_TEXT("()Ljava/lang/String;")); Class_getField_mid = (*env)->GetMethodID(env, Class_class, "getField", - MP_ERROR_TEXT("(Ljava/lang/String;)Ljava/lang/reflect/Field;")); + MP_COMPRESSED_ROM_TEXT("(Ljava/lang/String;)Ljava/lang/reflect/Field;")); Class_getMethods_mid = (*env)->GetMethodID(env, Class_class, "getMethods", - MP_ERROR_TEXT("()[Ljava/lang/reflect/Method;")); + MP_COMPRESSED_ROM_TEXT("()[Ljava/lang/reflect/Method;")); Class_getConstructors_mid = (*env)->GetMethodID(env, Class_class, "getConstructors", - MP_ERROR_TEXT("()[Ljava/lang/reflect/Constructor;")); + MP_COMPRESSED_ROM_TEXT("()[Ljava/lang/reflect/Constructor;")); Method_getName_mid = (*env)->GetMethodID(env, method_class, "getName", - MP_ERROR_TEXT("()Ljava/lang/String;")); + MP_COMPRESSED_ROM_TEXT("()Ljava/lang/String;")); List_class = JJ(FindClass, "java/util/List"); List_get_mid = JJ(GetMethodID, List_class, "get", - MP_ERROR_TEXT("(I)Ljava/lang/Object;")); + MP_COMPRESSED_ROM_TEXT("(I)Ljava/lang/Object;")); List_set_mid = JJ(GetMethodID, List_class, "set", - MP_ERROR_TEXT("(ILjava/lang/Object;)Ljava/lang/Object;")); + MP_COMPRESSED_ROM_TEXT("(ILjava/lang/Object;)Ljava/lang/Object;")); List_size_mid = JJ(GetMethodID, List_class, "size", - MP_ERROR_TEXT("()I")); + MP_COMPRESSED_ROM_TEXT("()I")); IndexException_class = JJ(FindClass, "java/lang/IndexOutOfBoundsException"); } diff --git a/ports/unix/modselect.c b/ports/unix/modselect.c deleted file mode 100644 index 894820c63d..0000000000 --- a/ports/unix/modselect.c +++ /dev/null @@ -1,356 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Damien P. George - * Copyright (c) 2015-2017 Paul Sokolovsky - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "py/mpconfig.h" - -#if MICROPY_PY_SELECT_POSIX - -#if MICROPY_PY_SELECT -#error "Can't have both MICROPY_PY_SELECT and MICROPY_PY_SELECT_POSIX." -#endif - -#include -#include -#include - -#include "py/runtime.h" -#include "py/stream.h" -#include "py/obj.h" -#include "py/objlist.h" -#include "py/objtuple.h" -#include "py/mphal.h" -#include "py/mpthread.h" - -#define DEBUG 0 - -#if MICROPY_PY_SOCKET -extern const mp_obj_type_t mp_type_socket; -#endif - -// Flags for poll() -#define FLAG_ONESHOT (1) - -/// \class Poll - poll class - -typedef struct _mp_obj_poll_t { - mp_obj_base_t base; - unsigned short alloc; - unsigned short len; - struct pollfd *entries; - mp_obj_t *obj_map; - short iter_cnt; - short iter_idx; - int flags; - // callee-owned tuple - mp_obj_t ret_tuple; -} mp_obj_poll_t; - -STATIC int get_fd(mp_obj_t fdlike) { - if (mp_obj_is_obj(fdlike)) { - const mp_stream_p_t *stream_p = mp_get_stream_raise(fdlike, MP_STREAM_OP_IOCTL); - int err; - mp_uint_t res = stream_p->ioctl(fdlike, MP_STREAM_GET_FILENO, 0, &err); - if (res != MP_STREAM_ERROR) { - return res; - } - } - return mp_obj_get_int(fdlike); -} - -/// \method register(obj[, eventmask]) -STATIC mp_obj_t poll_register(size_t n_args, const mp_obj_t *args) { - mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); - bool is_fd = mp_obj_is_int(args[1]); - int fd = get_fd(args[1]); - - mp_uint_t flags; - if (n_args == 3) { - flags = mp_obj_get_int(args[2]); - } else { - flags = POLLIN | POLLOUT; - } - - struct pollfd *free_slot = NULL; - - struct pollfd *entry = self->entries; - for (int i = 0; i < self->len; i++, entry++) { - int entry_fd = entry->fd; - if (entry_fd == fd) { - entry->events = flags; - return mp_const_false; - } - if (entry_fd == -1) { - free_slot = entry; - } - } - - if (free_slot == NULL) { - if (self->len >= self->alloc) { - self->entries = m_renew(struct pollfd, self->entries, self->alloc, self->alloc + 4); - if (self->obj_map) { - self->obj_map = m_renew(mp_obj_t, self->obj_map, self->alloc, self->alloc + 4); - } - self->alloc += 4; - } - free_slot = &self->entries[self->len++]; - } - - if (!is_fd) { - if (self->obj_map == NULL) { - self->obj_map = m_new0(mp_obj_t, self->alloc); - } - self->obj_map[free_slot - self->entries] = args[1]; - } - - free_slot->fd = fd; - free_slot->events = flags; - free_slot->revents = 0; - return mp_const_true; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register); - -/// \method unregister(obj) -STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) { - mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); - struct pollfd *entries = self->entries; - int fd = get_fd(obj_in); - for (int i = self->len - 1; i >= 0; i--) { - if (entries->fd == fd) { - entries->fd = -1; - if (self->obj_map) { - self->obj_map[entries - self->entries] = MP_OBJ_NULL; - } - break; - } - entries++; - } - - // TODO raise KeyError if obj didn't exist in map - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_2(poll_unregister_obj, poll_unregister); - -/// \method modify(obj, eventmask) -STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) { - mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); - struct pollfd *entries = self->entries; - int fd = get_fd(obj_in); - for (int i = self->len - 1; i >= 0; i--) { - if (entries->fd == fd) { - entries->events = mp_obj_get_int(eventmask_in); - return mp_const_none; - } - entries++; - } - - // obj doesn't exist in poller - mp_raise_OSError(MP_ENOENT); -} -MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify); - -STATIC int poll_poll_internal(size_t n_args, const mp_obj_t *args) { - mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); - - // work out timeout (it's given already in ms) - int timeout = -1; - int flags = 0; - if (n_args >= 2) { - if (args[1] != mp_const_none) { - mp_int_t timeout_i = mp_obj_get_int(args[1]); - if (timeout_i >= 0) { - timeout = timeout_i; - } - } - if (n_args >= 3) { - flags = mp_obj_get_int(args[2]); - } - } - - self->flags = flags; - - int n_ready; - MP_HAL_RETRY_SYSCALL(n_ready, poll(self->entries, self->len, timeout), mp_raise_OSError(err)); - return n_ready; -} - -/// \method poll([timeout]) -/// Timeout is in milliseconds. -STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) { - int n_ready = poll_poll_internal(n_args, args); - - if (n_ready == 0) { - return mp_const_empty_tuple; - } - - mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); - - mp_obj_list_t *ret_list = MP_OBJ_TO_PTR(mp_obj_new_list(n_ready, NULL)); - int ret_i = 0; - struct pollfd *entries = self->entries; - for (int i = 0; i < self->len; i++, entries++) { - if (entries->revents != 0) { - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); - // If there's an object stored, return it, otherwise raw fd - if (self->obj_map && self->obj_map[i] != MP_OBJ_NULL) { - t->items[0] = self->obj_map[i]; - } else { - t->items[0] = MP_OBJ_NEW_SMALL_INT(entries->fd); - } - t->items[1] = MP_OBJ_NEW_SMALL_INT(entries->revents); - ret_list->items[ret_i++] = MP_OBJ_FROM_PTR(t); - if (self->flags & FLAG_ONESHOT) { - entries->events = 0; - } - } - } - - return MP_OBJ_FROM_PTR(ret_list); -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 3, poll_poll); - -STATIC mp_obj_t poll_ipoll(size_t n_args, const mp_obj_t *args) { - mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); - - if (self->ret_tuple == MP_OBJ_NULL) { - self->ret_tuple = mp_obj_new_tuple(2, NULL); - } - - int n_ready = poll_poll_internal(n_args, args); - self->iter_cnt = n_ready; - self->iter_idx = 0; - - return args[0]; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_ipoll_obj, 1, 3, poll_ipoll); - -STATIC mp_obj_t poll_iternext(mp_obj_t self_in) { - mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); - - if (self->iter_cnt == 0) { - return MP_OBJ_STOP_ITERATION; - } - - self->iter_cnt--; - - struct pollfd *entries = self->entries + self->iter_idx; - for (int i = self->iter_idx; i < self->len; i++, entries++) { - self->iter_idx++; - if (entries->revents != 0) { - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->ret_tuple); - // If there's an object stored, return it, otherwise raw fd - if (self->obj_map && self->obj_map[i] != MP_OBJ_NULL) { - t->items[0] = self->obj_map[i]; - } else { - t->items[0] = MP_OBJ_NEW_SMALL_INT(entries->fd); - } - t->items[1] = MP_OBJ_NEW_SMALL_INT(entries->revents); - if (self->flags & FLAG_ONESHOT) { - entries->events = 0; - } - return MP_OBJ_FROM_PTR(t); - } - } - - assert(!"inconsistent number of poll active entries"); - self->iter_cnt = 0; - return MP_OBJ_STOP_ITERATION; -} - -#if DEBUG -STATIC mp_obj_t poll_dump(mp_obj_t self_in) { - mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); - - struct pollfd *entries = self->entries; - for (int i = self->len - 1; i >= 0; i--) { - printf("fd: %d ev: %x rev: %x", entries->fd, entries->events, entries->revents); - if (self->obj_map) { - printf(" obj: %p", self->obj_map[entries - self->entries]); - } - printf("\n"); - entries++; - } - - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(poll_dump_obj, poll_dump); -#endif - -STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_register), MP_ROM_PTR(&poll_register_obj) }, - { MP_ROM_QSTR(MP_QSTR_unregister), MP_ROM_PTR(&poll_unregister_obj) }, - { MP_ROM_QSTR(MP_QSTR_modify), MP_ROM_PTR(&poll_modify_obj) }, - { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&poll_poll_obj) }, - { MP_ROM_QSTR(MP_QSTR_ipoll), MP_ROM_PTR(&poll_ipoll_obj) }, - #if DEBUG - { MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&poll_dump_obj) }, - #endif -}; -STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table); - -STATIC MP_DEFINE_CONST_OBJ_TYPE( - mp_type_poll, - MP_QSTR_poll, - MP_TYPE_FLAG_ITER_IS_ITERNEXT, - iter, poll_iternext, - locals_dict, &poll_locals_dict - ); - -STATIC mp_obj_t select_poll(size_t n_args, const mp_obj_t *args) { - int alloc = 4; - if (n_args > 0) { - alloc = mp_obj_get_int(args[0]); - } - mp_obj_poll_t *poll = mp_obj_malloc(mp_obj_poll_t, &mp_type_poll); - poll->entries = m_new(struct pollfd, alloc); - poll->alloc = alloc; - poll->len = 0; - poll->obj_map = NULL; - poll->iter_cnt = 0; - poll->ret_tuple = MP_OBJ_NULL; - return MP_OBJ_FROM_PTR(poll); -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_select_poll_obj, 0, 1, select_poll); - -STATIC const mp_rom_map_elem_t mp_module_select_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_select) }, - { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&mp_select_poll_obj) }, - { MP_ROM_QSTR(MP_QSTR_POLLIN), MP_ROM_INT(POLLIN) }, - { MP_ROM_QSTR(MP_QSTR_POLLOUT), MP_ROM_INT(POLLOUT) }, - { MP_ROM_QSTR(MP_QSTR_POLLERR), MP_ROM_INT(POLLERR) }, - { MP_ROM_QSTR(MP_QSTR_POLLHUP), MP_ROM_INT(POLLHUP) }, -}; - -STATIC MP_DEFINE_CONST_DICT(mp_module_select_globals, mp_module_select_globals_table); - -const mp_obj_module_t mp_module_select = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&mp_module_select_globals, -}; - -MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_select, mp_module_select); - -#endif // MICROPY_PY_SELECT_POSIX diff --git a/ports/unix/modsocket.c b/ports/unix/modsocket.c index 871be8dcf7..737550b428 100644 --- a/ports/unix/modsocket.c +++ b/ports/unix/modsocket.c @@ -164,6 +164,15 @@ STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i if (pfd.revents & POLLOUT) { ret |= MP_STREAM_POLL_WR; } + if (pfd.revents & POLLERR) { + ret |= MP_STREAM_POLL_ERR; + } + if (pfd.revents & POLLHUP) { + ret |= MP_STREAM_POLL_HUP; + } + if (pfd.revents & POLLNVAL) { + ret |= MP_STREAM_POLL_NVAL; + } } return ret; } diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index c20aff1683..2de05a0a6c 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -134,12 +134,6 @@ typedef long mp_off_t; #define MICROPY_STACKLESS_STRICT (0) #endif -// If settrace is enabled then we need code saving. -#if MICROPY_PY_SYS_SETTRACE -#define MICROPY_PERSISTENT_CODE_SAVE (1) -#define MICROPY_COMP_CONST (0) -#endif - // Unix-specific configuration of machine.mem*. #define MICROPY_MACHINE_MEM_GET_READ_ADDR mod_machine_mem_get_addr #define MICROPY_MACHINE_MEM_GET_WRITE_ADDR mod_machine_mem_get_addr diff --git a/ports/unix/mpthreadport.c b/ports/unix/mpthreadport.c index 6a267e7236..2190bf4ad1 100644 --- a/ports/unix/mpthreadport.c +++ b/ports/unix/mpthreadport.c @@ -191,6 +191,10 @@ void mp_thread_set_state(mp_state_thread_t *state) { pthread_setspecific(tls_key, state); } +mp_uint_t mp_thread_get_id(void) { + return (mp_uint_t)pthread_self(); +} + void mp_thread_start(void) { // enable realtime priority if `-X realtime` command line parameter was set #if defined(__APPLE__) @@ -210,7 +214,7 @@ void mp_thread_start(void) { mp_thread_unix_end_atomic_section(); } -void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { +mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { // default stack size is 8k machine-words if (*stack_size == 0) { *stack_size = 8192 * sizeof(void *); @@ -265,7 +269,8 @@ void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { mp_thread_unix_end_atomic_section(); - return; + MP_STATIC_ASSERT(sizeof(mp_uint_t) >= sizeof(pthread_t)); + return (mp_uint_t)id; er: mp_raise_OSError(ret); diff --git a/ports/unix/variants/mpconfigvariant_common.h b/ports/unix/variants/mpconfigvariant_common.h index 8cb1f88e68..082938ed5f 100644 --- a/ports/unix/variants/mpconfigvariant_common.h +++ b/ports/unix/variants/mpconfigvariant_common.h @@ -106,14 +106,9 @@ #define MICROPY_PY_CRYPTOLIB (1) #endif -// Use the posix implementation of the "select" module (unless the variant -// specifically asks for the MicroPython version). -#ifndef MICROPY_PY_SELECT -#define MICROPY_PY_SELECT (0) -#endif -#ifndef MICROPY_PY_SELECT_POSIX -#define MICROPY_PY_SELECT_POSIX (!MICROPY_PY_SELECT) -#endif +// The "select" module is enabled by default, but disable select.select(). +#define MICROPY_PY_SELECT_POSIX_OPTIMISATIONS (1) +#define MICROPY_PY_SELECT_SELECT (0) // Enable the "websocket" module. #define MICROPY_PY_WEBSOCKET (1) diff --git a/py/dynruntime.h b/py/dynruntime.h index 8564715c0b..90c401ab4b 100644 --- a/py/dynruntime.h +++ b/py/dynruntime.h @@ -79,7 +79,7 @@ static inline void *m_realloc_dyn(void *ptr, size_t new_num_bytes) { /******************************************************************************/ // Types and objects -#define MP_OBJ_NEW_QSTR(x) MP_OBJ_NEW_QSTR_##x +#define MP_OBJ_NEW_QSTR(x) (mp_fun_table.native_to_obj(x, MP_NATIVE_TYPE_QSTR)) #define mp_type_type (*mp_fun_table.type_type) #define mp_type_NoneType (*mp_obj_get_type(mp_const_none)) diff --git a/py/gc.c b/py/gc.c index 9fefd3638b..b2e4aa4aae 100644 --- a/py/gc.c +++ b/py/gc.c @@ -79,7 +79,7 @@ #define ATB_3_IS_FREE(a) (((a) & ATB_MASK_3) == 0) #if MICROPY_GC_SPLIT_HEAP -#define NEXT_AREA(area) (area->next) +#define NEXT_AREA(area) ((area)->next) #else #define NEXT_AREA(area) (NULL) #endif @@ -129,7 +129,13 @@ STATIC void gc_setup_area(mp_state_mem_area_t *area, void *start, void *end) { // => T = A * (1 + BLOCKS_PER_ATB / BLOCKS_PER_FTB + BLOCKS_PER_ATB * BYTES_PER_BLOCK) size_t total_byte_len = (byte *)end - (byte *)start; #if MICROPY_ENABLE_FINALISER - area->gc_alloc_table_byte_len = (total_byte_len - ALLOC_TABLE_GAP_BYTE) * MP_BITS_PER_BYTE / (MP_BITS_PER_BYTE + MP_BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB + MP_BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK); + area->gc_alloc_table_byte_len = (total_byte_len - ALLOC_TABLE_GAP_BYTE) + * MP_BITS_PER_BYTE + / ( + MP_BITS_PER_BYTE + + MP_BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB + + MP_BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK + ); #else area->gc_alloc_table_byte_len = (total_byte_len - ALLOC_TABLE_GAP_BYTE) / (1 + MP_BITS_PER_BYTE / 2 * BYTES_PER_BLOCK); #endif @@ -158,17 +164,26 @@ STATIC void gc_setup_area(mp_state_mem_area_t *area, void *start, void *end) { #endif area->gc_last_free_atb_index = 0; + area->gc_last_used_block = 0; #if MICROPY_GC_SPLIT_HEAP area->next = NULL; #endif DEBUG_printf("GC layout:\n"); - DEBUG_printf(" alloc table at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", MP_STATE_MEM(area).gc_alloc_table_start, MP_STATE_MEM(area).gc_alloc_table_byte_len, MP_STATE_MEM(area).gc_alloc_table_byte_len * BLOCKS_PER_ATB); + DEBUG_printf(" alloc table at %p, length " UINT_FMT " bytes, " + UINT_FMT " blocks\n", + area->gc_alloc_table_start, area->gc_alloc_table_byte_len, + area->gc_alloc_table_byte_len * BLOCKS_PER_ATB); #if MICROPY_ENABLE_FINALISER - DEBUG_printf(" finaliser table at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", MP_STATE_MEM(area).gc_finaliser_table_start, gc_finaliser_table_byte_len, gc_finaliser_table_byte_len * BLOCKS_PER_FTB); + DEBUG_printf(" finaliser table at %p, length " UINT_FMT " bytes, " + UINT_FMT " blocks\n", area->gc_finaliser_table_start, + gc_finaliser_table_byte_len, + gc_finaliser_table_byte_len * BLOCKS_PER_FTB); #endif - DEBUG_printf(" pool at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", MP_STATE_MEM(area).gc_pool_start, gc_pool_block_len * BYTES_PER_BLOCK, gc_pool_block_len); + DEBUG_printf(" pool at %p, length " UINT_FMT " bytes, " + UINT_FMT " blocks\n", area->gc_pool_start, + gc_pool_block_len * BYTES_PER_BLOCK, gc_pool_block_len); } void gc_init(void *start, void *end) { @@ -221,6 +236,83 @@ void gc_add(void *start, void *end) { // Add this area to the linked list prev_area->next = area; } + +#if MICROPY_GC_SPLIT_HEAP_AUTO +// Try to automatically add a heap area large enough to fulfill 'failed_alloc'. +STATIC bool gc_try_add_heap(size_t failed_alloc) { + // 'needed' is the size of a heap large enough to hold failed_alloc, with + // the additional metadata overheads as calculated in gc_setup_area(). + // + // Rather than reproduce all of that logic here, we approximate that adding + // (13/512) is enough overhead for sufficiently large heap areas (the + // overhead converges to 3/128, but there's some fixed overhead and some + // rounding up of partial block sizes). + size_t needed = failed_alloc + MAX(2048, failed_alloc * 13 / 512); + + size_t avail = gc_get_max_new_split(); + + DEBUG_printf("gc_try_add_heap failed_alloc " UINT_FMT ", " + "needed " UINT_FMT ", avail " UINT_FMT " bytes \n", + failed_alloc, + needed, + avail); + + if (avail < needed) { + // Can't fit this allocation, or system heap has nearly run out anyway + return false; + } + + // Deciding how much to grow the total heap by each time is tricky: + // + // - Grow by too small amounts, leads to heap fragmentation issues. + // + // - Grow by too large amounts, may lead to system heap running out of + // space. + // + // Currently, this implementation is: + // + // - At minimum, aim to double the total heap size each time we add a new + // heap. i.e. without any large single allocations, total size will be + // 64KB -> 128KB -> 256KB -> 512KB -> 1MB, etc + // + // - If the failed allocation is too large to fit in that size, the new + // heap is made exactly large enough for that allocation. Future growth + // will double the total heap size again. + // + // - If the new heap won't fit in the available free space, add the largest + // new heap that will fit (this may lead to failed system heap allocations + // elsewhere, but some allocation will likely fail in this circumstance!) + size_t total_heap = 0; + for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); + area != NULL; + area = NEXT_AREA(area)) { + total_heap += area->gc_pool_end - area->gc_alloc_table_start; + total_heap += ALLOC_TABLE_GAP_BYTE + sizeof(mp_state_mem_area_t); + } + + DEBUG_printf("total_heap " UINT_FMT " bytes\n", total_heap); + + size_t to_alloc = MIN(avail, MAX(total_heap, needed)); + + mp_state_mem_area_t *new_heap = MP_PLAT_ALLOC_HEAP(to_alloc); + + DEBUG_printf("MP_PLAT_ALLOC_HEAP " UINT_FMT " = %p\n", + to_alloc, new_heap); + + if (new_heap == NULL) { + // This should only fail: + // - In a threaded environment if another thread has + // allocated while this function ran. + // - If there is a bug in gc_get_max_new_split(). + return false; + } + + gc_add(new_heap, (void *)new_heap + to_alloc); + + return true; +} +#endif + #endif void gc_lock(void) { @@ -377,8 +469,18 @@ STATIC void gc_sweep(void) { #endif // free unmarked heads and their tails int free_tail = 0; + #if MICROPY_GC_SPLIT_HEAP_AUTO + mp_state_mem_area_t *prev_area = NULL; + #endif for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { - for (size_t block = 0; block < area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) { + size_t end_block = area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; + if (area->gc_last_used_block < end_block) { + end_block = area->gc_last_used_block + 1; + } + + size_t last_used_block = 0; + + for (size_t block = 0; block < end_block; block++) { MICROPY_GC_HOOK_LOOP(block); switch (ATB_GET_KIND(area, block)) { case AT_HEAD: @@ -418,15 +520,31 @@ STATIC void gc_sweep(void) { #if CLEAR_ON_SWEEP memset((void *)PTR_FROM_BLOCK(area, block), 0, BYTES_PER_BLOCK); #endif + } else { + last_used_block = block; } break; case AT_MARK: ATB_MARK_TO_HEAD(area, block); free_tail = 0; + last_used_block = block; break; } } + + area->gc_last_used_block = last_used_block; + + #if MICROPY_GC_SPLIT_HEAP_AUTO + // Free any empty area, aside from the first one + if (last_used_block == 0 && prev_area != NULL) { + DEBUG_printf("gc_sweep free empty area %p\n", area); + NEXT_AREA(prev_area) = NEXT_AREA(area); + MP_PLAT_FREE_HEAP(area); + area = prev_area; + } + prev_area = area; + #endif } } @@ -609,6 +727,9 @@ void *gc_alloc(size_t n_bytes, unsigned int alloc_flags) { size_t start_block; size_t n_free; int collected = !MP_STATE_MEM(gc_auto_collect_enabled); + #if MICROPY_GC_SPLIT_HEAP_AUTO + bool added = false; + #endif #if MICROPY_GC_ALLOC_THRESHOLD if (!collected && MP_STATE_MEM(gc_alloc_amount) >= MP_STATE_MEM(gc_alloc_threshold)) { @@ -654,6 +775,12 @@ void *gc_alloc(size_t n_bytes, unsigned int alloc_flags) { GC_EXIT(); // nothing found! if (collected) { + #if MICROPY_GC_SPLIT_HEAP_AUTO + if (!added && gc_try_add_heap(n_bytes)) { + added = true; + continue; + } + #endif return NULL; } DEBUG_printf("gc_alloc(" UINT_FMT "): no free mem, triggering GC\n", n_bytes); @@ -680,6 +807,8 @@ found: area->gc_last_free_atb_index = (i + 1) / BLOCKS_PER_ATB; } + area->gc_last_used_block = MAX(area->gc_last_used_block, end_block); + // mark first block as used head ATB_FREE_TO_HEAD(area, start_block); @@ -971,11 +1100,14 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { // check if we can expand in place if (new_blocks <= n_blocks + n_free) { // mark few more blocks as used tail - for (size_t bl = block + n_blocks; bl < block + new_blocks; bl++) { + size_t end_block = block + new_blocks; + for (size_t bl = block + n_blocks; bl < end_block; bl++) { assert(ATB_GET_KIND(area, bl) == AT_FREE); ATB_FREE_TO_TAIL(area, bl); } + area->gc_last_used_block = MAX(area->gc_last_used_block, end_block); + GC_EXIT(); #if MICROPY_GC_CONSERVATIVE_CLEAR @@ -1024,9 +1156,12 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { void gc_dump_info(const mp_print_t *print) { gc_info_t info; gc_info(&info); - mp_printf(print, "GC: total: %u, used: %u, free: %u\n", + mp_printf(print, "GC: total: %u, used: %u, free: %u", (uint)info.total, (uint)info.used, (uint)info.free); - mp_printf(print, " No. of 1-blocks: %u, 2-blocks: %u, max blk sz: %u, max free sz: %u\n", + #if MICROPY_GC_SPLIT_HEAP_AUTO + mp_printf(print, ", max new split: %u", (uint)gc_get_max_new_split()); + #endif + mp_printf(print, "\n No. of 1-blocks: %u, 2-blocks: %u, max blk sz: %u, max free sz: %u\n", (uint)info.num_1block, (uint)info.num_2block, (uint)info.max_block, (uint)info.max_free); } diff --git a/py/gc.h b/py/gc.h index 8431c0a6cf..7eec6265c8 100644 --- a/py/gc.h +++ b/py/gc.h @@ -35,7 +35,13 @@ void gc_init(void *start, void *end); #if MICROPY_GC_SPLIT_HEAP // Used to add additional memory areas to the heap. void gc_add(void *start, void *end); -#endif + +#if MICROPY_GC_SPLIT_HEAP_AUTO +// Port must implement this function to return the maximum available block of +// RAM to allocate a new heap area into using MP_PLAT_ALLOC_HEAP. +size_t gc_get_max_new_split(void); +#endif // MICROPY_GC_SPLIT_HEAP_AUTO +#endif // MICROPY_GC_SPLIT_HEAP // These lock/unlock functions can be nested. // They can be used to prevent the GC from allocating/freeing. diff --git a/py/malloc.c b/py/malloc.c index efdff75396..ddf139e386 100644 --- a/py/malloc.c +++ b/py/malloc.c @@ -185,7 +185,7 @@ void *m_realloc_maybe(void *ptr, size_t new_num_bytes, bool allow_move) #if MICROPY_MALLOC_USES_ALLOCATED_SIZE DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr); #else - DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, new_num_bytes, new_ptr); + DEBUG_printf("realloc %p, %d : %p\n", ptr, new_num_bytes, new_ptr); #endif return new_ptr; } diff --git a/py/mkenv.mk b/py/mkenv.mk index 5368279e29..d3dddcc32d 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -42,6 +42,7 @@ SED = sed CAT = cat TOUCH = touch PYTHON = python3 +ZIP = zip AS = $(CROSS_COMPILE)as CC = $(CROSS_COMPILE)gcc diff --git a/py/mkrules.cmake b/py/mkrules.cmake index 7eb5fcf018..02e3148f2b 100644 --- a/py/mkrules.cmake +++ b/py/mkrules.cmake @@ -178,7 +178,12 @@ if(MICROPY_FROZEN_MANIFEST) set(MICROPY_LIB_DIR ${MICROPY_DIR}/lib/micropython-lib) endif() - if(NOT (${ECHO_SUBMODULES}) AND NOT EXISTS ${MICROPY_LIB_DIR}/README.md) + if(ECHO_SUBMODULES) + # No-op, we're just doing submodule/variant discovery. + # Note: All the following rules are safe to run in discovery mode even + # though the submodule might not be available as they do not directly depend + # on anything from the submodule. + elseif(NOT EXISTS ${MICROPY_LIB_DIR}/README.md) message(FATAL_ERROR " micropython-lib not initialized.\n Run 'make BOARD=${MICROPY_BOARD} submodules'") endif() @@ -218,9 +223,3 @@ if(ECHO_SUBMODULES) execute_process(COMMAND ${CMAKE_COMMAND} -E echo "GIT_SUBMODULES=${GIT_SUBMODULES}") message(FATAL_ERROR "Done") endif() - -# Display BOARD_VARIANTS -if(ECHO_BOARD_VARIANTS) - execute_process(COMMAND ${CMAKE_COMMAND} -E echo "BOARD_VARIANTS=${BOARD_VARIANTS}") - message(FATAL_ERROR "Done") -endif() diff --git a/py/modstruct.c b/py/modstruct.c index 42f91b282c..b3edc96328 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -92,7 +92,9 @@ STATIC size_t calc_size_items(const char *fmt, size_t *total_sz) { cnt = get_fmt_num(&fmt); } - if (*fmt == 's') { + if (*fmt == 'x') { + size += cnt; + } else if (*fmt == 's') { total_cnt += 1; size += cnt; } else { @@ -159,7 +161,9 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) { cnt = get_fmt_num(&fmt); } mp_obj_t item; - if (*fmt == 's') { + if (*fmt == 'x') { + p += cnt; + } else if (*fmt == 's') { item = mp_obj_new_bytes(p, cnt); p += cnt; res->items[i++] = item; @@ -192,7 +196,10 @@ STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, size_t n_args, c cnt = get_fmt_num(&fmt); } - if (*fmt == 's') { + if (*fmt == 'x') { + memset(p, 0, cnt); + p += cnt; + } else if (*fmt == 's') { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[i++], &bufinfo, MP_BUFFER_READ); mp_uint_t to_copy = cnt; diff --git a/py/modthread.c b/py/modthread.c index 51d63e4703..6b75474904 100644 --- a/py/modthread.c +++ b/py/modthread.c @@ -129,7 +129,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( STATIC size_t thread_stack_size = 0; STATIC mp_obj_t mod_thread_get_ident(void) { - return mp_obj_new_int_from_uint((uintptr_t)mp_thread_get_state()); + return mp_obj_new_int_from_uint(mp_thread_get_id()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_get_ident_obj, mod_thread_get_ident); @@ -268,9 +268,7 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args) th_args->fun = args[0]; // spawn the thread! - mp_thread_create(thread_entry, th_args, &th_args->stack_size); - - return mp_const_none; + return mp_obj_new_int_from_uint(mp_thread_create(thread_entry, th_args, &th_args->stack_size)); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_start_new_thread_obj, 2, 3, mod_thread_start_new_thread); diff --git a/py/mpconfig.h b/py/mpconfig.h index c617f573b6..433d6e50de 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -312,9 +312,11 @@ #define MICROPY_PERSISTENT_CODE_LOAD (0) #endif -// Whether to support saving of persistent code +// Whether to support saving of persistent code, i.e. for mpy-cross to +// generate .mpy files. Enabling this enables additional metadata on raw code +// objects which is also required for sys.settrace. #ifndef MICROPY_PERSISTENT_CODE_SAVE -#define MICROPY_PERSISTENT_CODE_SAVE (0) +#define MICROPY_PERSISTENT_CODE_SAVE (MICROPY_PY_SYS_SETTRACE) #endif // Whether to support saving persistent code to a file via mp_raw_code_save_file @@ -616,6 +618,11 @@ #define MICROPY_GC_SPLIT_HEAP (0) #endif +// Whether regions should be added/removed from the split heap as needed. +#ifndef MICROPY_GC_SPLIT_HEAP_AUTO +#define MICROPY_GC_SPLIT_HEAP_AUTO (0) +#endif + // Hook to run code during time consuming garbage collector operations // *i* is the loop index variable (e.g. can be used to run every x loops) #ifndef MICROPY_GC_HOOK_LOOP @@ -1485,11 +1492,16 @@ typedef double mp_float_t; #define MICROPY_PY_ERRNO_ERRORCODE (1) #endif -// Whether to provide "select" module (baremetal implementation) +// Whether to provide "select" module #ifndef MICROPY_PY_SELECT #define MICROPY_PY_SELECT (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) #endif +// Whether to enable POSIX optimisations in the "select" module (requires system poll) +#ifndef MICROPY_PY_SELECT_POSIX_OPTIMISATIONS +#define MICROPY_PY_SELECT_POSIX_OPTIMISATIONS (0) +#endif + // Whether to enable the select() function in the "select" module (baremetal // implementation). This is present for compatibility but can be disabled to // save space. @@ -1706,7 +1718,7 @@ typedef double mp_float_t; // Whether to add finaliser code to ssl objects #ifndef MICROPY_PY_SSL_FINALISER -#define MICROPY_PY_SSL_FINALISER (0) +#define MICROPY_PY_SSL_FINALISER (MICROPY_ENABLE_FINALISER) #endif #ifndef MICROPY_PY_WEBSOCKET @@ -1891,6 +1903,16 @@ typedef double mp_float_t; #define MP_PLAT_FREE_EXEC(ptr, size) m_del(byte, ptr, size) #endif +// Allocating new heap area at runtime requires port to be able to allocate from system heap +#if MICROPY_GC_SPLIT_HEAP_AUTO +#ifndef MP_PLAT_ALLOC_HEAP +#define MP_PLAT_ALLOC_HEAP(size) malloc(size) +#endif +#ifndef MP_PLAT_FREE_HEAP +#define MP_PLAT_FREE_HEAP(ptr) free(ptr) +#endif +#endif + // This macro is used to do all output (except when MICROPY_PY_IO is defined) #ifndef MP_PLAT_PRINT_STRN #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) @@ -1993,14 +2015,4 @@ typedef double mp_float_t; #define MP_WARN_CAT(x) (NULL) #endif -// Feature dependency check. -#if MICROPY_PY_SYS_SETTRACE -#if !MICROPY_PERSISTENT_CODE_SAVE -#error "MICROPY_PY_SYS_SETTRACE requires MICROPY_PERSISTENT_CODE_SAVE to be enabled" -#endif -#if MICROPY_COMP_CONST -#error "MICROPY_PY_SYS_SETTRACE requires MICROPY_COMP_CONST to be disabled" -#endif -#endif - #endif // MICROPY_INCLUDED_PY_MPCONFIG_H diff --git a/py/mpstate.h b/py/mpstate.h index 080dc1380b..64915ab87d 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -93,6 +93,7 @@ typedef struct _mp_state_mem_area_t { byte *gc_pool_end; size_t gc_last_free_atb_index; + size_t gc_last_used_block; // The block ID of the highest block allocated in the area } mp_state_mem_area_t; // This structure hold information about the memory allocation system. diff --git a/py/mpthread.h b/py/mpthread.h index e611ef4c11..f335cc0291 100644 --- a/py/mpthread.h +++ b/py/mpthread.h @@ -40,7 +40,8 @@ struct _mp_state_thread_t; struct _mp_state_thread_t *mp_thread_get_state(void); void mp_thread_set_state(struct _mp_state_thread_t *state); -void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size); +mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size); +mp_uint_t mp_thread_get_id(void); void mp_thread_start(void); void mp_thread_finish(void); void mp_thread_mutex_init(mp_thread_mutex_t *mutex); diff --git a/py/nativeglue.c b/py/nativeglue.c index 743ff38ccb..d92d815abd 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -104,6 +104,8 @@ mp_obj_t mp_native_to_obj(mp_uint_t val, mp_uint_t type) { return mp_obj_new_int(val); case MP_NATIVE_TYPE_UINT: return mp_obj_new_int_from_uint(val); + case MP_NATIVE_TYPE_QSTR: + return MP_OBJ_NEW_QSTR(val); default: // a pointer // we return just the value of the pointer as an integer return mp_obj_new_int_from_uint(val); diff --git a/py/objstr.c b/py/objstr.c index b966a70169..5dfe94ac4f 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -1645,7 +1645,9 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_ } } - if (arg_i != n_args) { + if (dict == MP_OBJ_NULL && arg_i != n_args) { + // NOTE: if `dict` exists, then `n_args` is 1 and the dict is always consumed; either + // positionally, or as a map of named args, even if none were actually referenced. mp_raise_TypeError(MP_ERROR_TEXT("format string didn't convert all arguments")); } diff --git a/py/profile.c b/py/profile.c index 89af8640a0..274089d702 100644 --- a/py/profile.c +++ b/py/profile.c @@ -31,6 +31,12 @@ #if MICROPY_PY_SYS_SETTRACE +#if !MICROPY_PERSISTENT_CODE_SAVE +// The settrace feature requires that we maintain additional metadata on the raw +// code object which is normally only done when writing .mpy files. +#error "MICROPY_PY_SYS_SETTRACE requires MICROPY_PERSISTENT_CODE_SAVE to be enabled" +#endif + #define prof_trace_cb MP_STATE_THREAD(prof_trace_callback) #define QSTR_MAP(context, idx) (context->constants.qstr_table[idx]) diff --git a/py/runtime0.h b/py/runtime0.h index 6ef2d727c1..69af38ddcb 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -50,6 +50,9 @@ #define MP_NATIVE_TYPE_PTR16 (0x06) #define MP_NATIVE_TYPE_PTR32 (0x07) +// Not use for viper, but for dynamic native modules +#define MP_NATIVE_TYPE_QSTR (0x08) + // Bytecode and runtime boundaries for unary ops #define MP_UNARY_OP_NUM_BYTECODE (MP_UNARY_OP_NOT + 1) #define MP_UNARY_OP_NUM_RUNTIME (MP_UNARY_OP_SIZEOF + 1) diff --git a/pyproject.toml b/pyproject.toml index dfd26bd8c9..e3d70385c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,6 @@ ignore = [ "F401", "F403", "F405", - "F821", "PLC1901", ] line-length = 337 @@ -46,3 +45,7 @@ max-complexity = 40 [tool.ruff.per-file-ignores] "ports/cc3200/tools/uniflash.py" = ["E711"] + +# manifest.py files are evaluated with some global names pre-defined +"**/manifest.py" = ["F821"] +"ports/**/boards/**/manifest_*.py" = ["F821"] diff --git a/tests/basics/string_format_modulo.py b/tests/basics/string_format_modulo.py index 14b4a6a484..7bddd96750 100644 --- a/tests/basics/string_format_modulo.py +++ b/tests/basics/string_format_modulo.py @@ -51,8 +51,9 @@ print('%c' % True) # Should be able to print dicts; in this case they aren't used # to lookup keywords in formats like %(foo)s -print('%s' % {}) -print('%s' % ({},)) +print('%s' % {}) # dict treated as the single (positional) arg to % +print('%s' % ({},)) # dict is the first (and only) arg in the positional arg tuple +print('foo' % {}) # no error, dict treated as an empty map of named args # Cases when "*" used and there's not enough values total try: @@ -65,7 +66,11 @@ except TypeError: print("TypeError") print("%(foo)s" % {"foo": "bar", "baz": False}) -print("%s %(foo)s %(foo)s" % {"foo": 1}) +print("%s %(foo)s %(foo)s" % {"foo": 1}) # dict consumed positionally, then used as map - ok +try: + print("%(foo)s %s %(foo)s" % {"foo": 1}) # used as map, then positionally - not enough args +except TypeError: + print("TypeError") try: print("%(foo)s" % {}) except KeyError: diff --git a/tests/basics/struct1.py b/tests/basics/struct1.py index a18655517b..e473ffcc11 100644 --- a/tests/basics/struct1.py +++ b/tests/basics/struct1.py @@ -20,6 +20,8 @@ print(struct.pack("h", 1)) print(struct.pack("b", 1)) +print(struct.pack("x")) print(struct.pack("bI", -128, 256)) @@ -29,6 +31,13 @@ print(struct.calcsize("97sI")) print(struct.unpack("<6sH", b"foo\0\0\0\x12\x34")) print(struct.pack("<6sH", b"foo", 10000)) +print(struct.calcsize("7xx")) +print(struct.pack("7xx")) + +print(struct.calcsize(">bxI3xH")) +print(struct.pack(">bxI3xH", 1, 2, 3)) +print(struct.unpack(">bxI3xH", b"\x01\0\0\0\0\x02\0\0\0\0\x03")) + s = struct.pack("BHBI", 10, 100, 200, 300) v = struct.unpack("BHBI", s) print(v == (10, 100, 200, 300)) diff --git a/tests/extmod/select_ipoll.py b/tests/extmod/select_ipoll.py new file mode 100644 index 0000000000..0b661c11c8 --- /dev/null +++ b/tests/extmod/select_ipoll.py @@ -0,0 +1,55 @@ +# Test select.ipoll(). + +try: + import socket, select +except ImportError: + print("SKIP") + raise SystemExit + + +def print_poll_output(lst): + print([(type(obj), flags) for obj, flags in lst]) + + +poller = select.poll() + +# Use a new UDP socket for tests, which should be writable but not readable. +try: + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.bind(socket.getaddrinfo("127.0.0.1", 8000)[0][-1]) +except OSError: + print("SKIP") + raise SystemExit + +poller.register(s) + +# Basic polling. +print_poll_output(poller.ipoll(0)) + +# Pass in flags=1 for one-shot behaviour. +print_poll_output(poller.ipoll(0, 1)) + +# Socket should be deregistered and poll should return nothing. +print_poll_output(poller.ipoll(0)) + +# Create a second socket. +s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +s2.bind(socket.getaddrinfo("127.0.0.1", 8001)[0][-1]) + +# Register both sockets (to reset the first one). +poller.register(s) +poller.register(s2) + +# Basic polling with two sockets. +print_poll_output(poller.ipoll(0)) + +# Unregister the first socket, to test polling the remaining one. +poller.unregister(s) +print_poll_output(poller.ipoll(0)) + +# Unregister the second socket, to test polling none. +poller.unregister(s2) +print_poll_output(poller.ipoll(0)) + +s2.close() +s.close() diff --git a/tests/extmod/select_ipoll.py.exp b/tests/extmod/select_ipoll.py.exp new file mode 100644 index 0000000000..cbeabdce90 --- /dev/null +++ b/tests/extmod/select_ipoll.py.exp @@ -0,0 +1,6 @@ +[(, 4)] +[(, 4)] +[] +[(, 4), (, 4)] +[(, 4)] +[] diff --git a/tests/extmod/select_poll_basic.py b/tests/extmod/select_poll_basic.py index b36e16f018..0814d89ce9 100644 --- a/tests/extmod/select_poll_basic.py +++ b/tests/extmod/select_poll_basic.py @@ -16,6 +16,7 @@ poller.register(s) # "Registering a file descriptor that’s already registered is not an error, # and has the same effect as registering the descriptor exactly once." poller.register(s) +poller.register(s, select.POLLIN | select.POLLOUT) # 2 args are mandatory unlike register() try: diff --git a/tests/extmod/select_poll_custom.py b/tests/extmod/select_poll_custom.py new file mode 100644 index 0000000000..b854a8a14d --- /dev/null +++ b/tests/extmod/select_poll_custom.py @@ -0,0 +1,102 @@ +# Test custom pollable objects implemented in Python. + +from micropython import const + +try: + import socket, select, io +except ImportError: + print("SKIP") + raise SystemExit + +_MP_STREAM_POLL = const(3) +_MP_STREAM_GET_FILENO = const(10) + +_MP_STREAM_POLL_RD = const(0x0001) +_MP_STREAM_POLL_WR = const(0x0004) + + +def print_poll_output(lst): + print([(type(obj), flags) for obj, flags in lst]) + + +class CustomPollable(io.IOBase): + def __init__(self): + self.poll_state = 0 + + def ioctl(self, cmd, arg): + if cmd == _MP_STREAM_GET_FILENO: + # Bare-metal ports don't call this ioctl, so don't print it. + return -1 + + print("CustomPollable.ioctl", cmd, arg) + if cmd == _MP_STREAM_POLL: + if self.poll_state == "delay_rd": + self.poll_state = _MP_STREAM_POLL_RD + return 0 + elif self.poll_state < 0: + return self.poll_state + else: + return self.poll_state & arg + + +poller = select.poll() + +# Use a new UDP socket for tests, which should be writable but not readable. +try: + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.bind(socket.getaddrinfo("127.0.0.1", 8000)[0][-1]) +except OSError: + print("SKIP") + raise SystemExit + +x = CustomPollable() + +# Register both a file-descriptor-based object and a custom pure-Python object. +poller.register(s) +poller.register(x) + +# Modify the flags for the custom object. +poller.modify(x, select.POLLIN) + +# Test polling. +print_poll_output(poller.poll(0)) +x.poll_state = _MP_STREAM_POLL_WR +print_poll_output(poller.poll(0)) +x.poll_state = _MP_STREAM_POLL_RD +print_poll_output(poller.poll(0)) + +# The custom object becomes readable only after being polled. +poller.modify(s, select.POLLIN) +x.poll_state = "delay_rd" +print_poll_output(poller.poll()) + +# The custom object returns an error. +x.poll_state = -1000 +try: + poller.poll(0) +except OSError as er: + print("OSError", er.errno) + +# Register then unregister a socket (a native stream), then test +# that the Python object is still pollable. +s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +x.poll_state = _MP_STREAM_POLL_RD +poller.register(s2) +poller.unregister(s2) +print_poll_output(poller.poll()) + +# Test registering and unregistering multiple times. +for _ in range(2): + poller.unregister(s) + poller.unregister(x) + poller.register(s2) + poller.register(s, select.POLLIN) + poller.register(x, select.POLLIN) + poller.unregister(s2) + print_poll_output(poller.poll()) + +# Clean up. +poller.unregister(x) +poller.unregister(s) +s2.close() +s.close() diff --git a/tests/extmod/select_poll_custom.py.exp b/tests/extmod/select_poll_custom.py.exp new file mode 100644 index 0000000000..d85508bab2 --- /dev/null +++ b/tests/extmod/select_poll_custom.py.exp @@ -0,0 +1,17 @@ +CustomPollable.ioctl 3 1 +[(, 4)] +CustomPollable.ioctl 3 1 +[(, 4)] +CustomPollable.ioctl 3 1 +[(, 4), (, 1)] +CustomPollable.ioctl 3 1 +CustomPollable.ioctl 3 1 +[(, 1)] +CustomPollable.ioctl 3 1 +OSError 1000 +CustomPollable.ioctl 3 1 +[(, 1)] +CustomPollable.ioctl 3 1 +[(, 1)] +CustomPollable.ioctl 3 1 +[(, 1)] diff --git a/tests/extmod/select_poll_eintr.py b/tests/extmod/select_poll_eintr.py new file mode 100644 index 0000000000..e1cbc2aaf5 --- /dev/null +++ b/tests/extmod/select_poll_eintr.py @@ -0,0 +1,50 @@ +# Test interruption of select.poll by EINTR signal, when +# MICROPY_PY_SELECT_POSIX_OPTIMISATIONS is enabled. + +try: + import time, gc, select, socket, _thread + + time.time_ns # Check for time_ns on MicroPython + select.poll # Raises AttributeError for CPython implementations without poll() +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + + +def thread_main(): + lock.acquire() + time.sleep(0.2) + print("thread gc start") + # The unix gc.collect() implementation will raise EINTR on other threads. + # Could possibly use _thread._interrupt_main() instead if MicroPython had it. + gc.collect() + print("thread gc end") + + +# Start a thread to interrupt the main thread during its call to poll. +lock = _thread.allocate_lock() +lock.acquire() +_thread.start_new_thread(thread_main, ()) + +# Use a new UDP socket for tests, which should be writable but not readable. +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +s.bind(socket.getaddrinfo("127.0.0.1", 8000)[0][-1]) + +# Create the poller object. +poller = select.poll() +poller.register(s, select.POLLIN) + +# Poll on the UDP socket for a set timeout, which should be reached. +print("poll") +lock.release() +t0 = time.time_ns() +result = poller.poll(400) +dt_ms = (time.time_ns() - t0) / 1e6 +print("result:", result) +if 380 <= dt_ms <= 600: + print("dt in range") +else: + print("dt not in range:", dt_ms) + +# Clean up. +s.close() diff --git a/tests/extmod/select_poll_fd.py b/tests/extmod/select_poll_fd.py new file mode 100644 index 0000000000..fab9c0e0e9 --- /dev/null +++ b/tests/extmod/select_poll_fd.py @@ -0,0 +1,44 @@ +# Test select.poll in combination with file descriptors. + +try: + import select, errno + + select.poll # Raises AttributeError for CPython implementations without poll() +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + +# Check that poll supports registering file descriptors (integers). +try: + select.poll().register(0) +except OSError: + print("SKIP") + raise SystemExit + +# Register invalid file descriptor. +try: + select.poll().register(-1) +except ValueError: + print("ValueError") + +# Test polling stdout, it should be writable. +poller = select.poll() +poller.register(1) +poller.modify(1, select.POLLOUT) +print(poller.poll()) + +# Unregister then re-register. +poller.unregister(1) +poller.register(1, select.POLLIN) + +# Poll for input, should return an empty list. +print(poller.poll(0)) + +# Test registering a very large number of file descriptors. +poller = select.poll() +for fd in range(6000): + poller.register(fd) +try: + poller.poll() +except OSError as er: + print(er.errno == errno.EINVAL) diff --git a/tests/extmod/select_poll_udp.py b/tests/extmod/select_poll_udp.py index 336f987c12..133871b1a4 100644 --- a/tests/extmod/select_poll_udp.py +++ b/tests/extmod/select_poll_udp.py @@ -8,9 +8,13 @@ except (ImportError, AttributeError): print("SKIP") raise SystemExit +try: + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.bind(socket.getaddrinfo("127.0.0.1", 8000)[0][-1]) +except OSError: + print("SKIP") + raise SystemExit -s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -s.bind(socket.getaddrinfo("127.0.0.1", 8000)[0][-1]) poll = select.poll() # UDP socket should not be readable diff --git a/tests/extmod/socket_udp_nonblock.py b/tests/extmod/socket_udp_nonblock.py index f7ce5f3444..1e74e2917d 100644 --- a/tests/extmod/socket_udp_nonblock.py +++ b/tests/extmod/socket_udp_nonblock.py @@ -6,9 +6,13 @@ except ImportError: print("SKIP") raise SystemExit +try: + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.bind(socket.getaddrinfo("127.0.0.1", 8000)[0][-1]) +except OSError: + print("SKIP") + raise SystemExit -s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -s.bind(socket.getaddrinfo("127.0.0.1", 8000)[0][-1]) s.settimeout(0) try: diff --git a/tests/extmod/ssl_ioctl.py b/tests/extmod/ssl_ioctl.py new file mode 100644 index 0000000000..4db7c2df82 --- /dev/null +++ b/tests/extmod/ssl_ioctl.py @@ -0,0 +1,31 @@ +# Test SSL ioctl method. +# Direct access to this method is only available if MICROPY_UNIX_COVERAGE is enabled. + +try: + import io, ssl + + io.BytesIO +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + +_MP_STREAM_POLL = 3 +_MP_STREAM_CLOSE = 4 +_MP_STREAM_GET_FILENO = 10 + +s = ssl.wrap_socket(io.BytesIO(), server_side=1, do_handshake=0) + +if not hasattr(s, "ioctl"): + print("SKIP") + raise SystemExit + +# These ioctl's should be unsupported. +for request in (-1, 0, _MP_STREAM_GET_FILENO): + try: + s.ioctl(request, 0) + except OSError: + print(request, "OSError") + +# These ioctl's should be supported. +for request in (_MP_STREAM_CLOSE, _MP_STREAM_POLL, _MP_STREAM_CLOSE): + print(request, s.ioctl(request, 0)) diff --git a/tests/extmod/ssl_ioctl.py.exp b/tests/extmod/ssl_ioctl.py.exp new file mode 100644 index 0000000000..22208b00cc --- /dev/null +++ b/tests/extmod/ssl_ioctl.py.exp @@ -0,0 +1,6 @@ +-1 OSError +0 OSError +10 OSError +4 0 +3 32 +4 0 diff --git a/tests/io/file_stdio.py b/tests/io/file_stdio.py index cbdb070163..d714bffd4d 100644 --- a/tests/io/file_stdio.py +++ b/tests/io/file_stdio.py @@ -2,3 +2,4 @@ import sys print(sys.stdin.fileno()) print(sys.stdout.fileno()) +print(sys.stderr.fileno()) diff --git a/tests/io/file_stdio2.py b/tests/io/file_stdio2.py new file mode 100644 index 0000000000..5b8a5a7692 --- /dev/null +++ b/tests/io/file_stdio2.py @@ -0,0 +1,65 @@ +# Test sys.std*.buffer objects. + +import sys + +try: + sys.stdout.buffer + sys.stdin.buffer + sys.stderr.buffer +except AttributeError: + print("SKIP") + raise SystemExit + + +# force cpython to flush after every print +# this is to sequence stdout and stderr +def print_flush(*args, **kwargs): + try: + print(*args, **kwargs, flush=True) + except TypeError: + print(*args, **kwargs) + + +print_flush("==stdin==") +print_flush(sys.stdin.buffer.fileno()) + + +print_flush("==stdout==") +print_flush(sys.stdout.buffer.fileno()) +n_text = sys.stdout.write("The quick brown fox jumps over the lazy dog\n") +sys.stdout.flush() +n_binary = sys.stdout.buffer.write("The quick brown fox jumps over the lazy dog\n".encode("utf-8")) +sys.stdout.buffer.flush() +print_flush("n_text:{} n_binary:{}".format(n_text, n_binary)) + +# temporarily disabling unicode tests until future PR which fixes unicode write character count +# n_text = sys.stdout.write("🚀") +# sys.stdout.flush() +# n_binary = sys.stdout.buffer.write("🚀".encode("utf-8")) +# sys.stdout.buffer.flush() +# print_flush("") +# print_flush("n_text:{} n_binary:{}".format(n_text, n_binary)) +# n_text = sys.stdout.write("1🚀2a3α4b5β6c7γ8d9δ0ぁ1🙐") +# sys.stdout.flush() +# n_binary = sys.stdout.buffer.write("1🚀2a3α4b5β6c7γ8d9δ0ぁ1🙐".encode("utf-8")) +# sys.stdout.buffer.flush() +# print_flush("") +# print_flush("n_text:{} n_binary:{}".format(n_text, n_binary)) + + +print_flush("==stderr==") +print_flush(sys.stderr.buffer.fileno()) +n_text = sys.stderr.write("The quick brown fox jumps over the lazy dog\n") +sys.stderr.flush() +n_binary = sys.stderr.buffer.write("The quick brown fox jumps over the lazy dog\n".encode("utf-8")) +sys.stderr.buffer.flush() +print_flush("n_text:{} n_binary:{}".format(n_text, n_binary)) + +# temporarily disabling unicode tests until future PR which fixes unicode write character count +# n_text = sys.stderr.write("🚀") +# sys.stderr.flush() +# n_binary = sys.stderr.buffer.write("🚀".encode("utf-8")) +# sys.stderr.buffer.flush() +# print_flush("") +# print_flush("n_text:{} n_binary:{}".format(n_text, n_binary)) +# print_flush("") diff --git a/tests/micropython/import_mpy_native_gc.py b/tests/micropython/import_mpy_native_gc.py index 5a3855dc7d..5f2a2a6f45 100644 --- a/tests/micropython/import_mpy_native_gc.py +++ b/tests/micropython/import_mpy_native_gc.py @@ -47,6 +47,10 @@ class UserFS: # Pre-compiled examples/natmod/features0 example for various architectures, keyed # by the required value of sys.implementation._mpy (without sub-version). +# cd examples/natmod/features0 +# make clean +# make ARCH=x64 # or ARCH=armv6m +# cat features0.mpy | python -c 'import sys; print(sys.stdin.buffer.read())' features0_file_contents = { # -march=x64 0x806: b'M\x06\x09\x1f\x02\x004build/features0.native.mpy\x00\x12factorial\x00\x8a\x02\xe9/\x00\x00\x00SH\x8b\x1d\x83\x00\x00\x00\xbe\x02\x00\x00\x00\xffS\x18\xbf\x01\x00\x00\x00H\x85\xc0u\x0cH\x8bC \xbe\x02\x00\x00\x00[\xff\xe0H\x0f\xaf\xf8H\xff\xc8\xeb\xe6ATUSH\x8b\x1dQ\x00\x00\x00H\x8bG\x08L\x8bc(H\x8bx\x08A\xff\xd4H\x8d5+\x00\x00\x00H\x89\xc5H\x8b\x059\x00\x00\x00\x0f\xb7x\x02\xffShH\x89\xefA\xff\xd4H\x8b\x03[]A\\\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x11$\r&\xa3 \x01"\xff', diff --git a/tests/misc/sys_settrace_features.py b/tests/misc/sys_settrace_features.py index 8a38b7534f..8ca6b382e3 100644 --- a/tests/misc/sys_settrace_features.py +++ b/tests/misc/sys_settrace_features.py @@ -22,7 +22,9 @@ def print_stacktrace(frame, level=0): frame.f_code.co_name, # Keep just the filename. "sys_settrace_" + frame.f_code.co_filename.split("sys_settrace_")[-1], - frame.f_lineno, + max( + 1, frame.f_lineno + ), # CPython 3.11 emits `0` where CPython 3.6 emits `1` for the "call" event corresponding to import. ) ) @@ -65,6 +67,11 @@ def trace_tick_handler(frame, event, arg): if any(name in frame_name for name in to_ignore): return + # Lines 4,5,7 create the `const` lambda, and line `15` is a `_X = const()` which + # MicroPython will not see as it's optimised out. + if "sys_settrace_importme" in frame.f_code.co_filename and frame.f_lineno in (4, 5, 7, 15): + return trace_tick_handler + print("### trace_handler::main event:", event) __prof__.trace_tick(frame, event, arg) diff --git a/tests/misc/sys_settrace_subdir/sys_settrace_importme.py b/tests/misc/sys_settrace_subdir/sys_settrace_importme.py index de561ef217..fdfa06134e 100644 --- a/tests/misc/sys_settrace_subdir/sys_settrace_importme.py +++ b/tests/misc/sys_settrace_subdir/sys_settrace_importme.py @@ -3,12 +3,18 @@ print("Yep, I got imported.") try: x = const(1) except NameError: - print("const not defined") + # Either running on CPython or MICROPY_COMP_CONST disabled. + const = lambda x: x -const = lambda x: x +# No const optimisation. _CNT01 = "CONST01" + +# Const assigned to an underscore name. Invisible to MicroPython with +# MICROPY_COMP_CONST enabled. _CNT02 = const(123) + +# Consts assigned to regular name, executed normally. A123 = const(123) a123 = const(123) diff --git a/tests/multi_net/asyncio_tcp_close_write.py b/tests/multi_net/asyncio_tcp_close_write.py index d1892fe895..ea206c9219 100644 --- a/tests/multi_net/asyncio_tcp_close_write.py +++ b/tests/multi_net/asyncio_tcp_close_write.py @@ -33,7 +33,7 @@ async def tcp_server(): print("server running") multitest.next() async with server: - await asyncio.wait_for(ev.wait(), 5) + await asyncio.wait_for(ev.wait(), 10) async def tcp_client(): diff --git a/tests/multi_net/asyncio_tcp_readall.py b/tests/multi_net/asyncio_tcp_readall.py index 66ad97549c..45eac229d2 100644 --- a/tests/multi_net/asyncio_tcp_readall.py +++ b/tests/multi_net/asyncio_tcp_readall.py @@ -14,7 +14,7 @@ async def handle_connection(reader, writer): await writer.drain() # Split the first 2 bytes up so the client must wait for the second one - await asyncio.sleep(0.1) + await asyncio.sleep(1) writer.write(b"b") await writer.drain() @@ -37,7 +37,7 @@ async def tcp_server(): print("server running") multitest.next() async with server: - await asyncio.wait_for(ev.wait(), 2) + await asyncio.wait_for(ev.wait(), 10) async def tcp_client(): diff --git a/tests/multi_net/asyncio_tcp_readexactly.py b/tests/multi_net/asyncio_tcp_readexactly.py index 2c8df1f30a..4024e23fed 100644 --- a/tests/multi_net/asyncio_tcp_readexactly.py +++ b/tests/multi_net/asyncio_tcp_readexactly.py @@ -14,7 +14,7 @@ async def handle_connection(reader, writer): await writer.drain() # Split the first 2 bytes up so the client must wait for the second one - await asyncio.sleep(0.1) + await asyncio.sleep(1) writer.write(b"b") await writer.drain() diff --git a/tests/run-tests.py b/tests/run-tests.py index 019b30189f..de886b8ae7 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -709,7 +709,9 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): # run CPython to work out expected output try: output_expected = subprocess.check_output( - CPYTHON3_CMD + [os.path.abspath(test_file)], cwd=os.path.dirname(test_file) + CPYTHON3_CMD + [os.path.abspath(test_file)], + cwd=os.path.dirname(test_file), + stderr=subprocess.STDOUT, ) if args.write_exp: with open(test_file_expected, "wb") as f: diff --git a/tests/thread/thread_ident1.py b/tests/thread/thread_ident1.py index 390193accc..8e106cd317 100644 --- a/tests/thread/thread_ident1.py +++ b/tests/thread/thread_ident1.py @@ -5,7 +5,11 @@ import _thread +tid = None + + def thread_entry(): + global tid tid = _thread.get_ident() print("thread", type(tid) == int, tid != 0, tid != tid_main) global finished @@ -16,8 +20,9 @@ tid_main = _thread.get_ident() print("main", type(tid_main) == int, tid_main != 0) finished = False -_thread.start_new_thread(thread_entry, ()) +new_tid = _thread.start_new_thread(thread_entry, ()) while not finished: pass -print("done") + +print("done", type(new_tid) == int, new_tid == tid) diff --git a/tests/unix/mod_os.py b/tests/unix/mod_os.py index 17554d9375..f69fa45b2b 100644 --- a/tests/unix/mod_os.py +++ b/tests/unix/mod_os.py @@ -12,7 +12,7 @@ os.unsetenv("TEST_VARIABLE") print(os.getenv("TEST_VARIABLE")) print(os.getenv("TEST_VARIABLE", "TEST_DEFAULT_VALUE")) -print(os.system("true")) +print(os.system("exit 0")) rand = os.urandom(4) print(type(rand) is bytes, len(rand)) diff --git a/tools/autobuild/autobuild.sh b/tools/autobuild/autobuild.sh index b3c9c19c7c..e1f2287ee5 100755 --- a/tools/autobuild/autobuild.sh +++ b/tools/autobuild/autobuild.sh @@ -60,9 +60,9 @@ FW_TAG="-$FW_DATE-unstable-$FW_GIT" # build new firmware cd ports/cc3200 -${AUTODIR}/build-cc3200-latest.sh ${FW_TAG} ${LOCAL_FIRMWARE} +build_cc3200_boards ${FW_TAG} ${LOCAL_FIRMWARE} cd ../esp8266 -${AUTODIR}/build-esp8266-latest.sh ${FW_TAG} ${LOCAL_FIRMWARE} +build_esp8266_boards ${FW_TAG} ${LOCAL_FIRMWARE} cd ../esp32 (source ${IDF_PATH_V50}/export.sh && build_esp32_boards ${FW_TAG} ${LOCAL_FIRMWARE}) cd ../mimxrt @@ -77,7 +77,6 @@ cd ../samd build_samd_boards ${FW_TAG} ${LOCAL_FIRMWARE} cd ../stm32 build_stm32_boards ${FW_TAG} ${LOCAL_FIRMWARE} -${AUTODIR}/build-stm32-extra.sh ${FW_TAG} ${LOCAL_FIRMWARE} popd diff --git a/tools/autobuild/build-boards.sh b/tools/autobuild/build-boards.sh index 689444a988..2b323ba9b0 100755 --- a/tools/autobuild/build-boards.sh +++ b/tools/autobuild/build-boards.sh @@ -3,8 +3,36 @@ # The functions in this file can be run independently to build boards. # For example: # -# $ source build-boards.sh -# $ MICROPY_AUTOBUILD_MAKE=make build_rp2_boards -latest /tmp +# $ source tools/autobuild/build-boards.sh +# $ cd ports/rp2 +# $ MICROPY_AUTOBUILD_MAKE="make -j8" build_rp2_boards -latest /tmp +# +# Or to build a single board: +# +# $ source tools/autobuild/build-boards.sh +# $ cd ports/rp2 +# $ MICROPY_AUTOBUILD_MAKE="make -j8" build_board boards/PICO/board.json -latest /tmp uf2 + +function copy_artefacts { + local dest_dir=$1 + local descr=$2 + local fw_tag=$3 + local build_dir=$4 + shift 4 + + for ext in $@; do + dest=$dest_dir/$descr$fw_tag.$ext + if [ -r $build_dir/firmware.$ext ]; then + mv $build_dir/firmware.$ext $dest + elif [ -r $build_dir/micropython.$ext ]; then + # esp32 has micropython.elf, etc + mv $build_dir/micropython.$ext $dest + elif [ $ext = app-bin -a -r $build_dir/micropython.bin ]; then + # esp32 has micropython.bin which is just the application + mv $build_dir/micropython.bin $dest + fi + done +} function build_board { # check/get parameters @@ -13,33 +41,29 @@ function build_board { return 1 fi - board_json=$1 - fw_tag=$2 - dest_dir=$3 - shift - shift - shift + local board_json=$1 + local fw_tag=$2 + local dest_dir=$3 + shift 3 - board=$(echo $board_json | awk -F '/' '{ print $2 }') - descr=$(cat $board_json | python3 -c "import json,sys; print(json.load(sys.stdin).get('id', '$board'))") - build_dir=/tmp/micropython-build-$board + local board=$(echo $board_json | awk -F '/' '{ print $2 }') + local descr=$(cat $board_json | python3 -c "import json,sys; print(json.load(sys.stdin).get('id', '$board'))") + # Build the "default" variant. For most boards this is the only thing we build. echo "building $descr $board" - $MICROPY_AUTOBUILD_MAKE BOARD=$board BUILD=$build_dir && ( - for ext in $@; do - dest=$dest_dir/$descr$fw_tag.$ext - if [ -r $build_dir/firmware.$ext ]; then - mv $build_dir/firmware.$ext $dest - elif [ -r $build_dir/micropython.$ext ]; then - # esp32 has micropython.elf, etc - mv $build_dir/micropython.$ext $dest - elif [ $ext = app-bin -a -r $build_dir/micropython.bin ]; then - # esp32 has micropython.bin which is just the application - mv $build_dir/micropython.bin $dest - fi - done - ) + local build_dir=/tmp/micropython-build-$board + $MICROPY_AUTOBUILD_MAKE BOARD=$board BUILD=$build_dir && copy_artefacts $dest_dir $descr $fw_tag $build_dir $@ rm -rf $build_dir + + # Query variants from board.json and build them. Ignore the special "IDF3" + # variant for ESP32 boards (this allows the downloads page to still have + # the idf3 files for older releases that used to be explicitly built). + for variant in `cat $board_json | python3 -c "import json,sys; print(' '.join(v for v in json.load(sys.stdin).get('variants', {}).keys() if v != 'IDF3'))"`; do + local variant_build_dir=$build_dir-$variant + echo "building variant $descr $board $variant" + $MICROPY_AUTOBUILD_MAKE BOARD=$board BOARD_VARIANT=$variant BUILD=$variant_build_dir && copy_artefacts $dest_dir $descr-$variant $fw_tag $variant_build_dir $@ + rm -rf $variant_build_dir + done } function build_boards { @@ -49,7 +73,7 @@ function build_boards { return 1 fi - check_file=$1 + local check_file=$1 shift # check we are in the correct directory @@ -64,10 +88,18 @@ function build_boards { done } +function build_cc3200_boards { + build_boards hal/cc3200_hal.c $1 $2 zip +} + function build_esp32_boards { build_boards modesp32.c $1 $2 bin elf map uf2 app-bin } +function build_esp8266_boards { + build_boards modesp.c $1 $2 bin elf map +} + function build_mimxrt_boards { build_boards modmimxrt.c $1 $2 bin hex } diff --git a/tools/autobuild/build-cc3200-latest.sh b/tools/autobuild/build-cc3200-latest.sh deleted file mode 100755 index 0cbdb9c428..0000000000 --- a/tools/autobuild/build-cc3200-latest.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -# function for building firmware -function do_build() { - descr=$1 - board=$2 - shift - shift - echo "building $descr $board" - build_dir=/tmp/cc3200-build-$board - $MICROPY_AUTOBUILD_MAKE $@ BTARGET=application BOARD=$board BUILD=$build_dir || exit 1 - zip $dest_dir/$descr$fw_tag.zip $build_dir/mcuimg.bin - rm -rf $build_dir -} - -# check/get parameters -if [ $# != 2 ]; then - echo "usage: $0 " - exit 1 -fi - -fw_tag=$1 -dest_dir=$2 - -# check we are in the correct directory -if [ ! -r application.mk ]; then - echo "must be in cc3200 directory" - exit 1 -fi - -# build the versions -do_build wipy WIPY diff --git a/tools/autobuild/build-esp8266-latest.sh b/tools/autobuild/build-esp8266-latest.sh deleted file mode 100755 index 1972e85fcd..0000000000 --- a/tools/autobuild/build-esp8266-latest.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash - -PYTHON3=python3 -yaota8266=$HOME/yaota8266 - -# for debugging -#exec &> /tmp/esp-log-$$.txt - -# function for building firmware -function do_build() { - descr=$1 - board=$2 - shift - shift - echo "building $descr $board" - build_dir=/tmp/esp8266-build-$board - $MICROPY_AUTOBUILD_MAKE $@ BOARD=$board BUILD=$build_dir || exit 1 - mv $build_dir/firmware-combined.bin $dest_dir/$descr$fw_tag.bin - mv $build_dir/firmware.elf $dest_dir/$descr$fw_tag.elf - mv $build_dir/firmware.map $dest_dir/$descr$fw_tag.map - rm -rf $build_dir -} - -function do_build_ota() { - descr=$1 - board=$2 - shift - shift - echo "building $descr $board" - build_dir=/tmp/esp8266-build-$board - $MICROPY_AUTOBUILD_MAKE $@ BOARD=$board BUILD=$build_dir || exit 1 - cat $yaota8266/yaota8266.bin $build_dir/firmware-ota.bin > $dest_dir/$descr$fw_tag.bin - pushd $yaota8266/ota-client - $PYTHON3 ota_client.py sign $build_dir/firmware-ota.bin - popd - mv $build_dir/firmware-ota.bin.ota $dest_dir/$descr$fw_tag.ota - mv $build_dir/firmware.elf $dest_dir/$descr$fw_tag.elf - mv $build_dir/firmware.map $dest_dir/$descr$fw_tag.map - rm -rf $build_dir -} - -# check/get parameters -if [ $# != 2 ]; then - echo "usage: $0 " - exit 1 -fi - -fw_tag=$1 -dest_dir=$2 - -# check we are in the correct directory -if [ ! -r boards/esp8266_common.ld ]; then - echo "must be in esp8266 directory" - exit 1 -fi - -# build the versions -do_build esp8266 GENERIC -do_build esp8266-512k GENERIC_512K -do_build esp8266-1m GENERIC_1M -do_build_ota esp8266-ota GENERIC_1M ota diff --git a/tools/autobuild/build-stm32-extra.sh b/tools/autobuild/build-stm32-extra.sh deleted file mode 100755 index 887e3cd246..0000000000 --- a/tools/autobuild/build-stm32-extra.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -# Build additional variants of pyboard firmware (base variants are built by build-boards.sh). - -# function for building firmware -function do_build() { - descr=$1 - board=$2 - shift - shift - for variant in `$MICROPY_AUTOBUILD_MAKE BOARD=$board query-variants | grep VARIANTS: | cut -d' ' -f2-`; do - target=$descr-$variant - echo "building $target $board" - build_dir=/tmp/stm-build-$board-$variant - $MICROPY_AUTOBUILD_MAKE $@ BOARD=$board BOARD_VARIANT=$variant BUILD=$build_dir || exit 1 - mv $build_dir/firmware.dfu $dest_dir/$target$fw_tag.dfu - mv $build_dir/firmware.hex $dest_dir/$target$fw_tag.hex - rm -rf $build_dir - done -} - -# check/get parameters -if [ $# != 2 ]; then - echo "usage: $0 " - exit 1 -fi - -fw_tag=$1 -dest_dir=$2 - -# check we are in the correct directory -if [ ! -r modpyb.c ]; then - echo "must be in stm directory" - exit 1 -fi - -# build the variants for each board -do_build pybv10 PYBV10 -do_build pybv11 PYBV11 -do_build pyblitev10 PYBLITEV10 diff --git a/tools/ci.sh b/tools/ci.sh index 98e78dc78a..5ce742b01b 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -129,9 +129,9 @@ function ci_esp32_build { make ${MAKEOPTS} -C ports/esp32 \ USER_C_MODULES=../../../examples/usercmodule/micropython.cmake \ FROZEN_MANIFEST=$(pwd)/ports/esp32/boards/manifest_test.py - make ${MAKEOPTS} -C ports/esp32 BOARD=GENERIC_C3 - make ${MAKEOPTS} -C ports/esp32 BOARD=GENERIC_S2 - make ${MAKEOPTS} -C ports/esp32 BOARD=GENERIC_S3 + make ${MAKEOPTS} -C ports/esp32 BOARD=ESP32_GENERIC_C3 + make ${MAKEOPTS} -C ports/esp32 BOARD=ESP32_GENERIC_S2 + make ${MAKEOPTS} -C ports/esp32 BOARD=ESP32_GENERIC_S3 # Test building native .mpy with xtensawin architecture. ci_native_mpy_modules_build xtensawin @@ -155,9 +155,9 @@ function ci_esp8266_path { function ci_esp8266_build { make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/esp8266 submodules - make ${MAKEOPTS} -C ports/esp8266 - make ${MAKEOPTS} -C ports/esp8266 BOARD=GENERIC_512K - make ${MAKEOPTS} -C ports/esp8266 BOARD=GENERIC_1M + make ${MAKEOPTS} -C ports/esp8266 BOARD=ESP8266_GENERIC + make ${MAKEOPTS} -C ports/esp8266 BOARD=ESP8266_GENERIC BOARD_VARIANT=FLASH_512K + make ${MAKEOPTS} -C ports/esp8266 BOARD=ESP8266_GENERIC BOARD_VARIANT=FLASH_1M } ######################################################################################## @@ -204,10 +204,10 @@ function ci_nrf_build { ports/nrf/drivers/bluetooth/download_ble_stack.sh s140_nrf52_6_1_1 make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/nrf submodules - make ${MAKEOPTS} -C ports/nrf BOARD=pca10040 - make ${MAKEOPTS} -C ports/nrf BOARD=microbit - make ${MAKEOPTS} -C ports/nrf BOARD=pca10056 SD=s140 - make ${MAKEOPTS} -C ports/nrf BOARD=pca10090 + make ${MAKEOPTS} -C ports/nrf BOARD=PCA10040 + make ${MAKEOPTS} -C ports/nrf BOARD=MICROBIT + make ${MAKEOPTS} -C ports/nrf BOARD=PCA10056 SD=s140 + make ${MAKEOPTS} -C ports/nrf BOARD=PCA10090 } ######################################################################################## @@ -272,8 +272,8 @@ function ci_rp2_build { make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/rp2 submodules make ${MAKEOPTS} -C ports/rp2 - make ${MAKEOPTS} -C ports/rp2 BOARD=PICO_W submodules - make ${MAKEOPTS} -C ports/rp2 BOARD=PICO_W USER_C_MODULES=../../examples/usercmodule/micropython.cmake + make ${MAKEOPTS} -C ports/rp2 BOARD=RPI_PICO_W submodules + make ${MAKEOPTS} -C ports/rp2 BOARD=RPI_PICO_W USER_C_MODULES=../../examples/usercmodule/micropython.cmake make ${MAKEOPTS} -C ports/rp2 BOARD=W5100S_EVB_PICO submodules make ${MAKEOPTS} -C ports/rp2 BOARD=W5100S_EVB_PICO @@ -425,6 +425,7 @@ function ci_native_mpy_modules_build { make -C examples/natmod/features1 ARCH=$arch make -C examples/natmod/features2 ARCH=$arch make -C examples/natmod/features3 ARCH=$arch + make -C examples/natmod/features4 ARCH=$arch make -C examples/natmod/btree ARCH=$arch make -C examples/natmod/deflate ARCH=$arch make -C examples/natmod/framebuf ARCH=$arch diff --git a/tools/codeformat.py b/tools/codeformat.py index 517aced37a..761bde3a81 100755 --- a/tools/codeformat.py +++ b/tools/codeformat.py @@ -60,6 +60,8 @@ PATHS = [ EXCLUSIONS = [ # The cc3200 port is not fully formatted yet. "ports/cc3200/*/*.[ch]", + # ESP-IDF downloads 3rd party code. + "ports/esp32/managed_components/*", # The nrf port is not fully formatted yet. "ports/nrf/boards/*.[ch]", "ports/nrf/device/*.[ch]", @@ -88,6 +90,7 @@ EXCLUSIONS = [ TOP = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) UNCRUSTIFY_CFG = os.path.join(TOP, "tools/uncrustify.cfg") +PYPROJECT_TOML = os.path.join(TOP, "pyproject.toml") C_EXTS = ( ".c", @@ -206,7 +209,7 @@ def main(): # Format Python files with black. if format_py: - command = ["black", "--fast", "--line-length=99"] + command = ["black", "--fast", "--config={}".format(PYPROJECT_TOML)] if args.v: command.append("-v") else: diff --git a/tools/metrics.py b/tools/metrics.py index 13161e9b9a..95156e3012 100755 --- a/tools/metrics.py +++ b/tools/metrics.py @@ -68,8 +68,8 @@ port_data = { "3": PortData("esp32", "esp32", "build-GENERIC/micropython.elf"), "x": PortData("mimxrt", "mimxrt", "build-TEENSY40/firmware.elf"), "e": PortData("renesas-ra", "renesas-ra", "build-EK_RA6M2/firmware.elf"), - "r": PortData("nrf", "nrf", "build-pca10040/firmware.elf"), - "p": PortData("rp2", "rp2", "build-PICO/firmware.elf"), + "r": PortData("nrf", "nrf", "build-PCA10040/firmware.elf"), + "p": PortData("rp2", "rp2", "build-RPI_PICO/firmware.elf"), "d": PortData("samd", "samd", "build-ADAFRUIT_ITSYBITSY_M4_EXPRESS/firmware.elf"), } diff --git a/tools/mpremote/mpremote/commands.py b/tools/mpremote/mpremote/commands.py index de12aa0bb1..aae612765b 100644 --- a/tools/mpremote/mpremote/commands.py +++ b/tools/mpremote/mpremote/commands.py @@ -238,6 +238,7 @@ def do_resume(state, _args=None): def do_soft_reset(state, _args=None): state.ensure_raw_repl(soft_reset=True) + state.did_action() def do_rtc(state, args): diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 7f581d0b13..5ef69b267a 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -33,9 +33,9 @@ if platform.python_version_tuple()[0] == "2": str_cons = lambda val, enc=None: str(val) bytes_cons = lambda val, enc=None: bytearray(val) - is_str_type = lambda o: type(o) is str + is_str_type = lambda o: isinstance(o, str) is_bytes_type = lambda o: type(o) is bytearray - is_int_type = lambda o: type(o) is int or type(o) is long + is_int_type = lambda o: isinstance(o, int) or isinstance(o, long) # noqa: F821 def hexlify_to_str(b): x = hexlify_py2(b) @@ -46,9 +46,9 @@ else: str_cons = str bytes_cons = bytes - is_str_type = lambda o: type(o) is str - is_bytes_type = lambda o: type(o) is bytes - is_int_type = lambda o: type(o) is int + is_str_type = lambda o: isinstance(o, str) + is_bytes_type = lambda o: isinstance(o, bytes) + is_int_type = lambda o: isinstance(o, int) def hexlify_to_str(b): return str(hexlify(b, ":"), "ascii") @@ -756,7 +756,7 @@ class CompiledModule: const_int_content += (digs.count(",") + 1) * bits_per_dig // 8 const_obj_content += 4 * 4 return "MP_ROM_PTR(&%s)" % obj_name - elif type(obj) is float: + elif isinstance(obj, float): macro_name = "%s_macro" % obj_name print( "#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B" @@ -777,7 +777,7 @@ class CompiledModule: print("#endif") const_obj_content += 3 * 4 return macro_name - elif type(obj) is complex: + elif isinstance(obj, complex): print( "static const mp_obj_complex_t %s = {{&mp_type_complex}, (mp_float_t)%.16g, (mp_float_t)%.16g};" % (obj_name, obj.real, obj.imag) diff --git a/tools/mpy_ld.py b/tools/mpy_ld.py index 87e57869f6..7f0fcbca22 100755 --- a/tools/mpy_ld.py +++ b/tools/mpy_ld.py @@ -232,34 +232,20 @@ def extract_qstrs(source_files): def read_qstrs(f): with open(f) as f: vals = set() - objs = set() for line in f: - while line: - m = re.search(r"MP_OBJ_NEW_QSTR\((MP_QSTR_[A-Za-z0-9_]*)\)", line) - if m: - objs.add(m.group(1)) - else: - m = re.search(r"MP_QSTR_[A-Za-z0-9_]*", line) - if m: - vals.add(m.group()) - if m: - s = m.span() - line = line[: s[0]] + line[s[1] :] - else: - line = "" - return vals, objs + for m in re.finditer(r"MP_QSTR_[A-Za-z0-9_]*", line): + vals.add(m.group()) + return vals static_qstrs = ["MP_QSTR_" + qstrutil.qstr_escape(q) for q in qstrutil.static_qstr_list] qstr_vals = set() - qstr_objs = set() for f in source_files: - vals, objs = read_qstrs(f) + vals = read_qstrs(f) qstr_vals.update(vals) - qstr_objs.update(objs) qstr_vals.difference_update(static_qstrs) - return static_qstrs, qstr_vals, qstr_objs + return static_qstrs, qstr_vals ################################################################################ @@ -730,7 +716,7 @@ def load_object_file(env, felf): env.unresolved_syms.append(sym) -def link_objects(env, native_qstr_vals_len, native_qstr_objs_len): +def link_objects(env, native_qstr_vals_len): # Build GOT information if env.arch.name == "EM_XTENSA": build_got_xtensa(env) @@ -761,7 +747,7 @@ def link_objects(env, native_qstr_vals_len, native_qstr_objs_len): # Create section to contain mp_native_obj_table env.obj_table_section = Section( ".external.obj_table", - bytearray(native_qstr_objs_len * env.arch.word_size), + bytearray(0 * env.arch.word_size), # currently empty env.arch.word_size, ) @@ -899,7 +885,7 @@ class MPYOutput: self.write_uint(n) -def build_mpy(env, entry_offset, fmpy, native_qstr_vals, native_qstr_objs): +def build_mpy(env, entry_offset, fmpy, native_qstr_vals): # Write jump instruction to start of text jump = env.arch.asm_jump(entry_offset) env.full_text[: len(jump)] = jump @@ -927,7 +913,7 @@ def build_mpy(env, entry_offset, fmpy, native_qstr_vals, native_qstr_objs): out.write_uint(1 + len(native_qstr_vals)) # MPY: n_obj - out.write_uint(len(native_qstr_objs)) + out.write_uint(0) # MPY: qstr table out.write_qstr(fmpy) # filename @@ -935,10 +921,7 @@ def build_mpy(env, entry_offset, fmpy, native_qstr_vals, native_qstr_objs): out.write_qstr(q) # MPY: object table - for q in native_qstr_objs: - out.write_bytes(bytearray([MP_PERSISTENT_OBJ_STR])) - out.write_uint(len(q)) - out.write_bytes(bytes(q, "utf8") + b"\x00") + # # MPY: kind/len out.write_uint(len(env.full_text) << 3 | (MP_CODE_NATIVE_VIPER - MP_CODE_BYTECODE)) @@ -965,11 +948,15 @@ def build_mpy(env, entry_offset, fmpy, native_qstr_vals, native_qstr_objs): out.write_bytes(env.full_rodata) # MPY: relocation information + # See py/persistentcode.c:mp_native_relocate for meaning of the `kind` integer values. prev_kind = None + prev_base = None + prev_offset = None + prev_n = None for base, addr, kind in env.mpy_relocs: if isinstance(kind, str) and kind.startswith(".text"): kind = 0 - elif kind in (".rodata", ".data.rel.ro"): + elif isinstance(kind, str) and kind.startswith((".rodata", ".data.rel.ro")): if env.arch.separate_rodata: kind = rodata_const_table_idx else: @@ -1013,7 +1000,7 @@ def do_preprocess(args): if args.output is None: assert args.files[0].endswith(".c") args.output = args.files[0][:-1] + "config.h" - static_qstrs, qstr_vals, qstr_objs = extract_qstrs(args.files) + static_qstrs, qstr_vals = extract_qstrs(args.files) with open(args.output, "w") as f: print( "#include \n" @@ -1026,11 +1013,6 @@ def do_preprocess(args): print("#define %s (%u)" % (q, i + 1), file=f) for i, q in enumerate(sorted(qstr_vals)): print("#define %s (mp_native_qstr_table[%d])" % (q, i + 1), file=f) - for i, q in enumerate(sorted(qstr_objs)): - print( - "#define MP_OBJ_NEW_QSTR_%s ((mp_obj_t)mp_native_obj_table[%d])" % (q, i), - file=f, - ) print("extern const uint16_t mp_native_qstr_table[];", file=f) print("extern const mp_uint_t mp_native_obj_table[];", file=f) @@ -1040,25 +1022,19 @@ def do_link(args): assert args.files[0].endswith(".o") args.output = args.files[0][:-1] + "mpy" native_qstr_vals = [] - native_qstr_objs = [] if args.qstrs is not None: with open(args.qstrs) as f: for l in f: m = re.match(r"#define MP_QSTR_([A-Za-z0-9_]*) \(mp_native_", l) if m: native_qstr_vals.append(m.group(1)) - else: - m = re.match(r"#define MP_OBJ_NEW_QSTR_MP_QSTR_([A-Za-z0-9_]*)", l) - if m: - native_qstr_objs.append(m.group(1)) log(LOG_LEVEL_2, "qstr vals: " + ", ".join(native_qstr_vals)) - log(LOG_LEVEL_2, "qstr objs: " + ", ".join(native_qstr_objs)) env = LinkEnv(args.arch) try: for file in args.files: load_object_file(env, file) - link_objects(env, len(native_qstr_vals), len(native_qstr_objs)) - build_mpy(env, env.find_addr("mpy_init"), args.output, native_qstr_vals, native_qstr_objs) + link_objects(env, len(native_qstr_vals)) + build_mpy(env, env.find_addr("mpy_init"), args.output, native_qstr_vals) except LinkError as er: print("LinkError:", er.args[0]) sys.exit(1)